1552f7358SJed Brown #define PETSCDM_DLL 2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h> /*I "petscdmplex.h" I*/ 40c312b8eSJed Brown #include <petscsf.h> 54663dae6SJed Brown #include <petscdmplextransform.h> 6b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h> 7b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h> 8552f7358SJed Brown 9b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 1058cd63d5SVaclav Hapla 119318fe57SMatthew G. Knepley /* External function declarations here */ 129318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm); 139318fe57SMatthew G. Knepley 14e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */ 159371c9d4SSatish Balay PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout) { 164fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 176858538eSMatthew G. Knepley PetscBool dist; 186bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 19e600fa54SMatthew G. Knepley 20e600fa54SMatthew G. Knepley PetscFunctionBegin; 21e600fa54SMatthew G. Knepley if (copyPeriodicity) { 224fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L)); 234fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L)); 24e600fa54SMatthew G. Knepley } 259566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dmin, &dist)); 269566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dmout, dist)); 276bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dmin, &reorder)); 286bc1bd01Sksagiyam PetscCall(DMPlexReorderSetDefault(dmout, reorder)); 29e600fa54SMatthew G. Knepley ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation; 301baa6e33SBarry Smith if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0)); 31e600fa54SMatthew G. Knepley PetscFunctionReturn(0); 32e600fa54SMatthew G. Knepley } 33e600fa54SMatthew G. Knepley 349318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 359318fe57SMatthew G. Knepley - Share the DM_Plex structure 369318fe57SMatthew G. Knepley - Share the coordinates 379318fe57SMatthew G. Knepley - Share the SF 389318fe57SMatthew G. Knepley */ 3969d8a87bSksagiyam PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm) { 409318fe57SMatthew G. Knepley PetscSF sf; 419318fe57SMatthew G. Knepley DM dmNew = *ndm, coordDM, coarseDM; 429318fe57SMatthew G. Knepley Vec coords; 434fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 449318fe57SMatthew G. Knepley PetscInt dim, cdim; 459318fe57SMatthew G. Knepley 469318fe57SMatthew G. Knepley PetscFunctionBegin; 479318fe57SMatthew G. Knepley if (dm == dmNew) { 489566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 499318fe57SMatthew G. Knepley PetscFunctionReturn(0); 509318fe57SMatthew G. Knepley } 519318fe57SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 529566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmNew, &dim)); 539566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmNew, &cdim)); 559566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 569566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sf)); 579566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sf)); 589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmNew, &coordDM)); 599566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmNew, &coords)); 609566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dm, coordDM)); 619566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 626858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM)); 636858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords)); 646858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dm, coordDM)); 656858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 669318fe57SMatthew G. Knepley /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */ 676858538eSMatthew G. Knepley PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 686858538eSMatthew G. Knepley dm->coordinates[0].field = dmNew->coordinates[0].field; 6961a622f3SMatthew G. Knepley ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc; 704fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 714fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 729566063dSJacob Faibussowitsch PetscCall(DMDestroy_Plex(dm)); 739566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 749318fe57SMatthew G. Knepley dm->data = dmNew->data; 759318fe57SMatthew G. Knepley ((DM_Plex *)dmNew->data)->refct++; 769566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 779566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 789566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmNew, &coarseDM)); 799566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 809566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 819318fe57SMatthew G. Knepley PetscFunctionReturn(0); 829318fe57SMatthew G. Knepley } 839318fe57SMatthew G. Knepley 849318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew 859318fe57SMatthew G. Knepley - Swap the DM_Plex structure 869318fe57SMatthew G. Knepley - Swap the coordinates 879318fe57SMatthew G. Knepley - Swap the point PetscSF 889318fe57SMatthew G. Knepley */ 899371c9d4SSatish Balay static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) { 909318fe57SMatthew G. Knepley DM coordDMA, coordDMB; 919318fe57SMatthew G. Knepley Vec coordsA, coordsB; 929318fe57SMatthew G. Knepley PetscSF sfA, sfB; 939318fe57SMatthew G. Knepley DMField fieldTmp; 949318fe57SMatthew G. Knepley void *tmp; 959318fe57SMatthew G. Knepley DMLabelLink listTmp; 969318fe57SMatthew G. Knepley DMLabel depthTmp; 979318fe57SMatthew G. Knepley PetscInt tmpI; 989318fe57SMatthew G. Knepley 999318fe57SMatthew G. Knepley PetscFunctionBegin; 1009318fe57SMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 1019566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmA, &sfA)); 1029566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmB, &sfB)); 1039566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sfA)); 1049566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmA, sfB)); 1059566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmB, sfA)); 1069566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)sfA)); 1079318fe57SMatthew G. Knepley 1089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &coordDMA)); 1099566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &coordDMB)); 1109566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordDMA)); 1119566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmA, coordDMB)); 1129566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmB, coordDMA)); 1139566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 1149318fe57SMatthew G. Knepley 1159566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordsA)); 1169566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmB, &coordsB)); 1179566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordsA)); 1189566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmA, coordsB)); 1199566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordsA)); 1209566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordsA)); 1219318fe57SMatthew G. Knepley 1226858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA)); 1236858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB)); 1246858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordDMA)); 1256858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmA, coordDMB)); 1266858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmB, coordDMA)); 1276858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 1286858538eSMatthew G. Knepley 1296858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA)); 1306858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB)); 1316858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordsA)); 1326858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB)); 1336858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA)); 1346858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordsA)); 1356858538eSMatthew G. Knepley 1366858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[0].field; 1376858538eSMatthew G. Knepley dmA->coordinates[0].field = dmB->coordinates[0].field; 1386858538eSMatthew G. Knepley dmB->coordinates[0].field = fieldTmp; 1396858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[1].field; 1406858538eSMatthew G. Knepley dmA->coordinates[1].field = dmB->coordinates[1].field; 1416858538eSMatthew G. Knepley dmB->coordinates[1].field = fieldTmp; 1429318fe57SMatthew G. Knepley tmp = dmA->data; 1439318fe57SMatthew G. Knepley dmA->data = dmB->data; 1449318fe57SMatthew G. Knepley dmB->data = tmp; 1459318fe57SMatthew G. Knepley listTmp = dmA->labels; 1469318fe57SMatthew G. Knepley dmA->labels = dmB->labels; 1479318fe57SMatthew G. Knepley dmB->labels = listTmp; 1489318fe57SMatthew G. Knepley depthTmp = dmA->depthLabel; 1499318fe57SMatthew G. Knepley dmA->depthLabel = dmB->depthLabel; 1509318fe57SMatthew G. Knepley dmB->depthLabel = depthTmp; 1519318fe57SMatthew G. Knepley depthTmp = dmA->celltypeLabel; 1529318fe57SMatthew G. Knepley dmA->celltypeLabel = dmB->celltypeLabel; 1539318fe57SMatthew G. Knepley dmB->celltypeLabel = depthTmp; 1549318fe57SMatthew G. Knepley tmpI = dmA->levelup; 1559318fe57SMatthew G. Knepley dmA->levelup = dmB->levelup; 1569318fe57SMatthew G. Knepley dmB->levelup = tmpI; 1579318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1589318fe57SMatthew G. Knepley } 1599318fe57SMatthew G. Knepley 1609371c9d4SSatish Balay static PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) { 1619318fe57SMatthew G. Knepley DM idm; 1629318fe57SMatthew G. Knepley 1639318fe57SMatthew G. Knepley PetscFunctionBegin; 1649566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 1659566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 16669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 1679318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1689318fe57SMatthew G. Knepley } 1699318fe57SMatthew G. Knepley 1709318fe57SMatthew G. Knepley /*@C 1719318fe57SMatthew G. Knepley DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates 1729318fe57SMatthew G. Knepley 1739318fe57SMatthew G. Knepley Collective 1749318fe57SMatthew G. Knepley 1759318fe57SMatthew G. Knepley Input Parameters: 1769318fe57SMatthew G. Knepley + DM - The DM 1774f9ab2b4SJed Brown . degree - The degree of the finite element or PETSC_DECIDE 1789318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface 1799318fe57SMatthew G. Knepley 1809318fe57SMatthew G. Knepley Level: advanced 1819318fe57SMatthew G. Knepley 182db781477SPatrick Sanan .seealso: `PetscFECreateLagrange()`, `DMGetCoordinateDM()` 1839318fe57SMatthew G. Knepley @*/ 1849371c9d4SSatish Balay PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc) { 1859318fe57SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1869318fe57SMatthew G. Knepley DM cdm; 1879318fe57SMatthew G. Knepley PetscDS cds; 1889318fe57SMatthew G. Knepley PetscFE fe; 1899318fe57SMatthew G. Knepley PetscClassId id; 1909318fe57SMatthew G. Knepley 1919318fe57SMatthew G. Knepley PetscFunctionBegin; 1929566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 1939566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 1949566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, (PetscObject *)&fe)); 1959566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 1969318fe57SMatthew G. Knepley if (id != PETSCFE_CLASSID) { 1979318fe57SMatthew G. Knepley PetscBool simplex; 1989318fe57SMatthew G. Knepley PetscInt dim, dE, qorder; 1999318fe57SMatthew G. Knepley 2009566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 2019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 2029318fe57SMatthew G. Knepley qorder = degree; 203d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)cdm); 2049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-coord_dm_default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0)); 205d0609cedSBarry Smith PetscOptionsEnd(); 2064f9ab2b4SJed Brown if (degree == PETSC_DECIDE) fe = NULL; 2074f9ab2b4SJed Brown else { 2088c4475acSStefano Zampini PetscCall(DMPlexIsSimplex(dm, &simplex)); 2099566063dSJacob Faibussowitsch PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, degree, qorder, &fe)); 2104f9ab2b4SJed Brown } 2119566063dSJacob Faibussowitsch PetscCall(DMProjectCoordinates(dm, fe)); 2129566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 2139318fe57SMatthew G. Knepley } 2149318fe57SMatthew G. Knepley mesh->coordFunc = coordFunc; 2159318fe57SMatthew G. Knepley PetscFunctionReturn(0); 2169318fe57SMatthew G. Knepley } 2179318fe57SMatthew G. Knepley 2181df5d5c5SMatthew G. Knepley /*@ 2191df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 2201df5d5c5SMatthew G. Knepley 221d083f849SBarry Smith Collective 2221df5d5c5SMatthew G. Knepley 2231df5d5c5SMatthew G. Knepley Input Parameters: 2241df5d5c5SMatthew G. Knepley + comm - The communicator for the DM object 2251df5d5c5SMatthew G. Knepley . dim - The spatial dimension 2261df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 2271df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 2281df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 2291df5d5c5SMatthew G. Knepley 2301df5d5c5SMatthew G. Knepley Output Parameter: 2311df5d5c5SMatthew G. Knepley . dm - The DM object 2321df5d5c5SMatthew G. Knepley 2331df5d5c5SMatthew G. Knepley Level: beginner 2341df5d5c5SMatthew G. Knepley 235db781477SPatrick Sanan .seealso: `DMSetType()`, `DMCreate()` 2361df5d5c5SMatthew G. Knepley @*/ 2379371c9d4SSatish Balay PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) { 2381df5d5c5SMatthew G. Knepley DM dm; 2391df5d5c5SMatthew G. Knepley PetscMPIInt rank; 2401df5d5c5SMatthew G. Knepley 2411df5d5c5SMatthew G. Knepley PetscFunctionBegin; 2429566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &dm)); 2439566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 2449566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 2459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 246ce78fa2fSMatthew G. Knepley switch (dim) { 247ce78fa2fSMatthew G. Knepley case 2: 2489566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular")); 2499566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral")); 250ce78fa2fSMatthew G. Knepley break; 251ce78fa2fSMatthew G. Knepley case 3: 2529566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral")); 2539566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral")); 254ce78fa2fSMatthew G. Knepley break; 2559371c9d4SSatish Balay default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 256ce78fa2fSMatthew G. Knepley } 2571df5d5c5SMatthew G. Knepley if (rank) { 2581df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 2599566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 2601df5d5c5SMatthew G. Knepley } else { 2611df5d5c5SMatthew G. Knepley switch (dim) { 2621df5d5c5SMatthew G. Knepley case 2: 2631df5d5c5SMatthew G. Knepley if (simplex) { 2641df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 2651df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 2661df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 2671df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 2681df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 2691df5d5c5SMatthew G. Knepley 2709566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2711df5d5c5SMatthew G. Knepley } else { 2721df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 2731df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 2741df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 2751df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2761df5d5c5SMatthew 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}; 2771df5d5c5SMatthew G. Knepley 2789566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2791df5d5c5SMatthew G. Knepley } 2801df5d5c5SMatthew G. Knepley break; 2811df5d5c5SMatthew G. Knepley case 3: 2821df5d5c5SMatthew G. Knepley if (simplex) { 2831df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 2841df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 2851df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 2861df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2871df5d5c5SMatthew 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}; 2881df5d5c5SMatthew G. Knepley 2899566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2901df5d5c5SMatthew G. Knepley } else { 2911df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 2921df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 2931df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 2941df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 2959371c9d4SSatish 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}; 2961df5d5c5SMatthew G. Knepley 2979566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2981df5d5c5SMatthew G. Knepley } 2991df5d5c5SMatthew G. Knepley break; 3009371c9d4SSatish Balay default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 3011df5d5c5SMatthew G. Knepley } 3021df5d5c5SMatthew G. Knepley } 3031df5d5c5SMatthew G. Knepley *newdm = dm; 3041df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 3051df5d5c5SMatthew G. Knepley DM rdm; 3061df5d5c5SMatthew G. Knepley const char *name; 3071df5d5c5SMatthew G. Knepley 3089566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 3099566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 3109566063dSJacob Faibussowitsch PetscCall(DMRefine(*newdm, comm, &rdm)); 3119566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)*newdm, &name)); 3129566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, name)); 3139566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 3141df5d5c5SMatthew G. Knepley *newdm = rdm; 3151df5d5c5SMatthew G. Knepley } 3161df5d5c5SMatthew G. Knepley if (interpolate) { 3175fd9971aSMatthew G. Knepley DM idm; 3181df5d5c5SMatthew G. Knepley 3199566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*newdm, &idm)); 3209566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 3211df5d5c5SMatthew G. Knepley *newdm = idm; 3221df5d5c5SMatthew G. Knepley } 3231df5d5c5SMatthew G. Knepley PetscFunctionReturn(0); 3241df5d5c5SMatthew G. Knepley } 3251df5d5c5SMatthew G. Knepley 3269371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) { 3279318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 3289318fe57SMatthew G. Knepley PetscInt markerRight = 1; 3299318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 3309318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 3319318fe57SMatthew G. Knepley Vec coordinates; 3329318fe57SMatthew G. Knepley PetscSection coordSection; 3339318fe57SMatthew G. Knepley PetscScalar *coords; 3349318fe57SMatthew G. Knepley PetscInt coordSize; 3359318fe57SMatthew G. Knepley PetscMPIInt rank; 3369318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 337552f7358SJed Brown 3389318fe57SMatthew G. Knepley PetscFunctionBegin; 3399566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 3409318fe57SMatthew G. Knepley if (markerSeparate) { 3419318fe57SMatthew G. Knepley markerRight = 2; 3429318fe57SMatthew G. Knepley markerLeft = 1; 3439318fe57SMatthew G. Knepley } 3449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 345c5853193SPierre Jolivet if (rank == 0) { 3469566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numVertices)); 3479566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3489566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft)); 3499566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight)); 3509318fe57SMatthew G. Knepley } 3519566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 3529566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 3539318fe57SMatthew G. Knepley /* Build coordinates */ 3549566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 3559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 3569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 3579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, 0, numVertices)); 3589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 3599318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 3609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 3619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 3629318fe57SMatthew G. Knepley } 3639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 3649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 3659566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 3669566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 3679566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 3689566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 3699566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 3709566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 3719318fe57SMatthew G. Knepley coords[0] = lower[0]; 3729318fe57SMatthew G. Knepley coords[1] = upper[0]; 3739566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 3749566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 3759566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 3769318fe57SMatthew G. Knepley PetscFunctionReturn(0); 3779318fe57SMatthew G. Knepley } 37826492d91SMatthew G. Knepley 3799371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) { 3801df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0] + 1) * (edges[1] + 1); 3811df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1]; 382552f7358SJed Brown PetscInt markerTop = 1; 383552f7358SJed Brown PetscInt markerBottom = 1; 384552f7358SJed Brown PetscInt markerRight = 1; 385552f7358SJed Brown PetscInt markerLeft = 1; 386552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 387552f7358SJed Brown Vec coordinates; 388552f7358SJed Brown PetscSection coordSection; 389552f7358SJed Brown PetscScalar *coords; 390552f7358SJed Brown PetscInt coordSize; 391552f7358SJed Brown PetscMPIInt rank; 392552f7358SJed Brown PetscInt v, vx, vy; 393552f7358SJed Brown 394552f7358SJed Brown PetscFunctionBegin; 3959566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 396552f7358SJed Brown if (markerSeparate) { 3971df21d24SMatthew G. Knepley markerTop = 3; 3981df21d24SMatthew G. Knepley markerBottom = 1; 3991df21d24SMatthew G. Knepley markerRight = 2; 4001df21d24SMatthew G. Knepley markerLeft = 4; 401552f7358SJed Brown } 4029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 403dd400576SPatrick Sanan if (rank == 0) { 404552f7358SJed Brown PetscInt e, ex, ey; 405552f7358SJed Brown 4069566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices)); 40748a46eb9SPierre Jolivet for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 4089566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 409552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 410552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 411552f7358SJed Brown PetscInt edge = vx * edges[1] + ey + edges[0] * (edges[1] + 1); 412552f7358SJed Brown PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges; 413da80777bSKarl Rupp PetscInt cone[2]; 414552f7358SJed Brown 4159371c9d4SSatish Balay cone[0] = vertex; 4169371c9d4SSatish Balay cone[1] = vertex + edges[0] + 1; 4179566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 418552f7358SJed Brown if (vx == edges[0]) { 4199566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 4209566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 421552f7358SJed Brown if (ey == edges[1] - 1) { 4229566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 4239566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 424552f7358SJed Brown } 425552f7358SJed Brown } else if (vx == 0) { 4269566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 4279566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 428552f7358SJed Brown if (ey == edges[1] - 1) { 4299566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 4309566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 431552f7358SJed Brown } 432552f7358SJed Brown } 433552f7358SJed Brown } 434552f7358SJed Brown } 435552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 436552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 437552f7358SJed Brown PetscInt edge = vy * edges[0] + ex; 438552f7358SJed Brown PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges; 439da80777bSKarl Rupp PetscInt cone[2]; 440552f7358SJed Brown 4419371c9d4SSatish Balay cone[0] = vertex; 4429371c9d4SSatish Balay cone[1] = vertex + 1; 4439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 444552f7358SJed Brown if (vy == edges[1]) { 4459566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 4469566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 447552f7358SJed Brown if (ex == edges[0] - 1) { 4489566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 4499566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 450552f7358SJed Brown } 451552f7358SJed Brown } else if (vy == 0) { 4529566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 4539566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 454552f7358SJed Brown if (ex == edges[0] - 1) { 4559566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 4569566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 457552f7358SJed Brown } 458552f7358SJed Brown } 459552f7358SJed Brown } 460552f7358SJed Brown } 461552f7358SJed Brown } 4629566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 4639566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 464552f7358SJed Brown /* Build coordinates */ 4659566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 2)); 4669566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 4679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 4689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 4699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 470552f7358SJed Brown for (v = numEdges; v < numEdges + numVertices; ++v) { 4719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 2)); 4729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 473552f7358SJed Brown } 4749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 4769566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 4779566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 4789566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 4799566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 2)); 4809566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 4819566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 482552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 483552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 484552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx; 485552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy; 486552f7358SJed Brown } 487552f7358SJed Brown } 4889566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 4899566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 4909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 491552f7358SJed Brown PetscFunctionReturn(0); 492552f7358SJed Brown } 493552f7358SJed Brown 4949371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) { 4959e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 4967b59f5a9SMichael Lange PetscInt numFaces = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2]; 497c2df9bbfSMatthew G. Knepley PetscInt markerTop = 1; 498c2df9bbfSMatthew G. Knepley PetscInt markerBottom = 1; 499c2df9bbfSMatthew G. Knepley PetscInt markerFront = 1; 500c2df9bbfSMatthew G. Knepley PetscInt markerBack = 1; 501c2df9bbfSMatthew G. Knepley PetscInt markerRight = 1; 502c2df9bbfSMatthew G. Knepley PetscInt markerLeft = 1; 503c2df9bbfSMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 504552f7358SJed Brown Vec coordinates; 505552f7358SJed Brown PetscSection coordSection; 506552f7358SJed Brown PetscScalar *coords; 507552f7358SJed Brown PetscInt coordSize; 508552f7358SJed Brown PetscMPIInt rank; 509552f7358SJed Brown PetscInt v, vx, vy, vz; 5107b59f5a9SMichael Lange PetscInt voffset, iface = 0, cone[4]; 511552f7358SJed Brown 512552f7358SJed Brown PetscFunctionBegin; 5131dca8a05SBarry 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"); 5149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 515c2df9bbfSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 516c2df9bbfSMatthew G. Knepley if (markerSeparate) { 517c2df9bbfSMatthew G. Knepley markerBottom = 1; 518c2df9bbfSMatthew G. Knepley markerTop = 2; 519c2df9bbfSMatthew G. Knepley markerFront = 3; 520c2df9bbfSMatthew G. Knepley markerBack = 4; 521c2df9bbfSMatthew G. Knepley markerRight = 5; 522c2df9bbfSMatthew G. Knepley markerLeft = 6; 523c2df9bbfSMatthew G. Knepley } 5249371c9d4SSatish Balay vertices[0] = faces[0] + 1; 5259371c9d4SSatish Balay vertices[1] = faces[1] + 1; 5269371c9d4SSatish Balay vertices[2] = faces[2] + 1; 5279e8abbc3SMichael Lange numVertices = vertices[0] * vertices[1] * vertices[2]; 528dd400576SPatrick Sanan if (rank == 0) { 529552f7358SJed Brown PetscInt f; 530552f7358SJed Brown 5319566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices)); 53248a46eb9SPierre Jolivet for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 5339566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 5347b59f5a9SMichael Lange 5357b59f5a9SMichael Lange /* Side 0 (Top) */ 5367b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5377b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5387b59f5a9SMichael Lange voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx; 5399371c9d4SSatish Balay cone[0] = voffset; 5409371c9d4SSatish Balay cone[1] = voffset + 1; 5419371c9d4SSatish Balay cone[2] = voffset + vertices[0] + 1; 5429371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 5439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 544c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop)); 545c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop)); 546c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop)); 547c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop)); 548c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop)); 5497b59f5a9SMichael Lange iface++; 550552f7358SJed Brown } 551552f7358SJed Brown } 5527b59f5a9SMichael Lange 5537b59f5a9SMichael Lange /* Side 1 (Bottom) */ 5547b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5557b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5567b59f5a9SMichael Lange voffset = numFaces + vy * (faces[0] + 1) + vx; 5579371c9d4SSatish Balay cone[0] = voffset + 1; 5589371c9d4SSatish Balay cone[1] = voffset; 5599371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 5609371c9d4SSatish Balay cone[3] = voffset + vertices[0] + 1; 5619566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 562c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom)); 563c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom)); 564c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom)); 565c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom)); 566c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom)); 5677b59f5a9SMichael Lange iface++; 568552f7358SJed Brown } 569552f7358SJed Brown } 5707b59f5a9SMichael Lange 5717b59f5a9SMichael Lange /* Side 2 (Front) */ 5727b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 5737b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5747b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vx; 5759371c9d4SSatish Balay cone[0] = voffset; 5769371c9d4SSatish Balay cone[1] = voffset + 1; 5779371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + 1; 5789371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1]; 5799566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 580c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront)); 581c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront)); 582c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront)); 583c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront)); 584c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront)); 5857b59f5a9SMichael Lange iface++; 586552f7358SJed Brown } 5877b59f5a9SMichael Lange } 5887b59f5a9SMichael Lange 5897b59f5a9SMichael Lange /* Side 3 (Back) */ 5907b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 5917b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5927b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx; 5939371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 5949371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1] + 1; 5959371c9d4SSatish Balay cone[2] = voffset + 1; 5969371c9d4SSatish Balay cone[3] = voffset; 5979566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 598c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack)); 599c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack)); 600c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack)); 601c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack)); 602c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack)); 6037b59f5a9SMichael Lange iface++; 6047b59f5a9SMichael Lange } 6057b59f5a9SMichael Lange } 6067b59f5a9SMichael Lange 6077b59f5a9SMichael Lange /* Side 4 (Left) */ 6087b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6097b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 6107b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0]; 6119371c9d4SSatish Balay cone[0] = voffset; 6129371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1]; 6139371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + vertices[0]; 6149371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 6159566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 616c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft)); 617c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft)); 618c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft)); 619c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft)); 620c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft)); 6217b59f5a9SMichael Lange iface++; 6227b59f5a9SMichael Lange } 6237b59f5a9SMichael Lange } 6247b59f5a9SMichael Lange 6257b59f5a9SMichael Lange /* Side 5 (Right) */ 6267b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6277b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 628aab5bcd8SJed Brown voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0]; 6299371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 6309371c9d4SSatish Balay cone[1] = voffset; 6319371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 6329371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1] + vertices[0]; 6339566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 634c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight)); 635c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight)); 636c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight)); 637c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight)); 638c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight)); 6397b59f5a9SMichael Lange iface++; 6407b59f5a9SMichael Lange } 641552f7358SJed Brown } 642552f7358SJed Brown } 6439566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 6449566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 645552f7358SJed Brown /* Build coordinates */ 6469566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 3)); 6479566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 6489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 6509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 651552f7358SJed Brown for (v = numFaces; v < numFaces + numVertices; ++v) { 6529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 3)); 6539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 654552f7358SJed Brown } 6559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 6579566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 6589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 6599566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6609566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 3)); 6619566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 6629566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 663552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 664552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 665552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 666552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx; 667552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy; 668552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz; 669552f7358SJed Brown } 670552f7358SJed Brown } 671552f7358SJed Brown } 6729566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 6739566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 6749566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 675552f7358SJed Brown PetscFunctionReturn(0); 676552f7358SJed Brown } 677552f7358SJed Brown 6789371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) { 6799318fe57SMatthew G. Knepley PetscFunctionBegin; 6809318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 6819566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim - 1)); 6829566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim)); 6839318fe57SMatthew G. Knepley switch (dim) { 6849566063dSJacob Faibussowitsch case 1: PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); break; 6859566063dSJacob Faibussowitsch case 2: PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); break; 6869566063dSJacob Faibussowitsch case 3: PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); break; 68763a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim); 6889318fe57SMatthew G. Knepley } 6899566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 6909318fe57SMatthew G. Knepley PetscFunctionReturn(0); 6919318fe57SMatthew G. Knepley } 6929318fe57SMatthew G. Knepley 6939318fe57SMatthew G. Knepley /*@C 6949318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 6959318fe57SMatthew G. Knepley 6969318fe57SMatthew G. Knepley Collective 6979318fe57SMatthew G. Knepley 6989318fe57SMatthew G. Knepley Input Parameters: 6999318fe57SMatthew G. Knepley + comm - The communicator for the DM object 7009318fe57SMatthew G. Knepley . dim - The spatial dimension of the box, so the resulting mesh is has dimension dim-1 7019318fe57SMatthew G. Knepley . faces - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 7029318fe57SMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 7039318fe57SMatthew G. Knepley . upper - The upper right corner, or NULL for (1, 1, 1) 7049318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 7059318fe57SMatthew G. Knepley 7069318fe57SMatthew G. Knepley Output Parameter: 7079318fe57SMatthew G. Knepley . dm - The DM object 7089318fe57SMatthew G. Knepley 7099318fe57SMatthew G. Knepley Level: beginner 7109318fe57SMatthew G. Knepley 711db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()` 7129318fe57SMatthew G. Knepley @*/ 7139371c9d4SSatish Balay PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) { 7149318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 7159318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 7169318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 7179318fe57SMatthew G. Knepley 7189318fe57SMatthew G. Knepley PetscFunctionBegin; 7199566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 7209566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 7219566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 7229318fe57SMatthew G. Knepley PetscFunctionReturn(0); 7239318fe57SMatthew G. Knepley } 7249318fe57SMatthew G. Knepley 7259371c9d4SSatish Balay static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) { 726fdbf62faSLisandro Dalcin PetscInt i, fStart, fEnd, numCells = 0, numVerts = 0; 727fdbf62faSLisandro Dalcin PetscInt numPoints[2], *coneSize, *cones, *coneOrientations; 728fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 729fdbf62faSLisandro Dalcin PetscReal L, maxCell; 730fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 731fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 732fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 733fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 734fdbf62faSLisandro Dalcin PetscMPIInt rank; 735fdbf62faSLisandro Dalcin 736fdbf62faSLisandro Dalcin PetscFunctionBegin; 7379318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 738fdbf62faSLisandro Dalcin 7399566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, 1)); 7409566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 7419566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 742fdbf62faSLisandro Dalcin 7439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 744dd400576SPatrick Sanan if (rank == 0) numCells = segments; 745dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 746fdbf62faSLisandro Dalcin 7479371c9d4SSatish Balay numPoints[0] = numVerts; 7489371c9d4SSatish Balay numPoints[1] = numCells; 7499566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords)); 7509566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts)); 751ad540459SPierre Jolivet for (i = 0; i < numCells; ++i) coneSize[i] = 2; 752ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0; 7539371c9d4SSatish Balay for (i = 0; i < numCells; ++i) { 7549371c9d4SSatish Balay cones[2 * i] = numCells + i % numVerts; 7559371c9d4SSatish Balay cones[2 * i + 1] = numCells + (i + 1) % numVerts; 7569371c9d4SSatish Balay } 757ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); 7589566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 7599566063dSJacob Faibussowitsch PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords)); 760fdbf62faSLisandro Dalcin 7619566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 7629371c9d4SSatish Balay if (markerSeparate) { 7639371c9d4SSatish Balay markerLeft = faceMarkerLeft; 7649371c9d4SSatish Balay markerRight = faceMarkerRight; 7659371c9d4SSatish Balay } 766dd400576SPatrick Sanan if (!wrap && rank == 0) { 7679566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 7689566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft)); 7699566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight)); 7709566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft)); 7719566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight)); 772fdbf62faSLisandro Dalcin } 773fdbf62faSLisandro Dalcin if (wrap) { 774fdbf62faSLisandro Dalcin L = upper - lower; 775fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments)); 7764fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L)); 777fdbf62faSLisandro Dalcin } 7789566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 779fdbf62faSLisandro Dalcin PetscFunctionReturn(0); 780fdbf62faSLisandro Dalcin } 781fdbf62faSLisandro Dalcin 7829371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) { 7839318fe57SMatthew G. Knepley DM boundary, vol; 784c22d3578SMatthew G. Knepley DMLabel bdlabel; 785d6218766SMatthew G. Knepley 786d6218766SMatthew G. Knepley PetscFunctionBegin; 7879318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 788c22d3578SMatthew 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"); 7899566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary)); 7909566063dSJacob Faibussowitsch PetscCall(DMSetType(boundary, DMPLEX)); 7919566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 7929566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 793c22d3578SMatthew G. Knepley PetscCall(DMGetLabel(vol, "marker", &bdlabel)); 794c22d3578SMatthew G. Knepley if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel)); 7955de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol)); 79669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 7979566063dSJacob Faibussowitsch PetscCall(DMDestroy(&boundary)); 798d6218766SMatthew G. Knepley PetscFunctionReturn(0); 799d6218766SMatthew G. Knepley } 800d6218766SMatthew G. Knepley 8019371c9d4SSatish Balay static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) { 802ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 803f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 804f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 805f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 806f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 807f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 808f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 8093dfda0b1SToby Isaac PetscInt dim; 810d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 8113dfda0b1SToby Isaac PetscMPIInt rank; 8123dfda0b1SToby Isaac 8133dfda0b1SToby Isaac PetscFunctionBegin; 8149566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8169566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 8179566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 8189566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 8199371c9d4SSatish 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) { 8209371c9d4SSatish Balay if (cutMarker) { 8219371c9d4SSatish Balay PetscCall(DMCreateLabel(dm, "periodic_cut")); 8229371c9d4SSatish Balay PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 8239371c9d4SSatish Balay } 824d8211ee3SMatthew G. Knepley } 8253dfda0b1SToby Isaac switch (dim) { 8263dfda0b1SToby Isaac case 2: 827f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 828f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 829f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 830f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 8313dfda0b1SToby Isaac break; 8323dfda0b1SToby Isaac case 3: 833f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 834f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 835f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 836f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 837f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 838f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 8393dfda0b1SToby Isaac break; 8409371c9d4SSatish Balay default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 8413dfda0b1SToby Isaac } 8429566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 843f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 844f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 845f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 846f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 847f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 848f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 849f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 8503dfda0b1SToby Isaac } 8513dfda0b1SToby Isaac { 852dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 853dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 854dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 855dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0; 856dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0; 857dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0; 8583dfda0b1SToby Isaac const PetscInt numCells = numXEdges * numYEdges * numZEdges; 8593dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges * numZEdges; 8603dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges * numZEdges; 8613dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges * numYEdges; 8623dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices * numXFaces; 8633dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices * numYFaces; 8643dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices * numZFaces; 8653dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 8663dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices; 8673dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices; 8683dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices; 8693dfda0b1SToby Isaac const PetscInt numVertices = numXVertices * numYVertices * numZVertices; 8703dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 8713dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 8723dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 8733dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 8743dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 8753dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 8763dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 8773dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 8783dfda0b1SToby Isaac Vec coordinates; 8793dfda0b1SToby Isaac PetscSection coordSection; 8803dfda0b1SToby Isaac PetscScalar *coords; 8813dfda0b1SToby Isaac PetscInt coordSize; 8823dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 8833dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 8843dfda0b1SToby Isaac 8859566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices)); 88648a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 88748a46eb9SPierre Jolivet for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 88848a46eb9SPierre Jolivet for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 8899566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 8903dfda0b1SToby Isaac /* Build cells */ 8913dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 8923dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 8933dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 8943dfda0b1SToby Isaac PetscInt cell = (fz * numYEdges + fy) * numXEdges + fx; 8953dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 8963dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices); 8973dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 8983dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices); 8993dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 9003dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices); 9013dfda0b1SToby Isaac /* B, T, F, K, R, L */ 902b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 90342206facSLisandro Dalcin PetscInt cone[6]; 9043dfda0b1SToby Isaac 9053dfda0b1SToby Isaac /* no boundary twisting in 3D */ 9069371c9d4SSatish Balay cone[0] = faceB; 9079371c9d4SSatish Balay cone[1] = faceT; 9089371c9d4SSatish Balay cone[2] = faceF; 9099371c9d4SSatish Balay cone[3] = faceK; 9109371c9d4SSatish Balay cone[4] = faceR; 9119371c9d4SSatish Balay cone[5] = faceL; 9129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, cell, cone)); 9139566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, cell, ornt)); 9149566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9159566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9169566063dSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9173dfda0b1SToby Isaac } 9183dfda0b1SToby Isaac } 9193dfda0b1SToby Isaac } 9203dfda0b1SToby Isaac /* Build x faces */ 9213dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 9223dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 9233dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 9243dfda0b1SToby Isaac PetscInt face = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 9253dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 9263dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz; 9273dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 9283dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy; 929b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 9303dfda0b1SToby Isaac PetscInt cone[4]; 9313dfda0b1SToby Isaac 9323dfda0b1SToby Isaac if (dim == 3) { 9333dfda0b1SToby Isaac /* markers */ 9343dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 9353dfda0b1SToby Isaac if (fx == numXVertices - 1) { 9369566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 9379566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerRight)); 9389371c9d4SSatish Balay } else if (fx == 0) { 9399566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 9409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft)); 9413dfda0b1SToby Isaac } 9423dfda0b1SToby Isaac } 9433dfda0b1SToby Isaac } 9449371c9d4SSatish Balay cone[0] = edgeB; 9459371c9d4SSatish Balay cone[1] = edgeR; 9469371c9d4SSatish Balay cone[2] = edgeT; 9479371c9d4SSatish Balay cone[3] = edgeL; 9489566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 9499566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 9503dfda0b1SToby Isaac } 9513dfda0b1SToby Isaac } 9523dfda0b1SToby Isaac } 9533dfda0b1SToby Isaac /* Build y faces */ 9543dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 95542206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 9563dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 9573dfda0b1SToby Isaac PetscInt face = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 9583dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 9593dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz; 9603dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 9613dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx; 962b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 9633dfda0b1SToby Isaac PetscInt cone[4]; 9643dfda0b1SToby Isaac 9653dfda0b1SToby Isaac if (dim == 3) { 9663dfda0b1SToby Isaac /* markers */ 9673dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 9683dfda0b1SToby Isaac if (fy == numYVertices - 1) { 9699566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 9709566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBack)); 9719371c9d4SSatish Balay } else if (fy == 0) { 9729566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 9739566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerFront)); 9743dfda0b1SToby Isaac } 9753dfda0b1SToby Isaac } 9763dfda0b1SToby Isaac } 9779371c9d4SSatish Balay cone[0] = edgeB; 9789371c9d4SSatish Balay cone[1] = edgeR; 9799371c9d4SSatish Balay cone[2] = edgeT; 9809371c9d4SSatish Balay cone[3] = edgeL; 9819566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 9829566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 9833dfda0b1SToby Isaac } 9843dfda0b1SToby Isaac } 9853dfda0b1SToby Isaac } 9863dfda0b1SToby Isaac /* Build z faces */ 9873dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 9883dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 9893dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 9903dfda0b1SToby Isaac PetscInt face = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 9913dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 9923dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy; 9933dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 9943dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx; 995b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 9963dfda0b1SToby Isaac PetscInt cone[4]; 9973dfda0b1SToby Isaac 9983dfda0b1SToby Isaac if (dim == 2) { 9999371c9d4SSatish Balay if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) { 10009371c9d4SSatish Balay edgeR += numYEdges - 1 - 2 * fy; 10019371c9d4SSatish Balay ornt[1] = -1; 10029371c9d4SSatish Balay } 10039371c9d4SSatish Balay if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) { 10049371c9d4SSatish Balay edgeT += numXEdges - 1 - 2 * fx; 10059371c9d4SSatish Balay ornt[2] = 0; 10069371c9d4SSatish Balay } 10079566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 10089566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 1009d1c88043SMatthew G. Knepley } else { 10103dfda0b1SToby Isaac /* markers */ 10113dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 10123dfda0b1SToby Isaac if (fz == numZVertices - 1) { 10139566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 10149566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerTop)); 10159371c9d4SSatish Balay } else if (fz == 0) { 10169566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 10179566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom)); 10183dfda0b1SToby Isaac } 10193dfda0b1SToby Isaac } 10203dfda0b1SToby Isaac } 10219371c9d4SSatish Balay cone[0] = edgeB; 10229371c9d4SSatish Balay cone[1] = edgeR; 10239371c9d4SSatish Balay cone[2] = edgeT; 10249371c9d4SSatish Balay cone[3] = edgeL; 10259566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 10269566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 10273dfda0b1SToby Isaac } 10283dfda0b1SToby Isaac } 10293dfda0b1SToby Isaac } 10303dfda0b1SToby Isaac /* Build Z edges*/ 10313dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 10323dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 10333dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 10343dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez; 10353dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx; 10363dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx; 10373dfda0b1SToby Isaac PetscInt cone[2]; 10383dfda0b1SToby Isaac 10399371c9d4SSatish Balay cone[0] = vertexB; 10409371c9d4SSatish Balay cone[1] = vertexT; 1041c2df9bbfSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, edge, cone)); 10423dfda0b1SToby Isaac if (dim == 3) { 10433dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 10443dfda0b1SToby Isaac if (vx == numXVertices - 1) { 10459566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1046c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1047c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1048c2df9bbfSMatthew G. Knepley } else if (vx == 0) { 10499566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1050c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1051c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 10523dfda0b1SToby Isaac } 10533dfda0b1SToby Isaac } 10543dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 10553dfda0b1SToby Isaac if (vy == numYVertices - 1) { 10569566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1057c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1058c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1059c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 10609566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1061c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1062c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 10633dfda0b1SToby Isaac } 10643dfda0b1SToby Isaac } 10653dfda0b1SToby Isaac } 10663dfda0b1SToby Isaac } 10673dfda0b1SToby Isaac } 10683dfda0b1SToby Isaac } 10693dfda0b1SToby Isaac /* Build Y edges*/ 10703dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 10713dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 10723dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 10733dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx; 10743dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey; 10753dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx; 10763dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 10773dfda0b1SToby Isaac PetscInt cone[2]; 10783dfda0b1SToby Isaac 10799371c9d4SSatish Balay cone[0] = vertexF; 10809371c9d4SSatish Balay cone[1] = vertexK; 10819566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 10823dfda0b1SToby Isaac if (dim == 2) { 10833dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 10843dfda0b1SToby Isaac if (vx == numXVertices - 1) { 10859566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 10869566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 10879566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1088c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1089d8211ee3SMatthew G. Knepley } else if (vx == 0) { 10909566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 10919566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 10929566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1093c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 10943dfda0b1SToby Isaac } 1095d8211ee3SMatthew G. Knepley } else { 10964c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 10979566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 10989566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1099c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 11003dfda0b1SToby Isaac } 1101d8211ee3SMatthew G. Knepley } 1102d8211ee3SMatthew G. Knepley } else { 11033dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 11043dfda0b1SToby Isaac if (vx == numXVertices - 1) { 11059566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1106c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1107c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1108d8211ee3SMatthew G. Knepley } else if (vx == 0) { 11099566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1110c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1111c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 11123dfda0b1SToby Isaac } 11133dfda0b1SToby Isaac } 11143dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 11153dfda0b1SToby Isaac if (vz == numZVertices - 1) { 11169566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1117c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1118c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1119d8211ee3SMatthew G. Knepley } else if (vz == 0) { 11209566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1121c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1122c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 11233dfda0b1SToby Isaac } 11243dfda0b1SToby Isaac } 11253dfda0b1SToby Isaac } 11263dfda0b1SToby Isaac } 11273dfda0b1SToby Isaac } 11283dfda0b1SToby Isaac } 11293dfda0b1SToby Isaac /* Build X edges*/ 11303dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 11313dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 11323dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 11333dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices; 11343dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex; 11353dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex; 11363dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 11373dfda0b1SToby Isaac PetscInt cone[2]; 11383dfda0b1SToby Isaac 11399371c9d4SSatish Balay cone[0] = vertexL; 11409371c9d4SSatish Balay cone[1] = vertexR; 11419566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 11423dfda0b1SToby Isaac if (dim == 2) { 11433dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 11443dfda0b1SToby Isaac if (vy == numYVertices - 1) { 11459566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 11469566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 11479566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1148c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1149d8211ee3SMatthew G. Knepley } else if (vy == 0) { 11509566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 11519566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 11529566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1153c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 11543dfda0b1SToby Isaac } 1155d8211ee3SMatthew G. Knepley } else { 11564c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 11579566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 11589566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1159c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 11603dfda0b1SToby Isaac } 1161d8211ee3SMatthew G. Knepley } 1162d8211ee3SMatthew G. Knepley } else { 11633dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 11643dfda0b1SToby Isaac if (vy == numYVertices - 1) { 11659566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1166c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1167c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1168c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 11699566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1170c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1171c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 11723dfda0b1SToby Isaac } 11733dfda0b1SToby Isaac } 11743dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 11753dfda0b1SToby Isaac if (vz == numZVertices - 1) { 11769566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1177c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1178c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1179c2df9bbfSMatthew G. Knepley } else if (vz == 0) { 11809566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1181c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1182c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 11833dfda0b1SToby Isaac } 11843dfda0b1SToby Isaac } 11853dfda0b1SToby Isaac } 11863dfda0b1SToby Isaac } 11873dfda0b1SToby Isaac } 11883dfda0b1SToby Isaac } 11899566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 11909566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 11913dfda0b1SToby Isaac /* Build coordinates */ 11929566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 11939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 11949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 11959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 11963dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex + numVertices; ++v) { 11979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 11989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 11993dfda0b1SToby Isaac } 12009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 12019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 12029566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 12039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 12049566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 12059566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 12069566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 12079566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12083dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 12093dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 12103dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 12113dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 12123dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1213ad540459SPierre Jolivet if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; 12143dfda0b1SToby Isaac } 12153dfda0b1SToby Isaac } 12163dfda0b1SToby Isaac } 12179566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12189566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 12199566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 12203dfda0b1SToby Isaac } 12213dfda0b1SToby Isaac PetscFunctionReturn(0); 12223dfda0b1SToby Isaac } 12233dfda0b1SToby Isaac 12249371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) { 12259318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 12269318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1227552f7358SJed Brown 1228552f7358SJed Brown PetscFunctionBegin; 12299318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 12309318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 12319566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 12329371c9d4SSatish Balay for (d = 0; d < dim; ++d) { 12339371c9d4SSatish Balay fac[d] = faces[d]; 12349371c9d4SSatish Balay bdt[d] = periodicity[d]; 12359371c9d4SSatish Balay } 12369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 12379371c9d4SSatish 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))) { 12386858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 12396858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1240552f7358SJed Brown 12419318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 12426858538eSMatthew G. Knepley if (periodicity[d] != DM_BOUNDARY_NONE) { 12439318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 12449318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1245768d5fceSMatthew G. Knepley } 12466858538eSMatthew G. Knepley } 12474fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1248768d5fceSMatthew G. Knepley } 12499566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 12509318fe57SMatthew G. Knepley PetscFunctionReturn(0); 12519318fe57SMatthew G. Knepley } 12529318fe57SMatthew G. Knepley 12539371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) { 12549318fe57SMatthew G. Knepley PetscFunctionBegin; 12559566063dSJacob Faibussowitsch if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 12569566063dSJacob Faibussowitsch else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 12579566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 12589318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1259768d5fceSMatthew G. Knepley DM udm; 1260768d5fceSMatthew G. Knepley 12619566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 12629566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, udm)); 126369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 1264768d5fceSMatthew G. Knepley } 1265768d5fceSMatthew G. Knepley PetscFunctionReturn(0); 1266c8c68bd8SToby Isaac } 1267c8c68bd8SToby Isaac 1268768d5fceSMatthew G. Knepley /*@C 1269768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1270768d5fceSMatthew G. Knepley 1271d083f849SBarry Smith Collective 1272768d5fceSMatthew G. Knepley 1273768d5fceSMatthew G. Knepley Input Parameters: 1274768d5fceSMatthew G. Knepley + comm - The communicator for the DM object 1275768d5fceSMatthew G. Knepley . dim - The spatial dimension 1276768d5fceSMatthew G. Knepley . simplex - PETSC_TRUE for simplices, PETSC_FALSE for tensor cells 1277fdbf62faSLisandro Dalcin . faces - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 1278768d5fceSMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 1279768d5fceSMatthew G. Knepley . upper - The upper right corner, or NULL for (1, 1, 1) 1280fdbf62faSLisandro Dalcin . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE 1281768d5fceSMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 1282768d5fceSMatthew G. Knepley 1283768d5fceSMatthew G. Knepley Output Parameter: 1284768d5fceSMatthew G. Knepley . dm - The DM object 1285768d5fceSMatthew G. Knepley 12869318fe57SMatthew G. Knepley Note: If you want to customize this mesh using options, you just need to 12879318fe57SMatthew G. Knepley $ DMCreate(comm, &dm); 12889318fe57SMatthew G. Knepley $ DMSetType(dm, DMPLEX); 12899318fe57SMatthew G. Knepley $ DMSetFromOptions(dm); 12909318fe57SMatthew G. Knepley and use the options on the DMSetFromOptions() page. 12911367e252SJed Brown 12921367e252SJed Brown Here is the numbering returned for 2 faces in each direction for tensor cells: 1293768d5fceSMatthew G. Knepley $ 10---17---11---18----12 1294768d5fceSMatthew G. Knepley $ | | | 1295768d5fceSMatthew G. Knepley $ | | | 1296768d5fceSMatthew G. Knepley $ 20 2 22 3 24 1297768d5fceSMatthew G. Knepley $ | | | 1298768d5fceSMatthew G. Knepley $ | | | 1299768d5fceSMatthew G. Knepley $ 7---15----8---16----9 1300768d5fceSMatthew G. Knepley $ | | | 1301768d5fceSMatthew G. Knepley $ | | | 1302768d5fceSMatthew G. Knepley $ 19 0 21 1 23 1303768d5fceSMatthew G. Knepley $ | | | 1304768d5fceSMatthew G. Knepley $ | | | 1305768d5fceSMatthew G. Knepley $ 4---13----5---14----6 1306768d5fceSMatthew G. Knepley 1307768d5fceSMatthew G. Knepley and for simplicial cells 1308768d5fceSMatthew G. Knepley 1309768d5fceSMatthew G. Knepley $ 14----8---15----9----16 1310768d5fceSMatthew G. Knepley $ |\ 5 |\ 7 | 1311768d5fceSMatthew G. Knepley $ | \ | \ | 1312768d5fceSMatthew G. Knepley $ 13 2 14 3 15 1313768d5fceSMatthew G. Knepley $ | 4 \ | 6 \ | 1314768d5fceSMatthew G. Knepley $ | \ | \ | 1315768d5fceSMatthew G. Knepley $ 11----6---12----7----13 1316768d5fceSMatthew G. Knepley $ |\ |\ | 1317768d5fceSMatthew G. Knepley $ | \ 1 | \ 3 | 1318768d5fceSMatthew G. Knepley $ 10 0 11 1 12 1319768d5fceSMatthew G. Knepley $ | 0 \ | 2 \ | 1320768d5fceSMatthew G. Knepley $ | \ | \ | 1321768d5fceSMatthew G. Knepley $ 8----4----9----5----10 1322768d5fceSMatthew G. Knepley 1323768d5fceSMatthew G. Knepley Level: beginner 1324768d5fceSMatthew G. Knepley 1325db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 1326768d5fceSMatthew G. Knepley @*/ 13279371c9d4SSatish Balay PetscErrorCode DMPlexCreateBoxMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate, DM *dm) { 13289318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 1329fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 1330fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 1331fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1332552f7358SJed Brown 1333768d5fceSMatthew G. Knepley PetscFunctionBegin; 13349566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 13359566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 13369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 13377ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 13389318fe57SMatthew G. Knepley PetscFunctionReturn(0); 13399318fe57SMatthew G. Knepley } 1340fdbf62faSLisandro Dalcin 13419371c9d4SSatish Balay static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) { 13429318fe57SMatthew G. Knepley DM bdm, vol; 13439318fe57SMatthew G. Knepley PetscInt i; 13449318fe57SMatthew G. Knepley 13459318fe57SMatthew G. Knepley PetscFunctionBegin; 134608401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 13479566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 13489566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 13499566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 13509566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 13519566063dSJacob Faibussowitsch PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol)); 13529566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 135369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 13549318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 13559318fe57SMatthew G. Knepley Vec v; 13569318fe57SMatthew G. Knepley PetscScalar *x; 13579318fe57SMatthew G. Knepley PetscInt cDim, n; 13589318fe57SMatthew G. Knepley 13599566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 13609566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 13619566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 13629566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 13639318fe57SMatthew G. Knepley x += cDim; 13649318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 13659566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 13669566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 13679318fe57SMatthew G. Knepley } 1368552f7358SJed Brown PetscFunctionReturn(0); 1369552f7358SJed Brown } 1370552f7358SJed Brown 137100dabe28SStefano Zampini /*@ 137200dabe28SStefano Zampini DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells. 137300dabe28SStefano Zampini 1374d083f849SBarry Smith Collective 137500dabe28SStefano Zampini 137600dabe28SStefano Zampini Input Parameters: 137700dabe28SStefano Zampini + comm - The communicator for the DM object 137800dabe28SStefano Zampini . faces - Number of faces per dimension, or NULL for (1, 1, 1) 137900dabe28SStefano Zampini . lower - The lower left corner, or NULL for (0, 0, 0) 138000dabe28SStefano Zampini . upper - The upper right corner, or NULL for (1, 1, 1) 138100dabe28SStefano Zampini . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE 1382d0fcb9c2SMatthew G. Knepley . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 138300dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 138400dabe28SStefano Zampini 138500dabe28SStefano Zampini Output Parameter: 138600dabe28SStefano Zampini . dm - The DM object 138700dabe28SStefano Zampini 138800dabe28SStefano Zampini Level: beginner 138900dabe28SStefano Zampini 1390db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 139100dabe28SStefano Zampini @*/ 13929371c9d4SSatish Balay PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) { 13939318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 139400dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 139500dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 139600dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 139700dabe28SStefano Zampini 139800dabe28SStefano Zampini PetscFunctionBegin; 13999566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 14009566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 14019566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 1402d410b0cfSMatthew G. Knepley if (!interpolate) { 1403d410b0cfSMatthew G. Knepley DM udm; 140400dabe28SStefano Zampini 14059566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 140669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 140700dabe28SStefano Zampini } 14087ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 140900dabe28SStefano Zampini PetscFunctionReturn(0); 141000dabe28SStefano Zampini } 141100dabe28SStefano Zampini 1412a9074c1eSMatthew G. Knepley /*@C 1413a9074c1eSMatthew G. Knepley DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database. 1414a9074c1eSMatthew G. Knepley 1415d083f849SBarry Smith Logically Collective on dm 1416a9074c1eSMatthew G. Knepley 1417a9074c1eSMatthew G. Knepley Input Parameters: 1418a9074c1eSMatthew G. Knepley + dm - the DM context 1419a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 1420a9074c1eSMatthew G. Knepley 1421a9074c1eSMatthew G. Knepley Notes: 1422a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 1423a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 1424a9074c1eSMatthew G. Knepley 1425a9074c1eSMatthew G. Knepley Level: advanced 1426a9074c1eSMatthew G. Knepley 1427db781477SPatrick Sanan .seealso: `SNESSetFromOptions()` 1428a9074c1eSMatthew G. Knepley @*/ 14299371c9d4SSatish Balay PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) { 1430a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1431a9074c1eSMatthew G. Knepley 1432a9074c1eSMatthew G. Knepley PetscFunctionBegin; 1433a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14349566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 14359566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 1436a9074c1eSMatthew G. Knepley PetscFunctionReturn(0); 1437a9074c1eSMatthew G. Knepley } 1438a9074c1eSMatthew G. Knepley 14399318fe57SMatthew G. Knepley /* Remap geometry to cylinder 144061a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 144161a622f3SMatthew G. Knepley 14429318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 14439318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 14449318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 14450510c589SMatthew G. Knepley 14469318fe57SMatthew G. Knepley phi = arctan(y/x) 14479318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 14489318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 14490510c589SMatthew G. Knepley 14509318fe57SMatthew G. Knepley so we remap them using 14510510c589SMatthew G. Knepley 14529318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 14539318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 14540510c589SMatthew G. Knepley 14559318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 14569318fe57SMatthew G. Knepley */ 14579371c9d4SSatish Balay 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[]) { 14589318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 14599318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 146022cc497dSMatthew G. Knepley 14619318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 14629318fe57SMatthew G. Knepley f0[0] = u[0]; 14639318fe57SMatthew G. Knepley f0[1] = u[1]; 14649318fe57SMatthew G. Knepley } else { 14659318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 14660510c589SMatthew G. Knepley 14679318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 14689318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 14699318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 14709318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 14719318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 14729318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 14739318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 14749318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 14759318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 14769318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 14779318fe57SMatthew G. Knepley } else { 14789318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 14799318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 14809318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 14819318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 14829318fe57SMatthew G. Knepley } 14839318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 14849318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 14859318fe57SMatthew G. Knepley } 14869318fe57SMatthew G. Knepley f0[2] = u[2]; 14879318fe57SMatthew G. Knepley } 14880510c589SMatthew G. Knepley 14899371c9d4SSatish Balay static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ) { 14900510c589SMatthew G. Knepley const PetscInt dim = 3; 14919318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 1492d8c47e87SMatthew G. Knepley PetscMPIInt rank; 14930510c589SMatthew G. Knepley 14940510c589SMatthew G. Knepley PetscFunctionBegin; 14959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 14969566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 14970510c589SMatthew G. Knepley /* Create topology */ 14980510c589SMatthew G. Knepley { 14990510c589SMatthew G. Knepley PetscInt cone[8], c; 15000510c589SMatthew G. Knepley 1501dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 1502dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 1503006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 1504ae8bcbbbSMatthew G. Knepley numCells *= 3; 1505dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 1506006a8963SMatthew G. Knepley } 15079566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 15089566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 15099566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 1510dd400576SPatrick Sanan if (rank == 0) { 1511006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 15129371c9d4SSatish Balay cone[0] = 15; 15139371c9d4SSatish Balay cone[1] = 18; 15149371c9d4SSatish Balay cone[2] = 17; 15159371c9d4SSatish Balay cone[3] = 16; 15169371c9d4SSatish Balay cone[4] = 31; 15179371c9d4SSatish Balay cone[5] = 32; 15189371c9d4SSatish Balay cone[6] = 33; 15199371c9d4SSatish Balay cone[7] = 34; 15209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 15219371c9d4SSatish Balay cone[0] = 16; 15229371c9d4SSatish Balay cone[1] = 17; 15239371c9d4SSatish Balay cone[2] = 24; 15249371c9d4SSatish Balay cone[3] = 23; 15259371c9d4SSatish Balay cone[4] = 32; 15269371c9d4SSatish Balay cone[5] = 36; 15279371c9d4SSatish Balay cone[6] = 37; 15289371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 15299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 15309371c9d4SSatish Balay cone[0] = 18; 15319371c9d4SSatish Balay cone[1] = 27; 15329371c9d4SSatish Balay cone[2] = 24; 15339371c9d4SSatish Balay cone[3] = 17; 15349371c9d4SSatish Balay cone[4] = 34; 15359371c9d4SSatish Balay cone[5] = 33; 15369371c9d4SSatish Balay cone[6] = 37; 15379371c9d4SSatish Balay cone[7] = 38; 15389566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 15399371c9d4SSatish Balay cone[0] = 29; 15409371c9d4SSatish Balay cone[1] = 27; 15419371c9d4SSatish Balay cone[2] = 18; 15429371c9d4SSatish Balay cone[3] = 15; 15439371c9d4SSatish Balay cone[4] = 35; 15449371c9d4SSatish Balay cone[5] = 31; 15459371c9d4SSatish Balay cone[6] = 34; 15469371c9d4SSatish Balay cone[7] = 38; 15479566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 15489371c9d4SSatish Balay cone[0] = 29; 15499371c9d4SSatish Balay cone[1] = 15; 15509371c9d4SSatish Balay cone[2] = 16; 15519371c9d4SSatish Balay cone[3] = 23; 15529371c9d4SSatish Balay cone[4] = 35; 15539371c9d4SSatish Balay cone[5] = 36; 15549371c9d4SSatish Balay cone[6] = 32; 15559371c9d4SSatish Balay cone[7] = 31; 15569566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1557006a8963SMatthew G. Knepley 15589371c9d4SSatish Balay cone[0] = 31; 15599371c9d4SSatish Balay cone[1] = 34; 15609371c9d4SSatish Balay cone[2] = 33; 15619371c9d4SSatish Balay cone[3] = 32; 15629371c9d4SSatish Balay cone[4] = 19; 15639371c9d4SSatish Balay cone[5] = 22; 15649371c9d4SSatish Balay cone[6] = 21; 15659371c9d4SSatish Balay cone[7] = 20; 15669566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 15679371c9d4SSatish Balay cone[0] = 32; 15689371c9d4SSatish Balay cone[1] = 33; 15699371c9d4SSatish Balay cone[2] = 37; 15709371c9d4SSatish Balay cone[3] = 36; 15719371c9d4SSatish Balay cone[4] = 22; 15729371c9d4SSatish Balay cone[5] = 25; 15739371c9d4SSatish Balay cone[6] = 26; 15749371c9d4SSatish Balay cone[7] = 21; 15759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 15769371c9d4SSatish Balay cone[0] = 34; 15779371c9d4SSatish Balay cone[1] = 38; 15789371c9d4SSatish Balay cone[2] = 37; 15799371c9d4SSatish Balay cone[3] = 33; 15809371c9d4SSatish Balay cone[4] = 20; 15819371c9d4SSatish Balay cone[5] = 21; 15829371c9d4SSatish Balay cone[6] = 26; 15839371c9d4SSatish Balay cone[7] = 28; 15849566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 15859371c9d4SSatish Balay cone[0] = 35; 15869371c9d4SSatish Balay cone[1] = 38; 15879371c9d4SSatish Balay cone[2] = 34; 15889371c9d4SSatish Balay cone[3] = 31; 15899371c9d4SSatish Balay cone[4] = 30; 15909371c9d4SSatish Balay cone[5] = 19; 15919371c9d4SSatish Balay cone[6] = 20; 15929371c9d4SSatish Balay cone[7] = 28; 15939566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 15949371c9d4SSatish Balay cone[0] = 35; 15959371c9d4SSatish Balay cone[1] = 31; 15969371c9d4SSatish Balay cone[2] = 32; 15979371c9d4SSatish Balay cone[3] = 36; 15989371c9d4SSatish Balay cone[4] = 30; 15999371c9d4SSatish Balay cone[5] = 25; 16009371c9d4SSatish Balay cone[6] = 22; 16019371c9d4SSatish Balay cone[7] = 19; 16029566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 1603ae8bcbbbSMatthew G. Knepley 16049371c9d4SSatish Balay cone[0] = 19; 16059371c9d4SSatish Balay cone[1] = 20; 16069371c9d4SSatish Balay cone[2] = 21; 16079371c9d4SSatish Balay cone[3] = 22; 16089371c9d4SSatish Balay cone[4] = 15; 16099371c9d4SSatish Balay cone[5] = 16; 16109371c9d4SSatish Balay cone[6] = 17; 16119371c9d4SSatish Balay cone[7] = 18; 16129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 16139371c9d4SSatish Balay cone[0] = 22; 16149371c9d4SSatish Balay cone[1] = 21; 16159371c9d4SSatish Balay cone[2] = 26; 16169371c9d4SSatish Balay cone[3] = 25; 16179371c9d4SSatish Balay cone[4] = 16; 16189371c9d4SSatish Balay cone[5] = 23; 16199371c9d4SSatish Balay cone[6] = 24; 16209371c9d4SSatish Balay cone[7] = 17; 16219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 16229371c9d4SSatish Balay cone[0] = 20; 16239371c9d4SSatish Balay cone[1] = 28; 16249371c9d4SSatish Balay cone[2] = 26; 16259371c9d4SSatish Balay cone[3] = 21; 16269371c9d4SSatish Balay cone[4] = 18; 16279371c9d4SSatish Balay cone[5] = 17; 16289371c9d4SSatish Balay cone[6] = 24; 16299371c9d4SSatish Balay cone[7] = 27; 16309566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 16319371c9d4SSatish Balay cone[0] = 30; 16329371c9d4SSatish Balay cone[1] = 28; 16339371c9d4SSatish Balay cone[2] = 20; 16349371c9d4SSatish Balay cone[3] = 19; 16359371c9d4SSatish Balay cone[4] = 29; 16369371c9d4SSatish Balay cone[5] = 15; 16379371c9d4SSatish Balay cone[6] = 18; 16389371c9d4SSatish Balay cone[7] = 27; 16399566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 16409371c9d4SSatish Balay cone[0] = 30; 16419371c9d4SSatish Balay cone[1] = 19; 16429371c9d4SSatish Balay cone[2] = 22; 16439371c9d4SSatish Balay cone[3] = 25; 16449371c9d4SSatish Balay cone[4] = 29; 16459371c9d4SSatish Balay cone[5] = 23; 16469371c9d4SSatish Balay cone[6] = 16; 16479371c9d4SSatish Balay cone[7] = 15; 16489566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 1649006a8963SMatthew G. Knepley } else { 16509371c9d4SSatish Balay cone[0] = 5; 16519371c9d4SSatish Balay cone[1] = 8; 16529371c9d4SSatish Balay cone[2] = 7; 16539371c9d4SSatish Balay cone[3] = 6; 16549371c9d4SSatish Balay cone[4] = 9; 16559371c9d4SSatish Balay cone[5] = 12; 16569371c9d4SSatish Balay cone[6] = 11; 16579371c9d4SSatish Balay cone[7] = 10; 16589566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 16599371c9d4SSatish Balay cone[0] = 6; 16609371c9d4SSatish Balay cone[1] = 7; 16619371c9d4SSatish Balay cone[2] = 14; 16629371c9d4SSatish Balay cone[3] = 13; 16639371c9d4SSatish Balay cone[4] = 12; 16649371c9d4SSatish Balay cone[5] = 15; 16659371c9d4SSatish Balay cone[6] = 16; 16669371c9d4SSatish Balay cone[7] = 11; 16679566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 16689371c9d4SSatish Balay cone[0] = 8; 16699371c9d4SSatish Balay cone[1] = 17; 16709371c9d4SSatish Balay cone[2] = 14; 16719371c9d4SSatish Balay cone[3] = 7; 16729371c9d4SSatish Balay cone[4] = 10; 16739371c9d4SSatish Balay cone[5] = 11; 16749371c9d4SSatish Balay cone[6] = 16; 16759371c9d4SSatish Balay cone[7] = 18; 16769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 16779371c9d4SSatish Balay cone[0] = 19; 16789371c9d4SSatish Balay cone[1] = 17; 16799371c9d4SSatish Balay cone[2] = 8; 16809371c9d4SSatish Balay cone[3] = 5; 16819371c9d4SSatish Balay cone[4] = 20; 16829371c9d4SSatish Balay cone[5] = 9; 16839371c9d4SSatish Balay cone[6] = 10; 16849371c9d4SSatish Balay cone[7] = 18; 16859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 16869371c9d4SSatish Balay cone[0] = 19; 16879371c9d4SSatish Balay cone[1] = 5; 16889371c9d4SSatish Balay cone[2] = 6; 16899371c9d4SSatish Balay cone[3] = 13; 16909371c9d4SSatish Balay cone[4] = 20; 16919371c9d4SSatish Balay cone[5] = 15; 16929371c9d4SSatish Balay cone[6] = 12; 16939371c9d4SSatish Balay cone[7] = 9; 16949566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1695006a8963SMatthew G. Knepley } 1696d8c47e87SMatthew G. Knepley } 16979566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 16989566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 16990510c589SMatthew G. Knepley } 1700dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 17010510c589SMatthew G. Knepley { 17020510c589SMatthew G. Knepley Vec coordinates; 17030510c589SMatthew G. Knepley PetscSection coordSection; 17040510c589SMatthew G. Knepley PetscScalar *coords; 17050510c589SMatthew G. Knepley PetscInt coordSize, v; 17060510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 17070510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 17080510c589SMatthew G. Knepley 17090510c589SMatthew G. Knepley /* Build coordinates */ 17109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 17119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 17129566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 17139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 17140510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 17159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 17169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 17170510c589SMatthew G. Knepley } 17189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 17199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 17209566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 17219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 17229566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 17239566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 17249566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 17259566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 1726dd400576SPatrick Sanan if (rank == 0) { 17279371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 17289371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 17299371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 17309371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 17319371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 17329371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 17339371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 17349371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 17359371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 17369371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 17379371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 17389371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 17399371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 17409371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 17419371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 17429371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 17439371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 17449371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 17459371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 17469371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 17479371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 17489371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 17499371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 17509371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 17519371c9d4SSatish Balay coords[8 * dim + 0] = dis; 17529371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 17539371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 17549371c9d4SSatish Balay coords[9 * dim + 0] = dis; 17559371c9d4SSatish Balay coords[9 * dim + 1] = dis; 17569371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 17579371c9d4SSatish Balay coords[10 * dim + 0] = dis; 17589371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 17599371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 17609371c9d4SSatish Balay coords[11 * dim + 0] = dis; 17619371c9d4SSatish Balay coords[11 * dim + 1] = dis; 17629371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 17639371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 17649371c9d4SSatish Balay coords[12 * dim + 1] = dis; 17659371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 17669371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 17679371c9d4SSatish Balay coords[13 * dim + 1] = dis; 17689371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 17699371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 17709371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 17719371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 17729371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 17739371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 17749371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 1775ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 17769371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 17779371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 17789371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 17799371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 17809371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 17819371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 17829371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 17839371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 17849371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 17859371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 17869371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 17879371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 17889371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 17899371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 17909371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 17919371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 17929371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 17939371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 17949371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 17959371c9d4SSatish Balay coords[22 * dim + 1] = dis; 17969371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 17979371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 17989371c9d4SSatish Balay coords[23 * dim + 1] = dis; 17999371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 1800ae8bcbbbSMatthew G. Knepley } 1801d8c47e87SMatthew G. Knepley } 18029566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 18039566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 18049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 18050510c589SMatthew G. Knepley } 1806006a8963SMatthew G. Knepley /* Create periodicity */ 1807006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 18086858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 18096858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1810006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 1811ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 18126858538eSMatthew G. Knepley PetscInt numZCells = 3; 1813006a8963SMatthew G. Knepley 18146858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 18156858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 18164fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1817006a8963SMatthew G. Knepley } 1818dbc1dc17SMatthew G. Knepley { 18199318fe57SMatthew G. Knepley DM cdm; 18209318fe57SMatthew G. Knepley PetscDS cds; 18219318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 1822dbc1dc17SMatthew G. Knepley 18239566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder)); 18249566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18259566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 18269566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 1827dbc1dc17SMatthew G. Knepley } 18289318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 18299566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 18300510c589SMatthew G. Knepley PetscFunctionReturn(0); 18310510c589SMatthew G. Knepley } 18320510c589SMatthew G. Knepley 183324119c2aSMatthew G. Knepley /*@ 18349318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 183524119c2aSMatthew G. Knepley 1836d083f849SBarry Smith Collective 183724119c2aSMatthew G. Knepley 183824119c2aSMatthew G. Knepley Input Parameters: 183924119c2aSMatthew G. Knepley + comm - The communicator for the DM object 18409318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction 184124119c2aSMatthew G. Knepley 184224119c2aSMatthew G. Knepley Output Parameter: 184324119c2aSMatthew G. Knepley . dm - The DM object 184424119c2aSMatthew G. Knepley 18459318fe57SMatthew G. Knepley Note: 18469318fe57SMatthew G. Knepley Here is the output numbering looking from the bottom of the cylinder: 18479318fe57SMatthew G. Knepley $ 17-----14 18489318fe57SMatthew G. Knepley $ | | 18499318fe57SMatthew G. Knepley $ | 2 | 18509318fe57SMatthew G. Knepley $ | | 18519318fe57SMatthew G. Knepley $ 17-----8-----7-----14 18529318fe57SMatthew G. Knepley $ | | | | 18539318fe57SMatthew G. Knepley $ | 3 | 0 | 1 | 18549318fe57SMatthew G. Knepley $ | | | | 18559318fe57SMatthew G. Knepley $ 19-----5-----6-----13 18569318fe57SMatthew G. Knepley $ | | 18579318fe57SMatthew G. Knepley $ | 4 | 18589318fe57SMatthew G. Knepley $ | | 18599318fe57SMatthew G. Knepley $ 19-----13 18609318fe57SMatthew G. Knepley $ 18619318fe57SMatthew G. Knepley $ and up through the top 18629318fe57SMatthew G. Knepley $ 18639318fe57SMatthew G. Knepley $ 18-----16 18649318fe57SMatthew G. Knepley $ | | 18659318fe57SMatthew G. Knepley $ | 2 | 18669318fe57SMatthew G. Knepley $ | | 18679318fe57SMatthew G. Knepley $ 18----10----11-----16 18689318fe57SMatthew G. Knepley $ | | | | 18699318fe57SMatthew G. Knepley $ | 3 | 0 | 1 | 18709318fe57SMatthew G. Knepley $ | | | | 18719318fe57SMatthew G. Knepley $ 20-----9----12-----15 18729318fe57SMatthew G. Knepley $ | | 18739318fe57SMatthew G. Knepley $ | 4 | 18749318fe57SMatthew G. Knepley $ | | 18759318fe57SMatthew G. Knepley $ 20-----15 18769318fe57SMatthew G. Knepley 187724119c2aSMatthew G. Knepley Level: beginner 187824119c2aSMatthew G. Knepley 1879db781477SPatrick Sanan .seealso: `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 188024119c2aSMatthew G. Knepley @*/ 18819371c9d4SSatish Balay PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm) { 18829318fe57SMatthew G. Knepley PetscFunctionBegin; 18839318fe57SMatthew G. Knepley PetscValidPointer(dm, 3); 18849566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 18859566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 18869566063dSJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ)); 18879318fe57SMatthew G. Knepley PetscFunctionReturn(0); 18889318fe57SMatthew G. Knepley } 18899318fe57SMatthew G. Knepley 18909371c9d4SSatish Balay static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) { 189124119c2aSMatthew G. Knepley const PetscInt dim = 3; 1892412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 18939fe9f049SMatthew G. Knepley PetscMPIInt rank; 189424119c2aSMatthew G. Knepley 189524119c2aSMatthew G. Knepley PetscFunctionBegin; 189663a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 18979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 18989566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 1899412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 19009566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 190124119c2aSMatthew G. Knepley /* Create topology */ 190224119c2aSMatthew G. Knepley { 190324119c2aSMatthew G. Knepley PetscInt cone[6], c; 190424119c2aSMatthew G. Knepley 1905dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 1906dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 19079566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 19089566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 19099566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 191024119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 19119371c9d4SSatish Balay cone[0] = c + n * 1; 19129371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 19139371c9d4SSatish Balay cone[2] = 0 + 3 * n; 19149371c9d4SSatish Balay cone[3] = c + n * 2; 19159371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 19169371c9d4SSatish Balay cone[5] = 1 + 3 * n; 19179566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 19189566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 191924119c2aSMatthew G. Knepley } 19209566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 19219566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 192224119c2aSMatthew G. Knepley } 192348a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 192424119c2aSMatthew G. Knepley /* Create cylinder geometry */ 192524119c2aSMatthew G. Knepley { 192624119c2aSMatthew G. Knepley Vec coordinates; 192724119c2aSMatthew G. Knepley PetscSection coordSection; 192824119c2aSMatthew G. Knepley PetscScalar *coords; 1929412e9a14SMatthew G. Knepley PetscInt coordSize, c; 193024119c2aSMatthew G. Knepley 193124119c2aSMatthew G. Knepley /* Build coordinates */ 19329566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 19339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 19349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 19359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 193624119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 19379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 19389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 193924119c2aSMatthew G. Knepley } 19409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 19419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 19429566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 19439566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 19449566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 19459566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 19469566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 19479566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 194824119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 19499371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 19509371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 19519371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 19529371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 19539371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 19549371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 195524119c2aSMatthew G. Knepley } 1956dd400576SPatrick Sanan if (rank == 0) { 19579371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 19589371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 19599371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 19609371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 19619371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 19629371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 19639fe9f049SMatthew G. Knepley } 19649566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 19659566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 19669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 196724119c2aSMatthew G. Knepley } 19689318fe57SMatthew G. Knepley /* Interpolate */ 19699566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 19709318fe57SMatthew G. Knepley PetscFunctionReturn(0); 19719318fe57SMatthew G. Knepley } 19729318fe57SMatthew G. Knepley 19739318fe57SMatthew G. Knepley /*@ 19749318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 19759318fe57SMatthew G. Knepley 19769318fe57SMatthew G. Knepley Collective 19779318fe57SMatthew G. Knepley 19789318fe57SMatthew G. Knepley Input Parameters: 19799318fe57SMatthew G. Knepley + comm - The communicator for the DM object 19809318fe57SMatthew G. Knepley . n - The number of wedges around the origin 19819318fe57SMatthew G. Knepley - interpolate - Create edges and faces 19829318fe57SMatthew G. Knepley 19839318fe57SMatthew G. Knepley Output Parameter: 19849318fe57SMatthew G. Knepley . dm - The DM object 19859318fe57SMatthew G. Knepley 19869318fe57SMatthew G. Knepley Level: beginner 19879318fe57SMatthew G. Knepley 1988db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 19899318fe57SMatthew G. Knepley @*/ 19909371c9d4SSatish Balay PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) { 19919318fe57SMatthew G. Knepley PetscFunctionBegin; 19929318fe57SMatthew G. Knepley PetscValidPointer(dm, 4); 19939566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 19949566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 19959566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 199624119c2aSMatthew G. Knepley PetscFunctionReturn(0); 199724119c2aSMatthew G. Knepley } 199824119c2aSMatthew G. Knepley 19999371c9d4SSatish Balay static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) { 200065a81367SMatthew G. Knepley PetscReal prod = 0.0; 200165a81367SMatthew G. Knepley PetscInt i; 200265a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 200365a81367SMatthew G. Knepley return PetscSqrtReal(prod); 200465a81367SMatthew G. Knepley } 20059371c9d4SSatish Balay static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) { 200665a81367SMatthew G. Knepley PetscReal prod = 0.0; 200765a81367SMatthew G. Knepley PetscInt i; 200865a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i] * y[i]; 200965a81367SMatthew G. Knepley return prod; 201065a81367SMatthew G. Knepley } 201165a81367SMatthew G. Knepley 201251a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 20139371c9d4SSatish Balay 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[]) { 201451a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 201551a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 201651a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 201751a74b61SMatthew G. Knepley 201851a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 201951a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 202051a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 202151a74b61SMatthew G. Knepley } 202251a74b61SMatthew G. Knepley 20239371c9d4SSatish Balay static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) { 202465a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 202565a81367SMatthew G. Knepley PetscSection coordSection; 202665a81367SMatthew G. Knepley Vec coordinates; 202765a81367SMatthew G. Knepley PetscScalar *coords; 202865a81367SMatthew G. Knepley PetscReal *coordsIn; 202965a81367SMatthew G. Knepley PetscInt numCells, numEdges, numVerts, firstVertex, v, firstEdge, coordSize, d, c, e; 203065a81367SMatthew G. Knepley PetscMPIInt rank; 203165a81367SMatthew G. Knepley 203265a81367SMatthew G. Knepley PetscFunctionBegin; 20339318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 20349566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 20359566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 20369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 203765a81367SMatthew G. Knepley switch (dim) { 203865a81367SMatthew G. Knepley case 2: 203965a81367SMatthew G. Knepley if (simplex) { 204051a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 204151a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 204265a81367SMatthew G. Knepley const PetscInt degree = 5; 204351a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 204465a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 204565a81367SMatthew G. Knepley PetscInt cone[3]; 204665a81367SMatthew G. Knepley PetscInt *graph, p, i, j, k; 204765a81367SMatthew G. Knepley 20489371c9d4SSatish Balay vertex[0] *= R / radius; 20499371c9d4SSatish Balay vertex[1] *= R / radius; 20509371c9d4SSatish Balay vertex[2] *= R / radius; 2051dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 2052dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 205365a81367SMatthew G. Knepley firstVertex = numCells; 205451a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 205565a81367SMatthew G. Knepley 205665a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 205765a81367SMatthew G. Knepley 205865a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 205951a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 206065a81367SMatthew G. Knepley */ 206165a81367SMatthew G. Knepley /* Construct vertices */ 20629566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2063dd400576SPatrick Sanan if (rank == 0) { 206465a81367SMatthew G. Knepley for (p = 0, i = 0; p < embedDim; ++p) { 206565a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 206665a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 206765a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 206865a81367SMatthew G. Knepley ++i; 206965a81367SMatthew G. Knepley } 207065a81367SMatthew G. Knepley } 207165a81367SMatthew G. Knepley } 207245da822fSValeria Barra } 207365a81367SMatthew G. Knepley /* Construct graph */ 20749566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 207565a81367SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 207665a81367SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 20779371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 20789371c9d4SSatish Balay graph[i * numVerts + j] = 1; 20799371c9d4SSatish Balay ++k; 20809371c9d4SSatish Balay } 208165a81367SMatthew G. Knepley } 208263a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 208365a81367SMatthew G. Knepley } 208465a81367SMatthew G. Knepley /* Build Topology */ 20859566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 208648a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 20879566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 208865a81367SMatthew G. Knepley /* Cells */ 208965a81367SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 209065a81367SMatthew G. Knepley for (j = 0; j < i; ++j) { 209165a81367SMatthew G. Knepley for (k = 0; k < j; ++k) { 209265a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 20939371c9d4SSatish Balay cone[0] = firstVertex + i; 20949371c9d4SSatish Balay cone[1] = firstVertex + j; 20959371c9d4SSatish Balay cone[2] = firstVertex + k; 209665a81367SMatthew G. Knepley /* Check orientation */ 209765a81367SMatthew G. Knepley { 20989371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 20999371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 21009371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 21019371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 21029371c9d4SSatish Balay }; 210365a81367SMatthew G. Knepley PetscReal normal[3]; 210465a81367SMatthew G. Knepley PetscInt e, f; 210565a81367SMatthew G. Knepley 210665a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 210765a81367SMatthew G. Knepley normal[d] = 0.0; 210865a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2109ad540459SPierre 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]); 211065a81367SMatthew G. Knepley } 211165a81367SMatthew G. Knepley } 21129371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 21139371c9d4SSatish Balay PetscInt tmp = cone[1]; 21149371c9d4SSatish Balay cone[1] = cone[2]; 21159371c9d4SSatish Balay cone[2] = tmp; 211665a81367SMatthew G. Knepley } 211765a81367SMatthew G. Knepley } 21189566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 211965a81367SMatthew G. Knepley } 212065a81367SMatthew G. Knepley } 212165a81367SMatthew G. Knepley } 212265a81367SMatthew G. Knepley } 21239566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 21249566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 21259566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 212665a81367SMatthew G. Knepley } else { 21272829fed8SMatthew G. Knepley /* 21282829fed8SMatthew G. Knepley 12-21--13 21292829fed8SMatthew G. Knepley | | 21302829fed8SMatthew G. Knepley 25 4 24 21312829fed8SMatthew G. Knepley | | 21322829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 21332829fed8SMatthew G. Knepley | | | | 21342829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 21352829fed8SMatthew G. Knepley | | | | 21362829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 21372829fed8SMatthew G. Knepley | | 21382829fed8SMatthew G. Knepley 20 1 19 21392829fed8SMatthew G. Knepley | | 21402829fed8SMatthew G. Knepley 10-18--11 21412829fed8SMatthew G. Knepley | | 21422829fed8SMatthew G. Knepley 23 2 22 21432829fed8SMatthew G. Knepley | | 21442829fed8SMatthew G. Knepley 12-21--13 21452829fed8SMatthew G. Knepley */ 21462829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 21472829fed8SMatthew G. Knepley 2148dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 2149dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 2150dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 215165a81367SMatthew G. Knepley firstVertex = numCells; 215265a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 21532829fed8SMatthew G. Knepley /* Build Topology */ 21549566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 215548a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 215648a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 21579566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2158dd400576SPatrick Sanan if (rank == 0) { 21592829fed8SMatthew G. Knepley /* Cell 0 */ 21609371c9d4SSatish Balay cone[0] = 14; 21619371c9d4SSatish Balay cone[1] = 15; 21629371c9d4SSatish Balay cone[2] = 16; 21639371c9d4SSatish Balay cone[3] = 17; 21649566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 21659371c9d4SSatish Balay ornt[0] = 0; 21669371c9d4SSatish Balay ornt[1] = 0; 21679371c9d4SSatish Balay ornt[2] = 0; 21689371c9d4SSatish Balay ornt[3] = 0; 21699566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 21702829fed8SMatthew G. Knepley /* Cell 1 */ 21719371c9d4SSatish Balay cone[0] = 18; 21729371c9d4SSatish Balay cone[1] = 19; 21739371c9d4SSatish Balay cone[2] = 14; 21749371c9d4SSatish Balay cone[3] = 20; 21759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 21769371c9d4SSatish Balay ornt[0] = 0; 21779371c9d4SSatish Balay ornt[1] = 0; 21789371c9d4SSatish Balay ornt[2] = -1; 21799371c9d4SSatish Balay ornt[3] = 0; 21809566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 21812829fed8SMatthew G. Knepley /* Cell 2 */ 21829371c9d4SSatish Balay cone[0] = 21; 21839371c9d4SSatish Balay cone[1] = 22; 21849371c9d4SSatish Balay cone[2] = 18; 21859371c9d4SSatish Balay cone[3] = 23; 21869566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 21879371c9d4SSatish Balay ornt[0] = 0; 21889371c9d4SSatish Balay ornt[1] = 0; 21899371c9d4SSatish Balay ornt[2] = -1; 21909371c9d4SSatish Balay ornt[3] = 0; 21919566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 21922829fed8SMatthew G. Knepley /* Cell 3 */ 21939371c9d4SSatish Balay cone[0] = 19; 21949371c9d4SSatish Balay cone[1] = 22; 21959371c9d4SSatish Balay cone[2] = 24; 21969371c9d4SSatish Balay cone[3] = 15; 21979566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 21989371c9d4SSatish Balay ornt[0] = -1; 21999371c9d4SSatish Balay ornt[1] = -1; 22009371c9d4SSatish Balay ornt[2] = 0; 22019371c9d4SSatish Balay ornt[3] = -1; 22029566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 22032829fed8SMatthew G. Knepley /* Cell 4 */ 22049371c9d4SSatish Balay cone[0] = 16; 22059371c9d4SSatish Balay cone[1] = 24; 22069371c9d4SSatish Balay cone[2] = 21; 22079371c9d4SSatish Balay cone[3] = 25; 22089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 22099371c9d4SSatish Balay ornt[0] = -1; 22109371c9d4SSatish Balay ornt[1] = -1; 22119371c9d4SSatish Balay ornt[2] = -1; 22129371c9d4SSatish Balay ornt[3] = 0; 22139566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 22142829fed8SMatthew G. Knepley /* Cell 5 */ 22159371c9d4SSatish Balay cone[0] = 20; 22169371c9d4SSatish Balay cone[1] = 17; 22179371c9d4SSatish Balay cone[2] = 25; 22189371c9d4SSatish Balay cone[3] = 23; 22199566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 22209371c9d4SSatish Balay ornt[0] = -1; 22219371c9d4SSatish Balay ornt[1] = -1; 22229371c9d4SSatish Balay ornt[2] = -1; 22239371c9d4SSatish Balay ornt[3] = -1; 22249566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 22252829fed8SMatthew G. Knepley /* Edges */ 22269371c9d4SSatish Balay cone[0] = 6; 22279371c9d4SSatish Balay cone[1] = 7; 22289566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 22299371c9d4SSatish Balay cone[0] = 7; 22309371c9d4SSatish Balay cone[1] = 8; 22319566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 22329371c9d4SSatish Balay cone[0] = 8; 22339371c9d4SSatish Balay cone[1] = 9; 22349566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 22359371c9d4SSatish Balay cone[0] = 9; 22369371c9d4SSatish Balay cone[1] = 6; 22379566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 22389371c9d4SSatish Balay cone[0] = 10; 22399371c9d4SSatish Balay cone[1] = 11; 22409566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 22419371c9d4SSatish Balay cone[0] = 11; 22429371c9d4SSatish Balay cone[1] = 7; 22439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 22449371c9d4SSatish Balay cone[0] = 6; 22459371c9d4SSatish Balay cone[1] = 10; 22469566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 22479371c9d4SSatish Balay cone[0] = 12; 22489371c9d4SSatish Balay cone[1] = 13; 22499566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 22509371c9d4SSatish Balay cone[0] = 13; 22519371c9d4SSatish Balay cone[1] = 11; 22529566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 22539371c9d4SSatish Balay cone[0] = 10; 22549371c9d4SSatish Balay cone[1] = 12; 22559566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 22569371c9d4SSatish Balay cone[0] = 13; 22579371c9d4SSatish Balay cone[1] = 8; 22589566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 22599371c9d4SSatish Balay cone[0] = 12; 22609371c9d4SSatish Balay cone[1] = 9; 22619566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 226245da822fSValeria Barra } 22639566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 22649566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 22652829fed8SMatthew G. Knepley /* Build coordinates */ 22669566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2267dd400576SPatrick Sanan if (rank == 0) { 22689371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 22699371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 22709371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 22719371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 22729371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 22739371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 22749371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 22759371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 22769371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 22779371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 22789371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 22799371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 22809371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 22819371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 22829371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 22839371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 22849371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 22859371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 22869371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 22879371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 22889371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 22899371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 22909371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 22919371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 229265a81367SMatthew G. Knepley } 229345da822fSValeria Barra } 229465a81367SMatthew G. Knepley break; 229565a81367SMatthew G. Knepley case 3: 2296116ded15SMatthew G. Knepley if (simplex) { 2297116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 229851a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 229951a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 230051a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 2301116ded15SMatthew G. Knepley const PetscInt degree = 12; 2302116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 23039371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 23049371c9d4SSatish Balay {0, 1, 2, 3}, 23059371c9d4SSatish Balay {0, 2, 3, 1}, 23069371c9d4SSatish Balay {0, 3, 1, 2}, 23079371c9d4SSatish Balay {1, 0, 3, 2}, 23089371c9d4SSatish Balay {1, 2, 0, 3}, 23099371c9d4SSatish Balay {1, 3, 2, 0}, 23109371c9d4SSatish Balay {2, 0, 1, 3}, 23119371c9d4SSatish Balay {2, 1, 3, 0}, 23129371c9d4SSatish Balay {2, 3, 0, 1}, 23139371c9d4SSatish Balay {3, 0, 2, 1}, 23149371c9d4SSatish Balay {3, 1, 0, 2}, 23159371c9d4SSatish Balay {3, 2, 1, 0} 23169371c9d4SSatish Balay }; 2317116ded15SMatthew G. Knepley PetscInt cone[4]; 2318116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 2319116ded15SMatthew G. Knepley 23209371c9d4SSatish Balay vertexA[0] *= R; 23219371c9d4SSatish Balay vertexA[1] *= R; 23229371c9d4SSatish Balay vertexA[2] *= R; 23239371c9d4SSatish Balay vertexA[3] *= R; 23249371c9d4SSatish Balay vertexB[0] *= R; 23259371c9d4SSatish Balay vertexB[1] *= R; 23269371c9d4SSatish Balay vertexB[2] *= R; 23279371c9d4SSatish Balay vertexB[3] *= R; 23289371c9d4SSatish Balay vertexC[0] *= R; 23299371c9d4SSatish Balay vertexC[1] *= R; 23309371c9d4SSatish Balay vertexC[2] *= R; 23319371c9d4SSatish Balay vertexC[3] *= R; 2332dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 2333dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 2334116ded15SMatthew G. Knepley firstVertex = numCells; 2335116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 2336116ded15SMatthew G. Knepley 2337116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 2338116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 2339116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 2340116ded15SMatthew G. Knepley 2341116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 23426333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 2343116ded15SMatthew G. Knepley 2344116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 2345116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 2346116ded15SMatthew G. Knepley */ 2347116ded15SMatthew G. Knepley /* Construct vertices */ 23489566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2349116ded15SMatthew G. Knepley i = 0; 2350dd400576SPatrick Sanan if (rank == 0) { 2351116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2352116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2353116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2354116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 2355116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 2356116ded15SMatthew G. Knepley ++i; 2357116ded15SMatthew G. Knepley } 2358116ded15SMatthew G. Knepley } 2359116ded15SMatthew G. Knepley } 2360116ded15SMatthew G. Knepley } 2361116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 2362116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 2363116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2364116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 2365116ded15SMatthew G. Knepley ++i; 2366116ded15SMatthew G. Knepley } 2367116ded15SMatthew G. Knepley } 2368116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 2369116ded15SMatthew G. Knepley s[3] = 1; 2370116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2371116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2372116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2373116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 2374116ded15SMatthew G. Knepley ++i; 2375116ded15SMatthew G. Knepley } 2376116ded15SMatthew G. Knepley } 2377116ded15SMatthew G. Knepley } 2378116ded15SMatthew G. Knepley } 237945da822fSValeria Barra } 238063a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 2381116ded15SMatthew G. Knepley /* Construct graph */ 23829566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 2383116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 2384116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 23859371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 23869371c9d4SSatish Balay graph[i * numVerts + j] = 1; 23879371c9d4SSatish Balay ++k; 23889371c9d4SSatish Balay } 2389116ded15SMatthew G. Knepley } 239063a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 2391116ded15SMatthew G. Knepley } 2392116ded15SMatthew G. Knepley /* Build Topology */ 23939566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 239448a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 23959566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2396116ded15SMatthew G. Knepley /* Cells */ 2397dd400576SPatrick Sanan if (rank == 0) { 2398116ded15SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 2399116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 2400116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 2401116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 24029371c9d4SSatish 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]) { 24039371c9d4SSatish Balay cone[0] = firstVertex + i; 24049371c9d4SSatish Balay cone[1] = firstVertex + j; 24059371c9d4SSatish Balay cone[2] = firstVertex + k; 24069371c9d4SSatish Balay cone[3] = firstVertex + l; 2407116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 2408116ded15SMatthew G. Knepley { 24099371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 24109371c9d4SSatish 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}}}, 2411116ded15SMatthew G. Knepley 24129371c9d4SSatish 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}}}, 2413116ded15SMatthew G. Knepley 24149371c9d4SSatish 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}}}, 2415116ded15SMatthew G. Knepley 24169371c9d4SSatish 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}} } 24179371c9d4SSatish Balay }; 2418116ded15SMatthew G. Knepley PetscReal normal[4]; 2419116ded15SMatthew G. Knepley PetscInt e, f, g; 2420116ded15SMatthew G. Knepley 2421116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 2422116ded15SMatthew G. Knepley normal[d] = 0.0; 2423116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2424116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 2425116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 2426116ded15SMatthew 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]); 2427116ded15SMatthew G. Knepley } 2428116ded15SMatthew G. Knepley } 2429116ded15SMatthew G. Knepley } 2430116ded15SMatthew G. Knepley } 24319371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 24329371c9d4SSatish Balay PetscInt tmp = cone[1]; 24339371c9d4SSatish Balay cone[1] = cone[2]; 24349371c9d4SSatish Balay cone[2] = tmp; 24359371c9d4SSatish Balay } 2436116ded15SMatthew G. Knepley } 24379566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 2438116ded15SMatthew G. Knepley } 2439116ded15SMatthew G. Knepley } 2440116ded15SMatthew G. Knepley } 2441116ded15SMatthew G. Knepley } 2442116ded15SMatthew G. Knepley } 244345da822fSValeria Barra } 24449566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 24459566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 24469566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 2447116ded15SMatthew G. Knepley break; 2448116ded15SMatthew G. Knepley } 244963a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 245065a81367SMatthew G. Knepley } 245165a81367SMatthew G. Knepley /* Create coordinates */ 24529566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 24539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 24549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 24559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 24562829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 24579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 24589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 24592829fed8SMatthew G. Knepley } 24609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 24619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 24629566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 24639566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 24649566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 24659566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 24669566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 24679566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 24689371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 2469ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 24709566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 24719566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 24729566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 24739566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 247451a74b61SMatthew G. Knepley { 247551a74b61SMatthew G. Knepley DM cdm; 247651a74b61SMatthew G. Knepley PetscDS cds; 24779318fe57SMatthew G. Knepley PetscScalar c = R; 247851a74b61SMatthew G. Knepley 24799566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere)); 24809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 24819566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 24829566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 248351a74b61SMatthew G. Knepley } 24849318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 24859566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 24869318fe57SMatthew G. Knepley PetscFunctionReturn(0); 24879318fe57SMatthew G. Knepley } 24889318fe57SMatthew G. Knepley 2489b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 2490b7f5c055SJed Brown 2491b7f5c055SJed Brown /* 2492b7f5c055SJed Brown The Schwarz P implicit surface is 2493b7f5c055SJed Brown 2494b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 2495b7f5c055SJed Brown */ 24969371c9d4SSatish Balay static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) { 2497b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 2498b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 2499b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 2500b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2501b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 2502ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 2503b7f5c055SJed Brown } 2504b7f5c055SJed Brown } 2505b7f5c055SJed Brown 25064663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 25074663dae6SJed Brown static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) { 2508ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 25094663dae6SJed Brown return 0; 25104663dae6SJed Brown } 25114663dae6SJed Brown 2512b7f5c055SJed Brown /* 2513b7f5c055SJed Brown The Gyroid implicit surface is 2514b7f5c055SJed Brown 2515b7f5c055SJed 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) 2516b7f5c055SJed Brown 2517b7f5c055SJed Brown */ 25189371c9d4SSatish Balay static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) { 2519b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 2520b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 2521b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 2522b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 2523b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 2524b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 2525b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 2526b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2527b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2528b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 2529b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2530b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2531b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 2532b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2533b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2534b7f5c055SJed Brown } 2535b7f5c055SJed Brown 25364663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 25374663dae6SJed Brown static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) { 25384663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 25394663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 25404663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 25414663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 25424663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 25434663dae6SJed Brown return 0; 25444663dae6SJed Brown } 25454663dae6SJed Brown 2546b7f5c055SJed Brown /* 2547b7f5c055SJed Brown We wish to solve 2548b7f5c055SJed Brown 2549b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 2550b7f5c055SJed Brown 2551b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 2552b7f5c055SJed 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 2553b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 2554b7f5c055SJed Brown 2555b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 2556b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 2557b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 2558b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 2559b7f5c055SJed Brown Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries. 2560b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 2561b7f5c055SJed Brown 2562b7f5c055SJed Brown f(y) = 0 1 equation 2563b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 2564b7f5c055SJed Brown 2565b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 2566b7f5c055SJed Brown */ 25679371c9d4SSatish Balay static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) { 2568b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 2569b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 25702f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 25719371c9d4SSatish Balay PetscReal n_y[3][3] = { 25729371c9d4SSatish Balay {0, 0, 0}, 25739371c9d4SSatish Balay {0, 0, 0}, 25749371c9d4SSatish Balay {0, 0, 0} 25759371c9d4SSatish Balay }; 2576b7f5c055SJed Brown 2577b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 2578b7f5c055SJed Brown 2579b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 2580b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2581ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 2582b7f5c055SJed Brown 2583b7f5c055SJed Brown // Define the Householder reflector 2584b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 2585b7f5c055SJed Brown n[0] += norm * sign; 2586b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 2587b7f5c055SJed Brown 2588b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2589b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 2590b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 2591b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 2592b7f5c055SJed Brown 2593b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2594b7f5c055SJed Brown n[i] /= norm; 2595b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2596b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 2597b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 2598b7f5c055SJed Brown } 2599b7f5c055SJed Brown } 2600b7f5c055SJed Brown 2601b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 2602b7f5c055SJed 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]; 2603b7f5c055SJed Brown 2604b7f5c055SJed Brown res[0] = f; 2605b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 2606b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 2607b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 2608b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2609b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 2610b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 2611b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 2612b7f5c055SJed Brown } 2613b7f5c055SJed Brown } 2614b7f5c055SJed Brown 2615b7f5c055SJed Brown /* 2616b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 2617b7f5c055SJed Brown */ 26189371c9d4SSatish Balay static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) { 2619b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 2620b7f5c055SJed Brown 2621b7f5c055SJed Brown PetscFunctionBegin; 2622b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 2623b7f5c055SJed Brown PetscScalar res[3], J[9]; 2624b7f5c055SJed Brown PetscReal resnorm; 2625b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 2626b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 2627b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 262863a3b9bcSJacob 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]))); 2629b7f5c055SJed Brown } 2630b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 2631b7f5c055SJed Brown 2632b7f5c055SJed Brown // Take the Newton step 26339566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 2634b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 2635b7f5c055SJed Brown } 2636b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 2637b7f5c055SJed Brown PetscFunctionReturn(0); 2638b7f5c055SJed Brown } 2639b7f5c055SJed Brown 2640b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 2641b7f5c055SJed Brown 26429371c9d4SSatish Balay static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) { 2643b7f5c055SJed Brown PetscMPIInt rank; 2644b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 2645b7f5c055SJed Brown PetscInt(*edges)[2] = NULL, *edgeSets = NULL; 2646b7f5c055SJed Brown PetscInt *cells_flat = NULL; 2647b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 2648b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 26494663dae6SJed Brown PetscSimplePointFunc normalFunc = NULL; 2650b7f5c055SJed Brown DMLabel label; 2651b7f5c055SJed Brown 2652b7f5c055SJed Brown PetscFunctionBegin; 26539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 265463a3b9bcSJacob 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); 2655b7f5c055SJed Brown switch (tpstype) { 2656b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 2657b7f5c055SJed 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"); 2658c5853193SPierre Jolivet if (rank == 0) { 2659b7f5c055SJed Brown PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 2660b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 2661b7f5c055SJed Brown PetscReal L = 1; 2662b7f5c055SJed Brown 2663b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 2664b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 2665b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 2666b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 2667b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 2668b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 26699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 26709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 26719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 26729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 2673b7f5c055SJed Brown // x-normal pipes 2674b7f5c055SJed Brown vcount = 0; 2675b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 2676b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2677b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2678b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2679b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 2680b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2681b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2682b7f5c055SJed Brown } 2683b7f5c055SJed Brown } 2684b7f5c055SJed Brown } 2685b7f5c055SJed Brown } 2686b7f5c055SJed Brown // y-normal pipes 2687b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2688b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 2689b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2690b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2691b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2692b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 2693b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2694b7f5c055SJed Brown } 2695b7f5c055SJed Brown } 2696b7f5c055SJed Brown } 2697b7f5c055SJed Brown } 2698b7f5c055SJed Brown // z-normal pipes 2699b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2700b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2701b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 2702b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2703b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2704b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2705b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 2706b7f5c055SJed Brown } 2707b7f5c055SJed Brown } 2708b7f5c055SJed Brown } 2709b7f5c055SJed Brown } 2710b7f5c055SJed Brown // junctions 2711b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2712b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2713b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2714b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 2715b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 2716b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 2717b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 2718b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 2719b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 2720b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 2721b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 2722b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 2723b7f5c055SJed Brown } 2724b7f5c055SJed Brown } 2725b7f5c055SJed Brown } 2726b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 2727b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 2728b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 2729b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 2730b7f5c055SJed Brown }; 2731b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 27329371c9d4SSatish 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}; 2733b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 27349371c9d4SSatish 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}; 2735b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 2736b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 2737b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 2738b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 2739b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 2740b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 2741b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 2742b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 2743b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 2744b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 2745b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 2746b7f5c055SJed Brown if (ijk[dir] == 0) { 2747b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 2748b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 2749b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 2750b7f5c055SJed Brown numEdges++; 2751b7f5c055SJed Brown } 2752b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 2753b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 2754b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 2755b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 2756b7f5c055SJed Brown numEdges++; 2757b7f5c055SJed Brown } 2758b7f5c055SJed Brown } 2759b7f5c055SJed Brown } 2760b7f5c055SJed Brown } 2761b7f5c055SJed Brown } 2762b7f5c055SJed Brown } 276363a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 2764b7f5c055SJed Brown numFaces = 24 * Njunctions; 2765b7f5c055SJed Brown cells_flat = cells[0][0][0]; 2766b7f5c055SJed Brown } 2767b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 27684663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 2769b7f5c055SJed Brown break; 2770b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 2771c5853193SPierre Jolivet if (rank == 0) { 2772b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 2773b7f5c055SJed Brown // 2774b7f5c055SJed 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) 2775b7f5c055SJed Brown // 2776b7f5c055SJed Brown // on the cell [0,2]^3. 2777b7f5c055SJed Brown // 2778b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 2779b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 2780b7f5c055SJed Brown // like a boomerang: 2781b7f5c055SJed Brown // 2782b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 2783b7f5c055SJed Brown // ----- ------- ------- ------- // 2784b7f5c055SJed Brown // // 2785b7f5c055SJed Brown // + + + + + + + \ + // 2786b7f5c055SJed Brown // \ / \ // 2787b7f5c055SJed Brown // \ `-_ _-' / } // 2788b7f5c055SJed Brown // *-_ `-' _-' / // 2789b7f5c055SJed Brown // + `-+ + + +-' + + / + // 2790b7f5c055SJed Brown // // 2791b7f5c055SJed Brown // // 2792b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 2793b7f5c055SJed Brown // ----- ------- ------- ------- // 2794b7f5c055SJed Brown // // 2795b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 2796b7f5c055SJed Brown // `-_ _-_ _-` / // 2797b7f5c055SJed Brown // \ _-' `-_ / { // 2798b7f5c055SJed Brown // \ / \ // 2799b7f5c055SJed Brown // + + + + + + + \ + // 2800b7f5c055SJed Brown // 2801b7f5c055SJed Brown // 2802b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 2803b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 2804b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 2805b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 2806b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 2807b7f5c055SJed Brown // 2808b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 2809b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 2810b7f5c055SJed Brown // 2811b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 2812b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 2813b7f5c055SJed Brown 2814b7f5c055SJed Brown PetscInt facesPerBlock = 64; 2815b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 2816b7f5c055SJed Brown PetscInt extentPlus[3]; 2817b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 28189371c9d4SSatish 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; 28199371c9d4SSatish Balay const PetscInt pattern[64][4] = { 28209371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 2821b7f5c055SJed Brown /* layer 0 */ 28229371c9d4SSatish Balay {A, C, K, G }, 28239371c9d4SSatish Balay {C, B, II, K }, 28249371c9d4SSatish Balay {D, A, H, L }, 28259371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 28269371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 28279371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 28289371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 28299371c9d4SSatish Balay {B, F, M, II }, 2830b7f5c055SJed Brown /* layer 1 */ 28319371c9d4SSatish Balay {G, K, Q, O }, 28329371c9d4SSatish Balay {K, II, P, Q }, 28339371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 28349371c9d4SSatish Balay {J, L, R, P }, 28359371c9d4SSatish Balay {N, J, P, S }, 28369371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 28379371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 28389371c9d4SSatish Balay {II, M, T, P }, 2839b7f5c055SJed Brown /* layer 2 */ 28409371c9d4SSatish Balay {O, Q, Y, U }, 28419371c9d4SSatish Balay {Q, P, W, Y }, 28429371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 28439371c9d4SSatish Balay {P, R, Ap, W }, 28449371c9d4SSatish Balay {S, P, X, Bp }, 28459371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 28469371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 28479371c9d4SSatish Balay {P, T, Z, X }, 2848b7f5c055SJed Brown /* layer 3 */ 28499371c9d4SSatish Balay {U, Y, Ep, Dp }, 28509371c9d4SSatish Balay {Y, W, Cp, Ep }, 28519371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 28529371c9d4SSatish Balay {W, Ap, Gp, Cp }, 28539371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 28549371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 28559371c9d4SSatish Balay {Z, V, Dp, Hp }, 28569371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 2857b7f5c055SJed Brown /* layer 4 */ 28589371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 28599371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 28609371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 28619371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 28629371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 28639371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 28649371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 28659371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 2866b7f5c055SJed Brown /* layer 5 */ 28679371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 28689371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 28699371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 28709371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 28719371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 28729371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 28739371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 28749371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 2875b7f5c055SJed Brown /* layer 6 */ 28769371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 28779371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 28789371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 28799371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 28809371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 28819371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 28829371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 28839371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 2884b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 28859371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 28869371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 28879371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 28889371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 28899371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 28909371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 28919371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 28929371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 2893b7f5c055SJed Brown }; 2894b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 28959371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 2896bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 2897bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 2898bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 2899bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 2900bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 2901bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 2902b7f5c055SJed Brown 2903bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 2904bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 2905bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 2906bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 2907bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 2908bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 2909bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 2910bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 2911b7f5c055SJed Brown 2912bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 2913bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 2914bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 2915bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 2916bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 2917bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 2918b7f5c055SJed Brown 2919bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 2920bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 2921bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 2922bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 2923bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 2924bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 2925bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 2926bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 2927b7f5c055SJed Brown 2928bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 2929bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 2930bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 2931bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 2932bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 2933bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 2934b7f5c055SJed Brown 2935bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 2936bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 2937bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 2938bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 2939bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 2940bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 2941bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 2942bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 2943b7f5c055SJed Brown 2944bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 2945bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 2946bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 2947bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 2948bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 2949bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 2950b7f5c055SJed Brown 2951bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 2952bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 2953bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 2954bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 2955bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 2956bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 2957bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 2958bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 2959b7f5c055SJed Brown }; 2960b7f5c055SJed Brown PetscInt(*cells)[64][4] = NULL; 2961b7f5c055SJed Brown PetscBool *seen; 2962b7f5c055SJed Brown PetscInt *vertToTrueVert; 2963b7f5c055SJed Brown PetscInt count; 2964b7f5c055SJed Brown 2965b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 2966b7f5c055SJed Brown numBlocks = 1; 2967b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 2968b7f5c055SJed Brown numBlocksPlus = 1; 2969b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 2970b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 29719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 29729566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 2973b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2974b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2975b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2976b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 2977b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 2978b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 2979b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 2980b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 2981b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 2982b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 2983b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 2984b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 2985b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 2986b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 2987b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 2988b7f5c055SJed Brown 2989b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 2990b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 2991b7f5c055SJed Brown } 2992b7f5c055SJed Brown } 2993b7f5c055SJed Brown } 2994b7f5c055SJed Brown } 2995b7f5c055SJed Brown } 29969371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 29979371c9d4SSatish Balay if (seen[i]) numVertices++; 2998b7f5c055SJed Brown count = 0; 29999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 30009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 3001b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 3002b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 3003b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 3004b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 3005b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 3006b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 3007b7f5c055SJed Brown 3008b7f5c055SJed Brown if (seen[vIdx]) { 3009b7f5c055SJed Brown PetscInt thisVert; 3010b7f5c055SJed Brown 3011b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 3012b7f5c055SJed Brown 3013b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 3014b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 3015b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 3016b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 3017b7f5c055SJed Brown } 3018b7f5c055SJed Brown } 3019b7f5c055SJed Brown } 3020b7f5c055SJed Brown } 3021b7f5c055SJed Brown } 3022b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 3023b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3024ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 3025b7f5c055SJed Brown } 3026b7f5c055SJed Brown } 30279566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 30289566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 3029b7f5c055SJed Brown cells_flat = cells[0][0]; 3030b7f5c055SJed Brown numEdges = 0; 3031b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 3032b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3033b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3034b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3035b7f5c055SJed Brown 3036b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3037b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 3038b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 3039b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 3040b7f5c055SJed Brown } 3041b7f5c055SJed Brown } 3042b7f5c055SJed Brown } 3043b7f5c055SJed Brown } 30449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 30459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 3046b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 3047b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3048b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3049b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3050b7f5c055SJed Brown 3051b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3052b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 3053b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 3054b7f5c055SJed Brown edges[edge][0] = ev[0]; 3055b7f5c055SJed Brown edges[edge][1] = ev[1]; 3056b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 3057b7f5c055SJed Brown } 3058b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 3059b7f5c055SJed Brown edges[edge][0] = ev[0]; 3060b7f5c055SJed Brown edges[edge][1] = ev[1]; 3061b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 3062b7f5c055SJed Brown } 3063b7f5c055SJed Brown } 3064b7f5c055SJed Brown } 3065b7f5c055SJed Brown } 3066b7f5c055SJed Brown } 3067b7f5c055SJed Brown } 3068b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 30694663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 3070b7f5c055SJed Brown break; 3071b7f5c055SJed Brown } 3072b7f5c055SJed Brown 30739566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 3074c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 30759566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 30769566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 3077b7f5c055SJed Brown { 3078b7f5c055SJed Brown DM idm; 30799566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 308069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3081b7f5c055SJed Brown } 3082c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 30839566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 30849566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 3085b7f5c055SJed Brown 30869566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 30879566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 3088b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 3089b7f5c055SJed Brown PetscInt njoin; 3090b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 30919566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 309263a3b9bcSJacob 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]); 30939566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 30949566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 3095b7f5c055SJed Brown } 30969566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 30979566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 30981436d7faSJed Brown if (tps_distribute) { 30991436d7faSJed Brown DM pdm = NULL; 31001436d7faSJed Brown PetscPartitioner part; 31011436d7faSJed Brown 31029566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 31039566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 31049566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 310548a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 31061436d7faSJed Brown // Do not auto-distribute again 31079566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 31081436d7faSJed Brown } 3109b7f5c055SJed Brown 31109566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 3111b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 3112b7f5c055SJed Brown PetscInt m; 3113b7f5c055SJed Brown DM dmf; 3114b7f5c055SJed Brown Vec X; 3115b7f5c055SJed Brown PetscScalar *x; 31169566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 311769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 3118b7f5c055SJed Brown 31199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 31209566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 31219566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 312248a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 31239566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 3124b7f5c055SJed Brown } 3125b7f5c055SJed Brown 3126b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 31279566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 31289566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 3129b7f5c055SJed Brown 3130b7f5c055SJed Brown if (thickness > 0) { 31314663dae6SJed Brown DM edm, cdm, ecdm; 31324663dae6SJed Brown DMPlexTransform tr; 31334663dae6SJed Brown const char *prefix; 31344663dae6SJed Brown PetscOptions options; 31354663dae6SJed Brown // Code from DMPlexExtrude 31364663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 31374663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 31384663dae6SJed Brown PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE)); 31394663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 31404663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 31414663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 31424663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 31434663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 31444663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 31454663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 31464663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 31474663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 31484663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 31494663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 31504663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 31514663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 31524663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 31534663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 31544663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 31554663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 31564663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 31574663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 31584663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 31594663dae6SJed Brown if (edm) { 31604663dae6SJed Brown ((DM_Plex *)edm->data)->printFEM = ((DM_Plex *)dm->data)->printFEM; 31614663dae6SJed Brown ((DM_Plex *)edm->data)->printL2 = ((DM_Plex *)dm->data)->printL2; 3162f5867de0SMatthew G. Knepley ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate; 31634663dae6SJed Brown } 316469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 3165b7f5c055SJed Brown } 3166b7f5c055SJed Brown PetscFunctionReturn(0); 3167b7f5c055SJed Brown } 3168b7f5c055SJed Brown 3169b7f5c055SJed Brown /*@ 3170b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 3171b7f5c055SJed Brown 3172b7f5c055SJed Brown Collective 3173b7f5c055SJed Brown 3174b7f5c055SJed Brown Input Parameters: 3175b7f5c055SJed Brown + comm - The communicator for the DM object 3176b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 3177b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 3178b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic 31791436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 3180817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 31811436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 3182817da375SSatish Balay - thickness - Thickness in normal direction 3183b7f5c055SJed Brown 3184b7f5c055SJed Brown Output Parameter: 3185b7f5c055SJed Brown . dm - The DM object 3186b7f5c055SJed Brown 3187b7f5c055SJed Brown Notes: 3188b7f5c055SJed Brown This meshes the surface of the Schwarz P or Gyroid surfaces. Schwarz P is is the simplest member of the triply-periodic minimal surfaces. 3189b7f5c055SJed Brown https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries. 3190b7f5c055SJed Brown 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. 3191b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 3192b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 3193b7f5c055SJed Brown This projection could readily be extended to related surfaces. 3194b7f5c055SJed Brown 3195b7f5c055SJed Brown The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z). 3196b7f5c055SJed Brown When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). Use DMPlexLabelComplete() to propagate to coarse-level vertices. 3197b7f5c055SJed Brown 3198b7f5c055SJed Brown References: 3199606c0280SSatish Balay . * - Maskery et al, Insights into the mechanical properties of several triply periodic minimal surface lattice structures made by polymer additive manufacturing, 2017. https://doi.org/10.1016/j.polymer.2017.11.049 3200b7f5c055SJed Brown 3201b7f5c055SJed Brown Developer Notes: 3202b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 3203b7f5c055SJed Brown 3204b7f5c055SJed Brown Level: beginner 3205b7f5c055SJed Brown 3206db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 3207b7f5c055SJed Brown @*/ 32089371c9d4SSatish Balay PetscErrorCode DMPlexCreateTPSMesh(MPI_Comm comm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness, DM *dm) { 3209b7f5c055SJed Brown PetscFunctionBegin; 32109566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 32119566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 32129566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 3213b7f5c055SJed Brown PetscFunctionReturn(0); 3214b7f5c055SJed Brown } 3215b7f5c055SJed Brown 32169318fe57SMatthew G. Knepley /*@ 32179318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 32189318fe57SMatthew G. Knepley 32199318fe57SMatthew G. Knepley Collective 32209318fe57SMatthew G. Knepley 32219318fe57SMatthew G. Knepley Input Parameters: 32229318fe57SMatthew G. Knepley + comm - The communicator for the DM object 32239318fe57SMatthew G. Knepley . dim - The dimension 32249318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 32259318fe57SMatthew G. Knepley - R - The radius 32269318fe57SMatthew G. Knepley 32279318fe57SMatthew G. Knepley Output Parameter: 32289318fe57SMatthew G. Knepley . dm - The DM object 32299318fe57SMatthew G. Knepley 32309318fe57SMatthew G. Knepley Level: beginner 32319318fe57SMatthew G. Knepley 3232db781477SPatrick Sanan .seealso: `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 32339318fe57SMatthew G. Knepley @*/ 32349371c9d4SSatish Balay PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) { 32359318fe57SMatthew G. Knepley PetscFunctionBegin; 32369318fe57SMatthew G. Knepley PetscValidPointer(dm, 5); 32379566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 32389566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 32399566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 32409318fe57SMatthew G. Knepley PetscFunctionReturn(0); 32419318fe57SMatthew G. Knepley } 32429318fe57SMatthew G. Knepley 32439371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) { 32449318fe57SMatthew G. Knepley DM sdm, vol; 32459318fe57SMatthew G. Knepley DMLabel bdlabel; 32469318fe57SMatthew G. Knepley 32479318fe57SMatthew G. Knepley PetscFunctionBegin; 32489566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 32499566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 32509566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_")); 32519566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 32529566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 32539566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 32549566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 32559566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 325669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 32579566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 32589566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 32599566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 32609566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 326151a74b61SMatthew G. Knepley PetscFunctionReturn(0); 326251a74b61SMatthew G. Knepley } 326351a74b61SMatthew G. Knepley 326451a74b61SMatthew G. Knepley /*@ 326551a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 326651a74b61SMatthew G. Knepley 326751a74b61SMatthew G. Knepley Collective 326851a74b61SMatthew G. Knepley 326951a74b61SMatthew G. Knepley Input Parameters: 327051a74b61SMatthew G. Knepley + comm - The communicator for the DM object 327151a74b61SMatthew G. Knepley . dim - The dimension 327251a74b61SMatthew G. Knepley - R - The radius 327351a74b61SMatthew G. Knepley 327451a74b61SMatthew G. Knepley Output Parameter: 327551a74b61SMatthew G. Knepley . dm - The DM object 327651a74b61SMatthew G. Knepley 327751a74b61SMatthew G. Knepley Options Database Keys: 327851a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 327951a74b61SMatthew G. Knepley 328051a74b61SMatthew G. Knepley Level: beginner 328151a74b61SMatthew G. Knepley 3282db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 328351a74b61SMatthew G. Knepley @*/ 32849371c9d4SSatish Balay PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) { 328551a74b61SMatthew G. Knepley PetscFunctionBegin; 32869566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 32879566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 32889566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 32892829fed8SMatthew G. Knepley PetscFunctionReturn(0); 32902829fed8SMatthew G. Knepley } 32912829fed8SMatthew G. Knepley 32929371c9d4SSatish Balay static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) { 32930a6ba040SMatthew G. Knepley PetscFunctionBegin; 32949318fe57SMatthew G. Knepley switch (ct) { 32959371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 32969318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 32979318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 32989318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 32999318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 33009318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 33019318fe57SMatthew G. Knepley 33029566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 33039566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33049371c9d4SSatish Balay } break; 33059371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 33069318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 33079318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 33089318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 33099318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 33109318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 33119318fe57SMatthew G. Knepley 33129566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 33139566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33149371c9d4SSatish Balay } break; 33159371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 3316b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 3317b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 3318b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 3319b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 3320b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 3321b5a892a1SMatthew G. Knepley 33229566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 33239566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33249371c9d4SSatish Balay } break; 33259371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 33269318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 33279318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 33289318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 33299318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 33309318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 33319318fe57SMatthew G. Knepley 33329566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 33339566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33349371c9d4SSatish Balay } break; 33359371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 33369318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 33379318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 33389318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 33399318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 33409318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 33419318fe57SMatthew G. Knepley 33429566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 33439566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33449371c9d4SSatish Balay } break; 33459371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 33469318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 33479318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 33489318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 33499318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 33509318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 33519318fe57SMatthew G. Knepley 33529566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 33539566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33549371c9d4SSatish Balay } break; 33559371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 33569318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 33579318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 3358f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 33599318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 3360f0edb160SMatthew 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}; 33619318fe57SMatthew G. Knepley 33629566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 33639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33649371c9d4SSatish Balay } break; 33659371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 33669318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 33679318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 3368f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 33699318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 33709371c9d4SSatish 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}; 33719318fe57SMatthew G. Knepley 33729566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 33739566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33749371c9d4SSatish Balay } break; 33759371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 33769318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 33779318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 3378f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 33799318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 33809371c9d4SSatish 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}; 33819318fe57SMatthew G. Knepley 33829566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 33839566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33849371c9d4SSatish Balay } break; 33859371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 33869318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 33879318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 33889318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 33899318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 33909371c9d4SSatish 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}; 33919318fe57SMatthew G. Knepley 33929566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 33939566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33949371c9d4SSatish Balay } break; 33959371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 33969318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 33979318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 33989318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 33999318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34009371c9d4SSatish 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}; 34019318fe57SMatthew G. Knepley 34029566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34039566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34049371c9d4SSatish Balay } break; 34059371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 34069318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 34079318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 3408f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 34099318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34109371c9d4SSatish 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}; 34119318fe57SMatthew G. Knepley 34129566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34139566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34149371c9d4SSatish Balay } break; 341598921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 34169318fe57SMatthew G. Knepley } 34179318fe57SMatthew G. Knepley { 34189318fe57SMatthew G. Knepley PetscInt Nv, v; 34199318fe57SMatthew G. Knepley 34209318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 34219566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 34229566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 34239566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 34249566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 34259318fe57SMatthew G. Knepley } 34269566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 34279566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 34280a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 34290a6ba040SMatthew G. Knepley } 34300a6ba040SMatthew G. Knepley 34319318fe57SMatthew G. Knepley /*@ 34329318fe57SMatthew G. Knepley DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell 34339318fe57SMatthew G. Knepley 34349318fe57SMatthew G. Knepley Collective 34359318fe57SMatthew G. Knepley 34369318fe57SMatthew G. Knepley Input Parameters: 34379318fe57SMatthew G. Knepley + comm - The communicator 34389318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 34399318fe57SMatthew G. Knepley 34409318fe57SMatthew G. Knepley Output Parameter: 34419318fe57SMatthew G. Knepley . refdm - The reference cell 34429318fe57SMatthew G. Knepley 34439318fe57SMatthew G. Knepley Level: intermediate 34449318fe57SMatthew G. Knepley 3445db781477SPatrick Sanan .seealso: `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()` 34469318fe57SMatthew G. Knepley @*/ 34479371c9d4SSatish Balay PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) { 34480a6ba040SMatthew G. Knepley PetscFunctionBegin; 34499566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 34509566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 34519566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 34529318fe57SMatthew G. Knepley PetscFunctionReturn(0); 34539318fe57SMatthew G. Knepley } 345479a015ccSMatthew G. Knepley 34559371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) { 34569318fe57SMatthew G. Knepley DM plex; 34579318fe57SMatthew G. Knepley DMLabel label; 34589318fe57SMatthew G. Knepley PetscBool hasLabel; 34590a6ba040SMatthew G. Knepley 3460c22d3578SMatthew G. Knepley PetscFunctionBegin; 34619566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 34629318fe57SMatthew G. Knepley if (hasLabel) PetscFunctionReturn(0); 34639566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 34649566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 34659566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 34669566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 34671c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 34689566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 34699318fe57SMatthew G. Knepley PetscFunctionReturn(0); 34709318fe57SMatthew G. Knepley } 3471acdc6f61SToby Isaac 3472*669647acSMatthew G. Knepley /* 3473*669647acSMatthew 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. 3474*669647acSMatthew G. Knepley 3475*669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 3476*669647acSMatthew G. Knepley */ 3477*669647acSMatthew G. Knepley 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[]) { 3478*669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 3479*669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 3480*669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 3481*669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 3482*669647acSMatthew G. Knepley 3483*669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 3484*669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 3485*669647acSMatthew G. Knepley } 3486*669647acSMatthew G. Knepley 3487*669647acSMatthew G. Knepley const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 34889318fe57SMatthew G. Knepley 34899371c9d4SSatish Balay static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm) { 34909318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 34919318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 34929318fe57SMatthew G. Knepley PetscInt dim = 2; 34939318fe57SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 3494cd7e8a5eSksagiyam PetscBool flg, flg2, fflg, bdfflg, nameflg; 34959318fe57SMatthew G. Knepley MPI_Comm comm; 3496ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3497ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3498ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 34999318fe57SMatthew G. Knepley 35009318fe57SMatthew G. Knepley PetscFunctionBegin; 35019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 35029318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 35039566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 35049566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 35059566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 35069566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 35079566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 35089566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 35099566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 351063a3b9bcSJacob Faibussowitsch PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim); 35119566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 35129566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 35139566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 35149566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 35159566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 35169318fe57SMatthew G. Knepley 351761a622f3SMatthew G. Knepley switch (cell) { 351861a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 351961a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 352061a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 352161a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 352261a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 352361a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 35249371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: *useCoordSpace = PETSC_TRUE; break; 352561a622f3SMatthew G. Knepley default: *useCoordSpace = PETSC_FALSE; break; 352661a622f3SMatthew G. Knepley } 352761a622f3SMatthew G. Knepley 35289318fe57SMatthew G. Knepley if (fflg) { 35299318fe57SMatthew G. Knepley DM dmnew; 35309318fe57SMatthew G. Knepley 35319566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew)); 35325de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 353369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 35349318fe57SMatthew G. Knepley } else if (refDomain) { 35359566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 35369318fe57SMatthew G. Knepley } else if (bdfflg) { 35379318fe57SMatthew G. Knepley DM bdm, dmnew; 35389318fe57SMatthew G. Knepley 35399566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm)); 35409566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 35419566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 35429566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 35439566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 35445de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 354569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 35469318fe57SMatthew G. Knepley } else { 35479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 35489318fe57SMatthew G. Knepley switch (shape) { 3549*669647acSMatthew G. Knepley case DM_SHAPE_BOX: 3550*669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 35519318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 35529318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 35539318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 35549318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3555*669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 35569318fe57SMatthew G. Knepley PetscInt i, n; 35579318fe57SMatthew G. Knepley 35589318fe57SMatthew G. Knepley n = dim; 35599318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 35609566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 35619318fe57SMatthew G. Knepley n = 3; 35629566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 356363a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 35649318fe57SMatthew G. Knepley n = 3; 35659566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 356663a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 35679318fe57SMatthew G. Knepley n = 3; 35689566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 356963a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 3570*669647acSMatthew G. Knepley 3571*669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 3572*669647acSMatthew G. Knepley if (isAnnular) 3573*669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 3574*669647acSMatthew G. Knepley 35759318fe57SMatthew G. Knepley switch (cell) { 357661a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 35779566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 3578d410b0cfSMatthew G. Knepley if (!interpolate) { 3579d410b0cfSMatthew G. Knepley DM udm; 3580d410b0cfSMatthew G. Knepley 35819566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 358269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3583d410b0cfSMatthew G. Knepley } 35849318fe57SMatthew G. Knepley break; 35859371c9d4SSatish Balay default: PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate)); break; 35869318fe57SMatthew G. Knepley } 3587*669647acSMatthew G. Knepley if (isAnnular) { 3588*669647acSMatthew G. Knepley DM cdm; 3589*669647acSMatthew G. Knepley PetscDS cds; 3590*669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 3591*669647acSMatthew G. Knepley 3592*669647acSMatthew G. Knepley // Fix coordinates for annular region 3593*669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 3594*669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 3595*669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 3596*669647acSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, NULL)); 3597*669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 3598*669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 3599*669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 3600*669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 3601*669647acSMatthew G. Knepley } 36029371c9d4SSatish Balay } break; 36039371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 36049318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 36059318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 36069318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 36079318fe57SMatthew G. Knepley PetscInt i, n; 36089318fe57SMatthew G. Knepley 36099318fe57SMatthew G. Knepley n = dim + 1; 36109318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 36119566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 36129318fe57SMatthew G. Knepley n = 3; 36139566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 361463a3b9bcSJacob 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); 36159318fe57SMatthew G. Knepley n = 3; 36169566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 361763a3b9bcSJacob 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); 36189566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 36199371c9d4SSatish Balay } break; 36209371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 36219318fe57SMatthew G. Knepley PetscReal R = 1.0; 36229318fe57SMatthew G. Knepley 36239566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 36249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 36259371c9d4SSatish Balay } break; 36269371c9d4SSatish Balay case DM_SHAPE_BALL: { 36279318fe57SMatthew G. Knepley PetscReal R = 1.0; 36289318fe57SMatthew G. Knepley 36299566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 36309566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 36319371c9d4SSatish Balay } break; 36329371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 36339318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 36349318fe57SMatthew G. Knepley PetscInt Nw = 6; 36359318fe57SMatthew G. Knepley 36369566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 36379566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 36389318fe57SMatthew G. Knepley switch (cell) { 36399371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); break; 36409371c9d4SSatish Balay default: PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt)); break; 36419318fe57SMatthew G. Knepley } 36429371c9d4SSatish Balay } break; 3643b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 36449371c9d4SSatish Balay case DM_SHAPE_GYROID: { 3645b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 3646b7f5c055SJed Brown PetscReal thickness = 0.; 3647b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3648b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 36491436d7faSJed Brown PetscBool tps_distribute; 36509566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 36519566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 36529566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 36539566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 36549566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 36559566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 36569566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 36579566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 36589371c9d4SSatish Balay } break; 36599371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 366005bd46c0SStefano Zampini DM dmnew; 366105bd46c0SStefano Zampini PetscReal rl = 0.0; 366205bd46c0SStefano Zampini 366305bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 366405bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 36655de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 366669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 36679371c9d4SSatish Balay } break; 366898921bdaSJacob Faibussowitsch default: SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 36699318fe57SMatthew G. Knepley } 36709318fe57SMatthew G. Knepley } 36719566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 367248a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 36730a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 36740a6ba040SMatthew G. Knepley } 36750a6ba040SMatthew G. Knepley 36769371c9d4SSatish Balay PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject) { 36770a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 36787f9d8d6cSVaclav Hapla PetscBool flg, flg2; 36799318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 36800a6ba040SMatthew G. Knepley 36810a6ba040SMatthew G. Knepley PetscFunctionBegin; 36820a6ba040SMatthew G. Knepley /* Handle viewing */ 36839566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 36849566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 36859566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 36869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 3687f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 36889566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 36899566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 36909318fe57SMatthew G. Knepley /* Labeling */ 36919566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 36929566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 3693953fc75cSMatthew G. Knepley /* Point Location */ 36949566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 36950848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 36969566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 36972e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 36989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 3699b29cfa1cSToby Isaac /* Projection behavior */ 37009566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maxmimum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 37019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 3702f12cf164SMatthew G. Knepley /* Checking structure */ 3703f12cf164SMatthew G. Knepley { 37047f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 3705f12cf164SMatthew G. Knepley 37067f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 37077f9d8d6cSVaclav Hapla if (all) { 37087f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 37097f9d8d6cSVaclav Hapla } else { 37109566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 37117f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 37129566063dSJacob 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)); 37137f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 37149566063dSJacob 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)); 37157f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 37169566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 37177f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 37189566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 37197f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL)); 37209566063dSJacob 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)); 37217f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 37227f9d8d6cSVaclav Hapla } 37239566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 37249566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 3725f12cf164SMatthew G. Knepley } 37269318fe57SMatthew G. Knepley { 37279318fe57SMatthew G. Knepley PetscReal scale = 1.0; 37284f3833eaSMatthew G. Knepley 37299566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 37309318fe57SMatthew G. Knepley if (flg) { 37319318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 37329318fe57SMatthew G. Knepley 37339566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 37349566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 37359566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 37369566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 37379318fe57SMatthew G. Knepley } 37389318fe57SMatthew G. Knepley } 37399566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 374068d4fef7SMatthew G. Knepley PetscFunctionReturn(0); 374168d4fef7SMatthew G. Knepley } 374268d4fef7SMatthew G. Knepley 37439371c9d4SSatish Balay PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap) { 3744c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 3745c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 3746c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 3747c506a872SMatthew G. Knepley PetscBool flg; 3748c506a872SMatthew G. Knepley 3749c506a872SMatthew G. Knepley PetscFunctionBegin; 3750c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 3751c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 3752c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 3753c506a872SMatthew G. Knepley if (numOvLabels) { 3754c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 3755c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 3756c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 3757c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 3758c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 3759c506a872SMatthew G. Knepley } 3760c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 3761c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 3762c506a872SMatthew 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); 3763c506a872SMatthew G. Knepley 3764c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 3765c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 3766c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 3767c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 3768c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 3769c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 3770c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 3771c506a872SMatthew G. Knepley } 3772c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 3773c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 3774c506a872SMatthew 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); 3775c506a872SMatthew G. Knepley } 3776c506a872SMatthew G. Knepley PetscFunctionReturn(0); 3777c506a872SMatthew G. Knepley } 3778c506a872SMatthew G. Knepley 37799371c9d4SSatish Balay static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject) { 3780bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 3781bdf63967SMatthew G. Knepley char oname[256]; 3782d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 37839318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 3784e600fa54SMatthew G. Knepley PetscBool uniformOrig, created = PETSC_FALSE, uniform = PETSC_TRUE, distribute, interpolate = PETSC_TRUE, coordSpace = PETSC_TRUE, remap = PETSC_TRUE, ghostCells = PETSC_FALSE, isHierarchy, ignoreModel = PETSC_FALSE, flg; 37856bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 378668d4fef7SMatthew G. Knepley 378768d4fef7SMatthew G. Knepley PetscFunctionBegin; 3788d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 37899318fe57SMatthew G. Knepley /* Handle automatic creation */ 37909566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 37916bc1bd01Sksagiyam if (dim < 0) { 37926bc1bd01Sksagiyam PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 37936bc1bd01Sksagiyam created = PETSC_TRUE; 37946bc1bd01Sksagiyam } 37956bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 3796d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 37979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 3798d89e6e46SMatthew G. Knepley if (flg) { 3799d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 3800d89e6e46SMatthew G. Knepley 38019566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 3802d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 3803d89e6e46SMatthew G. Knepley DM udm; 3804d89e6e46SMatthew G. Knepley 38059566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 380669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3807d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 3808d89e6e46SMatthew G. Knepley DM idm; 3809d89e6e46SMatthew G. Knepley 38109566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 381169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3812d89e6e46SMatthew G. Knepley } 3813d89e6e46SMatthew G. Knepley } 38149b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 38159566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg)); 3816ad540459SPierre Jolivet if (flg) ((DM_Plex *)dm->data)->ignoreModel = ignoreModel; 38179566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 38189566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 38199566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 38209566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 38219566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 38229566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 38239318fe57SMatthew G. Knepley if (flg) { 38249566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 38259566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 38269318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 38279318fe57SMatthew G. Knepley } 38289b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 38299b44eab4SMatthew G. Knepley DM rdm; 38309b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 38319b44eab4SMatthew G. Knepley 3832dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 38339566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 383469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 3835dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 383661a622f3SMatthew G. Knepley if (coordFunc && remap) { 38379566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 38389b44eab4SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 38399b44eab4SMatthew G. Knepley } 38409b44eab4SMatthew G. Knepley } 38419566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 38429318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 38439566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 38449318fe57SMatthew G. Knepley if (extLayers) { 38459318fe57SMatthew G. Knepley DM edm; 38469318fe57SMatthew G. Knepley 38479566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 384869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 384948d16a33SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = NULL; 3850dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3851d410b0cfSMatthew G. Knepley extLayers = 0; 38529318fe57SMatthew G. Knepley } 3853bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 38546bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 38559566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 38566bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 38579566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 38586bc1bd01Sksagiyam if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) { 3859bdf63967SMatthew G. Knepley DM pdm; 3860bdf63967SMatthew G. Knepley IS perm; 3861bdf63967SMatthew G. Knepley 38629566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 38639566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 38649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 386569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 3866dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3867bdf63967SMatthew G. Knepley } 38689b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 38699566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 3870c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 3871dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 38729b44eab4SMatthew G. Knepley if (distribute) { 38739b44eab4SMatthew G. Knepley DM pdm = NULL; 38749b44eab4SMatthew G. Knepley PetscPartitioner part; 38759b44eab4SMatthew G. Knepley 38769566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 38779566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 38789566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm)); 387948a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 38809b44eab4SMatthew G. Knepley } 38819318fe57SMatthew G. Knepley /* Create coordinate space */ 38829318fe57SMatthew G. Knepley if (created) { 388361a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 38849318fe57SMatthew G. Knepley PetscInt degree = 1; 38856858538eSMatthew G. Knepley PetscBool flg; 38869318fe57SMatthew G. Knepley 38879566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg)); 38889566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 38899566063dSJacob Faibussowitsch if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc)); 389061a622f3SMatthew G. Knepley if (flg && !coordSpace) { 389161a622f3SMatthew G. Knepley DM cdm; 389261a622f3SMatthew G. Knepley PetscDS cds; 389361a622f3SMatthew G. Knepley PetscObject obj; 389461a622f3SMatthew G. Knepley PetscClassId id; 389561a622f3SMatthew G. Knepley 38969566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 38979566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 38989566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 38999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 390061a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 390161a622f3SMatthew G. Knepley PetscContainer dummy; 390261a622f3SMatthew G. Knepley 39039566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 39049566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 39059566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 39069566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 39079566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 390861a622f3SMatthew G. Knepley } 390961a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 391061a622f3SMatthew G. Knepley } 39116858538eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg)); 39129566063dSJacob Faibussowitsch PetscCall(DMLocalizeCoordinates(dm)); 39139318fe57SMatthew G. Knepley } 391468d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 391561a622f3SMatthew G. Knepley remap = PETSC_TRUE; 39169566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 39179566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 39189566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 39199566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 392068d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 3921acdc6f61SToby Isaac DM *dms, coarseDM; 392268d4fef7SMatthew G. Knepley 39239566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 39249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 39259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 39269566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 392768d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 39289566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 392968d4fef7SMatthew G. Knepley if (refine == 1) { 39309566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 39319566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 393268d4fef7SMatthew G. Knepley } else { 39339566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 39349566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 39359566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 39369566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 393768d4fef7SMatthew G. Knepley } 39389566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 39399566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 394068d4fef7SMatthew G. Knepley /* Free DMs */ 394168d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 3942dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 39439566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 394468d4fef7SMatthew G. Knepley } 39459566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 394668d4fef7SMatthew G. Knepley } else { 394768d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 39489318fe57SMatthew G. Knepley DM rdm; 394951a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 395068d4fef7SMatthew G. Knepley 3951dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 39529566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 395368d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 395469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 3955dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 395661a622f3SMatthew G. Knepley if (coordFunc && remap) { 39579566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 395851a74b61SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 395951a74b61SMatthew G. Knepley } 396068d4fef7SMatthew G. Knepley } 396168d4fef7SMatthew G. Knepley } 39623cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 39639566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 39649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 3965b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 3966b653a561SMatthew G. Knepley DM *dms; 3967b653a561SMatthew G. Knepley 39689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 39699566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 3970b653a561SMatthew G. Knepley /* Free DMs */ 3971b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 3972dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 39739566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 3974b653a561SMatthew G. Knepley } 39759566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 3976b653a561SMatthew G. Knepley } else { 3977b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 39789318fe57SMatthew G. Knepley DM cdm; 39799318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 39803cf6fe12SMatthew G. Knepley 3981dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 39829566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 39833cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 398469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 3985dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 39869318fe57SMatthew G. Knepley if (coordFunc) { 39879566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 39889318fe57SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 39899318fe57SMatthew G. Knepley } 39903cf6fe12SMatthew G. Knepley } 3991b653a561SMatthew G. Knepley } 3992909dfd52SMatthew G. Knepley /* Handle ghost cells */ 39939566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 3994909dfd52SMatthew G. Knepley if (ghostCells) { 3995909dfd52SMatthew G. Knepley DM gdm; 3996909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 3997909dfd52SMatthew G. Knepley 3998909dfd52SMatthew G. Knepley lname[0] = '\0'; 39999566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 40009566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 400169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 4002909dfd52SMatthew G. Knepley } 40036913077dSMatthew G. Knepley /* Handle 1D order */ 40046bc1bd01Sksagiyam if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) { 40056913077dSMatthew G. Knepley DM cdm, rdm; 40066913077dSMatthew G. Knepley PetscDS cds; 40076913077dSMatthew G. Knepley PetscObject obj; 40086913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 40096913077dSMatthew G. Knepley IS perm; 40106bc1bd01Sksagiyam PetscInt Nf; 40116913077dSMatthew G. Knepley PetscBool distributed; 40126913077dSMatthew G. Knepley 40139566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 40149566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 40159566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 40169566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 40176913077dSMatthew G. Knepley if (Nf) { 40189566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 40199566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 40206913077dSMatthew G. Knepley } 40216bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 40229566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 40239566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 402469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 40259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 40266913077dSMatthew G. Knepley } 40276913077dSMatthew G. Knepley } 40283cf6fe12SMatthew G. Knepley /* Handle */ 4029dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 4030d0609cedSBarry Smith PetscOptionsHeadEnd(); 40310a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 40320a6ba040SMatthew G. Knepley } 40330a6ba040SMatthew G. Knepley 40349371c9d4SSatish Balay static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) { 4035552f7358SJed Brown PetscFunctionBegin; 40369566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 40379566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 40389566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 40399566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 40409566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 40419566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 4042552f7358SJed Brown PetscFunctionReturn(0); 4043552f7358SJed Brown } 4044552f7358SJed Brown 40459371c9d4SSatish Balay static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) { 4046552f7358SJed Brown PetscFunctionBegin; 40479566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 40489566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 40499566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 4050552f7358SJed Brown PetscFunctionReturn(0); 4051552f7358SJed Brown } 4052552f7358SJed Brown 40539371c9d4SSatish Balay static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) { 4054793f3fe5SMatthew G. Knepley PetscInt depth, d; 4055793f3fe5SMatthew G. Knepley 4056793f3fe5SMatthew G. Knepley PetscFunctionBegin; 40579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4058793f3fe5SMatthew G. Knepley if (depth == 1) { 40599566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 40609566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 40619566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 40629371c9d4SSatish Balay else { 40639371c9d4SSatish Balay *pStart = 0; 40649371c9d4SSatish Balay *pEnd = 0; 40659371c9d4SSatish Balay } 4066793f3fe5SMatthew G. Knepley } else { 40679566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 4068793f3fe5SMatthew G. Knepley } 4069793f3fe5SMatthew G. Knepley PetscFunctionReturn(0); 4070793f3fe5SMatthew G. Knepley } 4071793f3fe5SMatthew G. Knepley 40729371c9d4SSatish Balay static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) { 4073502a2867SDave May PetscSF sf; 40740a19bb7dSprj- PetscInt niranks, njranks, n; 40750a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 40760a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 4077502a2867SDave May 40782f356facSMatthew G. Knepley PetscFunctionBegin; 40799566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 40800a19bb7dSprj- if (!data->neighbors) { 40819566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 40829566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 40839566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 40849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 40859566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 40869566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 40870a19bb7dSprj- n = njranks + niranks; 40889566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 40890a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 40909566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 40910a19bb7dSprj- } 40920a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 40930a19bb7dSprj- if (ranks) { 40940a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 40950a19bb7dSprj- else *ranks = NULL; 40960a19bb7dSprj- } 4097502a2867SDave May PetscFunctionReturn(0); 4098502a2867SDave May } 4099502a2867SDave May 41001eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 41011eb70e55SToby Isaac 41029371c9d4SSatish Balay static PetscErrorCode DMInitialize_Plex(DM dm) { 4103552f7358SJed Brown PetscFunctionBegin; 4104552f7358SJed Brown dm->ops->view = DMView_Plex; 41052c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 4106552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 410738221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 4108552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 41091bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 411066ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 4111552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 4112552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 4113184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 41140298fd71SBarry Smith dm->ops->createfieldis = NULL; 4115552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 4116f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 41170a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 4118552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 4119bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 4120bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 4121b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 41225a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 4123552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 41240a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 41250a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 4126b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 4127d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 41280298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 41290298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 41300298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 41310298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 4132552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 4133552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 41342adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 4135793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 4136552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 41370709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 41380709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 4139bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 41408c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 4141ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 41420709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 4143b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 41442a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 414528d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 41469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 41479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 41489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 41499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 41509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 41519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 41529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 41536bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 41546bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 41559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 4156c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 4157c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 4158552f7358SJed Brown PetscFunctionReturn(0); 4159552f7358SJed Brown } 4160552f7358SJed Brown 41619371c9d4SSatish Balay PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) { 416263a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 416363a16f15SMatthew G. Knepley 416463a16f15SMatthew G. Knepley PetscFunctionBegin; 416563a16f15SMatthew G. Knepley mesh->refct++; 416663a16f15SMatthew G. Knepley (*newdm)->data = mesh; 41679566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 41689566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 416963a16f15SMatthew G. Knepley PetscFunctionReturn(0); 417063a16f15SMatthew G. Knepley } 417163a16f15SMatthew G. Knepley 41728818961aSMatthew G Knepley /*MC 41738818961aSMatthew G Knepley DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 41748818961aSMatthew G Knepley In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is 41758818961aSMatthew G Knepley specified by a PetscSection object. Ownership in the global representation is determined by 41768818961aSMatthew G Knepley ownership of the underlying DMPlex points. This is specified by another PetscSection object. 41778818961aSMatthew G Knepley 4178e5893cccSMatthew G. Knepley Options Database Keys: 4179250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 4180250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 4181250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 4182250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 4183250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 4184250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 4185250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 4186ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 4187f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 4188f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 4189f12cf164SMatthew G. Knepley . -dm_plex_max_projection_height - Maxmimum mesh point height used to project locally 4190f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 4191250712c9SMatthew G. Knepley . -dm_plex_check_all - Perform all shecks below 4192f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 4193f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 4194f12cf164SMatthew 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 4195f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 4196f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 4197e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 4198e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 4199e5893cccSMatthew G. Knepley 42008818961aSMatthew G Knepley Level: intermediate 42018818961aSMatthew G Knepley 4202db781477SPatrick Sanan .seealso: `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()` 42038818961aSMatthew G Knepley M*/ 42048818961aSMatthew G Knepley 42059371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) { 4206552f7358SJed Brown DM_Plex *mesh; 4207412e9a14SMatthew G. Knepley PetscInt unit; 4208552f7358SJed Brown 4209552f7358SJed Brown PetscFunctionBegin; 4210552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 42119566063dSJacob Faibussowitsch PetscCall(PetscNewLog(dm, &mesh)); 4212552f7358SJed Brown dm->data = mesh; 4213552f7358SJed Brown 4214552f7358SJed Brown mesh->refct = 1; 42159566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 42169566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 4217552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 4218552f7358SJed Brown mesh->refinementLimit = -1.0; 4219e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 42206bc1bd01Sksagiyam mesh->reorderDefault = DMPLEX_REORDER_DEFAULT_NOTSET; 42211d1f2f2aSksagiyam mesh->distributionName = NULL; 42227d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 42237d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 4224552f7358SJed Brown 42259566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 42262e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 4227d9deefdfSMatthew G. Knepley 42288865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 4229552f7358SJed Brown 4230df0420ecSMatthew G. Knepley mesh->depthState = -1; 4231ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 42326113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 4233552f7358SJed Brown 42349566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 4235552f7358SJed Brown PetscFunctionReturn(0); 4236552f7358SJed Brown } 4237552f7358SJed Brown 4238552f7358SJed Brown /*@ 4239552f7358SJed Brown DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 4240552f7358SJed Brown 4241d083f849SBarry Smith Collective 4242552f7358SJed Brown 4243552f7358SJed Brown Input Parameter: 4244552f7358SJed Brown . comm - The communicator for the DMPlex object 4245552f7358SJed Brown 4246552f7358SJed Brown Output Parameter: 4247552f7358SJed Brown . mesh - The DMPlex object 4248552f7358SJed Brown 4249552f7358SJed Brown Level: beginner 4250552f7358SJed Brown 4251552f7358SJed Brown @*/ 42529371c9d4SSatish Balay PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) { 4253552f7358SJed Brown PetscFunctionBegin; 4254552f7358SJed Brown PetscValidPointer(mesh, 2); 42559566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 42569566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 4257552f7358SJed Brown PetscFunctionReturn(0); 4258552f7358SJed Brown } 4259552f7358SJed Brown 4260b09969d6SVaclav Hapla /*@C 4261b09969d6SVaclav Hapla DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output) 4262b09969d6SVaclav Hapla 4263b09969d6SVaclav Hapla Input Parameters: 4264b09969d6SVaclav Hapla + dm - The DM 4265b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4266325d53feSBarry Smith . numVertices - The number of vertices to be owned by this process, or PETSC_DECIDE 4267325d53feSBarry Smith . NVertices - The global number of vertices, or PETSC_DETERMINE 4268b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 42695e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4270b09969d6SVaclav Hapla 4271be8c289dSNicolas Barral Output Parameters: 4272be8c289dSNicolas Barral + vertexSF - (Optional) SF describing complete vertex ownership 4273be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4274b09969d6SVaclav Hapla 4275b09969d6SVaclav Hapla Notes: 4276b09969d6SVaclav Hapla Two triangles sharing a face 4277b09969d6SVaclav Hapla $ 4278b09969d6SVaclav Hapla $ 2 4279b09969d6SVaclav Hapla $ / | \ 4280b09969d6SVaclav Hapla $ / | \ 4281b09969d6SVaclav Hapla $ / | \ 4282b09969d6SVaclav Hapla $ 0 0 | 1 3 4283b09969d6SVaclav Hapla $ \ | / 4284b09969d6SVaclav Hapla $ \ | / 4285b09969d6SVaclav Hapla $ \ | / 4286b09969d6SVaclav Hapla $ 1 4287b09969d6SVaclav Hapla would have input 4288b09969d6SVaclav Hapla $ numCells = 2, numVertices = 4 4289b09969d6SVaclav Hapla $ cells = [0 1 2 1 3 2] 4290b09969d6SVaclav Hapla $ 4291b09969d6SVaclav Hapla which would result in the DMPlex 4292b09969d6SVaclav Hapla $ 4293b09969d6SVaclav Hapla $ 4 4294b09969d6SVaclav Hapla $ / | \ 4295b09969d6SVaclav Hapla $ / | \ 4296b09969d6SVaclav Hapla $ / | \ 4297b09969d6SVaclav Hapla $ 2 0 | 1 5 4298b09969d6SVaclav Hapla $ \ | / 4299b09969d6SVaclav Hapla $ \ | / 4300b09969d6SVaclav Hapla $ \ | / 4301b09969d6SVaclav Hapla $ 3 4302b09969d6SVaclav Hapla 430325b6865aSVaclav Hapla Vertices are implicitly numbered consecutively 0,...,NVertices. 430425b6865aSVaclav Hapla Each rank owns a chunk of numVertices consecutive vertices. 430525b6865aSVaclav Hapla If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout. 4306325d53feSBarry Smith If NVertices is PETSC_DETERMINE and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 4307325d53feSBarry Smith If only NVertices is PETSC_DETERMINE, it is computed as the sum of numVertices over all ranks. 430825b6865aSVaclav Hapla 4309b09969d6SVaclav Hapla The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 4310b09969d6SVaclav Hapla 4311b09969d6SVaclav Hapla Not currently supported in Fortran. 4312b09969d6SVaclav Hapla 4313b09969d6SVaclav Hapla Level: advanced 4314b09969d6SVaclav Hapla 4315db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()` 4316b09969d6SVaclav Hapla @*/ 43179371c9d4SSatish Balay PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved) { 43182464107aSksagiyam PetscSF sfPoint; 43192464107aSksagiyam PetscLayout layout; 432082fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 4321a47d0d45SMatthew G. Knepley 4322a47d0d45SMatthew G. Knepley PetscFunctionBegin; 432325b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 43249566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 432525b6865aSVaclav Hapla /* Get/check global number of vertices */ 432625b6865aSVaclav Hapla { 432725b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 432825b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 432925b6865aSVaclav Hapla 433025b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 433125b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 43329371c9d4SSatish Balay for (i = 0; i < len; i++) 43339371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 433425b6865aSVaclav Hapla ++NVerticesInCells; 43359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 433625b6865aSVaclav Hapla 433725b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 43389371c9d4SSatish Balay else 43399371c9d4SSatish 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); 434025b6865aSVaclav Hapla } 43419079aca8SVaclav Hapla /* Count locally unique vertices */ 43429079aca8SVaclav Hapla { 43439079aca8SVaclav Hapla PetscHSetI vhash; 43449079aca8SVaclav Hapla PetscInt off = 0; 43459079aca8SVaclav Hapla 43469566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 4347a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 434848a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 4349a47d0d45SMatthew G. Knepley } 43509566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 43519566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 4352ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 43539566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 43549566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 435563a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 4356a47d0d45SMatthew G. Knepley } 43579566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 4358a47d0d45SMatthew G. Knepley /* Create cones */ 43599566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 43609566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 43619566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 43629566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4363a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 4364a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 4365a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 4366a47d0d45SMatthew G. Knepley PetscInt lv; 4367a47d0d45SMatthew G. Knepley 43689079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 43699079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 43709566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 437163a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 4372961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 4373a47d0d45SMatthew G. Knepley } 4374a47d0d45SMatthew G. Knepley } 43752464107aSksagiyam /* Build point sf */ 43769566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 43779566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 43789566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 43799566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 43809566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 43819566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 43829566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 43839566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 43842464107aSksagiyam if (dm->sf) { 43852464107aSksagiyam const char *prefix; 43862464107aSksagiyam 43879566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 43889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 43892464107aSksagiyam } 43909566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 43919566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 43929566063dSJacob Faibussowitsch if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF")); 4393a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 43949566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 43959566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 43969566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4397a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4398a47d0d45SMatthew G. Knepley } 4399a47d0d45SMatthew G. Knepley 4400b09969d6SVaclav Hapla /*@C 4401b09969d6SVaclav Hapla DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4402b09969d6SVaclav Hapla 4403b09969d6SVaclav Hapla Input Parameters: 4404b09969d6SVaclav Hapla + dm - The DM 4405b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4406b09969d6SVaclav Hapla . sfVert - SF describing complete vertex ownership 4407b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4408b09969d6SVaclav Hapla 4409b09969d6SVaclav Hapla Level: advanced 4410b09969d6SVaclav Hapla 4411b09969d6SVaclav Hapla Notes: 4412b09969d6SVaclav Hapla Not currently supported in Fortran. 4413b09969d6SVaclav Hapla 4414db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 4415b09969d6SVaclav Hapla @*/ 44169371c9d4SSatish Balay PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) { 4417a47d0d45SMatthew G. Knepley PetscSection coordSection; 4418a47d0d45SMatthew G. Knepley Vec coordinates; 4419a47d0d45SMatthew G. Knepley PetscScalar *coords; 44201edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 4421a47d0d45SMatthew G. Knepley 4422a47d0d45SMatthew G. Knepley PetscFunctionBegin; 44239566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 44249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 44251dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 44269566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 44279566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 44281dca8a05SBarry 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); 44299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 44309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 44319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 44329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 44331edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 44349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 44359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4436a47d0d45SMatthew G. Knepley } 44379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 44389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 44399566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 44409566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 44419566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 44429566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 44439566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 44449566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 4445a47d0d45SMatthew G. Knepley { 4446a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 4447a47d0d45SMatthew G. Knepley 4448a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 44499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype)); 44509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 445121016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 445221016a8bSBarry Smith { 445321016a8bSBarry Smith PetscScalar *svertexCoords; 445421016a8bSBarry Smith PetscInt i; 44559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 44563612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 44579566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 44589566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 44599566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 446021016a8bSBarry Smith } 446121016a8bSBarry Smith #else 44629566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 44639566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 446421016a8bSBarry Smith #endif 44659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 4466a47d0d45SMatthew G. Knepley } 44679566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 44689566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 44699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 44709566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4471a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4472a47d0d45SMatthew G. Knepley } 4473a47d0d45SMatthew G. Knepley 4474c3edce3dSSatish Balay /*@ 4475b09969d6SVaclav Hapla DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output) 4476a47d0d45SMatthew G. Knepley 4477a47d0d45SMatthew G. Knepley Input Parameters: 4478a47d0d45SMatthew G. Knepley + comm - The communicator 4479a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 4480a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 448125b6865aSVaclav Hapla . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 448225b6865aSVaclav Hapla . NVertices - The global number of vertices, or PETSC_DECIDE 4483a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 4484a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 4485a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4486a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 4487a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4488a47d0d45SMatthew G. Knepley 4489d8d19677SJose E. Roman Output Parameters: 449018d54ad4SMichael Lange + dm - The DM 4491be8c289dSNicolas Barral . vertexSF - (Optional) SF describing complete vertex ownership 4492be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4493a47d0d45SMatthew G. Knepley 4494b09969d6SVaclav Hapla Notes: 4495b09969d6SVaclav Hapla This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), 4496b09969d6SVaclav Hapla DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel() 4497a47d0d45SMatthew G. Knepley 449825b6865aSVaclav Hapla See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters. 449925b6865aSVaclav Hapla See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters. 450025b6865aSVaclav Hapla 4501b09969d6SVaclav Hapla Level: intermediate 4502a47d0d45SMatthew G. Knepley 4503db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 4504a47d0d45SMatthew G. Knepley @*/ 45059371c9d4SSatish Balay 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[], PetscSF *vertexSF, PetscInt **verticesAdj, DM *dm) { 4506a47d0d45SMatthew G. Knepley PetscSF sfVert; 4507a47d0d45SMatthew G. Knepley 4508a47d0d45SMatthew G. Knepley PetscFunctionBegin; 45099566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 45109566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 4511a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 4512064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 45139566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 45149566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 4515a47d0d45SMatthew G. Knepley if (interpolate) { 45165fd9971aSMatthew G. Knepley DM idm; 4517a47d0d45SMatthew G. Knepley 45189566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 45199566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 4520a47d0d45SMatthew G. Knepley *dm = idm; 4521a47d0d45SMatthew G. Knepley } 45229566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 452318d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 45249566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 4525a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4526a47d0d45SMatthew G. Knepley } 4527a47d0d45SMatthew G. Knepley 4528b09969d6SVaclav Hapla /*@C 4529b09969d6SVaclav Hapla DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output) 45309298eaa6SMatthew G Knepley 45319298eaa6SMatthew G Knepley Input Parameters: 4532b09969d6SVaclav Hapla + dm - The DM 4533b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4534325d53feSBarry Smith . numVertices - The number of vertices owned by this process, or PETSC_DETERMINE 45359298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 45365e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 45379298eaa6SMatthew G Knepley 4538b09969d6SVaclav Hapla Level: advanced 45399298eaa6SMatthew G Knepley 4540b09969d6SVaclav Hapla Notes: 4541b09969d6SVaclav Hapla Two triangles sharing a face 45429298eaa6SMatthew G Knepley $ 45439298eaa6SMatthew G Knepley $ 2 45449298eaa6SMatthew G Knepley $ / | \ 45459298eaa6SMatthew G Knepley $ / | \ 45469298eaa6SMatthew G Knepley $ / | \ 45479298eaa6SMatthew G Knepley $ 0 0 | 1 3 45489298eaa6SMatthew G Knepley $ \ | / 45499298eaa6SMatthew G Knepley $ \ | / 45509298eaa6SMatthew G Knepley $ \ | / 45519298eaa6SMatthew G Knepley $ 1 45529298eaa6SMatthew G Knepley would have input 45539298eaa6SMatthew G Knepley $ numCells = 2, numVertices = 4 45549298eaa6SMatthew G Knepley $ cells = [0 1 2 1 3 2] 45559298eaa6SMatthew G Knepley $ 45569298eaa6SMatthew G Knepley which would result in the DMPlex 45579298eaa6SMatthew G Knepley $ 45589298eaa6SMatthew G Knepley $ 4 45599298eaa6SMatthew G Knepley $ / | \ 45609298eaa6SMatthew G Knepley $ / | \ 45619298eaa6SMatthew G Knepley $ / | \ 45629298eaa6SMatthew G Knepley $ 2 0 | 1 5 45639298eaa6SMatthew G Knepley $ \ | / 45649298eaa6SMatthew G Knepley $ \ | / 45659298eaa6SMatthew G Knepley $ \ | / 45669298eaa6SMatthew G Knepley $ 3 45679298eaa6SMatthew G Knepley 4568325d53feSBarry Smith If numVertices is PETSC_DETERMINE, it is computed by PETSc as the maximum vertex index in cells + 1. 456925b6865aSVaclav Hapla 4570b09969d6SVaclav Hapla Not currently supported in Fortran. 45719298eaa6SMatthew G Knepley 4572db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 4573b09969d6SVaclav Hapla @*/ 45749371c9d4SSatish Balay PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) { 4575961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 4576b09969d6SVaclav Hapla 4577b09969d6SVaclav Hapla PetscFunctionBegin; 45789566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 45799566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 458025b6865aSVaclav Hapla /* Get/check global number of vertices */ 458125b6865aSVaclav Hapla { 458225b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 458325b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 458425b6865aSVaclav Hapla 458525b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 458625b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 45879371c9d4SSatish Balay for (i = 0; i < len; i++) 45889371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 458925b6865aSVaclav Hapla ++NVerticesInCells; 459025b6865aSVaclav Hapla 459125b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 45929371c9d4SSatish Balay else 45939371c9d4SSatish 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); 459425b6865aSVaclav Hapla } 45959566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 459648a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 45979566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 45989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4599b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 4600ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 4601b09969d6SVaclav Hapla } 46029566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 46039566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 46049566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4605b09969d6SVaclav Hapla PetscFunctionReturn(0); 4606b09969d6SVaclav Hapla } 4607b09969d6SVaclav Hapla 4608b09969d6SVaclav Hapla /*@C 4609b09969d6SVaclav Hapla DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4610b09969d6SVaclav Hapla 4611b09969d6SVaclav Hapla Input Parameters: 4612b09969d6SVaclav Hapla + dm - The DM 4613b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4614b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4615b09969d6SVaclav Hapla 4616b09969d6SVaclav Hapla Level: advanced 4617b09969d6SVaclav Hapla 4618b09969d6SVaclav Hapla Notes: 4619b09969d6SVaclav Hapla Not currently supported in Fortran. 4620b09969d6SVaclav Hapla 4621db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 4622b09969d6SVaclav Hapla @*/ 46239371c9d4SSatish Balay PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) { 4624b09969d6SVaclav Hapla PetscSection coordSection; 4625b09969d6SVaclav Hapla Vec coordinates; 4626b09969d6SVaclav Hapla DM cdm; 4627b09969d6SVaclav Hapla PetscScalar *coords; 46281edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 4629b09969d6SVaclav Hapla 4630b09969d6SVaclav Hapla PetscFunctionBegin; 46319566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 46329566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 46331dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 46349566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 46359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 46369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 46379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 46389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 46391edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 46409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 46419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4642b09969d6SVaclav Hapla } 46439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4644b09969d6SVaclav Hapla 46459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 46469566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 46479566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 46489566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 46499566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 46501edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 4651ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 4652b09969d6SVaclav Hapla } 46539566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 46549566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 46559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 46569566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4657b09969d6SVaclav Hapla PetscFunctionReturn(0); 4658b09969d6SVaclav Hapla } 4659b09969d6SVaclav Hapla 4660b09969d6SVaclav Hapla /*@ 46613df08285SMatthew G. Knepley DMPlexCreateFromCellListPetsc - Create DMPLEX from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 46623df08285SMatthew G. Knepley 46633df08285SMatthew G. Knepley Collective on comm 4664b09969d6SVaclav Hapla 4665b09969d6SVaclav Hapla Input Parameters: 4666b09969d6SVaclav Hapla + comm - The communicator 4667b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 46683df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 46693df08285SMatthew G. Knepley . numVertices - The number of vertices owned by this process, or PETSC_DECIDE, only on process 0 46703df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 4671b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 46723df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0 4673b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 46743df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0 4675b09969d6SVaclav Hapla 4676b09969d6SVaclav Hapla Output Parameter: 46773df08285SMatthew G. Knepley . dm - The DM, which only has points on process 0 4678b09969d6SVaclav Hapla 4679b09969d6SVaclav Hapla Notes: 4680b09969d6SVaclav Hapla This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(), 4681b09969d6SVaclav Hapla DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList() 4682b09969d6SVaclav Hapla 468325b6865aSVaclav Hapla See DMPlexBuildFromCellList() for an example and details about the topology-related parameters. 468425b6865aSVaclav Hapla See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters. 46853df08285SMatthew G. Knepley See DMPlexCreateFromCellListParallelPetsc() for parallel input 468625b6865aSVaclav Hapla 4687b09969d6SVaclav Hapla Level: intermediate 4688b09969d6SVaclav Hapla 4689db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 46909298eaa6SMatthew G Knepley @*/ 46919371c9d4SSatish Balay 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) { 46923df08285SMatthew G. Knepley PetscMPIInt rank; 46939298eaa6SMatthew G Knepley 46949298eaa6SMatthew G Knepley PetscFunctionBegin; 469528b400f6SJacob 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."); 46969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 46979566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 46989566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 46999566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 4700c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 47019566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 47029298eaa6SMatthew G Knepley if (interpolate) { 47035fd9971aSMatthew G. Knepley DM idm; 47049298eaa6SMatthew G Knepley 47059566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 47069566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 47079298eaa6SMatthew G Knepley *dm = idm; 47089298eaa6SMatthew G Knepley } 4709c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 47109566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 47119298eaa6SMatthew G Knepley PetscFunctionReturn(0); 47129298eaa6SMatthew G Knepley } 47139298eaa6SMatthew G Knepley 4714939f6067SMatthew G. Knepley /*@ 4715939f6067SMatthew G. Knepley DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a DM 4716939f6067SMatthew G. Knepley 4717939f6067SMatthew G. Knepley Input Parameters: 4718c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension() 4719939f6067SMatthew G. Knepley . depth - The depth of the DAG 4720367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth 4721939f6067SMatthew G. Knepley . coneSize - The cone size of each point 4722939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 4723939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 4724367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim() 4725939f6067SMatthew G. Knepley 4726939f6067SMatthew G. Knepley Output Parameter: 4727939f6067SMatthew G. Knepley . dm - The DM 4728939f6067SMatthew G. Knepley 4729939f6067SMatthew G. Knepley Note: Two triangles sharing a face would have input 4730939f6067SMatthew G. Knepley $ depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 4731939f6067SMatthew G. Knepley $ cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 4732939f6067SMatthew G. Knepley $ vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 4733939f6067SMatthew G. Knepley $ 4734939f6067SMatthew G. Knepley which would result in the DMPlex 4735939f6067SMatthew G. Knepley $ 4736939f6067SMatthew G. Knepley $ 4 4737939f6067SMatthew G. Knepley $ / | \ 4738939f6067SMatthew G. Knepley $ / | \ 4739939f6067SMatthew G. Knepley $ / | \ 4740939f6067SMatthew G. Knepley $ 2 0 | 1 5 4741939f6067SMatthew G. Knepley $ \ | / 4742939f6067SMatthew G. Knepley $ \ | / 4743939f6067SMatthew G. Knepley $ \ | / 4744939f6067SMatthew G. Knepley $ 3 4745939f6067SMatthew G. Knepley $ 4746a4a685f2SJacob Faibussowitsch $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc() 4747939f6067SMatthew G. Knepley 4748939f6067SMatthew G. Knepley Level: advanced 4749939f6067SMatthew G. Knepley 4750db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 4751939f6067SMatthew G. Knepley @*/ 47529371c9d4SSatish Balay PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) { 47539298eaa6SMatthew G Knepley Vec coordinates; 47549298eaa6SMatthew G Knepley PetscSection coordSection; 47559298eaa6SMatthew G Knepley PetscScalar *coords; 4756811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 47579298eaa6SMatthew G Knepley 47589298eaa6SMatthew G Knepley PetscFunctionBegin; 47599566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 47609566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 476163a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 47629298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 47639566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 47649298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 47659566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 4766ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 476797e052ccSToby Isaac } 47681dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 47699566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 47709298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 47719566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 47729566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 47739298eaa6SMatthew G Knepley } 47749566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 47759566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 47769298eaa6SMatthew G Knepley /* Build coordinates */ 47779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 47789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 47799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 47809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 47819298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 47829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 47839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 47849298eaa6SMatthew G Knepley } 47859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 47869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 47879566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 47889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 47899566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 47909566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dimEmbed)); 47919566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 47929318fe57SMatthew G. Knepley if (vertexCoords) { 47939566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 47949298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 47959298eaa6SMatthew G Knepley PetscInt off; 47969298eaa6SMatthew G Knepley 47979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 4798ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 47999298eaa6SMatthew G Knepley } 48009318fe57SMatthew G. Knepley } 48019566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 48029566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 48039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 48049298eaa6SMatthew G Knepley PetscFunctionReturn(0); 48059298eaa6SMatthew G Knepley } 48068415267dSToby Isaac 4807ca522641SMatthew G. Knepley /*@C 48088ca92349SMatthew G. Knepley DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file. 48098ca92349SMatthew G. Knepley 48108ca92349SMatthew G. Knepley + comm - The MPI communicator 48118ca92349SMatthew G. Knepley . filename - Name of the .dat file 48128ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 48138ca92349SMatthew G. Knepley 48148ca92349SMatthew G. Knepley Output Parameter: 48158ca92349SMatthew G. Knepley . dm - The DM object representing the mesh 48168ca92349SMatthew G. Knepley 48178ca92349SMatthew G. Knepley Note: The format is the simplest possible: 48188ca92349SMatthew G. Knepley $ Ne 48198ca92349SMatthew G. Knepley $ v0 v1 ... vk 48208ca92349SMatthew G. Knepley $ Nv 48218ca92349SMatthew G. Knepley $ x y z marker 48228ca92349SMatthew G. Knepley 48238ca92349SMatthew G. Knepley Level: beginner 48248ca92349SMatthew G. Knepley 4825db781477SPatrick Sanan .seealso: `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 48268ca92349SMatthew G. Knepley @*/ 48279371c9d4SSatish Balay PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) { 48288ca92349SMatthew G. Knepley DMLabel marker; 48298ca92349SMatthew G. Knepley PetscViewer viewer; 48308ca92349SMatthew G. Knepley Vec coordinates; 48318ca92349SMatthew G. Knepley PetscSection coordSection; 48328ca92349SMatthew G. Knepley PetscScalar *coords; 48338ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 48348ca92349SMatthew G. Knepley PetscInt dim = 3, cdim = 3, coordSize, v, c, d; 48358ca92349SMatthew G. Knepley PetscMPIInt rank; 4836f8d5e320SMatthew G. Knepley int snum, Nv, Nc, Ncn, Nl; 48378ca92349SMatthew G. Knepley 48388ca92349SMatthew G. Knepley PetscFunctionBegin; 48399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 48409566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 48419566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 48429566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 48439566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 4844dd400576SPatrick Sanan if (rank == 0) { 48459566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING)); 4846f8d5e320SMatthew G. Knepley snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl); 484708401ef6SPierre Jolivet PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 484825ce1634SJed Brown } else { 4849f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 48508ca92349SMatthew G. Knepley } 48519566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 48529566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 48539566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 48549566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 48559566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 48568ca92349SMatthew G. Knepley /* Read topology */ 4857dd400576SPatrick Sanan if (rank == 0) { 4858f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 4859f8d5e320SMatthew G. Knepley PetscInt cone[8]; 48608ca92349SMatthew G. Knepley int vbuf[8], v; 48618ca92349SMatthew G. Knepley 48629371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 48639371c9d4SSatish Balay format[c * 3 + 0] = '%'; 48649371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 48659371c9d4SSatish Balay format[c * 3 + 2] = ' '; 48669371c9d4SSatish Balay } 4867f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 48689566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 48699566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 48708ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 48719566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 4872f8d5e320SMatthew G. Knepley switch (Ncn) { 4873f8d5e320SMatthew G. Knepley case 2: snum = sscanf(line, format, &vbuf[0], &vbuf[1]); break; 4874f8d5e320SMatthew G. Knepley case 3: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); break; 4875f8d5e320SMatthew G. Knepley case 4: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); break; 4876f8d5e320SMatthew G. Knepley case 6: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); break; 4877f8d5e320SMatthew G. Knepley case 8: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); break; 487863a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 4879f8d5e320SMatthew G. Knepley } 488008401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 4881f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 48828ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 4883f8d5e320SMatthew G. Knepley if (Ncn == 8) { 48848ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 48858ca92349SMatthew G. Knepley cone[1] = cone[3]; 48868ca92349SMatthew G. Knepley cone[3] = tmp; 48878ca92349SMatthew G. Knepley } 48889566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 48898ca92349SMatthew G. Knepley } 48908ca92349SMatthew G. Knepley } 48919566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 48929566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 48938ca92349SMatthew G. Knepley /* Read coordinates */ 48949566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 48959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 48969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 48979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 48988ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 48999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 49009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 49018ca92349SMatthew G. Knepley } 49029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 49039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 49049566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 49059566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 49069566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 49079566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 49089566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 49099566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 4910dd400576SPatrick Sanan if (rank == 0) { 4911f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 49128ca92349SMatthew G. Knepley double x[3]; 4913f8d5e320SMatthew G. Knepley int l, val[3]; 49148ca92349SMatthew G. Knepley 4915f8d5e320SMatthew G. Knepley if (Nl) { 49169371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 49179371c9d4SSatish Balay format[l * 3 + 0] = '%'; 49189371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 49199371c9d4SSatish Balay format[l * 3 + 2] = ' '; 49209371c9d4SSatish Balay } 4921f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 49229566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 49239566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 4924f8d5e320SMatthew G. Knepley } 49258ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 49269566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 4927f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 492808401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 4929f8d5e320SMatthew G. Knepley switch (Nl) { 4930f8d5e320SMatthew G. Knepley case 0: snum = 0; break; 4931f8d5e320SMatthew G. Knepley case 1: snum = sscanf(line, format, &val[0]); break; 4932f8d5e320SMatthew G. Knepley case 2: snum = sscanf(line, format, &val[0], &val[1]); break; 4933f8d5e320SMatthew G. Knepley case 3: snum = sscanf(line, format, &val[0], &val[1], &val[2]); break; 493463a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 4935f8d5e320SMatthew G. Knepley } 493608401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 49378ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 49389566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 49398ca92349SMatthew G. Knepley } 49408ca92349SMatthew G. Knepley } 49419566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 49429566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 49439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 49449566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 49458ca92349SMatthew G. Knepley if (interpolate) { 49468ca92349SMatthew G. Knepley DM idm; 49478ca92349SMatthew G. Knepley DMLabel bdlabel; 49488ca92349SMatthew G. Knepley 49499566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 49509566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 49518ca92349SMatthew G. Knepley *dm = idm; 49528ca92349SMatthew G. Knepley 4953f8d5e320SMatthew G. Knepley if (!Nl) { 49549566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 49559566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 49569566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 49579566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 49588ca92349SMatthew G. Knepley } 4959f8d5e320SMatthew G. Knepley } 49608ca92349SMatthew G. Knepley PetscFunctionReturn(0); 49618ca92349SMatthew G. Knepley } 49628ca92349SMatthew G. Knepley 49638ca92349SMatthew G. Knepley /*@C 4964ca522641SMatthew G. Knepley DMPlexCreateFromFile - This takes a filename and produces a DM 4965ca522641SMatthew G. Knepley 4966ca522641SMatthew G. Knepley Input Parameters: 4967ca522641SMatthew G. Knepley + comm - The communicator 4968ca522641SMatthew G. Knepley . filename - A file name 4969cd7e8a5eSksagiyam . plexname - The object name of the resulting DM, also used for intra-datafile lookup by some formats 4970ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 4971ca522641SMatthew G. Knepley 4972ca522641SMatthew G. Knepley Output Parameter: 4973ca522641SMatthew G. Knepley . dm - The DM 4974ca522641SMatthew G. Knepley 497502ef0d99SVaclav Hapla Options Database Keys: 497602ef0d99SVaclav Hapla . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5 497702ef0d99SVaclav Hapla 4978bca97951SVaclav Hapla Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g. 4979bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 4980bca97951SVaclav Hapla 4981cd7e8a5eSksagiyam Notes: 4982cd7e8a5eSksagiyam Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex 4983cd7e8a5eSksagiyam meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName() 4984cd7e8a5eSksagiyam before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object. 4985cd7e8a5eSksagiyam The input parameter name is thus used to name the DMPlex object when DMPlexCreateFromFile() internally 4986cd7e8a5eSksagiyam calls DMLoad(). Currently, name is ignored for other viewer types and/or formats. 4987cd7e8a5eSksagiyam 4988ca522641SMatthew G. Knepley Level: beginner 4989ca522641SMatthew G. Knepley 4990db781477SPatrick Sanan .seealso: `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 4991ca522641SMatthew G. Knepley @*/ 49929371c9d4SSatish Balay PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) { 4993ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 4994ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 4995ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 4996ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 4997ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 4998ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 4999ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 5000ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 5001ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 5002ef3a5affSJacob Faibussowitsch const char extMed[] = ".med"; 5003ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 5004ef3a5affSJacob Faibussowitsch const char extEGADSLite[] = ".egadslite"; 5005ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 5006ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 5007ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 5008ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 5009ca522641SMatthew G. Knepley size_t len; 5010c1cad2e7SMatthew G. Knepley PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV; 5011ca522641SMatthew G. Knepley PetscMPIInt rank; 5012ca522641SMatthew G. Knepley 5013ca522641SMatthew G. Knepley PetscFunctionBegin; 50145d80c0bfSVaclav Hapla PetscValidCharPointer(filename, 2); 50150d862eaeSPierre Jolivet if (plexname) PetscValidCharPointer(plexname, 3); 5016cd7e8a5eSksagiyam PetscValidPointer(dm, 5); 50179566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 50189566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 50199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 50209566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 502128b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 5022ef3a5affSJacob Faibussowitsch 50239371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 50249371c9d4SSatish Balay do { \ 5025274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 5026274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 5027274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 5028274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 5029ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 5030ef3a5affSJacob Faibussowitsch } else { \ 5031274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 5032ef3a5affSJacob Faibussowitsch } \ 5033ef3a5affSJacob Faibussowitsch } while (0) 5034ef3a5affSJacob Faibussowitsch 5035ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 5036ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 5037ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 5038ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 5039ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 5040ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 5041ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 5042ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 5043ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 5044ef3a5affSJacob Faibussowitsch CheckExtension(extMed, isMed); 5045ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 5046ef3a5affSJacob Faibussowitsch CheckExtension(extEGADSLite, isEGADSLite); 5047ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 5048ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 5049ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 5050ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 5051ef3a5affSJacob Faibussowitsch 5052ef3a5affSJacob Faibussowitsch #undef CheckExtension 5053ef3a5affSJacob Faibussowitsch 5054de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 50559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 5056ca522641SMatthew G. Knepley } else if (isCGNS) { 50579566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 505890c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 50599566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 50602f0bd6dcSMichael Lange } else if (isFluent) { 50619566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 5062cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 50639c48423bSVaclav Hapla PetscBool load_hdf5_xdmf = PETSC_FALSE; 5064cc2f8f65SMatthew G. Knepley PetscViewer viewer; 5065cc2f8f65SMatthew G. Knepley 506643b242b4SVaclav 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 */ 50679566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf)); 50689566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL)); 50699566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 50709566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 50719566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 50729566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 50739566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 50749566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 5075cd7e8a5eSksagiyam 50769566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 50779566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 50789566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 50799566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 50809566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 50819566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer)); 50829566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 50835fd9971aSMatthew G. Knepley 50845fd9971aSMatthew G. Knepley if (interpolate) { 50855fd9971aSMatthew G. Knepley DM idm; 50865fd9971aSMatthew G. Knepley 50879566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 50889566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 50895fd9971aSMatthew G. Knepley *dm = idm; 50905fd9971aSMatthew G. Knepley } 5091707dd687SMichael Lange } else if (isMed) { 50929566063dSJacob Faibussowitsch PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm)); 5093f2801cd6SMatthew G. Knepley } else if (isPLY) { 50949566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 5095c1cad2e7SMatthew G. Knepley } else if (isEGADSLite || isEGADS || isIGES || isSTEP) { 50969566063dSJacob Faibussowitsch if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm)); 50979566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm)); 50987bee2925SMatthew Knepley if (!interpolate) { 50997bee2925SMatthew Knepley DM udm; 51007bee2925SMatthew Knepley 51019566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 51029566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 51037bee2925SMatthew Knepley *dm = udm; 51047bee2925SMatthew Knepley } 51058ca92349SMatthew G. Knepley } else if (isCV) { 51069566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 510798921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 51089566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 51099566063dSJacob Faibussowitsch if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 51109566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 5111ca522641SMatthew G. Knepley PetscFunctionReturn(0); 5112ca522641SMatthew G. Knepley } 5113