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 */ 39*69d8a87bSksagiyam 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)); 166*69d8a87bSksagiyam 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)); 4079371c9d4SSatish Balay 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)); 5329371c9d4SSatish Balay 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)); 751fdbf62faSLisandro Dalcin for (i = 0; i < numCells; ++i) { coneSize[i] = 2; } 752fdbf62faSLisandro Dalcin 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 } 757fdbf62faSLisandro Dalcin 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)); 796*69d8a87bSksagiyam 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)); 8869371c9d4SSatish Balay for (c = 0; c < numCells; c++) { PetscCall(DMPlexSetConeSize(dm, c, 6)); } 8879371c9d4SSatish Balay for (f = firstXFace; f < firstXFace + numFaces; ++f) { PetscCall(DMPlexSetConeSize(dm, f, 4)); } 8889371c9d4SSatish Balay 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; 12139371c9d4SSatish Balay 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)); 1263*69d8a87bSksagiyam 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)); 1353*69d8a87bSksagiyam 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)); 1406*69d8a87bSksagiyam 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 } 19239371c9d4SSatish Balay 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)); 20869371c9d4SSatish Balay 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) { 21099371c9d4SSatish Balay 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)); 21559371c9d4SSatish Balay for (c = 0; c < numCells; c++) { PetscCall(DMPlexSetConeSize(dm, c, 4)); } 21569371c9d4SSatish Balay 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)); 23949371c9d4SSatish Balay 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) 24699371c9d4SSatish Balay 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]; 25029371c9d4SSatish Balay 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) { 25089371c9d4SSatish Balay 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])); 25819371c9d4SSatish Balay 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++) { 30249371c9d4SSatish Balay 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)); 3080*69d8a87bSksagiyam 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)); 3105*69d8a87bSksagiyam 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)); 3117*69d8a87bSksagiyam 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)); 31229371c9d4SSatish Balay 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 } 3164*69d8a87bSksagiyam 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)); 3256*69d8a87bSksagiyam 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 347205bd46c0SStefano Zampini const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 34739318fe57SMatthew G. Knepley 34749371c9d4SSatish Balay static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm) { 34759318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 34769318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 34779318fe57SMatthew G. Knepley PetscInt dim = 2; 34789318fe57SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 3479cd7e8a5eSksagiyam PetscBool flg, flg2, fflg, bdfflg, nameflg; 34809318fe57SMatthew G. Knepley MPI_Comm comm; 3481ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3482ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3483ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 34849318fe57SMatthew G. Knepley 34859318fe57SMatthew G. Knepley PetscFunctionBegin; 34869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 34879318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 34889566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 34899566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 34909566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 34919566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 34929566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 34939566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 34949566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 349563a3b9bcSJacob Faibussowitsch PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim); 34969566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 34979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 34989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 34999566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 35009566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 35019318fe57SMatthew G. Knepley 350261a622f3SMatthew G. Knepley switch (cell) { 350361a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 350461a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 350561a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 350661a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 350761a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 350861a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 35099371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: *useCoordSpace = PETSC_TRUE; break; 351061a622f3SMatthew G. Knepley default: *useCoordSpace = PETSC_FALSE; break; 351161a622f3SMatthew G. Knepley } 351261a622f3SMatthew G. Knepley 35139318fe57SMatthew G. Knepley if (fflg) { 35149318fe57SMatthew G. Knepley DM dmnew; 35159318fe57SMatthew G. Knepley 35169566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew)); 35175de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 3518*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 35199318fe57SMatthew G. Knepley } else if (refDomain) { 35209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 35219318fe57SMatthew G. Knepley } else if (bdfflg) { 35229318fe57SMatthew G. Knepley DM bdm, dmnew; 35239318fe57SMatthew G. Knepley 35249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm)); 35259566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 35269566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 35279566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 35289566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 35295de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 3530*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 35319318fe57SMatthew G. Knepley } else { 35329566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 35339318fe57SMatthew G. Knepley switch (shape) { 35349371c9d4SSatish Balay case DM_SHAPE_BOX: { 35359318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 35369318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 35379318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 35389318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 35399318fe57SMatthew G. Knepley PetscInt i, n; 35409318fe57SMatthew G. Knepley 35419318fe57SMatthew G. Knepley n = dim; 35429318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 35439566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 35449318fe57SMatthew G. Knepley n = 3; 35459566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 354663a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 35479318fe57SMatthew G. Knepley n = 3; 35489566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 354963a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 35509318fe57SMatthew G. Knepley n = 3; 35519566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 355263a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 35539318fe57SMatthew G. Knepley switch (cell) { 355461a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 35559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 3556d410b0cfSMatthew G. Knepley if (!interpolate) { 3557d410b0cfSMatthew G. Knepley DM udm; 3558d410b0cfSMatthew G. Knepley 35599566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 3560*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3561d410b0cfSMatthew G. Knepley } 35629318fe57SMatthew G. Knepley break; 35639371c9d4SSatish Balay default: PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate)); break; 35649318fe57SMatthew G. Knepley } 35659371c9d4SSatish Balay } break; 35669371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 35679318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 35689318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 35699318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 35709318fe57SMatthew G. Knepley PetscInt i, n; 35719318fe57SMatthew G. Knepley 35729318fe57SMatthew G. Knepley n = dim + 1; 35739318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 35749566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 35759318fe57SMatthew G. Knepley n = 3; 35769566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 357763a3b9bcSJacob 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); 35789318fe57SMatthew G. Knepley n = 3; 35799566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 358063a3b9bcSJacob 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); 35819566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 35829371c9d4SSatish Balay } break; 35839371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 35849318fe57SMatthew G. Knepley PetscReal R = 1.0; 35859318fe57SMatthew G. Knepley 35869566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 35879566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 35889371c9d4SSatish Balay } break; 35899371c9d4SSatish Balay case DM_SHAPE_BALL: { 35909318fe57SMatthew G. Knepley PetscReal R = 1.0; 35919318fe57SMatthew G. Knepley 35929566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 35939566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 35949371c9d4SSatish Balay } break; 35959371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 35969318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 35979318fe57SMatthew G. Knepley PetscInt Nw = 6; 35989318fe57SMatthew G. Knepley 35999566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 36009566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 36019318fe57SMatthew G. Knepley switch (cell) { 36029371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); break; 36039371c9d4SSatish Balay default: PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt)); break; 36049318fe57SMatthew G. Knepley } 36059371c9d4SSatish Balay } break; 3606b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 36079371c9d4SSatish Balay case DM_SHAPE_GYROID: { 3608b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 3609b7f5c055SJed Brown PetscReal thickness = 0.; 3610b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3611b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 36121436d7faSJed Brown PetscBool tps_distribute; 36139566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 36149566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 36159566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 36169566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 36179566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 36189566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 36199566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 36209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 36219371c9d4SSatish Balay } break; 36229371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 362305bd46c0SStefano Zampini DM dmnew; 362405bd46c0SStefano Zampini PetscReal rl = 0.0; 362505bd46c0SStefano Zampini 362605bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 362705bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 36285de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 3629*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 36309371c9d4SSatish Balay } break; 363198921bdaSJacob Faibussowitsch default: SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 36329318fe57SMatthew G. Knepley } 36339318fe57SMatthew G. Knepley } 36349566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 36359371c9d4SSatish Balay if (!((PetscObject)dm)->name && nameflg) { PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); } 36360a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 36370a6ba040SMatthew G. Knepley } 36380a6ba040SMatthew G. Knepley 36399371c9d4SSatish Balay PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject) { 36400a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 36417f9d8d6cSVaclav Hapla PetscBool flg, flg2; 36429318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 36430a6ba040SMatthew G. Knepley 36440a6ba040SMatthew G. Knepley PetscFunctionBegin; 36450a6ba040SMatthew G. Knepley /* Handle viewing */ 36469566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 36479566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 36489566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 36499566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 3650f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 36519566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 36529566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 36539318fe57SMatthew G. Knepley /* Labeling */ 36549566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 36559566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 3656953fc75cSMatthew G. Knepley /* Point Location */ 36579566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 36580848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 36599566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 36602e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 36619566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 3662b29cfa1cSToby Isaac /* Projection behavior */ 36639566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maxmimum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 36649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 3665f12cf164SMatthew G. Knepley /* Checking structure */ 3666f12cf164SMatthew G. Knepley { 36677f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 3668f12cf164SMatthew G. Knepley 36697f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 36707f9d8d6cSVaclav Hapla if (all) { 36717f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 36727f9d8d6cSVaclav Hapla } else { 36739566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 36747f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 36759566063dSJacob 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)); 36767f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 36779566063dSJacob 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)); 36787f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 36799566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 36807f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 36819566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 36827f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL)); 36839566063dSJacob 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)); 36847f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 36857f9d8d6cSVaclav Hapla } 36869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 36879566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 3688f12cf164SMatthew G. Knepley } 36899318fe57SMatthew G. Knepley { 36909318fe57SMatthew G. Knepley PetscReal scale = 1.0; 36914f3833eaSMatthew G. Knepley 36929566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 36939318fe57SMatthew G. Knepley if (flg) { 36949318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 36959318fe57SMatthew G. Knepley 36969566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 36979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 36989566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 36999566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 37009318fe57SMatthew G. Knepley } 37019318fe57SMatthew G. Knepley } 37029566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 370368d4fef7SMatthew G. Knepley PetscFunctionReturn(0); 370468d4fef7SMatthew G. Knepley } 370568d4fef7SMatthew G. Knepley 37069371c9d4SSatish Balay PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap) { 3707c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 3708c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 3709c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 3710c506a872SMatthew G. Knepley PetscBool flg; 3711c506a872SMatthew G. Knepley 3712c506a872SMatthew G. Knepley PetscFunctionBegin; 3713c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 3714c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 3715c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 3716c506a872SMatthew G. Knepley if (numOvLabels) { 3717c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 3718c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 3719c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 3720c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 3721c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 3722c506a872SMatthew G. Knepley } 3723c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 3724c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 3725c506a872SMatthew 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); 3726c506a872SMatthew G. Knepley 3727c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 3728c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 3729c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 3730c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 3731c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 3732c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 3733c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 3734c506a872SMatthew G. Knepley } 3735c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 3736c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 3737c506a872SMatthew 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); 3738c506a872SMatthew G. Knepley } 3739c506a872SMatthew G. Knepley PetscFunctionReturn(0); 3740c506a872SMatthew G. Knepley } 3741c506a872SMatthew G. Knepley 37429371c9d4SSatish Balay static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject) { 3743bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 3744bdf63967SMatthew G. Knepley char oname[256]; 3745d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 37469318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 3747e600fa54SMatthew 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; 37486bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 374968d4fef7SMatthew G. Knepley 375068d4fef7SMatthew G. Knepley PetscFunctionBegin; 3751d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 37529318fe57SMatthew G. Knepley /* Handle automatic creation */ 37539566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 37546bc1bd01Sksagiyam if (dim < 0) { 37556bc1bd01Sksagiyam PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 37566bc1bd01Sksagiyam created = PETSC_TRUE; 37576bc1bd01Sksagiyam } 37586bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 3759d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 37609566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 3761d89e6e46SMatthew G. Knepley if (flg) { 3762d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 3763d89e6e46SMatthew G. Knepley 37649566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 3765d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 3766d89e6e46SMatthew G. Knepley DM udm; 3767d89e6e46SMatthew G. Knepley 37689566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 3769*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3770d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 3771d89e6e46SMatthew G. Knepley DM idm; 3772d89e6e46SMatthew G. Knepley 37739566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 3774*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3775d89e6e46SMatthew G. Knepley } 3776d89e6e46SMatthew G. Knepley } 37779b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 37789566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg)); 3779c1cad2e7SMatthew G. Knepley if (flg) { ((DM_Plex *)dm->data)->ignoreModel = ignoreModel; } 37809566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 37819566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 37829566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 37839566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 37849566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 37859566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 37869318fe57SMatthew G. Knepley if (flg) { 37879566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 37889566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 37899318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 37909318fe57SMatthew G. Knepley } 37919b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 37929b44eab4SMatthew G. Knepley DM rdm; 37939b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 37949b44eab4SMatthew G. Knepley 3795dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 37969566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 3797*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 3798dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 379961a622f3SMatthew G. Knepley if (coordFunc && remap) { 38009566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 38019b44eab4SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 38029b44eab4SMatthew G. Knepley } 38039b44eab4SMatthew G. Knepley } 38049566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 38059318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 38069566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 38079318fe57SMatthew G. Knepley if (extLayers) { 38089318fe57SMatthew G. Knepley DM edm; 38099318fe57SMatthew G. Knepley 38109566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 3811*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 381248d16a33SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = NULL; 3813dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3814d410b0cfSMatthew G. Knepley extLayers = 0; 38159318fe57SMatthew G. Knepley } 3816bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 38176bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 38189566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 38196bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 38209566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 38216bc1bd01Sksagiyam if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) { 3822bdf63967SMatthew G. Knepley DM pdm; 3823bdf63967SMatthew G. Knepley IS perm; 3824bdf63967SMatthew G. Knepley 38259566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 38269566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 38279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 3828*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 3829dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3830bdf63967SMatthew G. Knepley } 38319b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 38329566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 3833c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 3834dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 38359b44eab4SMatthew G. Knepley if (distribute) { 38369b44eab4SMatthew G. Knepley DM pdm = NULL; 38379b44eab4SMatthew G. Knepley PetscPartitioner part; 38389b44eab4SMatthew G. Knepley 38399566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 38409566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 38419566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm)); 3842*69d8a87bSksagiyam if (pdm) { PetscCall(DMPlexReplace_Internal(dm, &pdm)); } 38439b44eab4SMatthew G. Knepley } 38449318fe57SMatthew G. Knepley /* Create coordinate space */ 38459318fe57SMatthew G. Knepley if (created) { 384661a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 38479318fe57SMatthew G. Knepley PetscInt degree = 1; 38486858538eSMatthew G. Knepley PetscBool flg; 38499318fe57SMatthew G. Knepley 38509566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg)); 38519566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 38529566063dSJacob Faibussowitsch if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc)); 385361a622f3SMatthew G. Knepley if (flg && !coordSpace) { 385461a622f3SMatthew G. Knepley DM cdm; 385561a622f3SMatthew G. Knepley PetscDS cds; 385661a622f3SMatthew G. Knepley PetscObject obj; 385761a622f3SMatthew G. Knepley PetscClassId id; 385861a622f3SMatthew G. Knepley 38599566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 38609566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 38619566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 38629566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 386361a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 386461a622f3SMatthew G. Knepley PetscContainer dummy; 386561a622f3SMatthew G. Knepley 38669566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 38679566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 38689566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 38699566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 38709566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 387161a622f3SMatthew G. Knepley } 387261a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 387361a622f3SMatthew G. Knepley } 38746858538eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg)); 38759566063dSJacob Faibussowitsch PetscCall(DMLocalizeCoordinates(dm)); 38769318fe57SMatthew G. Knepley } 387768d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 387861a622f3SMatthew G. Knepley remap = PETSC_TRUE; 38799566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 38809566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 38819566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 38829566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 388368d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 3884acdc6f61SToby Isaac DM *dms, coarseDM; 388568d4fef7SMatthew G. Knepley 38869566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 38879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 38889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 38899566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 389068d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 38919566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 389268d4fef7SMatthew G. Knepley if (refine == 1) { 38939566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 38949566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 389568d4fef7SMatthew G. Knepley } else { 38969566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 38979566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 38989566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 38999566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 390068d4fef7SMatthew G. Knepley } 39019566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 39029566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 390368d4fef7SMatthew G. Knepley /* Free DMs */ 390468d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 3905dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 39069566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 390768d4fef7SMatthew G. Knepley } 39089566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 390968d4fef7SMatthew G. Knepley } else { 391068d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 39119318fe57SMatthew G. Knepley DM rdm; 391251a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 391368d4fef7SMatthew G. Knepley 3914dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 39159566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 391668d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 3917*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 3918dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 391961a622f3SMatthew G. Knepley if (coordFunc && remap) { 39209566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 392151a74b61SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 392251a74b61SMatthew G. Knepley } 392368d4fef7SMatthew G. Knepley } 392468d4fef7SMatthew G. Knepley } 39253cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 39269566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 39279566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 3928b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 3929b653a561SMatthew G. Knepley DM *dms; 3930b653a561SMatthew G. Knepley 39319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 39329566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 3933b653a561SMatthew G. Knepley /* Free DMs */ 3934b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 3935dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 39369566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 3937b653a561SMatthew G. Knepley } 39389566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 3939b653a561SMatthew G. Knepley } else { 3940b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 39419318fe57SMatthew G. Knepley DM cdm; 39429318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 39433cf6fe12SMatthew G. Knepley 3944dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 39459566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 39463cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 3947*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 3948dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 39499318fe57SMatthew G. Knepley if (coordFunc) { 39509566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 39519318fe57SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 39529318fe57SMatthew G. Knepley } 39533cf6fe12SMatthew G. Knepley } 3954b653a561SMatthew G. Knepley } 3955909dfd52SMatthew G. Knepley /* Handle ghost cells */ 39569566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 3957909dfd52SMatthew G. Knepley if (ghostCells) { 3958909dfd52SMatthew G. Knepley DM gdm; 3959909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 3960909dfd52SMatthew G. Knepley 3961909dfd52SMatthew G. Knepley lname[0] = '\0'; 39629566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 39639566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 3964*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 3965909dfd52SMatthew G. Knepley } 39666913077dSMatthew G. Knepley /* Handle 1D order */ 39676bc1bd01Sksagiyam if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) { 39686913077dSMatthew G. Knepley DM cdm, rdm; 39696913077dSMatthew G. Knepley PetscDS cds; 39706913077dSMatthew G. Knepley PetscObject obj; 39716913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 39726913077dSMatthew G. Knepley IS perm; 39736bc1bd01Sksagiyam PetscInt Nf; 39746913077dSMatthew G. Knepley PetscBool distributed; 39756913077dSMatthew G. Knepley 39769566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 39779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 39789566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 39799566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 39806913077dSMatthew G. Knepley if (Nf) { 39819566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 39829566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 39836913077dSMatthew G. Knepley } 39846bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 39859566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 39869566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 3987*69d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 39889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 39896913077dSMatthew G. Knepley } 39906913077dSMatthew G. Knepley } 39913cf6fe12SMatthew G. Knepley /* Handle */ 3992dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3993d0609cedSBarry Smith PetscOptionsHeadEnd(); 39940a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 39950a6ba040SMatthew G. Knepley } 39960a6ba040SMatthew G. Knepley 39979371c9d4SSatish Balay static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) { 3998552f7358SJed Brown PetscFunctionBegin; 39999566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 40009566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 40019566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 40029566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 40039566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 40049566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 4005552f7358SJed Brown PetscFunctionReturn(0); 4006552f7358SJed Brown } 4007552f7358SJed Brown 40089371c9d4SSatish Balay static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) { 4009552f7358SJed Brown PetscFunctionBegin; 40109566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 40119566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 40129566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 4013552f7358SJed Brown PetscFunctionReturn(0); 4014552f7358SJed Brown } 4015552f7358SJed Brown 40169371c9d4SSatish Balay static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) { 4017793f3fe5SMatthew G. Knepley PetscInt depth, d; 4018793f3fe5SMatthew G. Knepley 4019793f3fe5SMatthew G. Knepley PetscFunctionBegin; 40209566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4021793f3fe5SMatthew G. Knepley if (depth == 1) { 40229566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 40239566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 40249566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 40259371c9d4SSatish Balay else { 40269371c9d4SSatish Balay *pStart = 0; 40279371c9d4SSatish Balay *pEnd = 0; 40289371c9d4SSatish Balay } 4029793f3fe5SMatthew G. Knepley } else { 40309566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 4031793f3fe5SMatthew G. Knepley } 4032793f3fe5SMatthew G. Knepley PetscFunctionReturn(0); 4033793f3fe5SMatthew G. Knepley } 4034793f3fe5SMatthew G. Knepley 40359371c9d4SSatish Balay static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) { 4036502a2867SDave May PetscSF sf; 40370a19bb7dSprj- PetscInt niranks, njranks, n; 40380a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 40390a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 4040502a2867SDave May 40412f356facSMatthew G. Knepley PetscFunctionBegin; 40429566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 40430a19bb7dSprj- if (!data->neighbors) { 40449566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 40459566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 40469566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 40479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 40489566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 40499566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 40500a19bb7dSprj- n = njranks + niranks; 40519566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 40520a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 40539566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 40540a19bb7dSprj- } 40550a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 40560a19bb7dSprj- if (ranks) { 40570a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 40580a19bb7dSprj- else *ranks = NULL; 40590a19bb7dSprj- } 4060502a2867SDave May PetscFunctionReturn(0); 4061502a2867SDave May } 4062502a2867SDave May 40631eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 40641eb70e55SToby Isaac 40659371c9d4SSatish Balay static PetscErrorCode DMInitialize_Plex(DM dm) { 4066552f7358SJed Brown PetscFunctionBegin; 4067552f7358SJed Brown dm->ops->view = DMView_Plex; 40682c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 4069552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 407038221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 4071552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 40721bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 407366ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 4074552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 4075552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 4076184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 40770298fd71SBarry Smith dm->ops->createfieldis = NULL; 4078552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 4079f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 40800a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 4081552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 4082bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 4083bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 4084b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 40855a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 4086552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 40870a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 40880a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 4089b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 4090d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 40910298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 40920298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 40930298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 40940298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 4095552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 4096552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 40972adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 4098793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 4099552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 41000709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 41010709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 4102bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 41038c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 4104ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 41050709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 4106b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 41072a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 410828d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 41099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 41109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 41119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 41129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 41139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 41149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 41159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 41166bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 41176bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 41189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 4119c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 4120c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 4121552f7358SJed Brown PetscFunctionReturn(0); 4122552f7358SJed Brown } 4123552f7358SJed Brown 41249371c9d4SSatish Balay PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) { 412563a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 412663a16f15SMatthew G. Knepley 412763a16f15SMatthew G. Knepley PetscFunctionBegin; 412863a16f15SMatthew G. Knepley mesh->refct++; 412963a16f15SMatthew G. Knepley (*newdm)->data = mesh; 41309566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 41319566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 413263a16f15SMatthew G. Knepley PetscFunctionReturn(0); 413363a16f15SMatthew G. Knepley } 413463a16f15SMatthew G. Knepley 41358818961aSMatthew G Knepley /*MC 41368818961aSMatthew G Knepley DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 41378818961aSMatthew G Knepley In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is 41388818961aSMatthew G Knepley specified by a PetscSection object. Ownership in the global representation is determined by 41398818961aSMatthew G Knepley ownership of the underlying DMPlex points. This is specified by another PetscSection object. 41408818961aSMatthew G Knepley 4141e5893cccSMatthew G. Knepley Options Database Keys: 4142250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 4143250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 4144250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 4145250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 4146250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 4147250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 4148250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 4149ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 4150f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 4151f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 4152f12cf164SMatthew G. Knepley . -dm_plex_max_projection_height - Maxmimum mesh point height used to project locally 4153f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 4154250712c9SMatthew G. Knepley . -dm_plex_check_all - Perform all shecks below 4155f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 4156f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 4157f12cf164SMatthew 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 4158f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 4159f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 4160e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 4161e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 4162e5893cccSMatthew G. Knepley 41638818961aSMatthew G Knepley Level: intermediate 41648818961aSMatthew G Knepley 4165db781477SPatrick Sanan .seealso: `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()` 41668818961aSMatthew G Knepley M*/ 41678818961aSMatthew G Knepley 41689371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) { 4169552f7358SJed Brown DM_Plex *mesh; 4170412e9a14SMatthew G. Knepley PetscInt unit; 4171552f7358SJed Brown 4172552f7358SJed Brown PetscFunctionBegin; 4173552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41749566063dSJacob Faibussowitsch PetscCall(PetscNewLog(dm, &mesh)); 4175552f7358SJed Brown dm->data = mesh; 4176552f7358SJed Brown 4177552f7358SJed Brown mesh->refct = 1; 41789566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 41799566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 4180552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 4181552f7358SJed Brown mesh->refinementLimit = -1.0; 4182e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 41836bc1bd01Sksagiyam mesh->reorderDefault = DMPLEX_REORDER_DEFAULT_NOTSET; 41847d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 41857d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 4186552f7358SJed Brown 41879566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 41882e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 4189d9deefdfSMatthew G. Knepley 41908865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 4191552f7358SJed Brown 4192df0420ecSMatthew G. Knepley mesh->depthState = -1; 4193ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 41946113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 4195552f7358SJed Brown 41969566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 4197552f7358SJed Brown PetscFunctionReturn(0); 4198552f7358SJed Brown } 4199552f7358SJed Brown 4200552f7358SJed Brown /*@ 4201552f7358SJed Brown DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 4202552f7358SJed Brown 4203d083f849SBarry Smith Collective 4204552f7358SJed Brown 4205552f7358SJed Brown Input Parameter: 4206552f7358SJed Brown . comm - The communicator for the DMPlex object 4207552f7358SJed Brown 4208552f7358SJed Brown Output Parameter: 4209552f7358SJed Brown . mesh - The DMPlex object 4210552f7358SJed Brown 4211552f7358SJed Brown Level: beginner 4212552f7358SJed Brown 4213552f7358SJed Brown @*/ 42149371c9d4SSatish Balay PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) { 4215552f7358SJed Brown PetscFunctionBegin; 4216552f7358SJed Brown PetscValidPointer(mesh, 2); 42179566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 42189566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 4219552f7358SJed Brown PetscFunctionReturn(0); 4220552f7358SJed Brown } 4221552f7358SJed Brown 4222b09969d6SVaclav Hapla /*@C 4223b09969d6SVaclav Hapla DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output) 4224b09969d6SVaclav Hapla 4225b09969d6SVaclav Hapla Input Parameters: 4226b09969d6SVaclav Hapla + dm - The DM 4227b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4228325d53feSBarry Smith . numVertices - The number of vertices to be owned by this process, or PETSC_DECIDE 4229325d53feSBarry Smith . NVertices - The global number of vertices, or PETSC_DETERMINE 4230b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 42315e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4232b09969d6SVaclav Hapla 4233be8c289dSNicolas Barral Output Parameters: 4234be8c289dSNicolas Barral + vertexSF - (Optional) SF describing complete vertex ownership 4235be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4236b09969d6SVaclav Hapla 4237b09969d6SVaclav Hapla Notes: 4238b09969d6SVaclav Hapla Two triangles sharing a face 4239b09969d6SVaclav Hapla $ 4240b09969d6SVaclav Hapla $ 2 4241b09969d6SVaclav Hapla $ / | \ 4242b09969d6SVaclav Hapla $ / | \ 4243b09969d6SVaclav Hapla $ / | \ 4244b09969d6SVaclav Hapla $ 0 0 | 1 3 4245b09969d6SVaclav Hapla $ \ | / 4246b09969d6SVaclav Hapla $ \ | / 4247b09969d6SVaclav Hapla $ \ | / 4248b09969d6SVaclav Hapla $ 1 4249b09969d6SVaclav Hapla would have input 4250b09969d6SVaclav Hapla $ numCells = 2, numVertices = 4 4251b09969d6SVaclav Hapla $ cells = [0 1 2 1 3 2] 4252b09969d6SVaclav Hapla $ 4253b09969d6SVaclav Hapla which would result in the DMPlex 4254b09969d6SVaclav Hapla $ 4255b09969d6SVaclav Hapla $ 4 4256b09969d6SVaclav Hapla $ / | \ 4257b09969d6SVaclav Hapla $ / | \ 4258b09969d6SVaclav Hapla $ / | \ 4259b09969d6SVaclav Hapla $ 2 0 | 1 5 4260b09969d6SVaclav Hapla $ \ | / 4261b09969d6SVaclav Hapla $ \ | / 4262b09969d6SVaclav Hapla $ \ | / 4263b09969d6SVaclav Hapla $ 3 4264b09969d6SVaclav Hapla 426525b6865aSVaclav Hapla Vertices are implicitly numbered consecutively 0,...,NVertices. 426625b6865aSVaclav Hapla Each rank owns a chunk of numVertices consecutive vertices. 426725b6865aSVaclav Hapla If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout. 4268325d53feSBarry Smith If NVertices is PETSC_DETERMINE and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 4269325d53feSBarry Smith If only NVertices is PETSC_DETERMINE, it is computed as the sum of numVertices over all ranks. 427025b6865aSVaclav Hapla 4271b09969d6SVaclav Hapla The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 4272b09969d6SVaclav Hapla 4273b09969d6SVaclav Hapla Not currently supported in Fortran. 4274b09969d6SVaclav Hapla 4275b09969d6SVaclav Hapla Level: advanced 4276b09969d6SVaclav Hapla 4277db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()` 4278b09969d6SVaclav Hapla @*/ 42799371c9d4SSatish Balay PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved) { 42802464107aSksagiyam PetscSF sfPoint; 42812464107aSksagiyam PetscLayout layout; 428282fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 4283a47d0d45SMatthew G. Knepley 4284a47d0d45SMatthew G. Knepley PetscFunctionBegin; 428525b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 42869566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 428725b6865aSVaclav Hapla /* Get/check global number of vertices */ 428825b6865aSVaclav Hapla { 428925b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 429025b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 429125b6865aSVaclav Hapla 429225b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 429325b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 42949371c9d4SSatish Balay for (i = 0; i < len; i++) 42959371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 429625b6865aSVaclav Hapla ++NVerticesInCells; 42979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 429825b6865aSVaclav Hapla 429925b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 43009371c9d4SSatish Balay else 43019371c9d4SSatish 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); 430225b6865aSVaclav Hapla } 43039079aca8SVaclav Hapla /* Count locally unique vertices */ 43049079aca8SVaclav Hapla { 43059079aca8SVaclav Hapla PetscHSetI vhash; 43069079aca8SVaclav Hapla PetscInt off = 0; 43079079aca8SVaclav Hapla 43089566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 4309a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 43109371c9d4SSatish Balay for (p = 0; p < numCorners; ++p) { PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); } 4311a47d0d45SMatthew G. Knepley } 43129566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 43139566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 4314be8c289dSNicolas Barral else { verticesAdj = *verticesAdjSaved; } 43159566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 43169566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 431763a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 4318a47d0d45SMatthew G. Knepley } 43199566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 4320a47d0d45SMatthew G. Knepley /* Create cones */ 43219566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 43229566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 43239566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 43249566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4325a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 4326a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 4327a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 4328a47d0d45SMatthew G. Knepley PetscInt lv; 4329a47d0d45SMatthew G. Knepley 43309079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 43319079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 43329566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 433363a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 4334961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 4335a47d0d45SMatthew G. Knepley } 4336a47d0d45SMatthew G. Knepley } 43372464107aSksagiyam /* Build point sf */ 43389566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 43399566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 43409566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 43419566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 43429566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 43439566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 43449566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 43459566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 43462464107aSksagiyam if (dm->sf) { 43472464107aSksagiyam const char *prefix; 43482464107aSksagiyam 43499566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 43509566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 43512464107aSksagiyam } 43529566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 43539566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 43549566063dSJacob Faibussowitsch if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF")); 4355a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 43569566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 43579566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 43589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4359a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4360a47d0d45SMatthew G. Knepley } 4361a47d0d45SMatthew G. Knepley 4362b09969d6SVaclav Hapla /*@C 4363b09969d6SVaclav Hapla DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4364b09969d6SVaclav Hapla 4365b09969d6SVaclav Hapla Input Parameters: 4366b09969d6SVaclav Hapla + dm - The DM 4367b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4368b09969d6SVaclav Hapla . sfVert - SF describing complete vertex ownership 4369b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4370b09969d6SVaclav Hapla 4371b09969d6SVaclav Hapla Level: advanced 4372b09969d6SVaclav Hapla 4373b09969d6SVaclav Hapla Notes: 4374b09969d6SVaclav Hapla Not currently supported in Fortran. 4375b09969d6SVaclav Hapla 4376db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 4377b09969d6SVaclav Hapla @*/ 43789371c9d4SSatish Balay PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) { 4379a47d0d45SMatthew G. Knepley PetscSection coordSection; 4380a47d0d45SMatthew G. Knepley Vec coordinates; 4381a47d0d45SMatthew G. Knepley PetscScalar *coords; 43821edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 4383a47d0d45SMatthew G. Knepley 4384a47d0d45SMatthew G. Knepley PetscFunctionBegin; 43859566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 43869566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 43871dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 43889566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 43899566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 43901dca8a05SBarry 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); 43919566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 43929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 43939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 43949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 43951edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 43969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 43979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4398a47d0d45SMatthew G. Knepley } 43999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 44009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 44019566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 44029566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 44039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 44049566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 44059566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 44069566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 4407a47d0d45SMatthew G. Knepley { 4408a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 4409a47d0d45SMatthew G. Knepley 4410a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 44119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype)); 44129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 441321016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 441421016a8bSBarry Smith { 441521016a8bSBarry Smith PetscScalar *svertexCoords; 441621016a8bSBarry Smith PetscInt i; 44179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 44183612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 44199566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 44209566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 44219566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 442221016a8bSBarry Smith } 442321016a8bSBarry Smith #else 44249566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 44259566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 442621016a8bSBarry Smith #endif 44279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 4428a47d0d45SMatthew G. Knepley } 44299566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 44309566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 44319566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 44329566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4433a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4434a47d0d45SMatthew G. Knepley } 4435a47d0d45SMatthew G. Knepley 4436c3edce3dSSatish Balay /*@ 4437b09969d6SVaclav Hapla DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output) 4438a47d0d45SMatthew G. Knepley 4439a47d0d45SMatthew G. Knepley Input Parameters: 4440a47d0d45SMatthew G. Knepley + comm - The communicator 4441a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 4442a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 444325b6865aSVaclav Hapla . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 444425b6865aSVaclav Hapla . NVertices - The global number of vertices, or PETSC_DECIDE 4445a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 4446a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 4447a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4448a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 4449a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4450a47d0d45SMatthew G. Knepley 4451d8d19677SJose E. Roman Output Parameters: 445218d54ad4SMichael Lange + dm - The DM 4453be8c289dSNicolas Barral . vertexSF - (Optional) SF describing complete vertex ownership 4454be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4455a47d0d45SMatthew G. Knepley 4456b09969d6SVaclav Hapla Notes: 4457b09969d6SVaclav Hapla This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), 4458b09969d6SVaclav Hapla DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel() 4459a47d0d45SMatthew G. Knepley 446025b6865aSVaclav Hapla See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters. 446125b6865aSVaclav Hapla See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters. 446225b6865aSVaclav Hapla 4463b09969d6SVaclav Hapla Level: intermediate 4464a47d0d45SMatthew G. Knepley 4465db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 4466a47d0d45SMatthew G. Knepley @*/ 44679371c9d4SSatish 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) { 4468a47d0d45SMatthew G. Knepley PetscSF sfVert; 4469a47d0d45SMatthew G. Knepley 4470a47d0d45SMatthew G. Knepley PetscFunctionBegin; 44719566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44729566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 4473a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 4474064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 44759566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 44769566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 4477a47d0d45SMatthew G. Knepley if (interpolate) { 44785fd9971aSMatthew G. Knepley DM idm; 4479a47d0d45SMatthew G. Knepley 44809566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 44819566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 4482a47d0d45SMatthew G. Knepley *dm = idm; 4483a47d0d45SMatthew G. Knepley } 44849566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 448518d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 44869566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 4487a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4488a47d0d45SMatthew G. Knepley } 4489a47d0d45SMatthew G. Knepley 4490b09969d6SVaclav Hapla /*@C 4491b09969d6SVaclav Hapla DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output) 44929298eaa6SMatthew G Knepley 44939298eaa6SMatthew G Knepley Input Parameters: 4494b09969d6SVaclav Hapla + dm - The DM 4495b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4496325d53feSBarry Smith . numVertices - The number of vertices owned by this process, or PETSC_DETERMINE 44979298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 44985e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 44999298eaa6SMatthew G Knepley 4500b09969d6SVaclav Hapla Level: advanced 45019298eaa6SMatthew G Knepley 4502b09969d6SVaclav Hapla Notes: 4503b09969d6SVaclav Hapla Two triangles sharing a face 45049298eaa6SMatthew G Knepley $ 45059298eaa6SMatthew G Knepley $ 2 45069298eaa6SMatthew G Knepley $ / | \ 45079298eaa6SMatthew G Knepley $ / | \ 45089298eaa6SMatthew G Knepley $ / | \ 45099298eaa6SMatthew G Knepley $ 0 0 | 1 3 45109298eaa6SMatthew G Knepley $ \ | / 45119298eaa6SMatthew G Knepley $ \ | / 45129298eaa6SMatthew G Knepley $ \ | / 45139298eaa6SMatthew G Knepley $ 1 45149298eaa6SMatthew G Knepley would have input 45159298eaa6SMatthew G Knepley $ numCells = 2, numVertices = 4 45169298eaa6SMatthew G Knepley $ cells = [0 1 2 1 3 2] 45179298eaa6SMatthew G Knepley $ 45189298eaa6SMatthew G Knepley which would result in the DMPlex 45199298eaa6SMatthew G Knepley $ 45209298eaa6SMatthew G Knepley $ 4 45219298eaa6SMatthew G Knepley $ / | \ 45229298eaa6SMatthew G Knepley $ / | \ 45239298eaa6SMatthew G Knepley $ / | \ 45249298eaa6SMatthew G Knepley $ 2 0 | 1 5 45259298eaa6SMatthew G Knepley $ \ | / 45269298eaa6SMatthew G Knepley $ \ | / 45279298eaa6SMatthew G Knepley $ \ | / 45289298eaa6SMatthew G Knepley $ 3 45299298eaa6SMatthew G Knepley 4530325d53feSBarry Smith If numVertices is PETSC_DETERMINE, it is computed by PETSc as the maximum vertex index in cells + 1. 453125b6865aSVaclav Hapla 4532b09969d6SVaclav Hapla Not currently supported in Fortran. 45339298eaa6SMatthew G Knepley 4534db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 4535b09969d6SVaclav Hapla @*/ 45369371c9d4SSatish Balay PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) { 4537961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 4538b09969d6SVaclav Hapla 4539b09969d6SVaclav Hapla PetscFunctionBegin; 45409566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 45419566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 454225b6865aSVaclav Hapla /* Get/check global number of vertices */ 454325b6865aSVaclav Hapla { 454425b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 454525b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 454625b6865aSVaclav Hapla 454725b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 454825b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 45499371c9d4SSatish Balay for (i = 0; i < len; i++) 45509371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 455125b6865aSVaclav Hapla ++NVerticesInCells; 455225b6865aSVaclav Hapla 455325b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 45549371c9d4SSatish Balay else 45559371c9d4SSatish 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); 455625b6865aSVaclav Hapla } 45579566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 45589371c9d4SSatish Balay for (c = 0; c < numCells; ++c) { PetscCall(DMPlexSetConeSize(dm, c, numCorners)); } 45599566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 45609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4561b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 45629371c9d4SSatish Balay for (p = 0; p < numCorners; ++p) { cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; } 4563b09969d6SVaclav Hapla } 45649566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 45659566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 45669566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4567b09969d6SVaclav Hapla PetscFunctionReturn(0); 4568b09969d6SVaclav Hapla } 4569b09969d6SVaclav Hapla 4570b09969d6SVaclav Hapla /*@C 4571b09969d6SVaclav Hapla DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4572b09969d6SVaclav Hapla 4573b09969d6SVaclav Hapla Input Parameters: 4574b09969d6SVaclav Hapla + dm - The DM 4575b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4576b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4577b09969d6SVaclav Hapla 4578b09969d6SVaclav Hapla Level: advanced 4579b09969d6SVaclav Hapla 4580b09969d6SVaclav Hapla Notes: 4581b09969d6SVaclav Hapla Not currently supported in Fortran. 4582b09969d6SVaclav Hapla 4583db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 4584b09969d6SVaclav Hapla @*/ 45859371c9d4SSatish Balay PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) { 4586b09969d6SVaclav Hapla PetscSection coordSection; 4587b09969d6SVaclav Hapla Vec coordinates; 4588b09969d6SVaclav Hapla DM cdm; 4589b09969d6SVaclav Hapla PetscScalar *coords; 45901edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 4591b09969d6SVaclav Hapla 4592b09969d6SVaclav Hapla PetscFunctionBegin; 45939566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 45949566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 45951dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 45969566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 45979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 45989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 45999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 46009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 46011edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 46029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 46039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4604b09969d6SVaclav Hapla } 46059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4606b09969d6SVaclav Hapla 46079566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 46089566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 46099566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 46109566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 46119566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 46121edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 46139371c9d4SSatish Balay for (d = 0; d < spaceDim; ++d) { coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; } 4614b09969d6SVaclav Hapla } 46159566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 46169566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 46179566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 46189566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4619b09969d6SVaclav Hapla PetscFunctionReturn(0); 4620b09969d6SVaclav Hapla } 4621b09969d6SVaclav Hapla 4622b09969d6SVaclav Hapla /*@ 46233df08285SMatthew 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 46243df08285SMatthew G. Knepley 46253df08285SMatthew G. Knepley Collective on comm 4626b09969d6SVaclav Hapla 4627b09969d6SVaclav Hapla Input Parameters: 4628b09969d6SVaclav Hapla + comm - The communicator 4629b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 46303df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 46313df08285SMatthew G. Knepley . numVertices - The number of vertices owned by this process, or PETSC_DECIDE, only on process 0 46323df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 4633b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 46343df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0 4635b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 46363df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0 4637b09969d6SVaclav Hapla 4638b09969d6SVaclav Hapla Output Parameter: 46393df08285SMatthew G. Knepley . dm - The DM, which only has points on process 0 4640b09969d6SVaclav Hapla 4641b09969d6SVaclav Hapla Notes: 4642b09969d6SVaclav Hapla This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(), 4643b09969d6SVaclav Hapla DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList() 4644b09969d6SVaclav Hapla 464525b6865aSVaclav Hapla See DMPlexBuildFromCellList() for an example and details about the topology-related parameters. 464625b6865aSVaclav Hapla See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters. 46473df08285SMatthew G. Knepley See DMPlexCreateFromCellListParallelPetsc() for parallel input 464825b6865aSVaclav Hapla 4649b09969d6SVaclav Hapla Level: intermediate 4650b09969d6SVaclav Hapla 4651db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 46529298eaa6SMatthew G Knepley @*/ 46539371c9d4SSatish 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) { 46543df08285SMatthew G. Knepley PetscMPIInt rank; 46559298eaa6SMatthew G Knepley 46569298eaa6SMatthew G Knepley PetscFunctionBegin; 465728b400f6SJacob 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."); 46589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 46599566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 46609566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 46619566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 4662c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 46639566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 46649298eaa6SMatthew G Knepley if (interpolate) { 46655fd9971aSMatthew G. Knepley DM idm; 46669298eaa6SMatthew G Knepley 46679566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 46689566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 46699298eaa6SMatthew G Knepley *dm = idm; 46709298eaa6SMatthew G Knepley } 4671c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 46729566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 46739298eaa6SMatthew G Knepley PetscFunctionReturn(0); 46749298eaa6SMatthew G Knepley } 46759298eaa6SMatthew G Knepley 4676939f6067SMatthew G. Knepley /*@ 4677939f6067SMatthew 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 4678939f6067SMatthew G. Knepley 4679939f6067SMatthew G. Knepley Input Parameters: 4680c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension() 4681939f6067SMatthew G. Knepley . depth - The depth of the DAG 4682367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth 4683939f6067SMatthew G. Knepley . coneSize - The cone size of each point 4684939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 4685939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 4686367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim() 4687939f6067SMatthew G. Knepley 4688939f6067SMatthew G. Knepley Output Parameter: 4689939f6067SMatthew G. Knepley . dm - The DM 4690939f6067SMatthew G. Knepley 4691939f6067SMatthew G. Knepley Note: Two triangles sharing a face would have input 4692939f6067SMatthew G. Knepley $ depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 4693939f6067SMatthew G. Knepley $ cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 4694939f6067SMatthew G. Knepley $ vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 4695939f6067SMatthew G. Knepley $ 4696939f6067SMatthew G. Knepley which would result in the DMPlex 4697939f6067SMatthew G. Knepley $ 4698939f6067SMatthew G. Knepley $ 4 4699939f6067SMatthew G. Knepley $ / | \ 4700939f6067SMatthew G. Knepley $ / | \ 4701939f6067SMatthew G. Knepley $ / | \ 4702939f6067SMatthew G. Knepley $ 2 0 | 1 5 4703939f6067SMatthew G. Knepley $ \ | / 4704939f6067SMatthew G. Knepley $ \ | / 4705939f6067SMatthew G. Knepley $ \ | / 4706939f6067SMatthew G. Knepley $ 3 4707939f6067SMatthew G. Knepley $ 4708a4a685f2SJacob Faibussowitsch $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc() 4709939f6067SMatthew G. Knepley 4710939f6067SMatthew G. Knepley Level: advanced 4711939f6067SMatthew G. Knepley 4712db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 4713939f6067SMatthew G. Knepley @*/ 47149371c9d4SSatish Balay PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) { 47159298eaa6SMatthew G Knepley Vec coordinates; 47169298eaa6SMatthew G Knepley PetscSection coordSection; 47179298eaa6SMatthew G Knepley PetscScalar *coords; 4718811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 47199298eaa6SMatthew G Knepley 47209298eaa6SMatthew G Knepley PetscFunctionBegin; 47219566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 47229566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 472363a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 47249298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 47259566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 47269298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 47279566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 47289371c9d4SSatish Balay if (firstVertex < 0 && !coneSize[p - pStart]) { firstVertex = p - pStart; } 472997e052ccSToby Isaac } 47301dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 47319566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 47329298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 47339566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 47349566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 47359298eaa6SMatthew G Knepley } 47369566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 47379566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 47389298eaa6SMatthew G Knepley /* Build coordinates */ 47399566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 47409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 47419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 47429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 47439298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 47449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 47459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 47469298eaa6SMatthew G Knepley } 47479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 47489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 47499566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 47509566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 47519566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 47529566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dimEmbed)); 47539566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 47549318fe57SMatthew G. Knepley if (vertexCoords) { 47559566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 47569298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 47579298eaa6SMatthew G Knepley PetscInt off; 47589298eaa6SMatthew G Knepley 47599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 47609371c9d4SSatish Balay for (d = 0; d < dimEmbed; ++d) { coords[off + d] = vertexCoords[v * dimEmbed + d]; } 47619298eaa6SMatthew G Knepley } 47629318fe57SMatthew G. Knepley } 47639566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 47649566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 47659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 47669298eaa6SMatthew G Knepley PetscFunctionReturn(0); 47679298eaa6SMatthew G Knepley } 47688415267dSToby Isaac 4769ca522641SMatthew G. Knepley /*@C 47708ca92349SMatthew G. Knepley DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file. 47718ca92349SMatthew G. Knepley 47728ca92349SMatthew G. Knepley + comm - The MPI communicator 47738ca92349SMatthew G. Knepley . filename - Name of the .dat file 47748ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 47758ca92349SMatthew G. Knepley 47768ca92349SMatthew G. Knepley Output Parameter: 47778ca92349SMatthew G. Knepley . dm - The DM object representing the mesh 47788ca92349SMatthew G. Knepley 47798ca92349SMatthew G. Knepley Note: The format is the simplest possible: 47808ca92349SMatthew G. Knepley $ Ne 47818ca92349SMatthew G. Knepley $ v0 v1 ... vk 47828ca92349SMatthew G. Knepley $ Nv 47838ca92349SMatthew G. Knepley $ x y z marker 47848ca92349SMatthew G. Knepley 47858ca92349SMatthew G. Knepley Level: beginner 47868ca92349SMatthew G. Knepley 4787db781477SPatrick Sanan .seealso: `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 47888ca92349SMatthew G. Knepley @*/ 47899371c9d4SSatish Balay PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) { 47908ca92349SMatthew G. Knepley DMLabel marker; 47918ca92349SMatthew G. Knepley PetscViewer viewer; 47928ca92349SMatthew G. Knepley Vec coordinates; 47938ca92349SMatthew G. Knepley PetscSection coordSection; 47948ca92349SMatthew G. Knepley PetscScalar *coords; 47958ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 47968ca92349SMatthew G. Knepley PetscInt dim = 3, cdim = 3, coordSize, v, c, d; 47978ca92349SMatthew G. Knepley PetscMPIInt rank; 4798f8d5e320SMatthew G. Knepley int snum, Nv, Nc, Ncn, Nl; 47998ca92349SMatthew G. Knepley 48008ca92349SMatthew G. Knepley PetscFunctionBegin; 48019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 48029566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 48039566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 48049566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 48059566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 4806dd400576SPatrick Sanan if (rank == 0) { 48079566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING)); 4808f8d5e320SMatthew G. Knepley snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl); 480908401ef6SPierre Jolivet PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 481025ce1634SJed Brown } else { 4811f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 48128ca92349SMatthew G. Knepley } 48139566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 48149566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 48159566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 48169566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 48179566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 48188ca92349SMatthew G. Knepley /* Read topology */ 4819dd400576SPatrick Sanan if (rank == 0) { 4820f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 4821f8d5e320SMatthew G. Knepley PetscInt cone[8]; 48228ca92349SMatthew G. Knepley int vbuf[8], v; 48238ca92349SMatthew G. Knepley 48249371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 48259371c9d4SSatish Balay format[c * 3 + 0] = '%'; 48269371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 48279371c9d4SSatish Balay format[c * 3 + 2] = ' '; 48289371c9d4SSatish Balay } 4829f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 48309566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 48319566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 48328ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 48339566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 4834f8d5e320SMatthew G. Knepley switch (Ncn) { 4835f8d5e320SMatthew G. Knepley case 2: snum = sscanf(line, format, &vbuf[0], &vbuf[1]); break; 4836f8d5e320SMatthew G. Knepley case 3: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); break; 4837f8d5e320SMatthew G. Knepley case 4: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); break; 4838f8d5e320SMatthew G. Knepley case 6: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); break; 4839f8d5e320SMatthew 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; 484063a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 4841f8d5e320SMatthew G. Knepley } 484208401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 4843f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 48448ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 4845f8d5e320SMatthew G. Knepley if (Ncn == 8) { 48468ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 48478ca92349SMatthew G. Knepley cone[1] = cone[3]; 48488ca92349SMatthew G. Knepley cone[3] = tmp; 48498ca92349SMatthew G. Knepley } 48509566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 48518ca92349SMatthew G. Knepley } 48528ca92349SMatthew G. Knepley } 48539566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 48549566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 48558ca92349SMatthew G. Knepley /* Read coordinates */ 48569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 48579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 48589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 48599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 48608ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 48619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 48629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 48638ca92349SMatthew G. Knepley } 48649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 48659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 48669566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 48679566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 48689566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 48699566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 48709566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 48719566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 4872dd400576SPatrick Sanan if (rank == 0) { 4873f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 48748ca92349SMatthew G. Knepley double x[3]; 4875f8d5e320SMatthew G. Knepley int l, val[3]; 48768ca92349SMatthew G. Knepley 4877f8d5e320SMatthew G. Knepley if (Nl) { 48789371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 48799371c9d4SSatish Balay format[l * 3 + 0] = '%'; 48809371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 48819371c9d4SSatish Balay format[l * 3 + 2] = ' '; 48829371c9d4SSatish Balay } 4883f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 48849566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 48859566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 4886f8d5e320SMatthew G. Knepley } 48878ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 48889566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 4889f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 489008401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 4891f8d5e320SMatthew G. Knepley switch (Nl) { 4892f8d5e320SMatthew G. Knepley case 0: snum = 0; break; 4893f8d5e320SMatthew G. Knepley case 1: snum = sscanf(line, format, &val[0]); break; 4894f8d5e320SMatthew G. Knepley case 2: snum = sscanf(line, format, &val[0], &val[1]); break; 4895f8d5e320SMatthew G. Knepley case 3: snum = sscanf(line, format, &val[0], &val[1], &val[2]); break; 489663a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 4897f8d5e320SMatthew G. Knepley } 489808401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 48998ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 49009566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 49018ca92349SMatthew G. Knepley } 49028ca92349SMatthew G. Knepley } 49039566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 49049566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 49059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 49069566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 49078ca92349SMatthew G. Knepley if (interpolate) { 49088ca92349SMatthew G. Knepley DM idm; 49098ca92349SMatthew G. Knepley DMLabel bdlabel; 49108ca92349SMatthew G. Knepley 49119566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 49129566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 49138ca92349SMatthew G. Knepley *dm = idm; 49148ca92349SMatthew G. Knepley 4915f8d5e320SMatthew G. Knepley if (!Nl) { 49169566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 49179566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 49189566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 49199566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 49208ca92349SMatthew G. Knepley } 4921f8d5e320SMatthew G. Knepley } 49228ca92349SMatthew G. Knepley PetscFunctionReturn(0); 49238ca92349SMatthew G. Knepley } 49248ca92349SMatthew G. Knepley 49258ca92349SMatthew G. Knepley /*@C 4926ca522641SMatthew G. Knepley DMPlexCreateFromFile - This takes a filename and produces a DM 4927ca522641SMatthew G. Knepley 4928ca522641SMatthew G. Knepley Input Parameters: 4929ca522641SMatthew G. Knepley + comm - The communicator 4930ca522641SMatthew G. Knepley . filename - A file name 4931cd7e8a5eSksagiyam . plexname - The object name of the resulting DM, also used for intra-datafile lookup by some formats 4932ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 4933ca522641SMatthew G. Knepley 4934ca522641SMatthew G. Knepley Output Parameter: 4935ca522641SMatthew G. Knepley . dm - The DM 4936ca522641SMatthew G. Knepley 493702ef0d99SVaclav Hapla Options Database Keys: 493802ef0d99SVaclav Hapla . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5 493902ef0d99SVaclav Hapla 4940bca97951SVaclav Hapla Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g. 4941bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 4942bca97951SVaclav Hapla 4943cd7e8a5eSksagiyam Notes: 4944cd7e8a5eSksagiyam Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex 4945cd7e8a5eSksagiyam meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName() 4946cd7e8a5eSksagiyam before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object. 4947cd7e8a5eSksagiyam The input parameter name is thus used to name the DMPlex object when DMPlexCreateFromFile() internally 4948cd7e8a5eSksagiyam calls DMLoad(). Currently, name is ignored for other viewer types and/or formats. 4949cd7e8a5eSksagiyam 4950ca522641SMatthew G. Knepley Level: beginner 4951ca522641SMatthew G. Knepley 4952db781477SPatrick Sanan .seealso: `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 4953ca522641SMatthew G. Knepley @*/ 49549371c9d4SSatish Balay PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) { 4955ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 4956ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 4957ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 4958ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 4959ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 4960ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 4961ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 4962ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 4963ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 4964ef3a5affSJacob Faibussowitsch const char extMed[] = ".med"; 4965ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 4966ef3a5affSJacob Faibussowitsch const char extEGADSLite[] = ".egadslite"; 4967ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 4968ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 4969ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 4970ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 4971ca522641SMatthew G. Knepley size_t len; 4972c1cad2e7SMatthew G. Knepley PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV; 4973ca522641SMatthew G. Knepley PetscMPIInt rank; 4974ca522641SMatthew G. Knepley 4975ca522641SMatthew G. Knepley PetscFunctionBegin; 49765d80c0bfSVaclav Hapla PetscValidCharPointer(filename, 2); 49770d862eaeSPierre Jolivet if (plexname) PetscValidCharPointer(plexname, 3); 4978cd7e8a5eSksagiyam PetscValidPointer(dm, 5); 49799566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 49809566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 49819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 49829566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 498328b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 4984ef3a5affSJacob Faibussowitsch 49859371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 49869371c9d4SSatish Balay do { \ 4987274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 4988274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 4989274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 4990274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 4991ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 4992ef3a5affSJacob Faibussowitsch } else { \ 4993274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 4994ef3a5affSJacob Faibussowitsch } \ 4995ef3a5affSJacob Faibussowitsch } while (0) 4996ef3a5affSJacob Faibussowitsch 4997ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 4998ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 4999ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 5000ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 5001ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 5002ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 5003ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 5004ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 5005ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 5006ef3a5affSJacob Faibussowitsch CheckExtension(extMed, isMed); 5007ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 5008ef3a5affSJacob Faibussowitsch CheckExtension(extEGADSLite, isEGADSLite); 5009ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 5010ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 5011ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 5012ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 5013ef3a5affSJacob Faibussowitsch 5014ef3a5affSJacob Faibussowitsch #undef CheckExtension 5015ef3a5affSJacob Faibussowitsch 5016de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 50179566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 5018ca522641SMatthew G. Knepley } else if (isCGNS) { 50199566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 502090c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 50219566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 50222f0bd6dcSMichael Lange } else if (isFluent) { 50239566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 5024cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 50259c48423bSVaclav Hapla PetscBool load_hdf5_xdmf = PETSC_FALSE; 5026cc2f8f65SMatthew G. Knepley PetscViewer viewer; 5027cc2f8f65SMatthew G. Knepley 502843b242b4SVaclav 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 */ 50299566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf)); 50309566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL)); 50319566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 50329566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 50339566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 50349566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 50359566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 50369566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 5037cd7e8a5eSksagiyam 50389566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 50399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 50409566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 50419566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 50429566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 50439566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer)); 50449566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 50455fd9971aSMatthew G. Knepley 50465fd9971aSMatthew G. Knepley if (interpolate) { 50475fd9971aSMatthew G. Knepley DM idm; 50485fd9971aSMatthew G. Knepley 50499566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 50509566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 50515fd9971aSMatthew G. Knepley *dm = idm; 50525fd9971aSMatthew G. Knepley } 5053707dd687SMichael Lange } else if (isMed) { 50549566063dSJacob Faibussowitsch PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm)); 5055f2801cd6SMatthew G. Knepley } else if (isPLY) { 50569566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 5057c1cad2e7SMatthew G. Knepley } else if (isEGADSLite || isEGADS || isIGES || isSTEP) { 50589566063dSJacob Faibussowitsch if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm)); 50599566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm)); 50607bee2925SMatthew Knepley if (!interpolate) { 50617bee2925SMatthew Knepley DM udm; 50627bee2925SMatthew Knepley 50639566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 50649566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 50657bee2925SMatthew Knepley *dm = udm; 50667bee2925SMatthew Knepley } 50678ca92349SMatthew G. Knepley } else if (isCV) { 50689566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 506998921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 50709566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 50719566063dSJacob Faibussowitsch if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 50729566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 5073ca522641SMatthew G. Knepley PetscFunctionReturn(0); 5074ca522641SMatthew G. Knepley } 5075