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> 69f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h> 7b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h> 8b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h> 9552f7358SJed Brown 10b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 1158cd63d5SVaclav Hapla 129318fe57SMatthew G. Knepley /* External function declarations here */ 139318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm); 149318fe57SMatthew G. Knepley 15e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */ 16d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout) 17d71ae5a4SJacob Faibussowitsch { 184fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 196858538eSMatthew G. Knepley PetscBool dist; 206bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 21e600fa54SMatthew G. Knepley 22e600fa54SMatthew G. Knepley PetscFunctionBegin; 23e600fa54SMatthew G. Knepley if (copyPeriodicity) { 244fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L)); 254fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L)); 26e600fa54SMatthew G. Knepley } 279566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dmin, &dist)); 289566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dmout, dist)); 296bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dmin, &reorder)); 306bc1bd01Sksagiyam PetscCall(DMPlexReorderSetDefault(dmout, reorder)); 31e600fa54SMatthew G. Knepley ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation; 321baa6e33SBarry Smith if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0)); 33e600fa54SMatthew G. Knepley PetscFunctionReturn(0); 34e600fa54SMatthew G. Knepley } 35e600fa54SMatthew G. Knepley 369318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 379318fe57SMatthew G. Knepley - Share the DM_Plex structure 389318fe57SMatthew G. Knepley - Share the coordinates 399318fe57SMatthew G. Knepley - Share the SF 409318fe57SMatthew G. Knepley */ 41d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm) 42d71ae5a4SJacob Faibussowitsch { 439318fe57SMatthew G. Knepley PetscSF sf; 449318fe57SMatthew G. Knepley DM dmNew = *ndm, coordDM, coarseDM; 459318fe57SMatthew G. Knepley Vec coords; 464fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 479318fe57SMatthew G. Knepley PetscInt dim, cdim; 489318fe57SMatthew G. Knepley 499318fe57SMatthew G. Knepley PetscFunctionBegin; 509318fe57SMatthew G. Knepley if (dm == dmNew) { 519566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 529318fe57SMatthew G. Knepley PetscFunctionReturn(0); 539318fe57SMatthew G. Knepley } 549318fe57SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 559566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmNew, &dim)); 569566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmNew, &cdim)); 589566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 599566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sf)); 609566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sf)); 619566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmNew, &coordDM)); 629566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmNew, &coords)); 639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dm, coordDM)); 649566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 656858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM)); 666858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords)); 676858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dm, coordDM)); 686858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 699318fe57SMatthew G. Knepley /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */ 706858538eSMatthew G. Knepley PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 716858538eSMatthew G. Knepley dm->coordinates[0].field = dmNew->coordinates[0].field; 7261a622f3SMatthew G. Knepley ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc; 734fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 744fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 759566063dSJacob Faibussowitsch PetscCall(DMDestroy_Plex(dm)); 769566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 779318fe57SMatthew G. Knepley dm->data = dmNew->data; 789318fe57SMatthew G. Knepley ((DM_Plex *)dmNew->data)->refct++; 799566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 809566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 819566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmNew, &coarseDM)); 829566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 839566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 849318fe57SMatthew G. Knepley PetscFunctionReturn(0); 859318fe57SMatthew G. Knepley } 869318fe57SMatthew G. Knepley 879318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew 889318fe57SMatthew G. Knepley - Swap the DM_Plex structure 899318fe57SMatthew G. Knepley - Swap the coordinates 909318fe57SMatthew G. Knepley - Swap the point PetscSF 919318fe57SMatthew G. Knepley */ 92d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 93d71ae5a4SJacob Faibussowitsch { 949318fe57SMatthew G. Knepley DM coordDMA, coordDMB; 959318fe57SMatthew G. Knepley Vec coordsA, coordsB; 969318fe57SMatthew G. Knepley PetscSF sfA, sfB; 979318fe57SMatthew G. Knepley DMField fieldTmp; 989318fe57SMatthew G. Knepley void *tmp; 999318fe57SMatthew G. Knepley DMLabelLink listTmp; 1009318fe57SMatthew G. Knepley DMLabel depthTmp; 1019318fe57SMatthew G. Knepley PetscInt tmpI; 1029318fe57SMatthew G. Knepley 1039318fe57SMatthew G. Knepley PetscFunctionBegin; 1049318fe57SMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 1059566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmA, &sfA)); 1069566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmB, &sfB)); 1079566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sfA)); 1089566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmA, sfB)); 1099566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmB, sfA)); 1109566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)sfA)); 1119318fe57SMatthew G. Knepley 1129566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &coordDMA)); 1139566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &coordDMB)); 1149566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordDMA)); 1159566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmA, coordDMB)); 1169566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmB, coordDMA)); 1179566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 1189318fe57SMatthew G. Knepley 1199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordsA)); 1209566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmB, &coordsB)); 1219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordsA)); 1229566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmA, coordsB)); 1239566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordsA)); 1249566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordsA)); 1259318fe57SMatthew G. Knepley 1266858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA)); 1276858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB)); 1286858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordDMA)); 1296858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmA, coordDMB)); 1306858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmB, coordDMA)); 1316858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 1326858538eSMatthew G. Knepley 1336858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA)); 1346858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB)); 1356858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordsA)); 1366858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB)); 1376858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA)); 1386858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordsA)); 1396858538eSMatthew G. Knepley 1406858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[0].field; 1416858538eSMatthew G. Knepley dmA->coordinates[0].field = dmB->coordinates[0].field; 1426858538eSMatthew G. Knepley dmB->coordinates[0].field = fieldTmp; 1436858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[1].field; 1446858538eSMatthew G. Knepley dmA->coordinates[1].field = dmB->coordinates[1].field; 1456858538eSMatthew G. Knepley dmB->coordinates[1].field = fieldTmp; 1469318fe57SMatthew G. Knepley tmp = dmA->data; 1479318fe57SMatthew G. Knepley dmA->data = dmB->data; 1489318fe57SMatthew G. Knepley dmB->data = tmp; 1499318fe57SMatthew G. Knepley listTmp = dmA->labels; 1509318fe57SMatthew G. Knepley dmA->labels = dmB->labels; 1519318fe57SMatthew G. Knepley dmB->labels = listTmp; 1529318fe57SMatthew G. Knepley depthTmp = dmA->depthLabel; 1539318fe57SMatthew G. Knepley dmA->depthLabel = dmB->depthLabel; 1549318fe57SMatthew G. Knepley dmB->depthLabel = depthTmp; 1559318fe57SMatthew G. Knepley depthTmp = dmA->celltypeLabel; 1569318fe57SMatthew G. Knepley dmA->celltypeLabel = dmB->celltypeLabel; 1579318fe57SMatthew G. Knepley dmB->celltypeLabel = depthTmp; 1589318fe57SMatthew G. Knepley tmpI = dmA->levelup; 1599318fe57SMatthew G. Knepley dmA->levelup = dmB->levelup; 1609318fe57SMatthew G. Knepley dmB->levelup = tmpI; 1619318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1629318fe57SMatthew G. Knepley } 1639318fe57SMatthew G. Knepley 164d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) 165d71ae5a4SJacob Faibussowitsch { 1669318fe57SMatthew G. Knepley DM idm; 1679318fe57SMatthew G. Knepley 1689318fe57SMatthew G. Knepley PetscFunctionBegin; 1699566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 1709566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 17169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 1729318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1739318fe57SMatthew G. Knepley } 1749318fe57SMatthew G. Knepley 1759318fe57SMatthew G. Knepley /*@C 1769318fe57SMatthew G. Knepley DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates 1779318fe57SMatthew G. Knepley 1789318fe57SMatthew G. Knepley Collective 1799318fe57SMatthew G. Knepley 1809318fe57SMatthew G. Knepley Input Parameters: 1819318fe57SMatthew G. Knepley + DM - The DM 1824f9ab2b4SJed Brown . degree - The degree of the finite element or PETSC_DECIDE 1839318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface 1849318fe57SMatthew G. Knepley 1859318fe57SMatthew G. Knepley Level: advanced 1869318fe57SMatthew G. Knepley 187db781477SPatrick Sanan .seealso: `PetscFECreateLagrange()`, `DMGetCoordinateDM()` 1889318fe57SMatthew G. Knepley @*/ 189d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc) 190d71ae5a4SJacob Faibussowitsch { 1919318fe57SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1929318fe57SMatthew G. Knepley DM cdm; 1939318fe57SMatthew G. Knepley PetscDS cds; 1949318fe57SMatthew G. Knepley PetscFE fe; 1959318fe57SMatthew G. Knepley PetscClassId id; 1969318fe57SMatthew G. Knepley 1979318fe57SMatthew G. Knepley PetscFunctionBegin; 1989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 1999566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 2009566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, (PetscObject *)&fe)); 2019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 2029318fe57SMatthew G. Knepley if (id != PETSCFE_CLASSID) { 2039318fe57SMatthew G. Knepley PetscBool simplex; 2049318fe57SMatthew G. Knepley PetscInt dim, dE, qorder; 2059318fe57SMatthew G. Knepley 2069566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 2079566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 2089318fe57SMatthew G. Knepley qorder = degree; 209d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)cdm); 2109566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-coord_dm_default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0)); 211d0609cedSBarry Smith PetscOptionsEnd(); 2124f9ab2b4SJed Brown if (degree == PETSC_DECIDE) fe = NULL; 2134f9ab2b4SJed Brown else { 2148c4475acSStefano Zampini PetscCall(DMPlexIsSimplex(dm, &simplex)); 2159566063dSJacob Faibussowitsch PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, degree, qorder, &fe)); 2164f9ab2b4SJed Brown } 2179566063dSJacob Faibussowitsch PetscCall(DMProjectCoordinates(dm, fe)); 2189566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 2199318fe57SMatthew G. Knepley } 2209318fe57SMatthew G. Knepley mesh->coordFunc = coordFunc; 2219318fe57SMatthew G. Knepley PetscFunctionReturn(0); 2229318fe57SMatthew G. Knepley } 2239318fe57SMatthew G. Knepley 2241df5d5c5SMatthew G. Knepley /*@ 2251df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 2261df5d5c5SMatthew G. Knepley 227d083f849SBarry Smith Collective 2281df5d5c5SMatthew G. Knepley 2291df5d5c5SMatthew G. Knepley Input Parameters: 2301df5d5c5SMatthew G. Knepley + comm - The communicator for the DM object 2311df5d5c5SMatthew G. Knepley . dim - The spatial dimension 2321df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 2331df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 2341df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 2351df5d5c5SMatthew G. Knepley 2361df5d5c5SMatthew G. Knepley Output Parameter: 2371df5d5c5SMatthew G. Knepley . dm - The DM object 2381df5d5c5SMatthew G. Knepley 2391df5d5c5SMatthew G. Knepley Level: beginner 2401df5d5c5SMatthew G. Knepley 241db781477SPatrick Sanan .seealso: `DMSetType()`, `DMCreate()` 2421df5d5c5SMatthew G. Knepley @*/ 243d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) 244d71ae5a4SJacob Faibussowitsch { 2451df5d5c5SMatthew G. Knepley DM dm; 2461df5d5c5SMatthew G. Knepley PetscMPIInt rank; 2471df5d5c5SMatthew G. Knepley 2481df5d5c5SMatthew G. Knepley PetscFunctionBegin; 2499566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &dm)); 2509566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 2519566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 2529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 253ce78fa2fSMatthew G. Knepley switch (dim) { 254ce78fa2fSMatthew G. Knepley case 2: 2559566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular")); 2569566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral")); 257ce78fa2fSMatthew G. Knepley break; 258ce78fa2fSMatthew G. Knepley case 3: 2599566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral")); 2609566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral")); 261ce78fa2fSMatthew G. Knepley break; 262d71ae5a4SJacob Faibussowitsch default: 263d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 264ce78fa2fSMatthew G. Knepley } 2651df5d5c5SMatthew G. Knepley if (rank) { 2661df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 2679566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 2681df5d5c5SMatthew G. Knepley } else { 2691df5d5c5SMatthew G. Knepley switch (dim) { 2701df5d5c5SMatthew G. Knepley case 2: 2711df5d5c5SMatthew G. Knepley if (simplex) { 2721df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 2731df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 2741df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 2751df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 2761df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 2771df5d5c5SMatthew G. Knepley 2789566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2791df5d5c5SMatthew G. Knepley } else { 2801df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 2811df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 2821df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 2831df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2841df5d5c5SMatthew 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}; 2851df5d5c5SMatthew G. Knepley 2869566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2871df5d5c5SMatthew G. Knepley } 2881df5d5c5SMatthew G. Knepley break; 2891df5d5c5SMatthew G. Knepley case 3: 2901df5d5c5SMatthew G. Knepley if (simplex) { 2911df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 2921df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 2931df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 2941df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2951df5d5c5SMatthew 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}; 2961df5d5c5SMatthew G. Knepley 2979566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2981df5d5c5SMatthew G. Knepley } else { 2991df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 3001df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 3011df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 3021df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 3039371c9d4SSatish 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}; 3041df5d5c5SMatthew G. Knepley 3059566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 3061df5d5c5SMatthew G. Knepley } 3071df5d5c5SMatthew G. Knepley break; 308d71ae5a4SJacob Faibussowitsch default: 309d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 3101df5d5c5SMatthew G. Knepley } 3111df5d5c5SMatthew G. Knepley } 3121df5d5c5SMatthew G. Knepley *newdm = dm; 3131df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 3141df5d5c5SMatthew G. Knepley DM rdm; 3151df5d5c5SMatthew G. Knepley const char *name; 3161df5d5c5SMatthew G. Knepley 3179566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 3189566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 3199566063dSJacob Faibussowitsch PetscCall(DMRefine(*newdm, comm, &rdm)); 3209566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)*newdm, &name)); 3219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, name)); 3229566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 3231df5d5c5SMatthew G. Knepley *newdm = rdm; 3241df5d5c5SMatthew G. Knepley } 3251df5d5c5SMatthew G. Knepley if (interpolate) { 3265fd9971aSMatthew G. Knepley DM idm; 3271df5d5c5SMatthew G. Knepley 3289566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*newdm, &idm)); 3299566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 3301df5d5c5SMatthew G. Knepley *newdm = idm; 3311df5d5c5SMatthew G. Knepley } 3321df5d5c5SMatthew G. Knepley PetscFunctionReturn(0); 3331df5d5c5SMatthew G. Knepley } 3341df5d5c5SMatthew G. Knepley 335d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 336d71ae5a4SJacob Faibussowitsch { 3379318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 3389318fe57SMatthew G. Knepley PetscInt markerRight = 1; 3399318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 3409318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 3419318fe57SMatthew G. Knepley Vec coordinates; 3429318fe57SMatthew G. Knepley PetscSection coordSection; 3439318fe57SMatthew G. Knepley PetscScalar *coords; 3449318fe57SMatthew G. Knepley PetscInt coordSize; 3459318fe57SMatthew G. Knepley PetscMPIInt rank; 3469318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 347552f7358SJed Brown 3489318fe57SMatthew G. Knepley PetscFunctionBegin; 3499566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 3509318fe57SMatthew G. Knepley if (markerSeparate) { 3519318fe57SMatthew G. Knepley markerRight = 2; 3529318fe57SMatthew G. Knepley markerLeft = 1; 3539318fe57SMatthew G. Knepley } 3549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 355c5853193SPierre Jolivet if (rank == 0) { 3569566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numVertices)); 3579566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3589566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft)); 3599566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight)); 3609318fe57SMatthew G. Knepley } 3619566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 3629566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 3639318fe57SMatthew G. Knepley /* Build coordinates */ 3649566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 3659566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 3669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 3679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, 0, numVertices)); 3689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 3699318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 3709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 3719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 3729318fe57SMatthew G. Knepley } 3739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 3749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 3759566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 3769566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 3779566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 3789566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 3799566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 3809566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 3819318fe57SMatthew G. Knepley coords[0] = lower[0]; 3829318fe57SMatthew G. Knepley coords[1] = upper[0]; 3839566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 3849566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 3859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 3869318fe57SMatthew G. Knepley PetscFunctionReturn(0); 3879318fe57SMatthew G. Knepley } 38826492d91SMatthew G. Knepley 389d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 390d71ae5a4SJacob Faibussowitsch { 3911df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0] + 1) * (edges[1] + 1); 3921df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1]; 393552f7358SJed Brown PetscInt markerTop = 1; 394552f7358SJed Brown PetscInt markerBottom = 1; 395552f7358SJed Brown PetscInt markerRight = 1; 396552f7358SJed Brown PetscInt markerLeft = 1; 397552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 398552f7358SJed Brown Vec coordinates; 399552f7358SJed Brown PetscSection coordSection; 400552f7358SJed Brown PetscScalar *coords; 401552f7358SJed Brown PetscInt coordSize; 402552f7358SJed Brown PetscMPIInt rank; 403552f7358SJed Brown PetscInt v, vx, vy; 404552f7358SJed Brown 405552f7358SJed Brown PetscFunctionBegin; 4069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 407552f7358SJed Brown if (markerSeparate) { 4081df21d24SMatthew G. Knepley markerTop = 3; 4091df21d24SMatthew G. Knepley markerBottom = 1; 4101df21d24SMatthew G. Knepley markerRight = 2; 4111df21d24SMatthew G. Knepley markerLeft = 4; 412552f7358SJed Brown } 4139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 414dd400576SPatrick Sanan if (rank == 0) { 415552f7358SJed Brown PetscInt e, ex, ey; 416552f7358SJed Brown 4179566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices)); 41848a46eb9SPierre Jolivet for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 4199566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 420552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 421552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 422552f7358SJed Brown PetscInt edge = vx * edges[1] + ey + edges[0] * (edges[1] + 1); 423552f7358SJed Brown PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges; 424da80777bSKarl Rupp PetscInt cone[2]; 425552f7358SJed Brown 4269371c9d4SSatish Balay cone[0] = vertex; 4279371c9d4SSatish Balay cone[1] = vertex + edges[0] + 1; 4289566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 429552f7358SJed Brown if (vx == edges[0]) { 4309566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 4319566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 432552f7358SJed Brown if (ey == edges[1] - 1) { 4339566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 4349566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 435552f7358SJed Brown } 436552f7358SJed Brown } else if (vx == 0) { 4379566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 4389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 439552f7358SJed Brown if (ey == edges[1] - 1) { 4409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 4419566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 442552f7358SJed Brown } 443552f7358SJed Brown } 444552f7358SJed Brown } 445552f7358SJed Brown } 446552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 447552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 448552f7358SJed Brown PetscInt edge = vy * edges[0] + ex; 449552f7358SJed Brown PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges; 450da80777bSKarl Rupp PetscInt cone[2]; 451552f7358SJed Brown 4529371c9d4SSatish Balay cone[0] = vertex; 4539371c9d4SSatish Balay cone[1] = vertex + 1; 4549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 455552f7358SJed Brown if (vy == edges[1]) { 4569566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 4579566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 458552f7358SJed Brown if (ex == edges[0] - 1) { 4599566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 4609566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 461552f7358SJed Brown } 462552f7358SJed Brown } else if (vy == 0) { 4639566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 4649566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 465552f7358SJed Brown if (ex == edges[0] - 1) { 4669566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 4679566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 468552f7358SJed Brown } 469552f7358SJed Brown } 470552f7358SJed Brown } 471552f7358SJed Brown } 472552f7358SJed Brown } 4739566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 4749566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 475552f7358SJed Brown /* Build coordinates */ 4769566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 2)); 4779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 4789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 4799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 4809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 481552f7358SJed Brown for (v = numEdges; v < numEdges + numVertices; ++v) { 4829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 2)); 4839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 484552f7358SJed Brown } 4859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 4879566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 4889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 4899566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 4909566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 2)); 4919566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 4929566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 493552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 494552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 495552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx; 496552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy; 497552f7358SJed Brown } 498552f7358SJed Brown } 4999566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 5009566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 5019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 502552f7358SJed Brown PetscFunctionReturn(0); 503552f7358SJed Brown } 504552f7358SJed Brown 505d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 506d71ae5a4SJacob Faibussowitsch { 5079e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 5087b59f5a9SMichael Lange PetscInt numFaces = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2]; 509c2df9bbfSMatthew G. Knepley PetscInt markerTop = 1; 510c2df9bbfSMatthew G. Knepley PetscInt markerBottom = 1; 511c2df9bbfSMatthew G. Knepley PetscInt markerFront = 1; 512c2df9bbfSMatthew G. Knepley PetscInt markerBack = 1; 513c2df9bbfSMatthew G. Knepley PetscInt markerRight = 1; 514c2df9bbfSMatthew G. Knepley PetscInt markerLeft = 1; 515c2df9bbfSMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 516552f7358SJed Brown Vec coordinates; 517552f7358SJed Brown PetscSection coordSection; 518552f7358SJed Brown PetscScalar *coords; 519552f7358SJed Brown PetscInt coordSize; 520552f7358SJed Brown PetscMPIInt rank; 521552f7358SJed Brown PetscInt v, vx, vy, vz; 5227b59f5a9SMichael Lange PetscInt voffset, iface = 0, cone[4]; 523552f7358SJed Brown 524552f7358SJed Brown PetscFunctionBegin; 5251dca8a05SBarry 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"); 5269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 527c2df9bbfSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 528c2df9bbfSMatthew G. Knepley if (markerSeparate) { 529c2df9bbfSMatthew G. Knepley markerBottom = 1; 530c2df9bbfSMatthew G. Knepley markerTop = 2; 531c2df9bbfSMatthew G. Knepley markerFront = 3; 532c2df9bbfSMatthew G. Knepley markerBack = 4; 533c2df9bbfSMatthew G. Knepley markerRight = 5; 534c2df9bbfSMatthew G. Knepley markerLeft = 6; 535c2df9bbfSMatthew G. Knepley } 5369371c9d4SSatish Balay vertices[0] = faces[0] + 1; 5379371c9d4SSatish Balay vertices[1] = faces[1] + 1; 5389371c9d4SSatish Balay vertices[2] = faces[2] + 1; 5399e8abbc3SMichael Lange numVertices = vertices[0] * vertices[1] * vertices[2]; 540dd400576SPatrick Sanan if (rank == 0) { 541552f7358SJed Brown PetscInt f; 542552f7358SJed Brown 5439566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices)); 54448a46eb9SPierre Jolivet for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 5459566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 5467b59f5a9SMichael Lange 5477b59f5a9SMichael Lange /* Side 0 (Top) */ 5487b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5497b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5507b59f5a9SMichael Lange voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx; 5519371c9d4SSatish Balay cone[0] = voffset; 5529371c9d4SSatish Balay cone[1] = voffset + 1; 5539371c9d4SSatish Balay cone[2] = voffset + vertices[0] + 1; 5549371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 5559566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 556c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop)); 557c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop)); 558c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop)); 559c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop)); 560c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop)); 5617b59f5a9SMichael Lange iface++; 562552f7358SJed Brown } 563552f7358SJed Brown } 5647b59f5a9SMichael Lange 5657b59f5a9SMichael Lange /* Side 1 (Bottom) */ 5667b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5677b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5687b59f5a9SMichael Lange voffset = numFaces + vy * (faces[0] + 1) + vx; 5699371c9d4SSatish Balay cone[0] = voffset + 1; 5709371c9d4SSatish Balay cone[1] = voffset; 5719371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 5729371c9d4SSatish Balay cone[3] = voffset + vertices[0] + 1; 5739566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 574c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom)); 575c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom)); 576c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom)); 577c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom)); 578c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom)); 5797b59f5a9SMichael Lange iface++; 580552f7358SJed Brown } 581552f7358SJed Brown } 5827b59f5a9SMichael Lange 5837b59f5a9SMichael Lange /* Side 2 (Front) */ 5847b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 5857b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5867b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vx; 5879371c9d4SSatish Balay cone[0] = voffset; 5889371c9d4SSatish Balay cone[1] = voffset + 1; 5899371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + 1; 5909371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1]; 5919566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 592c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront)); 593c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront)); 594c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront)); 595c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront)); 596c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront)); 5977b59f5a9SMichael Lange iface++; 598552f7358SJed Brown } 5997b59f5a9SMichael Lange } 6007b59f5a9SMichael Lange 6017b59f5a9SMichael Lange /* Side 3 (Back) */ 6027b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6037b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 6047b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx; 6059371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 6069371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1] + 1; 6079371c9d4SSatish Balay cone[2] = voffset + 1; 6089371c9d4SSatish Balay cone[3] = voffset; 6099566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 610c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack)); 611c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack)); 612c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack)); 613c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack)); 614c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack)); 6157b59f5a9SMichael Lange iface++; 6167b59f5a9SMichael Lange } 6177b59f5a9SMichael Lange } 6187b59f5a9SMichael Lange 6197b59f5a9SMichael Lange /* Side 4 (Left) */ 6207b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6217b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 6227b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0]; 6239371c9d4SSatish Balay cone[0] = voffset; 6249371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1]; 6259371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + vertices[0]; 6269371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 6279566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 628c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft)); 629c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft)); 630c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft)); 631c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft)); 632c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft)); 6337b59f5a9SMichael Lange iface++; 6347b59f5a9SMichael Lange } 6357b59f5a9SMichael Lange } 6367b59f5a9SMichael Lange 6377b59f5a9SMichael Lange /* Side 5 (Right) */ 6387b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6397b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 640aab5bcd8SJed Brown voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0]; 6419371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 6429371c9d4SSatish Balay cone[1] = voffset; 6439371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 6449371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1] + vertices[0]; 6459566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 646c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight)); 647c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight)); 648c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight)); 649c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight)); 650c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight)); 6517b59f5a9SMichael Lange iface++; 6527b59f5a9SMichael Lange } 653552f7358SJed Brown } 654552f7358SJed Brown } 6559566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 6569566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 657552f7358SJed Brown /* Build coordinates */ 6589566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 3)); 6599566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 6609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 6629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 663552f7358SJed Brown for (v = numFaces; v < numFaces + numVertices; ++v) { 6649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 3)); 6659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 666552f7358SJed Brown } 6679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 6699566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 6709566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 6719566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6729566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 3)); 6739566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 6749566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 675552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 676552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 677552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 678552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx; 679552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy; 680552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz; 681552f7358SJed Brown } 682552f7358SJed Brown } 683552f7358SJed Brown } 6849566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 6859566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 6869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 687552f7358SJed Brown PetscFunctionReturn(0); 688552f7358SJed Brown } 689552f7358SJed Brown 690d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) 691d71ae5a4SJacob Faibussowitsch { 6929318fe57SMatthew G. Knepley PetscFunctionBegin; 6939318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 6949566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim - 1)); 6959566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim)); 6969318fe57SMatthew G. Knepley switch (dim) { 697d71ae5a4SJacob Faibussowitsch case 1: 698d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); 699d71ae5a4SJacob Faibussowitsch break; 700d71ae5a4SJacob Faibussowitsch case 2: 701d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); 702d71ae5a4SJacob Faibussowitsch break; 703d71ae5a4SJacob Faibussowitsch case 3: 704d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); 705d71ae5a4SJacob Faibussowitsch break; 706d71ae5a4SJacob Faibussowitsch default: 707d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim); 7089318fe57SMatthew G. Knepley } 7099566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 7109318fe57SMatthew G. Knepley PetscFunctionReturn(0); 7119318fe57SMatthew G. Knepley } 7129318fe57SMatthew G. Knepley 7139318fe57SMatthew G. Knepley /*@C 7149318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 7159318fe57SMatthew G. Knepley 7169318fe57SMatthew G. Knepley Collective 7179318fe57SMatthew G. Knepley 7189318fe57SMatthew G. Knepley Input Parameters: 7199318fe57SMatthew G. Knepley + comm - The communicator for the DM object 7209318fe57SMatthew G. Knepley . dim - The spatial dimension of the box, so the resulting mesh is has dimension dim-1 7219318fe57SMatthew 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 7229318fe57SMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 7239318fe57SMatthew G. Knepley . upper - The upper right corner, or NULL for (1, 1, 1) 7249318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 7259318fe57SMatthew G. Knepley 7269318fe57SMatthew G. Knepley Output Parameter: 7279318fe57SMatthew G. Knepley . dm - The DM object 7289318fe57SMatthew G. Knepley 7299318fe57SMatthew G. Knepley Level: beginner 7309318fe57SMatthew G. Knepley 731db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()` 7329318fe57SMatthew G. Knepley @*/ 733d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 734d71ae5a4SJacob Faibussowitsch { 7359318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 7369318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 7379318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 7389318fe57SMatthew G. Knepley 7399318fe57SMatthew G. Knepley PetscFunctionBegin; 7409566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 7419566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 7429566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 7439318fe57SMatthew G. Knepley PetscFunctionReturn(0); 7449318fe57SMatthew G. Knepley } 7459318fe57SMatthew G. Knepley 746d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) 747d71ae5a4SJacob Faibussowitsch { 748fdbf62faSLisandro Dalcin PetscInt i, fStart, fEnd, numCells = 0, numVerts = 0; 749fdbf62faSLisandro Dalcin PetscInt numPoints[2], *coneSize, *cones, *coneOrientations; 750fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 751fdbf62faSLisandro Dalcin PetscReal L, maxCell; 752fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 753fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 754fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 755fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 756fdbf62faSLisandro Dalcin PetscMPIInt rank; 757fdbf62faSLisandro Dalcin 758fdbf62faSLisandro Dalcin PetscFunctionBegin; 7599318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 760fdbf62faSLisandro Dalcin 7619566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, 1)); 7629566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 7639566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 764fdbf62faSLisandro Dalcin 7659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 766dd400576SPatrick Sanan if (rank == 0) numCells = segments; 767dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 768fdbf62faSLisandro Dalcin 7699371c9d4SSatish Balay numPoints[0] = numVerts; 7709371c9d4SSatish Balay numPoints[1] = numCells; 7719566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords)); 7729566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts)); 773ad540459SPierre Jolivet for (i = 0; i < numCells; ++i) coneSize[i] = 2; 774ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0; 7759371c9d4SSatish Balay for (i = 0; i < numCells; ++i) { 7769371c9d4SSatish Balay cones[2 * i] = numCells + i % numVerts; 7779371c9d4SSatish Balay cones[2 * i + 1] = numCells + (i + 1) % numVerts; 7789371c9d4SSatish Balay } 779ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); 7809566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 7819566063dSJacob Faibussowitsch PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords)); 782fdbf62faSLisandro Dalcin 7839566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 7849371c9d4SSatish Balay if (markerSeparate) { 7859371c9d4SSatish Balay markerLeft = faceMarkerLeft; 7869371c9d4SSatish Balay markerRight = faceMarkerRight; 7879371c9d4SSatish Balay } 788dd400576SPatrick Sanan if (!wrap && rank == 0) { 7899566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 7909566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft)); 7919566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight)); 7929566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft)); 7939566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight)); 794fdbf62faSLisandro Dalcin } 795fdbf62faSLisandro Dalcin if (wrap) { 796fdbf62faSLisandro Dalcin L = upper - lower; 797fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments)); 7984fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L)); 799fdbf62faSLisandro Dalcin } 8009566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 801fdbf62faSLisandro Dalcin PetscFunctionReturn(0); 802fdbf62faSLisandro Dalcin } 803fdbf62faSLisandro Dalcin 804d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 805d71ae5a4SJacob Faibussowitsch { 8069318fe57SMatthew G. Knepley DM boundary, vol; 807c22d3578SMatthew G. Knepley DMLabel bdlabel; 808d6218766SMatthew G. Knepley 809d6218766SMatthew G. Knepley PetscFunctionBegin; 8109318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 811c22d3578SMatthew 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"); 8129566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary)); 8139566063dSJacob Faibussowitsch PetscCall(DMSetType(boundary, DMPLEX)); 8149566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 8159566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 816c22d3578SMatthew G. Knepley PetscCall(DMGetLabel(vol, "marker", &bdlabel)); 817c22d3578SMatthew G. Knepley if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel)); 8185de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol)); 81969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 8209566063dSJacob Faibussowitsch PetscCall(DMDestroy(&boundary)); 821d6218766SMatthew G. Knepley PetscFunctionReturn(0); 822d6218766SMatthew G. Knepley } 823d6218766SMatthew G. Knepley 824d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 825d71ae5a4SJacob Faibussowitsch { 826ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 827f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 828f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 829f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 830f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 831f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 832f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 8333dfda0b1SToby Isaac PetscInt dim; 834d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 8353dfda0b1SToby Isaac PetscMPIInt rank; 8363dfda0b1SToby Isaac 8373dfda0b1SToby Isaac PetscFunctionBegin; 8389566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8409566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 8419566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 8429566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 8439371c9d4SSatish 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) { 8449371c9d4SSatish Balay if (cutMarker) { 8459371c9d4SSatish Balay PetscCall(DMCreateLabel(dm, "periodic_cut")); 8469371c9d4SSatish Balay PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 8479371c9d4SSatish Balay } 848d8211ee3SMatthew G. Knepley } 8493dfda0b1SToby Isaac switch (dim) { 8503dfda0b1SToby Isaac case 2: 851f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 852f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 853f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 854f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 8553dfda0b1SToby Isaac break; 8563dfda0b1SToby Isaac case 3: 857f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 858f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 859f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 860f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 861f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 862f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 8633dfda0b1SToby Isaac break; 864d71ae5a4SJacob Faibussowitsch default: 865d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 8663dfda0b1SToby Isaac } 8679566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 868f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 869f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 870f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 871f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 872f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 873f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 874f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 8753dfda0b1SToby Isaac } 8763dfda0b1SToby Isaac { 877dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 878dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 879dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 880dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0; 881dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0; 882dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0; 8833dfda0b1SToby Isaac const PetscInt numCells = numXEdges * numYEdges * numZEdges; 8843dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges * numZEdges; 8853dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges * numZEdges; 8863dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges * numYEdges; 8873dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices * numXFaces; 8883dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices * numYFaces; 8893dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices * numZFaces; 8903dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 8913dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices; 8923dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices; 8933dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices; 8943dfda0b1SToby Isaac const PetscInt numVertices = numXVertices * numYVertices * numZVertices; 8953dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 8963dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 8973dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 8983dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 8993dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 9003dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 9013dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 9023dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 9033dfda0b1SToby Isaac Vec coordinates; 9043dfda0b1SToby Isaac PetscSection coordSection; 9053dfda0b1SToby Isaac PetscScalar *coords; 9063dfda0b1SToby Isaac PetscInt coordSize; 9073dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 9083dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 9093dfda0b1SToby Isaac 9109566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices)); 91148a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 91248a46eb9SPierre Jolivet for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 91348a46eb9SPierre Jolivet for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 9149566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 9153dfda0b1SToby Isaac /* Build cells */ 9163dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 9173dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 9183dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 9193dfda0b1SToby Isaac PetscInt cell = (fz * numYEdges + fy) * numXEdges + fx; 9203dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 9213dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices); 9223dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 9233dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices); 9243dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 9253dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices); 9263dfda0b1SToby Isaac /* B, T, F, K, R, L */ 927b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 92842206facSLisandro Dalcin PetscInt cone[6]; 9293dfda0b1SToby Isaac 9303dfda0b1SToby Isaac /* no boundary twisting in 3D */ 9319371c9d4SSatish Balay cone[0] = faceB; 9329371c9d4SSatish Balay cone[1] = faceT; 9339371c9d4SSatish Balay cone[2] = faceF; 9349371c9d4SSatish Balay cone[3] = faceK; 9359371c9d4SSatish Balay cone[4] = faceR; 9369371c9d4SSatish Balay cone[5] = faceL; 9379566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, cell, cone)); 9389566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, cell, ornt)); 9399566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9409566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9419566063dSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9423dfda0b1SToby Isaac } 9433dfda0b1SToby Isaac } 9443dfda0b1SToby Isaac } 9453dfda0b1SToby Isaac /* Build x faces */ 9463dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 9473dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 9483dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 9493dfda0b1SToby Isaac PetscInt face = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 9503dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 9513dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz; 9523dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 9533dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy; 954b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 9553dfda0b1SToby Isaac PetscInt cone[4]; 9563dfda0b1SToby Isaac 9573dfda0b1SToby Isaac if (dim == 3) { 9583dfda0b1SToby Isaac /* markers */ 9593dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 9603dfda0b1SToby Isaac if (fx == numXVertices - 1) { 9619566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 9629566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerRight)); 9639371c9d4SSatish Balay } else if (fx == 0) { 9649566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 9659566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft)); 9663dfda0b1SToby Isaac } 9673dfda0b1SToby Isaac } 9683dfda0b1SToby Isaac } 9699371c9d4SSatish Balay cone[0] = edgeB; 9709371c9d4SSatish Balay cone[1] = edgeR; 9719371c9d4SSatish Balay cone[2] = edgeT; 9729371c9d4SSatish Balay cone[3] = edgeL; 9739566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 9749566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 9753dfda0b1SToby Isaac } 9763dfda0b1SToby Isaac } 9773dfda0b1SToby Isaac } 9783dfda0b1SToby Isaac /* Build y faces */ 9793dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 98042206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 9813dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 9823dfda0b1SToby Isaac PetscInt face = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 9833dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 9843dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz; 9853dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 9863dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx; 987b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 9883dfda0b1SToby Isaac PetscInt cone[4]; 9893dfda0b1SToby Isaac 9903dfda0b1SToby Isaac if (dim == 3) { 9913dfda0b1SToby Isaac /* markers */ 9923dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 9933dfda0b1SToby Isaac if (fy == numYVertices - 1) { 9949566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 9959566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBack)); 9969371c9d4SSatish Balay } else if (fy == 0) { 9979566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 9989566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerFront)); 9993dfda0b1SToby Isaac } 10003dfda0b1SToby Isaac } 10013dfda0b1SToby Isaac } 10029371c9d4SSatish Balay cone[0] = edgeB; 10039371c9d4SSatish Balay cone[1] = edgeR; 10049371c9d4SSatish Balay cone[2] = edgeT; 10059371c9d4SSatish Balay cone[3] = edgeL; 10069566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 10079566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 10083dfda0b1SToby Isaac } 10093dfda0b1SToby Isaac } 10103dfda0b1SToby Isaac } 10113dfda0b1SToby Isaac /* Build z faces */ 10123dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 10133dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 10143dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 10153dfda0b1SToby Isaac PetscInt face = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 10163dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 10173dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy; 10183dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 10193dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx; 1020b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 10213dfda0b1SToby Isaac PetscInt cone[4]; 10223dfda0b1SToby Isaac 10233dfda0b1SToby Isaac if (dim == 2) { 10249371c9d4SSatish Balay if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) { 10259371c9d4SSatish Balay edgeR += numYEdges - 1 - 2 * fy; 10269371c9d4SSatish Balay ornt[1] = -1; 10279371c9d4SSatish Balay } 10289371c9d4SSatish Balay if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) { 10299371c9d4SSatish Balay edgeT += numXEdges - 1 - 2 * fx; 10309371c9d4SSatish Balay ornt[2] = 0; 10319371c9d4SSatish Balay } 10329566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 10339566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 1034d1c88043SMatthew G. Knepley } else { 10353dfda0b1SToby Isaac /* markers */ 10363dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 10373dfda0b1SToby Isaac if (fz == numZVertices - 1) { 10389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 10399566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerTop)); 10409371c9d4SSatish Balay } else if (fz == 0) { 10419566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 10429566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom)); 10433dfda0b1SToby Isaac } 10443dfda0b1SToby Isaac } 10453dfda0b1SToby Isaac } 10469371c9d4SSatish Balay cone[0] = edgeB; 10479371c9d4SSatish Balay cone[1] = edgeR; 10489371c9d4SSatish Balay cone[2] = edgeT; 10499371c9d4SSatish Balay cone[3] = edgeL; 10509566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 10519566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 10523dfda0b1SToby Isaac } 10533dfda0b1SToby Isaac } 10543dfda0b1SToby Isaac } 10553dfda0b1SToby Isaac /* Build Z edges*/ 10563dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 10573dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 10583dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 10593dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez; 10603dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx; 10613dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx; 10623dfda0b1SToby Isaac PetscInt cone[2]; 10633dfda0b1SToby Isaac 10649371c9d4SSatish Balay cone[0] = vertexB; 10659371c9d4SSatish Balay cone[1] = vertexT; 1066c2df9bbfSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, edge, cone)); 10673dfda0b1SToby Isaac if (dim == 3) { 10683dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 10693dfda0b1SToby Isaac if (vx == numXVertices - 1) { 10709566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1071c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1072c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1073c2df9bbfSMatthew G. Knepley } else if (vx == 0) { 10749566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1075c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1076c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 10773dfda0b1SToby Isaac } 10783dfda0b1SToby Isaac } 10793dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 10803dfda0b1SToby Isaac if (vy == numYVertices - 1) { 10819566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1082c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1083c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1084c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 10859566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1086c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1087c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 10883dfda0b1SToby Isaac } 10893dfda0b1SToby Isaac } 10903dfda0b1SToby Isaac } 10913dfda0b1SToby Isaac } 10923dfda0b1SToby Isaac } 10933dfda0b1SToby Isaac } 10943dfda0b1SToby Isaac /* Build Y edges*/ 10953dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 10963dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 10973dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 10983dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx; 10993dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey; 11003dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx; 11013dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 11023dfda0b1SToby Isaac PetscInt cone[2]; 11033dfda0b1SToby Isaac 11049371c9d4SSatish Balay cone[0] = vertexF; 11059371c9d4SSatish Balay cone[1] = vertexK; 11069566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 11073dfda0b1SToby Isaac if (dim == 2) { 11083dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 11093dfda0b1SToby Isaac if (vx == numXVertices - 1) { 11109566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 11119566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 11129566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1113c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1114d8211ee3SMatthew G. Knepley } else if (vx == 0) { 11159566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 11169566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 11179566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1118c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 11193dfda0b1SToby Isaac } 1120d8211ee3SMatthew G. Knepley } else { 11214c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 11229566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 11239566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1124c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 11253dfda0b1SToby Isaac } 1126d8211ee3SMatthew G. Knepley } 1127d8211ee3SMatthew G. Knepley } else { 11283dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 11293dfda0b1SToby Isaac if (vx == numXVertices - 1) { 11309566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1131c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1132c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1133d8211ee3SMatthew G. Knepley } else if (vx == 0) { 11349566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1135c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1136c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 11373dfda0b1SToby Isaac } 11383dfda0b1SToby Isaac } 11393dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 11403dfda0b1SToby Isaac if (vz == numZVertices - 1) { 11419566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1142c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1143c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1144d8211ee3SMatthew G. Knepley } else if (vz == 0) { 11459566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1146c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1147c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 11483dfda0b1SToby Isaac } 11493dfda0b1SToby Isaac } 11503dfda0b1SToby Isaac } 11513dfda0b1SToby Isaac } 11523dfda0b1SToby Isaac } 11533dfda0b1SToby Isaac } 11543dfda0b1SToby Isaac /* Build X edges*/ 11553dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 11563dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 11573dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 11583dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices; 11593dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex; 11603dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex; 11613dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 11623dfda0b1SToby Isaac PetscInt cone[2]; 11633dfda0b1SToby Isaac 11649371c9d4SSatish Balay cone[0] = vertexL; 11659371c9d4SSatish Balay cone[1] = vertexR; 11669566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 11673dfda0b1SToby Isaac if (dim == 2) { 11683dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 11693dfda0b1SToby Isaac if (vy == numYVertices - 1) { 11709566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 11719566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 11729566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1173c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1174d8211ee3SMatthew G. Knepley } else if (vy == 0) { 11759566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 11769566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 11779566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1178c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 11793dfda0b1SToby Isaac } 1180d8211ee3SMatthew G. Knepley } else { 11814c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 11829566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 11839566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1184c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 11853dfda0b1SToby Isaac } 1186d8211ee3SMatthew G. Knepley } 1187d8211ee3SMatthew G. Knepley } else { 11883dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 11893dfda0b1SToby Isaac if (vy == numYVertices - 1) { 11909566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1191c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1192c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1193c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 11949566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1195c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1196c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 11973dfda0b1SToby Isaac } 11983dfda0b1SToby Isaac } 11993dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 12003dfda0b1SToby Isaac if (vz == numZVertices - 1) { 12019566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1202c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1203c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1204c2df9bbfSMatthew G. Knepley } else if (vz == 0) { 12059566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1206c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1207c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 12083dfda0b1SToby Isaac } 12093dfda0b1SToby Isaac } 12103dfda0b1SToby Isaac } 12113dfda0b1SToby Isaac } 12123dfda0b1SToby Isaac } 12133dfda0b1SToby Isaac } 12149566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 12159566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 12163dfda0b1SToby Isaac /* Build coordinates */ 12179566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 12189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 12199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 12209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 12213dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex + numVertices; ++v) { 12229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 12239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 12243dfda0b1SToby Isaac } 12259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 12269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 12279566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 12289566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 12299566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 12309566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 12319566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 12329566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12333dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 12343dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 12353dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 12363dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 12373dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1238ad540459SPierre Jolivet if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; 12393dfda0b1SToby Isaac } 12403dfda0b1SToby Isaac } 12413dfda0b1SToby Isaac } 12429566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12439566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 12449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 12453dfda0b1SToby Isaac } 12463dfda0b1SToby Isaac PetscFunctionReturn(0); 12473dfda0b1SToby Isaac } 12483dfda0b1SToby Isaac 1249d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1250d71ae5a4SJacob Faibussowitsch { 12519318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 12529318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1253552f7358SJed Brown 1254552f7358SJed Brown PetscFunctionBegin; 12559318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 12569318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 12579566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 12589371c9d4SSatish Balay for (d = 0; d < dim; ++d) { 12599371c9d4SSatish Balay fac[d] = faces[d]; 12609371c9d4SSatish Balay bdt[d] = periodicity[d]; 12619371c9d4SSatish Balay } 12629566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 12639371c9d4SSatish 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))) { 12646858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 12656858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1266552f7358SJed Brown 12679318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 12686858538eSMatthew G. Knepley if (periodicity[d] != DM_BOUNDARY_NONE) { 12699318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 12709318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1271768d5fceSMatthew G. Knepley } 12726858538eSMatthew G. Knepley } 12734fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1274768d5fceSMatthew G. Knepley } 12759566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 12769318fe57SMatthew G. Knepley PetscFunctionReturn(0); 12779318fe57SMatthew G. Knepley } 12789318fe57SMatthew G. Knepley 1279d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 1280d71ae5a4SJacob Faibussowitsch { 12819318fe57SMatthew G. Knepley PetscFunctionBegin; 12829566063dSJacob Faibussowitsch if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 12839566063dSJacob Faibussowitsch else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 12849566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 12859318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1286768d5fceSMatthew G. Knepley DM udm; 1287768d5fceSMatthew G. Knepley 12889566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 12899566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, udm)); 129069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 1291768d5fceSMatthew G. Knepley } 1292768d5fceSMatthew G. Knepley PetscFunctionReturn(0); 1293c8c68bd8SToby Isaac } 1294c8c68bd8SToby Isaac 1295768d5fceSMatthew G. Knepley /*@C 1296768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1297768d5fceSMatthew G. Knepley 1298d083f849SBarry Smith Collective 1299768d5fceSMatthew G. Knepley 1300768d5fceSMatthew G. Knepley Input Parameters: 1301768d5fceSMatthew G. Knepley + comm - The communicator for the DM object 1302768d5fceSMatthew G. Knepley . dim - The spatial dimension 1303768d5fceSMatthew G. Knepley . simplex - PETSC_TRUE for simplices, PETSC_FALSE for tensor cells 1304fdbf62faSLisandro Dalcin . faces - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 1305768d5fceSMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 1306768d5fceSMatthew G. Knepley . upper - The upper right corner, or NULL for (1, 1, 1) 1307fdbf62faSLisandro Dalcin . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE 1308768d5fceSMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 1309768d5fceSMatthew G. Knepley 1310768d5fceSMatthew G. Knepley Output Parameter: 1311768d5fceSMatthew G. Knepley . dm - The DM object 1312768d5fceSMatthew G. Knepley 13139318fe57SMatthew G. Knepley Note: If you want to customize this mesh using options, you just need to 13149318fe57SMatthew G. Knepley $ DMCreate(comm, &dm); 13159318fe57SMatthew G. Knepley $ DMSetType(dm, DMPLEX); 13169318fe57SMatthew G. Knepley $ DMSetFromOptions(dm); 13179318fe57SMatthew G. Knepley and use the options on the DMSetFromOptions() page. 13181367e252SJed Brown 13191367e252SJed Brown Here is the numbering returned for 2 faces in each direction for tensor cells: 1320768d5fceSMatthew G. Knepley $ 10---17---11---18----12 1321768d5fceSMatthew G. Knepley $ | | | 1322768d5fceSMatthew G. Knepley $ | | | 1323768d5fceSMatthew G. Knepley $ 20 2 22 3 24 1324768d5fceSMatthew G. Knepley $ | | | 1325768d5fceSMatthew G. Knepley $ | | | 1326768d5fceSMatthew G. Knepley $ 7---15----8---16----9 1327768d5fceSMatthew G. Knepley $ | | | 1328768d5fceSMatthew G. Knepley $ | | | 1329768d5fceSMatthew G. Knepley $ 19 0 21 1 23 1330768d5fceSMatthew G. Knepley $ | | | 1331768d5fceSMatthew G. Knepley $ | | | 1332768d5fceSMatthew G. Knepley $ 4---13----5---14----6 1333768d5fceSMatthew G. Knepley 1334768d5fceSMatthew G. Knepley and for simplicial cells 1335768d5fceSMatthew G. Knepley 1336768d5fceSMatthew G. Knepley $ 14----8---15----9----16 1337768d5fceSMatthew G. Knepley $ |\ 5 |\ 7 | 1338768d5fceSMatthew G. Knepley $ | \ | \ | 1339768d5fceSMatthew G. Knepley $ 13 2 14 3 15 1340768d5fceSMatthew G. Knepley $ | 4 \ | 6 \ | 1341768d5fceSMatthew G. Knepley $ | \ | \ | 1342768d5fceSMatthew G. Knepley $ 11----6---12----7----13 1343768d5fceSMatthew G. Knepley $ |\ |\ | 1344768d5fceSMatthew G. Knepley $ | \ 1 | \ 3 | 1345768d5fceSMatthew G. Knepley $ 10 0 11 1 12 1346768d5fceSMatthew G. Knepley $ | 0 \ | 2 \ | 1347768d5fceSMatthew G. Knepley $ | \ | \ | 1348768d5fceSMatthew G. Knepley $ 8----4----9----5----10 1349768d5fceSMatthew G. Knepley 1350768d5fceSMatthew G. Knepley Level: beginner 1351768d5fceSMatthew G. Knepley 1352db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 1353768d5fceSMatthew G. Knepley @*/ 1354d71ae5a4SJacob Faibussowitsch 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) 1355d71ae5a4SJacob Faibussowitsch { 13569318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 1357fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 1358fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 1359fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1360552f7358SJed Brown 1361768d5fceSMatthew G. Knepley PetscFunctionBegin; 13629566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 13639566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 13649566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 13657ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 13669318fe57SMatthew G. Knepley PetscFunctionReturn(0); 13679318fe57SMatthew G. Knepley } 1368fdbf62faSLisandro Dalcin 1369d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1370d71ae5a4SJacob Faibussowitsch { 13719318fe57SMatthew G. Knepley DM bdm, vol; 13729318fe57SMatthew G. Knepley PetscInt i; 13739318fe57SMatthew G. Knepley 13749318fe57SMatthew G. Knepley PetscFunctionBegin; 137508401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 13769566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 13779566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 13789566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 13799566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 13809566063dSJacob Faibussowitsch PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol)); 13819566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 138269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 13839318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 13849318fe57SMatthew G. Knepley Vec v; 13859318fe57SMatthew G. Knepley PetscScalar *x; 13869318fe57SMatthew G. Knepley PetscInt cDim, n; 13879318fe57SMatthew G. Knepley 13889566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 13899566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 13909566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 13919566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 13929318fe57SMatthew G. Knepley x += cDim; 13939318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 13949566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 13959566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 13969318fe57SMatthew G. Knepley } 1397552f7358SJed Brown PetscFunctionReturn(0); 1398552f7358SJed Brown } 1399552f7358SJed Brown 140000dabe28SStefano Zampini /*@ 140100dabe28SStefano Zampini DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells. 140200dabe28SStefano Zampini 1403d083f849SBarry Smith Collective 140400dabe28SStefano Zampini 140500dabe28SStefano Zampini Input Parameters: 140600dabe28SStefano Zampini + comm - The communicator for the DM object 140700dabe28SStefano Zampini . faces - Number of faces per dimension, or NULL for (1, 1, 1) 140800dabe28SStefano Zampini . lower - The lower left corner, or NULL for (0, 0, 0) 140900dabe28SStefano Zampini . upper - The upper right corner, or NULL for (1, 1, 1) 141000dabe28SStefano Zampini . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE 1411d0fcb9c2SMatthew G. Knepley . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 141200dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 141300dabe28SStefano Zampini 141400dabe28SStefano Zampini Output Parameter: 141500dabe28SStefano Zampini . dm - The DM object 141600dabe28SStefano Zampini 141700dabe28SStefano Zampini Level: beginner 141800dabe28SStefano Zampini 1419db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 142000dabe28SStefano Zampini @*/ 1421d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 1422d71ae5a4SJacob Faibussowitsch { 14239318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 142400dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 142500dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 142600dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 142700dabe28SStefano Zampini 142800dabe28SStefano Zampini PetscFunctionBegin; 14299566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 14309566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 14319566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 1432d410b0cfSMatthew G. Knepley if (!interpolate) { 1433d410b0cfSMatthew G. Knepley DM udm; 143400dabe28SStefano Zampini 14359566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 143669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 143700dabe28SStefano Zampini } 14387ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 143900dabe28SStefano Zampini PetscFunctionReturn(0); 144000dabe28SStefano Zampini } 144100dabe28SStefano Zampini 1442a9074c1eSMatthew G. Knepley /*@C 1443a9074c1eSMatthew G. Knepley DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database. 1444a9074c1eSMatthew G. Knepley 1445d083f849SBarry Smith Logically Collective on dm 1446a9074c1eSMatthew G. Knepley 1447a9074c1eSMatthew G. Knepley Input Parameters: 1448a9074c1eSMatthew G. Knepley + dm - the DM context 1449a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 1450a9074c1eSMatthew G. Knepley 1451a9074c1eSMatthew G. Knepley Notes: 1452a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 1453a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 1454a9074c1eSMatthew G. Knepley 1455a9074c1eSMatthew G. Knepley Level: advanced 1456a9074c1eSMatthew G. Knepley 1457db781477SPatrick Sanan .seealso: `SNESSetFromOptions()` 1458a9074c1eSMatthew G. Knepley @*/ 1459d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 1460d71ae5a4SJacob Faibussowitsch { 1461a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1462a9074c1eSMatthew G. Knepley 1463a9074c1eSMatthew G. Knepley PetscFunctionBegin; 1464a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14659566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 14669566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 1467a9074c1eSMatthew G. Knepley PetscFunctionReturn(0); 1468a9074c1eSMatthew G. Knepley } 1469a9074c1eSMatthew G. Knepley 14709318fe57SMatthew G. Knepley /* Remap geometry to cylinder 147161a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 147261a622f3SMatthew G. Knepley 14739318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 14749318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 14759318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 14760510c589SMatthew G. Knepley 14779318fe57SMatthew G. Knepley phi = arctan(y/x) 14789318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 14799318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 14800510c589SMatthew G. Knepley 14819318fe57SMatthew G. Knepley so we remap them using 14820510c589SMatthew G. Knepley 14839318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 14849318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 14850510c589SMatthew G. Knepley 14869318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 14879318fe57SMatthew G. Knepley */ 1488d71ae5a4SJacob Faibussowitsch static void snapToCylinder(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 1489d71ae5a4SJacob Faibussowitsch { 14909318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 14919318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 149222cc497dSMatthew G. Knepley 14939318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 14949318fe57SMatthew G. Knepley f0[0] = u[0]; 14959318fe57SMatthew G. Knepley f0[1] = u[1]; 14969318fe57SMatthew G. Knepley } else { 14979318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 14980510c589SMatthew G. Knepley 14999318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 15009318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 15019318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 15029318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 15039318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 15049318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 15059318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 15069318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 15079318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 15089318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 15099318fe57SMatthew G. Knepley } else { 15109318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 15119318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 15129318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 15139318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 15149318fe57SMatthew G. Knepley } 15159318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 15169318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 15179318fe57SMatthew G. Knepley } 15189318fe57SMatthew G. Knepley f0[2] = u[2]; 15199318fe57SMatthew G. Knepley } 15200510c589SMatthew G. Knepley 1521d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ) 1522d71ae5a4SJacob Faibussowitsch { 15230510c589SMatthew G. Knepley const PetscInt dim = 3; 15249318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 1525d8c47e87SMatthew G. Knepley PetscMPIInt rank; 15260510c589SMatthew G. Knepley 15270510c589SMatthew G. Knepley PetscFunctionBegin; 15289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15299566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 15300510c589SMatthew G. Knepley /* Create topology */ 15310510c589SMatthew G. Knepley { 15320510c589SMatthew G. Knepley PetscInt cone[8], c; 15330510c589SMatthew G. Knepley 1534dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 1535dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 1536006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 1537ae8bcbbbSMatthew G. Knepley numCells *= 3; 1538dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 1539006a8963SMatthew G. Knepley } 15409566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 15419566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 15429566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 1543dd400576SPatrick Sanan if (rank == 0) { 1544006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 15459371c9d4SSatish Balay cone[0] = 15; 15469371c9d4SSatish Balay cone[1] = 18; 15479371c9d4SSatish Balay cone[2] = 17; 15489371c9d4SSatish Balay cone[3] = 16; 15499371c9d4SSatish Balay cone[4] = 31; 15509371c9d4SSatish Balay cone[5] = 32; 15519371c9d4SSatish Balay cone[6] = 33; 15529371c9d4SSatish Balay cone[7] = 34; 15539566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 15549371c9d4SSatish Balay cone[0] = 16; 15559371c9d4SSatish Balay cone[1] = 17; 15569371c9d4SSatish Balay cone[2] = 24; 15579371c9d4SSatish Balay cone[3] = 23; 15589371c9d4SSatish Balay cone[4] = 32; 15599371c9d4SSatish Balay cone[5] = 36; 15609371c9d4SSatish Balay cone[6] = 37; 15619371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 15629566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 15639371c9d4SSatish Balay cone[0] = 18; 15649371c9d4SSatish Balay cone[1] = 27; 15659371c9d4SSatish Balay cone[2] = 24; 15669371c9d4SSatish Balay cone[3] = 17; 15679371c9d4SSatish Balay cone[4] = 34; 15689371c9d4SSatish Balay cone[5] = 33; 15699371c9d4SSatish Balay cone[6] = 37; 15709371c9d4SSatish Balay cone[7] = 38; 15719566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 15729371c9d4SSatish Balay cone[0] = 29; 15739371c9d4SSatish Balay cone[1] = 27; 15749371c9d4SSatish Balay cone[2] = 18; 15759371c9d4SSatish Balay cone[3] = 15; 15769371c9d4SSatish Balay cone[4] = 35; 15779371c9d4SSatish Balay cone[5] = 31; 15789371c9d4SSatish Balay cone[6] = 34; 15799371c9d4SSatish Balay cone[7] = 38; 15809566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 15819371c9d4SSatish Balay cone[0] = 29; 15829371c9d4SSatish Balay cone[1] = 15; 15839371c9d4SSatish Balay cone[2] = 16; 15849371c9d4SSatish Balay cone[3] = 23; 15859371c9d4SSatish Balay cone[4] = 35; 15869371c9d4SSatish Balay cone[5] = 36; 15879371c9d4SSatish Balay cone[6] = 32; 15889371c9d4SSatish Balay cone[7] = 31; 15899566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1590006a8963SMatthew G. Knepley 15919371c9d4SSatish Balay cone[0] = 31; 15929371c9d4SSatish Balay cone[1] = 34; 15939371c9d4SSatish Balay cone[2] = 33; 15949371c9d4SSatish Balay cone[3] = 32; 15959371c9d4SSatish Balay cone[4] = 19; 15969371c9d4SSatish Balay cone[5] = 22; 15979371c9d4SSatish Balay cone[6] = 21; 15989371c9d4SSatish Balay cone[7] = 20; 15999566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 16009371c9d4SSatish Balay cone[0] = 32; 16019371c9d4SSatish Balay cone[1] = 33; 16029371c9d4SSatish Balay cone[2] = 37; 16039371c9d4SSatish Balay cone[3] = 36; 16049371c9d4SSatish Balay cone[4] = 22; 16059371c9d4SSatish Balay cone[5] = 25; 16069371c9d4SSatish Balay cone[6] = 26; 16079371c9d4SSatish Balay cone[7] = 21; 16089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 16099371c9d4SSatish Balay cone[0] = 34; 16109371c9d4SSatish Balay cone[1] = 38; 16119371c9d4SSatish Balay cone[2] = 37; 16129371c9d4SSatish Balay cone[3] = 33; 16139371c9d4SSatish Balay cone[4] = 20; 16149371c9d4SSatish Balay cone[5] = 21; 16159371c9d4SSatish Balay cone[6] = 26; 16169371c9d4SSatish Balay cone[7] = 28; 16179566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 16189371c9d4SSatish Balay cone[0] = 35; 16199371c9d4SSatish Balay cone[1] = 38; 16209371c9d4SSatish Balay cone[2] = 34; 16219371c9d4SSatish Balay cone[3] = 31; 16229371c9d4SSatish Balay cone[4] = 30; 16239371c9d4SSatish Balay cone[5] = 19; 16249371c9d4SSatish Balay cone[6] = 20; 16259371c9d4SSatish Balay cone[7] = 28; 16269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 16279371c9d4SSatish Balay cone[0] = 35; 16289371c9d4SSatish Balay cone[1] = 31; 16299371c9d4SSatish Balay cone[2] = 32; 16309371c9d4SSatish Balay cone[3] = 36; 16319371c9d4SSatish Balay cone[4] = 30; 16329371c9d4SSatish Balay cone[5] = 25; 16339371c9d4SSatish Balay cone[6] = 22; 16349371c9d4SSatish Balay cone[7] = 19; 16359566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 1636ae8bcbbbSMatthew G. Knepley 16379371c9d4SSatish Balay cone[0] = 19; 16389371c9d4SSatish Balay cone[1] = 20; 16399371c9d4SSatish Balay cone[2] = 21; 16409371c9d4SSatish Balay cone[3] = 22; 16419371c9d4SSatish Balay cone[4] = 15; 16429371c9d4SSatish Balay cone[5] = 16; 16439371c9d4SSatish Balay cone[6] = 17; 16449371c9d4SSatish Balay cone[7] = 18; 16459566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 16469371c9d4SSatish Balay cone[0] = 22; 16479371c9d4SSatish Balay cone[1] = 21; 16489371c9d4SSatish Balay cone[2] = 26; 16499371c9d4SSatish Balay cone[3] = 25; 16509371c9d4SSatish Balay cone[4] = 16; 16519371c9d4SSatish Balay cone[5] = 23; 16529371c9d4SSatish Balay cone[6] = 24; 16539371c9d4SSatish Balay cone[7] = 17; 16549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 16559371c9d4SSatish Balay cone[0] = 20; 16569371c9d4SSatish Balay cone[1] = 28; 16579371c9d4SSatish Balay cone[2] = 26; 16589371c9d4SSatish Balay cone[3] = 21; 16599371c9d4SSatish Balay cone[4] = 18; 16609371c9d4SSatish Balay cone[5] = 17; 16619371c9d4SSatish Balay cone[6] = 24; 16629371c9d4SSatish Balay cone[7] = 27; 16639566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 16649371c9d4SSatish Balay cone[0] = 30; 16659371c9d4SSatish Balay cone[1] = 28; 16669371c9d4SSatish Balay cone[2] = 20; 16679371c9d4SSatish Balay cone[3] = 19; 16689371c9d4SSatish Balay cone[4] = 29; 16699371c9d4SSatish Balay cone[5] = 15; 16709371c9d4SSatish Balay cone[6] = 18; 16719371c9d4SSatish Balay cone[7] = 27; 16729566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 16739371c9d4SSatish Balay cone[0] = 30; 16749371c9d4SSatish Balay cone[1] = 19; 16759371c9d4SSatish Balay cone[2] = 22; 16769371c9d4SSatish Balay cone[3] = 25; 16779371c9d4SSatish Balay cone[4] = 29; 16789371c9d4SSatish Balay cone[5] = 23; 16799371c9d4SSatish Balay cone[6] = 16; 16809371c9d4SSatish Balay cone[7] = 15; 16819566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 1682006a8963SMatthew G. Knepley } else { 16839371c9d4SSatish Balay cone[0] = 5; 16849371c9d4SSatish Balay cone[1] = 8; 16859371c9d4SSatish Balay cone[2] = 7; 16869371c9d4SSatish Balay cone[3] = 6; 16879371c9d4SSatish Balay cone[4] = 9; 16889371c9d4SSatish Balay cone[5] = 12; 16899371c9d4SSatish Balay cone[6] = 11; 16909371c9d4SSatish Balay cone[7] = 10; 16919566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 16929371c9d4SSatish Balay cone[0] = 6; 16939371c9d4SSatish Balay cone[1] = 7; 16949371c9d4SSatish Balay cone[2] = 14; 16959371c9d4SSatish Balay cone[3] = 13; 16969371c9d4SSatish Balay cone[4] = 12; 16979371c9d4SSatish Balay cone[5] = 15; 16989371c9d4SSatish Balay cone[6] = 16; 16999371c9d4SSatish Balay cone[7] = 11; 17009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 17019371c9d4SSatish Balay cone[0] = 8; 17029371c9d4SSatish Balay cone[1] = 17; 17039371c9d4SSatish Balay cone[2] = 14; 17049371c9d4SSatish Balay cone[3] = 7; 17059371c9d4SSatish Balay cone[4] = 10; 17069371c9d4SSatish Balay cone[5] = 11; 17079371c9d4SSatish Balay cone[6] = 16; 17089371c9d4SSatish Balay cone[7] = 18; 17099566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 17109371c9d4SSatish Balay cone[0] = 19; 17119371c9d4SSatish Balay cone[1] = 17; 17129371c9d4SSatish Balay cone[2] = 8; 17139371c9d4SSatish Balay cone[3] = 5; 17149371c9d4SSatish Balay cone[4] = 20; 17159371c9d4SSatish Balay cone[5] = 9; 17169371c9d4SSatish Balay cone[6] = 10; 17179371c9d4SSatish Balay cone[7] = 18; 17189566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 17199371c9d4SSatish Balay cone[0] = 19; 17209371c9d4SSatish Balay cone[1] = 5; 17219371c9d4SSatish Balay cone[2] = 6; 17229371c9d4SSatish Balay cone[3] = 13; 17239371c9d4SSatish Balay cone[4] = 20; 17249371c9d4SSatish Balay cone[5] = 15; 17259371c9d4SSatish Balay cone[6] = 12; 17269371c9d4SSatish Balay cone[7] = 9; 17279566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1728006a8963SMatthew G. Knepley } 1729d8c47e87SMatthew G. Knepley } 17309566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 17319566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 17320510c589SMatthew G. Knepley } 1733dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 17340510c589SMatthew G. Knepley { 17350510c589SMatthew G. Knepley Vec coordinates; 17360510c589SMatthew G. Knepley PetscSection coordSection; 17370510c589SMatthew G. Knepley PetscScalar *coords; 17380510c589SMatthew G. Knepley PetscInt coordSize, v; 17390510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 17400510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 17410510c589SMatthew G. Knepley 17420510c589SMatthew G. Knepley /* Build coordinates */ 17439566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 17449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 17459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 17469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 17470510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 17489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 17499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 17500510c589SMatthew G. Knepley } 17519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 17529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 17539566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 17549566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 17559566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 17569566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 17579566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 17589566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 1759dd400576SPatrick Sanan if (rank == 0) { 17609371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 17619371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 17629371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 17639371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 17649371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 17659371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 17669371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 17679371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 17689371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 17699371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 17709371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 17719371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 17729371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 17739371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 17749371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 17759371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 17769371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 17779371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 17789371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 17799371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 17809371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 17819371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 17829371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 17839371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 17849371c9d4SSatish Balay coords[8 * dim + 0] = dis; 17859371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 17869371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 17879371c9d4SSatish Balay coords[9 * dim + 0] = dis; 17889371c9d4SSatish Balay coords[9 * dim + 1] = dis; 17899371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 17909371c9d4SSatish Balay coords[10 * dim + 0] = dis; 17919371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 17929371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 17939371c9d4SSatish Balay coords[11 * dim + 0] = dis; 17949371c9d4SSatish Balay coords[11 * dim + 1] = dis; 17959371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 17969371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 17979371c9d4SSatish Balay coords[12 * dim + 1] = dis; 17989371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 17999371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 18009371c9d4SSatish Balay coords[13 * dim + 1] = dis; 18019371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 18029371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 18039371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 18049371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 18059371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 18069371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 18079371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 1808ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 18099371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 18109371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 18119371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 18129371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 18139371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 18149371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 18159371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 18169371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 18179371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 18189371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 18199371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 18209371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 18219371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 18229371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 18239371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 18249371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 18259371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 18269371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 18279371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 18289371c9d4SSatish Balay coords[22 * dim + 1] = dis; 18299371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 18309371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 18319371c9d4SSatish Balay coords[23 * dim + 1] = dis; 18329371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 1833ae8bcbbbSMatthew G. Knepley } 1834d8c47e87SMatthew G. Knepley } 18359566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 18369566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 18379566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 18380510c589SMatthew G. Knepley } 1839006a8963SMatthew G. Knepley /* Create periodicity */ 1840006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 18416858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 18426858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1843006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 1844ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 18456858538eSMatthew G. Knepley PetscInt numZCells = 3; 1846006a8963SMatthew G. Knepley 18476858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 18486858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 18494fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1850006a8963SMatthew G. Knepley } 1851dbc1dc17SMatthew G. Knepley { 18529318fe57SMatthew G. Knepley DM cdm; 18539318fe57SMatthew G. Knepley PetscDS cds; 18549318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 1855dbc1dc17SMatthew G. Knepley 18569566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder)); 18579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18589566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 18599566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 1860dbc1dc17SMatthew G. Knepley } 18619318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 18629566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 18630510c589SMatthew G. Knepley PetscFunctionReturn(0); 18640510c589SMatthew G. Knepley } 18650510c589SMatthew G. Knepley 186624119c2aSMatthew G. Knepley /*@ 18679318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 186824119c2aSMatthew G. Knepley 1869d083f849SBarry Smith Collective 187024119c2aSMatthew G. Knepley 187124119c2aSMatthew G. Knepley Input Parameters: 187224119c2aSMatthew G. Knepley + comm - The communicator for the DM object 18739318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction 187424119c2aSMatthew G. Knepley 187524119c2aSMatthew G. Knepley Output Parameter: 187624119c2aSMatthew G. Knepley . dm - The DM object 187724119c2aSMatthew G. Knepley 18789318fe57SMatthew G. Knepley Note: 18799318fe57SMatthew G. Knepley Here is the output numbering looking from the bottom of the cylinder: 18809318fe57SMatthew G. Knepley $ 17-----14 18819318fe57SMatthew G. Knepley $ | | 18829318fe57SMatthew G. Knepley $ | 2 | 18839318fe57SMatthew G. Knepley $ | | 18849318fe57SMatthew G. Knepley $ 17-----8-----7-----14 18859318fe57SMatthew G. Knepley $ | | | | 18869318fe57SMatthew G. Knepley $ | 3 | 0 | 1 | 18879318fe57SMatthew G. Knepley $ | | | | 18889318fe57SMatthew G. Knepley $ 19-----5-----6-----13 18899318fe57SMatthew G. Knepley $ | | 18909318fe57SMatthew G. Knepley $ | 4 | 18919318fe57SMatthew G. Knepley $ | | 18929318fe57SMatthew G. Knepley $ 19-----13 18939318fe57SMatthew G. Knepley $ 18949318fe57SMatthew G. Knepley $ and up through the top 18959318fe57SMatthew G. Knepley $ 18969318fe57SMatthew G. Knepley $ 18-----16 18979318fe57SMatthew G. Knepley $ | | 18989318fe57SMatthew G. Knepley $ | 2 | 18999318fe57SMatthew G. Knepley $ | | 19009318fe57SMatthew G. Knepley $ 18----10----11-----16 19019318fe57SMatthew G. Knepley $ | | | | 19029318fe57SMatthew G. Knepley $ | 3 | 0 | 1 | 19039318fe57SMatthew G. Knepley $ | | | | 19049318fe57SMatthew G. Knepley $ 20-----9----12-----15 19059318fe57SMatthew G. Knepley $ | | 19069318fe57SMatthew G. Knepley $ | 4 | 19079318fe57SMatthew G. Knepley $ | | 19089318fe57SMatthew G. Knepley $ 20-----15 19099318fe57SMatthew G. Knepley 191024119c2aSMatthew G. Knepley Level: beginner 191124119c2aSMatthew G. Knepley 1912db781477SPatrick Sanan .seealso: `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 191324119c2aSMatthew G. Knepley @*/ 1914d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm) 1915d71ae5a4SJacob Faibussowitsch { 19169318fe57SMatthew G. Knepley PetscFunctionBegin; 19179318fe57SMatthew G. Knepley PetscValidPointer(dm, 3); 19189566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 19199566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 19209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ)); 19219318fe57SMatthew G. Knepley PetscFunctionReturn(0); 19229318fe57SMatthew G. Knepley } 19239318fe57SMatthew G. Knepley 1924d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 1925d71ae5a4SJacob Faibussowitsch { 192624119c2aSMatthew G. Knepley const PetscInt dim = 3; 1927412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 19289fe9f049SMatthew G. Knepley PetscMPIInt rank; 192924119c2aSMatthew G. Knepley 193024119c2aSMatthew G. Knepley PetscFunctionBegin; 193163a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 19329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 19339566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 1934412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 19359566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 193624119c2aSMatthew G. Knepley /* Create topology */ 193724119c2aSMatthew G. Knepley { 193824119c2aSMatthew G. Knepley PetscInt cone[6], c; 193924119c2aSMatthew G. Knepley 1940dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 1941dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 19429566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 19439566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 19449566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 194524119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 19469371c9d4SSatish Balay cone[0] = c + n * 1; 19479371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 19489371c9d4SSatish Balay cone[2] = 0 + 3 * n; 19499371c9d4SSatish Balay cone[3] = c + n * 2; 19509371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 19519371c9d4SSatish Balay cone[5] = 1 + 3 * n; 19529566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 19539566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 195424119c2aSMatthew G. Knepley } 19559566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 19569566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 195724119c2aSMatthew G. Knepley } 195848a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 195924119c2aSMatthew G. Knepley /* Create cylinder geometry */ 196024119c2aSMatthew G. Knepley { 196124119c2aSMatthew G. Knepley Vec coordinates; 196224119c2aSMatthew G. Knepley PetscSection coordSection; 196324119c2aSMatthew G. Knepley PetscScalar *coords; 1964412e9a14SMatthew G. Knepley PetscInt coordSize, c; 196524119c2aSMatthew G. Knepley 196624119c2aSMatthew G. Knepley /* Build coordinates */ 19679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 19689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 19699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 19709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 197124119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 19729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 19739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 197424119c2aSMatthew G. Knepley } 19759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 19769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 19779566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 19789566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 19799566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 19809566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 19819566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 19829566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 198324119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 19849371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 19859371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 19869371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 19879371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 19889371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 19899371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 199024119c2aSMatthew G. Knepley } 1991dd400576SPatrick Sanan if (rank == 0) { 19929371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 19939371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 19949371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 19959371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 19969371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 19979371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 19989fe9f049SMatthew G. Knepley } 19999566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 20009566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 20019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 200224119c2aSMatthew G. Knepley } 20039318fe57SMatthew G. Knepley /* Interpolate */ 20049566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 20059318fe57SMatthew G. Knepley PetscFunctionReturn(0); 20069318fe57SMatthew G. Knepley } 20079318fe57SMatthew G. Knepley 20089318fe57SMatthew G. Knepley /*@ 20099318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 20109318fe57SMatthew G. Knepley 20119318fe57SMatthew G. Knepley Collective 20129318fe57SMatthew G. Knepley 20139318fe57SMatthew G. Knepley Input Parameters: 20149318fe57SMatthew G. Knepley + comm - The communicator for the DM object 20159318fe57SMatthew G. Knepley . n - The number of wedges around the origin 20169318fe57SMatthew G. Knepley - interpolate - Create edges and faces 20179318fe57SMatthew G. Knepley 20189318fe57SMatthew G. Knepley Output Parameter: 20199318fe57SMatthew G. Knepley . dm - The DM object 20209318fe57SMatthew G. Knepley 20219318fe57SMatthew G. Knepley Level: beginner 20229318fe57SMatthew G. Knepley 2023db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 20249318fe57SMatthew G. Knepley @*/ 2025d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 2026d71ae5a4SJacob Faibussowitsch { 20279318fe57SMatthew G. Knepley PetscFunctionBegin; 20289318fe57SMatthew G. Knepley PetscValidPointer(dm, 4); 20299566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 20309566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 20319566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 203224119c2aSMatthew G. Knepley PetscFunctionReturn(0); 203324119c2aSMatthew G. Knepley } 203424119c2aSMatthew G. Knepley 2035d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2036d71ae5a4SJacob Faibussowitsch { 203765a81367SMatthew G. Knepley PetscReal prod = 0.0; 203865a81367SMatthew G. Knepley PetscInt i; 203965a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 204065a81367SMatthew G. Knepley return PetscSqrtReal(prod); 204165a81367SMatthew G. Knepley } 2042d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2043d71ae5a4SJacob Faibussowitsch { 204465a81367SMatthew G. Knepley PetscReal prod = 0.0; 204565a81367SMatthew G. Knepley PetscInt i; 204665a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i] * y[i]; 204765a81367SMatthew G. Knepley return prod; 204865a81367SMatthew G. Knepley } 204965a81367SMatthew G. Knepley 205051a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 2051d71ae5a4SJacob Faibussowitsch static void snapToSphere(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 2052d71ae5a4SJacob Faibussowitsch { 205351a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 205451a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 205551a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 205651a74b61SMatthew G. Knepley 205751a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 205851a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 205951a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 206051a74b61SMatthew G. Knepley } 206151a74b61SMatthew G. Knepley 2062d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 2063d71ae5a4SJacob Faibussowitsch { 206465a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 206565a81367SMatthew G. Knepley PetscSection coordSection; 206665a81367SMatthew G. Knepley Vec coordinates; 206765a81367SMatthew G. Knepley PetscScalar *coords; 206865a81367SMatthew G. Knepley PetscReal *coordsIn; 2069064cae4fSPierre Jolivet PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, c, e; 207065a81367SMatthew G. Knepley PetscMPIInt rank; 207165a81367SMatthew G. Knepley 207265a81367SMatthew G. Knepley PetscFunctionBegin; 20739318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 20749566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 20759566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 20769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 207765a81367SMatthew G. Knepley switch (dim) { 207865a81367SMatthew G. Knepley case 2: 207965a81367SMatthew G. Knepley if (simplex) { 208051a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 208151a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 208265a81367SMatthew G. Knepley const PetscInt degree = 5; 208351a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 208465a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 208565a81367SMatthew G. Knepley PetscInt cone[3]; 208665a81367SMatthew G. Knepley PetscInt *graph, p, i, j, k; 208765a81367SMatthew G. Knepley 20889371c9d4SSatish Balay vertex[0] *= R / radius; 20899371c9d4SSatish Balay vertex[1] *= R / radius; 20909371c9d4SSatish Balay vertex[2] *= R / radius; 2091dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 2092dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 209365a81367SMatthew G. Knepley firstVertex = numCells; 209451a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 209565a81367SMatthew G. Knepley 209665a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 209765a81367SMatthew G. Knepley 209865a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 209951a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 210065a81367SMatthew G. Knepley */ 210165a81367SMatthew G. Knepley /* Construct vertices */ 21029566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2103dd400576SPatrick Sanan if (rank == 0) { 210465a81367SMatthew G. Knepley for (p = 0, i = 0; p < embedDim; ++p) { 210565a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 210665a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 210765a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 210865a81367SMatthew G. Knepley ++i; 210965a81367SMatthew G. Knepley } 211065a81367SMatthew G. Knepley } 211165a81367SMatthew G. Knepley } 211245da822fSValeria Barra } 211365a81367SMatthew G. Knepley /* Construct graph */ 21149566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 211565a81367SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 211665a81367SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 21179371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 21189371c9d4SSatish Balay graph[i * numVerts + j] = 1; 21199371c9d4SSatish Balay ++k; 21209371c9d4SSatish Balay } 212165a81367SMatthew G. Knepley } 212263a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 212365a81367SMatthew G. Knepley } 212465a81367SMatthew G. Knepley /* Build Topology */ 21259566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 212648a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 21279566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 212865a81367SMatthew G. Knepley /* Cells */ 212965a81367SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 213065a81367SMatthew G. Knepley for (j = 0; j < i; ++j) { 213165a81367SMatthew G. Knepley for (k = 0; k < j; ++k) { 213265a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 21339371c9d4SSatish Balay cone[0] = firstVertex + i; 21349371c9d4SSatish Balay cone[1] = firstVertex + j; 21359371c9d4SSatish Balay cone[2] = firstVertex + k; 213665a81367SMatthew G. Knepley /* Check orientation */ 213765a81367SMatthew G. Knepley { 21389371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 21399371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 21409371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 21419371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 21429371c9d4SSatish Balay }; 214365a81367SMatthew G. Knepley PetscReal normal[3]; 214465a81367SMatthew G. Knepley PetscInt e, f; 214565a81367SMatthew G. Knepley 214665a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 214765a81367SMatthew G. Knepley normal[d] = 0.0; 214865a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2149ad540459SPierre Jolivet for (f = 0; f < embedDim; ++f) normal[d] += epsilon[d][e][f] * (coordsIn[j * embedDim + e] - coordsIn[i * embedDim + e]) * (coordsIn[k * embedDim + f] - coordsIn[i * embedDim + f]); 215065a81367SMatthew G. Knepley } 215165a81367SMatthew G. Knepley } 21529371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 21539371c9d4SSatish Balay PetscInt tmp = cone[1]; 21549371c9d4SSatish Balay cone[1] = cone[2]; 21559371c9d4SSatish Balay cone[2] = tmp; 215665a81367SMatthew G. Knepley } 215765a81367SMatthew G. Knepley } 21589566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 215965a81367SMatthew G. Knepley } 216065a81367SMatthew G. Knepley } 216165a81367SMatthew G. Knepley } 216265a81367SMatthew G. Knepley } 21639566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 21649566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 21659566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 216665a81367SMatthew G. Knepley } else { 21672829fed8SMatthew G. Knepley /* 21682829fed8SMatthew G. Knepley 12-21--13 21692829fed8SMatthew G. Knepley | | 21702829fed8SMatthew G. Knepley 25 4 24 21712829fed8SMatthew G. Knepley | | 21722829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 21732829fed8SMatthew G. Knepley | | | | 21742829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 21752829fed8SMatthew G. Knepley | | | | 21762829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 21772829fed8SMatthew G. Knepley | | 21782829fed8SMatthew G. Knepley 20 1 19 21792829fed8SMatthew G. Knepley | | 21802829fed8SMatthew G. Knepley 10-18--11 21812829fed8SMatthew G. Knepley | | 21822829fed8SMatthew G. Knepley 23 2 22 21832829fed8SMatthew G. Knepley | | 21842829fed8SMatthew G. Knepley 12-21--13 21852829fed8SMatthew G. Knepley */ 21862829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 21872829fed8SMatthew G. Knepley 2188dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 2189dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 2190dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 219165a81367SMatthew G. Knepley firstVertex = numCells; 219265a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 21932829fed8SMatthew G. Knepley /* Build Topology */ 21949566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 219548a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 219648a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 21979566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2198dd400576SPatrick Sanan if (rank == 0) { 21992829fed8SMatthew G. Knepley /* Cell 0 */ 22009371c9d4SSatish Balay cone[0] = 14; 22019371c9d4SSatish Balay cone[1] = 15; 22029371c9d4SSatish Balay cone[2] = 16; 22039371c9d4SSatish Balay cone[3] = 17; 22049566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 22059371c9d4SSatish Balay ornt[0] = 0; 22069371c9d4SSatish Balay ornt[1] = 0; 22079371c9d4SSatish Balay ornt[2] = 0; 22089371c9d4SSatish Balay ornt[3] = 0; 22099566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 22102829fed8SMatthew G. Knepley /* Cell 1 */ 22119371c9d4SSatish Balay cone[0] = 18; 22129371c9d4SSatish Balay cone[1] = 19; 22139371c9d4SSatish Balay cone[2] = 14; 22149371c9d4SSatish Balay cone[3] = 20; 22159566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 22169371c9d4SSatish Balay ornt[0] = 0; 22179371c9d4SSatish Balay ornt[1] = 0; 22189371c9d4SSatish Balay ornt[2] = -1; 22199371c9d4SSatish Balay ornt[3] = 0; 22209566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 22212829fed8SMatthew G. Knepley /* Cell 2 */ 22229371c9d4SSatish Balay cone[0] = 21; 22239371c9d4SSatish Balay cone[1] = 22; 22249371c9d4SSatish Balay cone[2] = 18; 22259371c9d4SSatish Balay cone[3] = 23; 22269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 22279371c9d4SSatish Balay ornt[0] = 0; 22289371c9d4SSatish Balay ornt[1] = 0; 22299371c9d4SSatish Balay ornt[2] = -1; 22309371c9d4SSatish Balay ornt[3] = 0; 22319566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 22322829fed8SMatthew G. Knepley /* Cell 3 */ 22339371c9d4SSatish Balay cone[0] = 19; 22349371c9d4SSatish Balay cone[1] = 22; 22359371c9d4SSatish Balay cone[2] = 24; 22369371c9d4SSatish Balay cone[3] = 15; 22379566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 22389371c9d4SSatish Balay ornt[0] = -1; 22399371c9d4SSatish Balay ornt[1] = -1; 22409371c9d4SSatish Balay ornt[2] = 0; 22419371c9d4SSatish Balay ornt[3] = -1; 22429566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 22432829fed8SMatthew G. Knepley /* Cell 4 */ 22449371c9d4SSatish Balay cone[0] = 16; 22459371c9d4SSatish Balay cone[1] = 24; 22469371c9d4SSatish Balay cone[2] = 21; 22479371c9d4SSatish Balay cone[3] = 25; 22489566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 22499371c9d4SSatish Balay ornt[0] = -1; 22509371c9d4SSatish Balay ornt[1] = -1; 22519371c9d4SSatish Balay ornt[2] = -1; 22529371c9d4SSatish Balay ornt[3] = 0; 22539566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 22542829fed8SMatthew G. Knepley /* Cell 5 */ 22559371c9d4SSatish Balay cone[0] = 20; 22569371c9d4SSatish Balay cone[1] = 17; 22579371c9d4SSatish Balay cone[2] = 25; 22589371c9d4SSatish Balay cone[3] = 23; 22599566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 22609371c9d4SSatish Balay ornt[0] = -1; 22619371c9d4SSatish Balay ornt[1] = -1; 22629371c9d4SSatish Balay ornt[2] = -1; 22639371c9d4SSatish Balay ornt[3] = -1; 22649566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 22652829fed8SMatthew G. Knepley /* Edges */ 22669371c9d4SSatish Balay cone[0] = 6; 22679371c9d4SSatish Balay cone[1] = 7; 22689566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 22699371c9d4SSatish Balay cone[0] = 7; 22709371c9d4SSatish Balay cone[1] = 8; 22719566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 22729371c9d4SSatish Balay cone[0] = 8; 22739371c9d4SSatish Balay cone[1] = 9; 22749566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 22759371c9d4SSatish Balay cone[0] = 9; 22769371c9d4SSatish Balay cone[1] = 6; 22779566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 22789371c9d4SSatish Balay cone[0] = 10; 22799371c9d4SSatish Balay cone[1] = 11; 22809566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 22819371c9d4SSatish Balay cone[0] = 11; 22829371c9d4SSatish Balay cone[1] = 7; 22839566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 22849371c9d4SSatish Balay cone[0] = 6; 22859371c9d4SSatish Balay cone[1] = 10; 22869566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 22879371c9d4SSatish Balay cone[0] = 12; 22889371c9d4SSatish Balay cone[1] = 13; 22899566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 22909371c9d4SSatish Balay cone[0] = 13; 22919371c9d4SSatish Balay cone[1] = 11; 22929566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 22939371c9d4SSatish Balay cone[0] = 10; 22949371c9d4SSatish Balay cone[1] = 12; 22959566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 22969371c9d4SSatish Balay cone[0] = 13; 22979371c9d4SSatish Balay cone[1] = 8; 22989566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 22999371c9d4SSatish Balay cone[0] = 12; 23009371c9d4SSatish Balay cone[1] = 9; 23019566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 230245da822fSValeria Barra } 23039566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 23049566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 23052829fed8SMatthew G. Knepley /* Build coordinates */ 23069566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2307dd400576SPatrick Sanan if (rank == 0) { 23089371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 23099371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 23109371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 23119371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 23129371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 23139371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 23149371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 23159371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 23169371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 23179371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 23189371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 23199371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 23209371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 23219371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 23229371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 23239371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 23249371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 23259371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 23269371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 23279371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 23289371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 23299371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 23309371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 23319371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 233265a81367SMatthew G. Knepley } 233345da822fSValeria Barra } 233465a81367SMatthew G. Knepley break; 233565a81367SMatthew G. Knepley case 3: 2336116ded15SMatthew G. Knepley if (simplex) { 2337116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 233851a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 233951a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 234051a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 2341116ded15SMatthew G. Knepley const PetscInt degree = 12; 2342116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 23439371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 23449371c9d4SSatish Balay {0, 1, 2, 3}, 23459371c9d4SSatish Balay {0, 2, 3, 1}, 23469371c9d4SSatish Balay {0, 3, 1, 2}, 23479371c9d4SSatish Balay {1, 0, 3, 2}, 23489371c9d4SSatish Balay {1, 2, 0, 3}, 23499371c9d4SSatish Balay {1, 3, 2, 0}, 23509371c9d4SSatish Balay {2, 0, 1, 3}, 23519371c9d4SSatish Balay {2, 1, 3, 0}, 23529371c9d4SSatish Balay {2, 3, 0, 1}, 23539371c9d4SSatish Balay {3, 0, 2, 1}, 23549371c9d4SSatish Balay {3, 1, 0, 2}, 23559371c9d4SSatish Balay {3, 2, 1, 0} 23569371c9d4SSatish Balay }; 2357116ded15SMatthew G. Knepley PetscInt cone[4]; 2358116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 2359116ded15SMatthew G. Knepley 23609371c9d4SSatish Balay vertexA[0] *= R; 23619371c9d4SSatish Balay vertexA[1] *= R; 23629371c9d4SSatish Balay vertexA[2] *= R; 23639371c9d4SSatish Balay vertexA[3] *= R; 23649371c9d4SSatish Balay vertexB[0] *= R; 23659371c9d4SSatish Balay vertexB[1] *= R; 23669371c9d4SSatish Balay vertexB[2] *= R; 23679371c9d4SSatish Balay vertexB[3] *= R; 23689371c9d4SSatish Balay vertexC[0] *= R; 23699371c9d4SSatish Balay vertexC[1] *= R; 23709371c9d4SSatish Balay vertexC[2] *= R; 23719371c9d4SSatish Balay vertexC[3] *= R; 2372dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 2373dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 2374116ded15SMatthew G. Knepley firstVertex = numCells; 2375116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 2376116ded15SMatthew G. Knepley 2377116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 2378116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 2379116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 2380116ded15SMatthew G. Knepley 2381116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 23826333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 2383116ded15SMatthew G. Knepley 2384116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 2385116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 2386116ded15SMatthew G. Knepley */ 2387116ded15SMatthew G. Knepley /* Construct vertices */ 23889566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2389116ded15SMatthew G. Knepley i = 0; 2390dd400576SPatrick Sanan if (rank == 0) { 2391116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2392116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2393116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2394116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 2395116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 2396116ded15SMatthew G. Knepley ++i; 2397116ded15SMatthew G. Knepley } 2398116ded15SMatthew G. Knepley } 2399116ded15SMatthew G. Knepley } 2400116ded15SMatthew G. Knepley } 2401116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 2402116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 2403116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2404116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 2405116ded15SMatthew G. Knepley ++i; 2406116ded15SMatthew G. Knepley } 2407116ded15SMatthew G. Knepley } 2408116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 2409116ded15SMatthew G. Knepley s[3] = 1; 2410116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2411116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2412116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2413116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 2414116ded15SMatthew G. Knepley ++i; 2415116ded15SMatthew G. Knepley } 2416116ded15SMatthew G. Knepley } 2417116ded15SMatthew G. Knepley } 2418116ded15SMatthew G. Knepley } 241945da822fSValeria Barra } 242063a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 2421116ded15SMatthew G. Knepley /* Construct graph */ 24229566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 2423116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 2424116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 24259371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 24269371c9d4SSatish Balay graph[i * numVerts + j] = 1; 24279371c9d4SSatish Balay ++k; 24289371c9d4SSatish Balay } 2429116ded15SMatthew G. Knepley } 243063a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 2431116ded15SMatthew G. Knepley } 2432116ded15SMatthew G. Knepley /* Build Topology */ 24339566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 243448a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 24359566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2436116ded15SMatthew G. Knepley /* Cells */ 2437dd400576SPatrick Sanan if (rank == 0) { 2438116ded15SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 2439116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 2440116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 2441116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 24429371c9d4SSatish 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]) { 24439371c9d4SSatish Balay cone[0] = firstVertex + i; 24449371c9d4SSatish Balay cone[1] = firstVertex + j; 24459371c9d4SSatish Balay cone[2] = firstVertex + k; 24469371c9d4SSatish Balay cone[3] = firstVertex + l; 2447116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 2448116ded15SMatthew G. Knepley { 24499371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 24509371c9d4SSatish 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}}}, 2451116ded15SMatthew G. Knepley 24529371c9d4SSatish 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}}}, 2453116ded15SMatthew G. Knepley 24549371c9d4SSatish 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}}}, 2455116ded15SMatthew G. Knepley 24569371c9d4SSatish 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}} } 24579371c9d4SSatish Balay }; 2458116ded15SMatthew G. Knepley PetscReal normal[4]; 2459116ded15SMatthew G. Knepley PetscInt e, f, g; 2460116ded15SMatthew G. Knepley 2461116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 2462116ded15SMatthew G. Knepley normal[d] = 0.0; 2463116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2464116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 2465116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 2466116ded15SMatthew 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]); 2467116ded15SMatthew G. Knepley } 2468116ded15SMatthew G. Knepley } 2469116ded15SMatthew G. Knepley } 2470116ded15SMatthew G. Knepley } 24719371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 24729371c9d4SSatish Balay PetscInt tmp = cone[1]; 24739371c9d4SSatish Balay cone[1] = cone[2]; 24749371c9d4SSatish Balay cone[2] = tmp; 24759371c9d4SSatish Balay } 2476116ded15SMatthew G. Knepley } 24779566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 2478116ded15SMatthew G. Knepley } 2479116ded15SMatthew G. Knepley } 2480116ded15SMatthew G. Knepley } 2481116ded15SMatthew G. Knepley } 2482116ded15SMatthew G. Knepley } 248345da822fSValeria Barra } 24849566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 24859566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 24869566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 2487116ded15SMatthew G. Knepley } 2488f4d061e9SPierre Jolivet break; 2489d71ae5a4SJacob Faibussowitsch default: 2490d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 249165a81367SMatthew G. Knepley } 249265a81367SMatthew G. Knepley /* Create coordinates */ 24939566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 24949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 24959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 24969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 24972829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 24989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 24999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 25002829fed8SMatthew G. Knepley } 25019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 25029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 25039566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 25049566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 25059566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 25069566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 25079566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 25089566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 25099371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 2510ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 25119566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 25129566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 25139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 25149566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 251551a74b61SMatthew G. Knepley { 251651a74b61SMatthew G. Knepley DM cdm; 251751a74b61SMatthew G. Knepley PetscDS cds; 25189318fe57SMatthew G. Knepley PetscScalar c = R; 251951a74b61SMatthew G. Knepley 25209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere)); 25219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 25229566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 25239566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 252451a74b61SMatthew G. Knepley } 25259318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 25269566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 25279318fe57SMatthew G. Knepley PetscFunctionReturn(0); 25289318fe57SMatthew G. Knepley } 25299318fe57SMatthew G. Knepley 2530b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 2531b7f5c055SJed Brown 2532b7f5c055SJed Brown /* 2533b7f5c055SJed Brown The Schwarz P implicit surface is 2534b7f5c055SJed Brown 2535b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 2536b7f5c055SJed Brown */ 2537d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2538d71ae5a4SJacob Faibussowitsch { 2539b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 2540b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 2541b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 2542b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2543b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 2544ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 2545b7f5c055SJed Brown } 2546b7f5c055SJed Brown } 2547b7f5c055SJed Brown 25484663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 2549d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 2550d71ae5a4SJacob Faibussowitsch { 2551ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 25524663dae6SJed Brown return 0; 25534663dae6SJed Brown } 25544663dae6SJed Brown 2555b7f5c055SJed Brown /* 2556b7f5c055SJed Brown The Gyroid implicit surface is 2557b7f5c055SJed Brown 2558b7f5c055SJed 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) 2559b7f5c055SJed Brown 2560b7f5c055SJed Brown */ 2561d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2562d71ae5a4SJacob Faibussowitsch { 2563b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 2564b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 2565b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 2566b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 2567b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 2568b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 2569b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 2570b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2571b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2572b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 2573b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2574b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2575b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 2576b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2577b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2578b7f5c055SJed Brown } 2579b7f5c055SJed Brown 25804663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 2581d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 2582d71ae5a4SJacob Faibussowitsch { 25834663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 25844663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 25854663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 25864663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 25874663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 25884663dae6SJed Brown return 0; 25894663dae6SJed Brown } 25904663dae6SJed Brown 2591b7f5c055SJed Brown /* 2592b7f5c055SJed Brown We wish to solve 2593b7f5c055SJed Brown 2594b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 2595b7f5c055SJed Brown 2596b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 2597b7f5c055SJed 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 2598b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 2599b7f5c055SJed Brown 2600b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 2601b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 2602b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 2603b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 2604b7f5c055SJed Brown Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries. 2605b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 2606b7f5c055SJed Brown 2607b7f5c055SJed Brown f(y) = 0 1 equation 2608b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 2609b7f5c055SJed Brown 2610b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 2611b7f5c055SJed Brown */ 2612d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 2613d71ae5a4SJacob Faibussowitsch { 2614b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 2615b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 26162f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 26179371c9d4SSatish Balay PetscReal n_y[3][3] = { 26189371c9d4SSatish Balay {0, 0, 0}, 26199371c9d4SSatish Balay {0, 0, 0}, 26209371c9d4SSatish Balay {0, 0, 0} 26219371c9d4SSatish Balay }; 2622b7f5c055SJed Brown 2623b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 2624b7f5c055SJed Brown 2625b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 2626b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2627ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 2628b7f5c055SJed Brown 2629b7f5c055SJed Brown // Define the Householder reflector 2630b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 2631b7f5c055SJed Brown n[0] += norm * sign; 2632b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 2633b7f5c055SJed Brown 2634b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2635b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 2636b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 2637b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 2638b7f5c055SJed Brown 2639b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2640b7f5c055SJed Brown n[i] /= norm; 2641b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2642b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 2643b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 2644b7f5c055SJed Brown } 2645b7f5c055SJed Brown } 2646b7f5c055SJed Brown 2647b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 2648b7f5c055SJed 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]; 2649b7f5c055SJed Brown 2650b7f5c055SJed Brown res[0] = f; 2651b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 2652b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 2653b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 2654b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2655b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 2656b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 2657b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 2658b7f5c055SJed Brown } 2659b7f5c055SJed Brown } 2660b7f5c055SJed Brown 2661b7f5c055SJed Brown /* 2662b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 2663b7f5c055SJed Brown */ 2664d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 2665d71ae5a4SJacob Faibussowitsch { 2666b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 2667b7f5c055SJed Brown 2668b7f5c055SJed Brown PetscFunctionBegin; 2669b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 2670b7f5c055SJed Brown PetscScalar res[3], J[9]; 2671b7f5c055SJed Brown PetscReal resnorm; 2672b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 2673b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 2674b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 267563a3b9bcSJacob 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]))); 2676b7f5c055SJed Brown } 2677b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 2678b7f5c055SJed Brown 2679b7f5c055SJed Brown // Take the Newton step 26809566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 2681b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 2682b7f5c055SJed Brown } 2683b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 2684b7f5c055SJed Brown PetscFunctionReturn(0); 2685b7f5c055SJed Brown } 2686b7f5c055SJed Brown 2687b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 2688b7f5c055SJed Brown 2689d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 2690d71ae5a4SJacob Faibussowitsch { 2691b7f5c055SJed Brown PetscMPIInt rank; 2692b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 2693b7f5c055SJed Brown PetscInt(*edges)[2] = NULL, *edgeSets = NULL; 2694b7f5c055SJed Brown PetscInt *cells_flat = NULL; 2695b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 2696b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 26974663dae6SJed Brown PetscSimplePointFunc normalFunc = NULL; 2698b7f5c055SJed Brown DMLabel label; 2699b7f5c055SJed Brown 2700b7f5c055SJed Brown PetscFunctionBegin; 27019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 270263a3b9bcSJacob 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); 2703b7f5c055SJed Brown switch (tpstype) { 2704b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 2705b7f5c055SJed 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"); 2706c5853193SPierre Jolivet if (rank == 0) { 2707b7f5c055SJed Brown PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 2708b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 2709b7f5c055SJed Brown PetscReal L = 1; 2710b7f5c055SJed Brown 2711b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 2712b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 2713b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 2714b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 2715b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 2716b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 27179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 27189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 27199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 27209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 2721b7f5c055SJed Brown // x-normal pipes 2722b7f5c055SJed Brown vcount = 0; 2723b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 2724b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2725b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2726b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2727b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 2728b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2729b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2730b7f5c055SJed Brown } 2731b7f5c055SJed Brown } 2732b7f5c055SJed Brown } 2733b7f5c055SJed Brown } 2734b7f5c055SJed Brown // y-normal pipes 2735b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2736b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 2737b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2738b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2739b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2740b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 2741b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2742b7f5c055SJed Brown } 2743b7f5c055SJed Brown } 2744b7f5c055SJed Brown } 2745b7f5c055SJed Brown } 2746b7f5c055SJed Brown // z-normal pipes 2747b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2748b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2749b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 2750b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2751b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2752b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2753b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 2754b7f5c055SJed Brown } 2755b7f5c055SJed Brown } 2756b7f5c055SJed Brown } 2757b7f5c055SJed Brown } 2758b7f5c055SJed Brown // junctions 2759b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2760b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2761b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2762b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 2763b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 2764b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 2765b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 2766b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 2767b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 2768b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 2769b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 2770b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 2771b7f5c055SJed Brown } 2772b7f5c055SJed Brown } 2773b7f5c055SJed Brown } 2774b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 2775b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 2776b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 2777b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 2778b7f5c055SJed Brown }; 2779b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 27809371c9d4SSatish 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}; 2781b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 27829371c9d4SSatish 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}; 2783b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 2784b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 2785b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 2786b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 2787b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 2788b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 2789b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 2790b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 2791b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 2792b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 2793b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 2794b7f5c055SJed Brown if (ijk[dir] == 0) { 2795b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 2796b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 2797b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 2798b7f5c055SJed Brown numEdges++; 2799b7f5c055SJed Brown } 2800b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 2801b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 2802b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 2803b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 2804b7f5c055SJed Brown numEdges++; 2805b7f5c055SJed Brown } 2806b7f5c055SJed Brown } 2807b7f5c055SJed Brown } 2808b7f5c055SJed Brown } 2809b7f5c055SJed Brown } 2810b7f5c055SJed Brown } 281163a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 2812b7f5c055SJed Brown numFaces = 24 * Njunctions; 2813b7f5c055SJed Brown cells_flat = cells[0][0][0]; 2814b7f5c055SJed Brown } 2815b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 28164663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 2817b7f5c055SJed Brown break; 2818b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 2819c5853193SPierre Jolivet if (rank == 0) { 2820b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 2821b7f5c055SJed Brown // 2822b7f5c055SJed 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) 2823b7f5c055SJed Brown // 2824b7f5c055SJed Brown // on the cell [0,2]^3. 2825b7f5c055SJed Brown // 2826b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 2827b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 2828b7f5c055SJed Brown // like a boomerang: 2829b7f5c055SJed Brown // 2830b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 2831b7f5c055SJed Brown // ----- ------- ------- ------- // 2832b7f5c055SJed Brown // // 2833b7f5c055SJed Brown // + + + + + + + \ + // 2834b7f5c055SJed Brown // \ / \ // 2835b7f5c055SJed Brown // \ `-_ _-' / } // 2836b7f5c055SJed Brown // *-_ `-' _-' / // 2837b7f5c055SJed Brown // + `-+ + + +-' + + / + // 2838b7f5c055SJed Brown // // 2839b7f5c055SJed Brown // // 2840b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 2841b7f5c055SJed Brown // ----- ------- ------- ------- // 2842b7f5c055SJed Brown // // 2843b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 2844b7f5c055SJed Brown // `-_ _-_ _-` / // 2845b7f5c055SJed Brown // \ _-' `-_ / { // 2846b7f5c055SJed Brown // \ / \ // 2847b7f5c055SJed Brown // + + + + + + + \ + // 2848b7f5c055SJed Brown // 2849b7f5c055SJed Brown // 2850b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 2851b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 2852b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 2853b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 2854b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 2855b7f5c055SJed Brown // 2856b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 2857b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 2858b7f5c055SJed Brown // 2859b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 2860b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 2861b7f5c055SJed Brown 2862b7f5c055SJed Brown PetscInt facesPerBlock = 64; 2863b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 2864b7f5c055SJed Brown PetscInt extentPlus[3]; 2865b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 28669371c9d4SSatish 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; 28679371c9d4SSatish Balay const PetscInt pattern[64][4] = { 28689371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 2869b7f5c055SJed Brown /* layer 0 */ 28709371c9d4SSatish Balay {A, C, K, G }, 28719371c9d4SSatish Balay {C, B, II, K }, 28729371c9d4SSatish Balay {D, A, H, L }, 28739371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 28749371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 28759371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 28769371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 28779371c9d4SSatish Balay {B, F, M, II }, 2878b7f5c055SJed Brown /* layer 1 */ 28799371c9d4SSatish Balay {G, K, Q, O }, 28809371c9d4SSatish Balay {K, II, P, Q }, 28819371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 28829371c9d4SSatish Balay {J, L, R, P }, 28839371c9d4SSatish Balay {N, J, P, S }, 28849371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 28859371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 28869371c9d4SSatish Balay {II, M, T, P }, 2887b7f5c055SJed Brown /* layer 2 */ 28889371c9d4SSatish Balay {O, Q, Y, U }, 28899371c9d4SSatish Balay {Q, P, W, Y }, 28909371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 28919371c9d4SSatish Balay {P, R, Ap, W }, 28929371c9d4SSatish Balay {S, P, X, Bp }, 28939371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 28949371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 28959371c9d4SSatish Balay {P, T, Z, X }, 2896b7f5c055SJed Brown /* layer 3 */ 28979371c9d4SSatish Balay {U, Y, Ep, Dp }, 28989371c9d4SSatish Balay {Y, W, Cp, Ep }, 28999371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 29009371c9d4SSatish Balay {W, Ap, Gp, Cp }, 29019371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 29029371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 29039371c9d4SSatish Balay {Z, V, Dp, Hp }, 29049371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 2905b7f5c055SJed Brown /* layer 4 */ 29069371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 29079371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 29089371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 29099371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 29109371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 29119371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 29129371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 29139371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 2914b7f5c055SJed Brown /* layer 5 */ 29159371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 29169371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 29179371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 29189371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 29199371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 29209371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 29219371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 29229371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 2923b7f5c055SJed Brown /* layer 6 */ 29249371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 29259371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 29269371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 29279371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 29289371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 29299371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 29309371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 29319371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 2932b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 29339371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 29349371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 29359371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 29369371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 29379371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 29389371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 29399371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 29409371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 2941b7f5c055SJed Brown }; 2942b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 29439371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 2944bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 2945bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 2946bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 2947bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 2948bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 2949bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 2950b7f5c055SJed Brown 2951bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 2952bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 2953bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 2954bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 2955bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 2956bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 2957bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 2958bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 2959b7f5c055SJed Brown 2960bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 2961bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 2962bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 2963bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 2964bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 2965bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 2966b7f5c055SJed Brown 2967bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 2968bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 2969bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 2970bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 2971bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 2972bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 2973bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 2974bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 2975b7f5c055SJed Brown 2976bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 2977bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 2978bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 2979bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 2980bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 2981bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 2982b7f5c055SJed Brown 2983bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 2984bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 2985bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 2986bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 2987bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 2988bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 2989bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 2990bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 2991b7f5c055SJed Brown 2992bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 2993bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 2994bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 2995bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 2996bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 2997bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 2998b7f5c055SJed Brown 2999bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 3000bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 3001bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 3002bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 3003bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 3004bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 3005bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 3006bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 3007b7f5c055SJed Brown }; 3008b7f5c055SJed Brown PetscInt(*cells)[64][4] = NULL; 3009b7f5c055SJed Brown PetscBool *seen; 3010b7f5c055SJed Brown PetscInt *vertToTrueVert; 3011b7f5c055SJed Brown PetscInt count; 3012b7f5c055SJed Brown 3013b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 3014b7f5c055SJed Brown numBlocks = 1; 3015b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 3016b7f5c055SJed Brown numBlocksPlus = 1; 3017b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 3018b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 30199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 30209566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 3021b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3022b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3023b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3024b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3025b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 3026b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 3027b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 3028b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 3029b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 3030b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 3031b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 3032b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 3033b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 3034b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 3035b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 3036b7f5c055SJed Brown 3037b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 3038b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 3039b7f5c055SJed Brown } 3040b7f5c055SJed Brown } 3041b7f5c055SJed Brown } 3042b7f5c055SJed Brown } 3043b7f5c055SJed Brown } 30449371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 30459371c9d4SSatish Balay if (seen[i]) numVertices++; 3046b7f5c055SJed Brown count = 0; 30479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 30489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 3049b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 3050b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 3051b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 3052b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 3053b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 3054b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 3055b7f5c055SJed Brown 3056b7f5c055SJed Brown if (seen[vIdx]) { 3057b7f5c055SJed Brown PetscInt thisVert; 3058b7f5c055SJed Brown 3059b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 3060b7f5c055SJed Brown 3061b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 3062b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 3063b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 3064b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 3065b7f5c055SJed Brown } 3066b7f5c055SJed Brown } 3067b7f5c055SJed Brown } 3068b7f5c055SJed Brown } 3069b7f5c055SJed Brown } 3070b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 3071b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3072ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 3073b7f5c055SJed Brown } 3074b7f5c055SJed Brown } 30759566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 30769566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 3077b7f5c055SJed Brown cells_flat = cells[0][0]; 3078b7f5c055SJed Brown numEdges = 0; 3079b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 3080b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3081b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3082b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3083b7f5c055SJed Brown 3084b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3085b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 3086b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 3087b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 3088b7f5c055SJed Brown } 3089b7f5c055SJed Brown } 3090b7f5c055SJed Brown } 3091b7f5c055SJed Brown } 30929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 30939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 3094b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 3095b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3096b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3097b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3098b7f5c055SJed Brown 3099b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3100b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 3101b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 3102b7f5c055SJed Brown edges[edge][0] = ev[0]; 3103b7f5c055SJed Brown edges[edge][1] = ev[1]; 3104b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 3105b7f5c055SJed Brown } 3106b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 3107b7f5c055SJed Brown edges[edge][0] = ev[0]; 3108b7f5c055SJed Brown edges[edge][1] = ev[1]; 3109b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 3110b7f5c055SJed Brown } 3111b7f5c055SJed Brown } 3112b7f5c055SJed Brown } 3113b7f5c055SJed Brown } 3114b7f5c055SJed Brown } 3115b7f5c055SJed Brown } 3116b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 31174663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 3118b7f5c055SJed Brown break; 3119b7f5c055SJed Brown } 3120b7f5c055SJed Brown 31219566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 3122c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 31239566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 31249566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 3125b7f5c055SJed Brown { 3126b7f5c055SJed Brown DM idm; 31279566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 312869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3129b7f5c055SJed Brown } 3130c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 31319566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 31329566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 3133b7f5c055SJed Brown 31349566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 31359566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 3136b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 3137b7f5c055SJed Brown PetscInt njoin; 3138b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 31399566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 314063a3b9bcSJacob 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]); 31419566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 31429566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 3143b7f5c055SJed Brown } 31449566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 31459566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 31461436d7faSJed Brown if (tps_distribute) { 31471436d7faSJed Brown DM pdm = NULL; 31481436d7faSJed Brown PetscPartitioner part; 31491436d7faSJed Brown 31509566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 31519566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 31529566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 315348a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 31541436d7faSJed Brown // Do not auto-distribute again 31559566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 31561436d7faSJed Brown } 3157b7f5c055SJed Brown 31589566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 3159b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 3160b7f5c055SJed Brown PetscInt m; 3161b7f5c055SJed Brown DM dmf; 3162b7f5c055SJed Brown Vec X; 3163b7f5c055SJed Brown PetscScalar *x; 31649566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 316569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 3166b7f5c055SJed Brown 31679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 31689566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 31699566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 317048a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 31719566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 3172b7f5c055SJed Brown } 3173b7f5c055SJed Brown 3174b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 31759566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 31769566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 3177b7f5c055SJed Brown 3178b7f5c055SJed Brown if (thickness > 0) { 31794663dae6SJed Brown DM edm, cdm, ecdm; 31804663dae6SJed Brown DMPlexTransform tr; 31814663dae6SJed Brown const char *prefix; 31824663dae6SJed Brown PetscOptions options; 31834663dae6SJed Brown // Code from DMPlexExtrude 31844663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 31854663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 31864663dae6SJed Brown PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE)); 31874663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 31884663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 31894663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 31904663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 31914663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 31924663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 31934663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 31944663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 31954663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 31964663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 31974663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 31984663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 31994663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 32004663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 32014663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 32024663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 32034663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 32044663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 32054663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 32064663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 32074663dae6SJed Brown if (edm) { 32084663dae6SJed Brown ((DM_Plex *)edm->data)->printFEM = ((DM_Plex *)dm->data)->printFEM; 32094663dae6SJed Brown ((DM_Plex *)edm->data)->printL2 = ((DM_Plex *)dm->data)->printL2; 3210f5867de0SMatthew G. Knepley ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate; 32114663dae6SJed Brown } 321269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 3213b7f5c055SJed Brown } 3214b7f5c055SJed Brown PetscFunctionReturn(0); 3215b7f5c055SJed Brown } 3216b7f5c055SJed Brown 3217b7f5c055SJed Brown /*@ 3218b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 3219b7f5c055SJed Brown 3220b7f5c055SJed Brown Collective 3221b7f5c055SJed Brown 3222b7f5c055SJed Brown Input Parameters: 3223b7f5c055SJed Brown + comm - The communicator for the DM object 3224b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 3225b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 3226b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic 32271436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 3228817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 32291436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 3230817da375SSatish Balay - thickness - Thickness in normal direction 3231b7f5c055SJed Brown 3232b7f5c055SJed Brown Output Parameter: 3233b7f5c055SJed Brown . dm - The DM object 3234b7f5c055SJed Brown 3235b7f5c055SJed Brown Notes: 3236b7f5c055SJed 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. 3237b7f5c055SJed Brown https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries. 3238b7f5c055SJed 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. 3239b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 3240b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 3241b7f5c055SJed Brown This projection could readily be extended to related surfaces. 3242b7f5c055SJed Brown 3243b7f5c055SJed Brown The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z). 3244b7f5c055SJed Brown When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). Use DMPlexLabelComplete() to propagate to coarse-level vertices. 3245b7f5c055SJed Brown 3246b7f5c055SJed Brown References: 3247606c0280SSatish 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 3248b7f5c055SJed Brown 3249b7f5c055SJed Brown Developer Notes: 3250b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 3251b7f5c055SJed Brown 3252b7f5c055SJed Brown Level: beginner 3253b7f5c055SJed Brown 3254db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 3255b7f5c055SJed Brown @*/ 3256d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateTPSMesh(MPI_Comm comm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness, DM *dm) 3257d71ae5a4SJacob Faibussowitsch { 3258b7f5c055SJed Brown PetscFunctionBegin; 32599566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 32609566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 32619566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 3262b7f5c055SJed Brown PetscFunctionReturn(0); 3263b7f5c055SJed Brown } 3264b7f5c055SJed Brown 32659318fe57SMatthew G. Knepley /*@ 32669318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 32679318fe57SMatthew G. Knepley 32689318fe57SMatthew G. Knepley Collective 32699318fe57SMatthew G. Knepley 32709318fe57SMatthew G. Knepley Input Parameters: 32719318fe57SMatthew G. Knepley + comm - The communicator for the DM object 32729318fe57SMatthew G. Knepley . dim - The dimension 32739318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 32749318fe57SMatthew G. Knepley - R - The radius 32759318fe57SMatthew G. Knepley 32769318fe57SMatthew G. Knepley Output Parameter: 32779318fe57SMatthew G. Knepley . dm - The DM object 32789318fe57SMatthew G. Knepley 32799318fe57SMatthew G. Knepley Level: beginner 32809318fe57SMatthew G. Knepley 3281db781477SPatrick Sanan .seealso: `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 32829318fe57SMatthew G. Knepley @*/ 3283d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 3284d71ae5a4SJacob Faibussowitsch { 32859318fe57SMatthew G. Knepley PetscFunctionBegin; 32869318fe57SMatthew G. Knepley PetscValidPointer(dm, 5); 32879566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 32889566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 32899566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 32909318fe57SMatthew G. Knepley PetscFunctionReturn(0); 32919318fe57SMatthew G. Knepley } 32929318fe57SMatthew G. Knepley 3293d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 3294d71ae5a4SJacob Faibussowitsch { 32959318fe57SMatthew G. Knepley DM sdm, vol; 32969318fe57SMatthew G. Knepley DMLabel bdlabel; 32979318fe57SMatthew G. Knepley 32989318fe57SMatthew G. Knepley PetscFunctionBegin; 32999566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 33009566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 33019566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_")); 33029566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 33039566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 33049566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 33059566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 33069566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 330769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 33089566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 33099566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 33109566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 33119566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 331251a74b61SMatthew G. Knepley PetscFunctionReturn(0); 331351a74b61SMatthew G. Knepley } 331451a74b61SMatthew G. Knepley 331551a74b61SMatthew G. Knepley /*@ 331651a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 331751a74b61SMatthew G. Knepley 331851a74b61SMatthew G. Knepley Collective 331951a74b61SMatthew G. Knepley 332051a74b61SMatthew G. Knepley Input Parameters: 332151a74b61SMatthew G. Knepley + comm - The communicator for the DM object 332251a74b61SMatthew G. Knepley . dim - The dimension 332351a74b61SMatthew G. Knepley - R - The radius 332451a74b61SMatthew G. Knepley 332551a74b61SMatthew G. Knepley Output Parameter: 332651a74b61SMatthew G. Knepley . dm - The DM object 332751a74b61SMatthew G. Knepley 332851a74b61SMatthew G. Knepley Options Database Keys: 332951a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 333051a74b61SMatthew G. Knepley 333151a74b61SMatthew G. Knepley Level: beginner 333251a74b61SMatthew G. Knepley 3333db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 333451a74b61SMatthew G. Knepley @*/ 3335d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 3336d71ae5a4SJacob Faibussowitsch { 333751a74b61SMatthew G. Knepley PetscFunctionBegin; 33389566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 33399566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 33409566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 33412829fed8SMatthew G. Knepley PetscFunctionReturn(0); 33422829fed8SMatthew G. Knepley } 33432829fed8SMatthew G. Knepley 3344d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 3345d71ae5a4SJacob Faibussowitsch { 33460a6ba040SMatthew G. Knepley PetscFunctionBegin; 33479318fe57SMatthew G. Knepley switch (ct) { 33489371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 33499318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 33509318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 33519318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 33529318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 33539318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 33549318fe57SMatthew G. Knepley 33559566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 33569566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33579371c9d4SSatish Balay } break; 33589371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 33599318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 33609318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 33619318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 33629318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 33639318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 33649318fe57SMatthew G. Knepley 33659566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 33669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33679371c9d4SSatish Balay } break; 33689371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 3369b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 3370b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 3371b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 3372b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 3373b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 3374b5a892a1SMatthew G. Knepley 33759566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 33769566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33779371c9d4SSatish Balay } break; 33789371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 33799318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 33809318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 33819318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 33829318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 33839318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 33849318fe57SMatthew G. Knepley 33859566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 33869566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33879371c9d4SSatish Balay } break; 33889371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 33899318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 33909318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 33919318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 33929318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 33939318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 33949318fe57SMatthew G. Knepley 33959566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 33969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33979371c9d4SSatish Balay } break; 33989371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 33999318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 34009318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 34019318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 34029318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 34039318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 34049318fe57SMatthew G. Knepley 34059566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 34069566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34079371c9d4SSatish Balay } break; 34089371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 34099318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 34109318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 3411f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 34129318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 3413f0edb160SMatthew 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}; 34149318fe57SMatthew G. Knepley 34159566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34169566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34179371c9d4SSatish Balay } break; 34189371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 34199318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 34209318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 3421f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 34229318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34239371c9d4SSatish 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}; 34249318fe57SMatthew G. Knepley 34259566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34269566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34279371c9d4SSatish Balay } break; 34289371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 34299318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 34309318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 3431f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 34329318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 34339371c9d4SSatish 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}; 34349318fe57SMatthew G. Knepley 34359566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34379371c9d4SSatish Balay } break; 34389371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 34399318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 34409318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 34419318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 34429318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 34439371c9d4SSatish 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}; 34449318fe57SMatthew G. Knepley 34459566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34479371c9d4SSatish Balay } break; 34489371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 34499318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 34509318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 34519318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 34529318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34539371c9d4SSatish 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}; 34549318fe57SMatthew G. Knepley 34559566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34569566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34579371c9d4SSatish Balay } break; 34589371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 34599318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 34609318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 3461f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 34629318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34639371c9d4SSatish 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}; 34649318fe57SMatthew G. Knepley 34659566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34679371c9d4SSatish Balay } break; 3468d71ae5a4SJacob Faibussowitsch default: 3469d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 34709318fe57SMatthew G. Knepley } 34719318fe57SMatthew G. Knepley { 34729318fe57SMatthew G. Knepley PetscInt Nv, v; 34739318fe57SMatthew G. Knepley 34749318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 34759566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 34769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 34779566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 34789566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 34799318fe57SMatthew G. Knepley } 34809566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 34819566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 34820a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 34830a6ba040SMatthew G. Knepley } 34840a6ba040SMatthew G. Knepley 34859318fe57SMatthew G. Knepley /*@ 34869318fe57SMatthew G. Knepley DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell 34879318fe57SMatthew G. Knepley 34889318fe57SMatthew G. Knepley Collective 34899318fe57SMatthew G. Knepley 34909318fe57SMatthew G. Knepley Input Parameters: 34919318fe57SMatthew G. Knepley + comm - The communicator 34929318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 34939318fe57SMatthew G. Knepley 34949318fe57SMatthew G. Knepley Output Parameter: 34959318fe57SMatthew G. Knepley . refdm - The reference cell 34969318fe57SMatthew G. Knepley 34979318fe57SMatthew G. Knepley Level: intermediate 34989318fe57SMatthew G. Knepley 3499db781477SPatrick Sanan .seealso: `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()` 35009318fe57SMatthew G. Knepley @*/ 3501d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 3502d71ae5a4SJacob Faibussowitsch { 35030a6ba040SMatthew G. Knepley PetscFunctionBegin; 35049566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 35059566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 35069566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 35079318fe57SMatthew G. Knepley PetscFunctionReturn(0); 35089318fe57SMatthew G. Knepley } 350979a015ccSMatthew G. Knepley 3510d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 3511d71ae5a4SJacob Faibussowitsch { 35129318fe57SMatthew G. Knepley DM plex; 35139318fe57SMatthew G. Knepley DMLabel label; 35149318fe57SMatthew G. Knepley PetscBool hasLabel; 35150a6ba040SMatthew G. Knepley 3516c22d3578SMatthew G. Knepley PetscFunctionBegin; 35179566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 35189318fe57SMatthew G. Knepley if (hasLabel) PetscFunctionReturn(0); 35199566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 35209566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 35219566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 35229566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 35231c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 35249566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 35259318fe57SMatthew G. Knepley PetscFunctionReturn(0); 35269318fe57SMatthew G. Knepley } 3527acdc6f61SToby Isaac 3528669647acSMatthew G. Knepley /* 3529669647acSMatthew G. Knepley We use the last coordinate as the radius, the inner radius is lower[dim-1] and the outer radius is upper[dim-1]. Then we map the first coordinate around the circle. 3530669647acSMatthew G. Knepley 3531669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 3532669647acSMatthew G. Knepley */ 3533d71ae5a4SJacob Faibussowitsch static void boxToAnnulus(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 3534d71ae5a4SJacob Faibussowitsch { 3535669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 3536669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 3537669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 3538669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 3539669647acSMatthew G. Knepley 3540669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 3541669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 3542669647acSMatthew G. Knepley } 3543669647acSMatthew G. Knepley 3544669647acSMatthew G. Knepley const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 35459318fe57SMatthew G. Knepley 3546d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 3547d71ae5a4SJacob Faibussowitsch { 35489318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 35499318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 35509318fe57SMatthew G. Knepley PetscInt dim = 2; 35519318fe57SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 3552cd7e8a5eSksagiyam PetscBool flg, flg2, fflg, bdfflg, nameflg; 35539318fe57SMatthew G. Knepley MPI_Comm comm; 3554ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3555ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3556ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 35579318fe57SMatthew G. Knepley 35589318fe57SMatthew G. Knepley PetscFunctionBegin; 35599566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 35609318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 35619566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 35629566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 35639566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 35649566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 35659566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 35669566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 35679566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 356863a3b9bcSJacob Faibussowitsch PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim); 35699566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 35709566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 35719566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 35729566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 35739566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 35749318fe57SMatthew G. Knepley 357561a622f3SMatthew G. Knepley switch (cell) { 357661a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 357761a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 357861a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 357961a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 358061a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 358161a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 3582d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 3583d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 3584d71ae5a4SJacob Faibussowitsch break; 3585d71ae5a4SJacob Faibussowitsch default: 3586d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 3587d71ae5a4SJacob Faibussowitsch break; 358861a622f3SMatthew G. Knepley } 358961a622f3SMatthew G. Knepley 35909318fe57SMatthew G. Knepley if (fflg) { 35919318fe57SMatthew G. Knepley DM dmnew; 35929318fe57SMatthew G. Knepley 35939566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew)); 35945de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 359569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 35969318fe57SMatthew G. Knepley } else if (refDomain) { 35979566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 35989318fe57SMatthew G. Knepley } else if (bdfflg) { 35999318fe57SMatthew G. Knepley DM bdm, dmnew; 36009318fe57SMatthew G. Knepley 36019566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm)); 36029566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 36039566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 36049566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 36059566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 36065de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 360769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 36089318fe57SMatthew G. Knepley } else { 36099566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 36109318fe57SMatthew G. Knepley switch (shape) { 3611669647acSMatthew G. Knepley case DM_SHAPE_BOX: 3612669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 36139318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 36149318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 36159318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 36169318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3617669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 36189318fe57SMatthew G. Knepley PetscInt i, n; 36199318fe57SMatthew G. Knepley 36209318fe57SMatthew G. Knepley n = dim; 36219318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 36229566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 36239318fe57SMatthew G. Knepley n = 3; 36249566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 362563a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 36269318fe57SMatthew G. Knepley n = 3; 36279566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 362863a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 36299318fe57SMatthew G. Knepley n = 3; 36309566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 363163a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 3632669647acSMatthew G. Knepley 3633669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 3634669647acSMatthew G. Knepley if (isAnnular) 3635669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 3636669647acSMatthew G. Knepley 36379318fe57SMatthew G. Knepley switch (cell) { 363861a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 36399566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 3640d410b0cfSMatthew G. Knepley if (!interpolate) { 3641d410b0cfSMatthew G. Knepley DM udm; 3642d410b0cfSMatthew G. Knepley 36439566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 364469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3645d410b0cfSMatthew G. Knepley } 36469318fe57SMatthew G. Knepley break; 3647d71ae5a4SJacob Faibussowitsch default: 3648d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate)); 3649d71ae5a4SJacob Faibussowitsch break; 36509318fe57SMatthew G. Knepley } 3651669647acSMatthew G. Knepley if (isAnnular) { 3652669647acSMatthew G. Knepley DM cdm; 3653669647acSMatthew G. Knepley PetscDS cds; 3654669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 3655669647acSMatthew G. Knepley 3656669647acSMatthew G. Knepley // Fix coordinates for annular region 3657669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 3658669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 3659669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 3660669647acSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, NULL)); 3661669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 3662669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 3663669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 3664669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 3665669647acSMatthew G. Knepley } 36669371c9d4SSatish Balay } break; 36679371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 36689318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 36699318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 36709318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 36719318fe57SMatthew G. Knepley PetscInt i, n; 36729318fe57SMatthew G. Knepley 36739318fe57SMatthew G. Knepley n = dim + 1; 36749318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 36759566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 36769318fe57SMatthew G. Knepley n = 3; 36779566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 367863a3b9bcSJacob 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); 36799318fe57SMatthew G. Knepley n = 3; 36809566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 368163a3b9bcSJacob 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); 36829566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 36839371c9d4SSatish Balay } break; 36849371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 36859318fe57SMatthew G. Knepley PetscReal R = 1.0; 36869318fe57SMatthew G. Knepley 36879566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 36889566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 36899371c9d4SSatish Balay } break; 36909371c9d4SSatish Balay case DM_SHAPE_BALL: { 36919318fe57SMatthew G. Knepley PetscReal R = 1.0; 36929318fe57SMatthew G. Knepley 36939566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 36949566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 36959371c9d4SSatish Balay } break; 36969371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 36979318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 36989318fe57SMatthew G. Knepley PetscInt Nw = 6; 36999318fe57SMatthew G. Knepley 37009566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 37019566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 37029318fe57SMatthew G. Knepley switch (cell) { 3703d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 3704d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 3705d71ae5a4SJacob Faibussowitsch break; 3706d71ae5a4SJacob Faibussowitsch default: 3707d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt)); 3708d71ae5a4SJacob Faibussowitsch break; 37099318fe57SMatthew G. Knepley } 37109371c9d4SSatish Balay } break; 3711b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 37129371c9d4SSatish Balay case DM_SHAPE_GYROID: { 3713b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 3714b7f5c055SJed Brown PetscReal thickness = 0.; 3715b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3716b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 37171436d7faSJed Brown PetscBool tps_distribute; 37189566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 37199566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 37209566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 37219566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 37229566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 37239566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 37249566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 37259566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 37269371c9d4SSatish Balay } break; 37279371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 372805bd46c0SStefano Zampini DM dmnew; 372905bd46c0SStefano Zampini PetscReal rl = 0.0; 373005bd46c0SStefano Zampini 373105bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 373205bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 37335de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 373469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 37359371c9d4SSatish Balay } break; 3736d71ae5a4SJacob Faibussowitsch default: 3737d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 37389318fe57SMatthew G. Knepley } 37399318fe57SMatthew G. Knepley } 37409566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 374148a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 37420a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 37430a6ba040SMatthew G. Knepley } 37440a6ba040SMatthew G. Knepley 3745d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 3746d71ae5a4SJacob Faibussowitsch { 37470a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 37487f9d8d6cSVaclav Hapla PetscBool flg, flg2; 37499318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 37500a6ba040SMatthew G. Knepley 37510a6ba040SMatthew G. Knepley PetscFunctionBegin; 37520a6ba040SMatthew G. Knepley /* Handle viewing */ 37539566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 37549566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 37559566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 37569566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 3757f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 37589566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 37599566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 37609318fe57SMatthew G. Knepley /* Labeling */ 37619566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 37629566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 3763953fc75cSMatthew G. Knepley /* Point Location */ 37649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 37650848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 37669566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 37672e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 37689566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 3769b29cfa1cSToby Isaac /* Projection behavior */ 3770d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 37719566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 3772f12cf164SMatthew G. Knepley /* Checking structure */ 3773f12cf164SMatthew G. Knepley { 37747f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 3775f12cf164SMatthew G. Knepley 37767f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 37777f9d8d6cSVaclav Hapla if (all) { 37787f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 37797f9d8d6cSVaclav Hapla } else { 37809566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 37817f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 37829566063dSJacob 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)); 37837f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 37849566063dSJacob 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)); 37857f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 37869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 37877f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 37889566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 3789d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 37909566063dSJacob 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)); 37917f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 37927f9d8d6cSVaclav Hapla } 37939566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 37949566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 3795f12cf164SMatthew G. Knepley } 37969318fe57SMatthew G. Knepley { 37979318fe57SMatthew G. Knepley PetscReal scale = 1.0; 37984f3833eaSMatthew G. Knepley 37999566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 38009318fe57SMatthew G. Knepley if (flg) { 38019318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 38029318fe57SMatthew G. Knepley 38039566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 38049566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 38059566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 38069566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 38079318fe57SMatthew G. Knepley } 38089318fe57SMatthew G. Knepley } 38099566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 381068d4fef7SMatthew G. Knepley PetscFunctionReturn(0); 381168d4fef7SMatthew G. Knepley } 381268d4fef7SMatthew G. Knepley 3813d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap) 3814d71ae5a4SJacob Faibussowitsch { 3815c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 3816c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 3817c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 3818c506a872SMatthew G. Knepley PetscBool flg; 3819c506a872SMatthew G. Knepley 3820c506a872SMatthew G. Knepley PetscFunctionBegin; 3821c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 3822c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 3823c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 3824c506a872SMatthew G. Knepley if (numOvLabels) { 3825c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 3826c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 3827c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 3828c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 3829c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 3830c506a872SMatthew G. Knepley } 3831c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 3832c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 3833c506a872SMatthew 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); 3834c506a872SMatthew G. Knepley 3835c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 3836c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 3837c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 3838c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 3839c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 3840c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 3841c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 3842c506a872SMatthew G. Knepley } 3843c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 3844c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 3845c506a872SMatthew 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); 3846c506a872SMatthew G. Knepley } 3847c506a872SMatthew G. Knepley PetscFunctionReturn(0); 3848c506a872SMatthew G. Knepley } 3849c506a872SMatthew G. Knepley 3850d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 3851d71ae5a4SJacob Faibussowitsch { 3852bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 3853bdf63967SMatthew G. Knepley char oname[256]; 3854d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 38559318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 3856e600fa54SMatthew 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; 38576bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 385868d4fef7SMatthew G. Knepley 385968d4fef7SMatthew G. Knepley PetscFunctionBegin; 3860d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 3861*dd4c3f67SMatthew G. Knepley if (dm->cloneOpts) goto non_refine; 38629318fe57SMatthew G. Knepley /* Handle automatic creation */ 38639566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 38646bc1bd01Sksagiyam if (dim < 0) { 38656bc1bd01Sksagiyam PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 38666bc1bd01Sksagiyam created = PETSC_TRUE; 38676bc1bd01Sksagiyam } 38686bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 3869d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 38709566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 3871d89e6e46SMatthew G. Knepley if (flg) { 3872d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 3873d89e6e46SMatthew G. Knepley 38749566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 3875d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 3876d89e6e46SMatthew G. Knepley DM udm; 3877d89e6e46SMatthew G. Knepley 38789566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 387969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3880d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 3881d89e6e46SMatthew G. Knepley DM idm; 3882d89e6e46SMatthew G. Knepley 38839566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 388469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3885d89e6e46SMatthew G. Knepley } 3886d89e6e46SMatthew G. Knepley } 38879b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 38889566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg)); 3889ad540459SPierre Jolivet if (flg) ((DM_Plex *)dm->data)->ignoreModel = ignoreModel; 38909566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 38919566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 38929566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 38939566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 38949566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 38959566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 38969318fe57SMatthew G. Knepley if (flg) { 38979566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 38989566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 38999318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 39009318fe57SMatthew G. Knepley } 39019b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 39029b44eab4SMatthew G. Knepley DM rdm; 39039b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 39049b44eab4SMatthew G. Knepley 3905dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 39069566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 390769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 3908dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 390961a622f3SMatthew G. Knepley if (coordFunc && remap) { 39109566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 39119b44eab4SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 39129b44eab4SMatthew G. Knepley } 39139b44eab4SMatthew G. Knepley } 39149566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 39159318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 39169566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 39179318fe57SMatthew G. Knepley if (extLayers) { 39189318fe57SMatthew G. Knepley DM edm; 39199318fe57SMatthew G. Knepley 39209566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 392169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 392248d16a33SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = NULL; 3923dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3924d410b0cfSMatthew G. Knepley extLayers = 0; 39255e17fc22SAidan Hamilton PetscCall(DMGetDimension(dm, &dim)); 39269318fe57SMatthew G. Knepley } 3927bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 39286bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 39299566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 39306bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 39319566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 39326bc1bd01Sksagiyam if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) { 3933bdf63967SMatthew G. Knepley DM pdm; 3934bdf63967SMatthew G. Knepley IS perm; 3935bdf63967SMatthew G. Knepley 39369566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 39379566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 39389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 393969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 3940dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3941bdf63967SMatthew G. Knepley } 39429b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 39439566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 3944c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 3945dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 39469b44eab4SMatthew G. Knepley if (distribute) { 39479b44eab4SMatthew G. Knepley DM pdm = NULL; 39489b44eab4SMatthew G. Knepley PetscPartitioner part; 39499b44eab4SMatthew G. Knepley 39509566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 39519566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 39529566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm)); 395348a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 39549b44eab4SMatthew G. Knepley } 39559318fe57SMatthew G. Knepley /* Create coordinate space */ 39569318fe57SMatthew G. Knepley if (created) { 395761a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 39589318fe57SMatthew G. Knepley PetscInt degree = 1; 39596858538eSMatthew G. Knepley PetscBool flg; 39609318fe57SMatthew G. Knepley 39619566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg)); 39629566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 39639566063dSJacob Faibussowitsch if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc)); 396461a622f3SMatthew G. Knepley if (flg && !coordSpace) { 396561a622f3SMatthew G. Knepley DM cdm; 396661a622f3SMatthew G. Knepley PetscDS cds; 396761a622f3SMatthew G. Knepley PetscObject obj; 396861a622f3SMatthew G. Knepley PetscClassId id; 396961a622f3SMatthew G. Knepley 39709566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 39719566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 39729566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 39739566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 397461a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 397561a622f3SMatthew G. Knepley PetscContainer dummy; 397661a622f3SMatthew G. Knepley 39779566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 39789566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 39799566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 39809566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 39819566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 398261a622f3SMatthew G. Knepley } 398361a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 398461a622f3SMatthew G. Knepley } 39856858538eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg)); 39869566063dSJacob Faibussowitsch PetscCall(DMLocalizeCoordinates(dm)); 39879318fe57SMatthew G. Knepley } 398868d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 398961a622f3SMatthew G. Knepley remap = PETSC_TRUE; 39909566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 39919566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 39929566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 39939566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 399468d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 3995acdc6f61SToby Isaac DM *dms, coarseDM; 399668d4fef7SMatthew G. Knepley 39979566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 39989566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 39999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 40009566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 400168d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 40029566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 400368d4fef7SMatthew G. Knepley if (refine == 1) { 40049566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 40059566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 400668d4fef7SMatthew G. Knepley } else { 40079566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 40089566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 40099566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 40109566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 401168d4fef7SMatthew G. Knepley } 40129566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 40139566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 401468d4fef7SMatthew G. Knepley /* Free DMs */ 401568d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 4016dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 40179566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 401868d4fef7SMatthew G. Knepley } 40199566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 402068d4fef7SMatthew G. Knepley } else { 402168d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 40229318fe57SMatthew G. Knepley DM rdm; 402351a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 402468d4fef7SMatthew G. Knepley 4025dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40269566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 402768d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 402869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 4029dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 403061a622f3SMatthew G. Knepley if (coordFunc && remap) { 40319566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 403251a74b61SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 403351a74b61SMatthew G. Knepley } 403468d4fef7SMatthew G. Knepley } 403568d4fef7SMatthew G. Knepley } 40363cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 40379566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 40389566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 4039b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 4040b653a561SMatthew G. Knepley DM *dms; 4041b653a561SMatthew G. Knepley 40429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 40439566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 4044b653a561SMatthew G. Knepley /* Free DMs */ 4045b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 4046dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 40479566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 4048b653a561SMatthew G. Knepley } 40499566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 4050b653a561SMatthew G. Knepley } else { 4051b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 40529318fe57SMatthew G. Knepley DM cdm; 40539318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 40543cf6fe12SMatthew G. Knepley 4055dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40569566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 40573cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 405869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 4059dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40609318fe57SMatthew G. Knepley if (coordFunc) { 40619566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 40629318fe57SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 40639318fe57SMatthew G. Knepley } 40643cf6fe12SMatthew G. Knepley } 4065b653a561SMatthew G. Knepley } 4066909dfd52SMatthew G. Knepley /* Handle ghost cells */ 40679566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 4068909dfd52SMatthew G. Knepley if (ghostCells) { 4069909dfd52SMatthew G. Knepley DM gdm; 4070909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 4071909dfd52SMatthew G. Knepley 4072909dfd52SMatthew G. Knepley lname[0] = '\0'; 40739566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 40749566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 407569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 4076909dfd52SMatthew G. Knepley } 40776913077dSMatthew G. Knepley /* Handle 1D order */ 40786bc1bd01Sksagiyam if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) { 40796913077dSMatthew G. Knepley DM cdm, rdm; 40806913077dSMatthew G. Knepley PetscDS cds; 40816913077dSMatthew G. Knepley PetscObject obj; 40826913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 40836913077dSMatthew G. Knepley IS perm; 40846bc1bd01Sksagiyam PetscInt Nf; 40856913077dSMatthew G. Knepley PetscBool distributed; 40866913077dSMatthew G. Knepley 40879566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 40889566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 40899566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 40909566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 40916913077dSMatthew G. Knepley if (Nf) { 40929566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 40939566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 40946913077dSMatthew G. Knepley } 40956bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 40969566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 40979566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 409869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 40999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 41006913077dSMatthew G. Knepley } 41016913077dSMatthew G. Knepley } 41023cf6fe12SMatthew G. Knepley /* Handle */ 4103*dd4c3f67SMatthew G. Knepley non_refine: 4104dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 4105d0609cedSBarry Smith PetscOptionsHeadEnd(); 41060a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 41070a6ba040SMatthew G. Knepley } 41080a6ba040SMatthew G. Knepley 4109d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 4110d71ae5a4SJacob Faibussowitsch { 4111552f7358SJed Brown PetscFunctionBegin; 41129566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 41139566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 41149566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 41159566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 41169566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 41179566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 4118552f7358SJed Brown PetscFunctionReturn(0); 4119552f7358SJed Brown } 4120552f7358SJed Brown 4121d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 4122d71ae5a4SJacob Faibussowitsch { 4123552f7358SJed Brown PetscFunctionBegin; 41249566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 41259566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 41269566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 4127552f7358SJed Brown PetscFunctionReturn(0); 4128552f7358SJed Brown } 4129552f7358SJed Brown 4130d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4131d71ae5a4SJacob Faibussowitsch { 4132793f3fe5SMatthew G. Knepley PetscInt depth, d; 4133793f3fe5SMatthew G. Knepley 4134793f3fe5SMatthew G. Knepley PetscFunctionBegin; 41359566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4136793f3fe5SMatthew G. Knepley if (depth == 1) { 41379566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 41389566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 41399566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 41409371c9d4SSatish Balay else { 41419371c9d4SSatish Balay *pStart = 0; 41429371c9d4SSatish Balay *pEnd = 0; 41439371c9d4SSatish Balay } 4144793f3fe5SMatthew G. Knepley } else { 41459566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 4146793f3fe5SMatthew G. Knepley } 4147793f3fe5SMatthew G. Knepley PetscFunctionReturn(0); 4148793f3fe5SMatthew G. Knepley } 4149793f3fe5SMatthew G. Knepley 4150d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 4151d71ae5a4SJacob Faibussowitsch { 4152502a2867SDave May PetscSF sf; 41530a19bb7dSprj- PetscInt niranks, njranks, n; 41540a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 41550a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 4156502a2867SDave May 41572f356facSMatthew G. Knepley PetscFunctionBegin; 41589566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 41590a19bb7dSprj- if (!data->neighbors) { 41609566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 41619566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 41629566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 41639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 41649566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 41659566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 41660a19bb7dSprj- n = njranks + niranks; 41679566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 41680a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 41699566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 41700a19bb7dSprj- } 41710a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 41720a19bb7dSprj- if (ranks) { 41730a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 41740a19bb7dSprj- else *ranks = NULL; 41750a19bb7dSprj- } 4176502a2867SDave May PetscFunctionReturn(0); 4177502a2867SDave May } 4178502a2867SDave May 41791eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 41801eb70e55SToby Isaac 4181d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 4182d71ae5a4SJacob Faibussowitsch { 4183552f7358SJed Brown PetscFunctionBegin; 4184552f7358SJed Brown dm->ops->view = DMView_Plex; 41852c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 4186552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 418738221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 4188552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 41891bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 419066ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 4191552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 4192552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 4193184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 41940298fd71SBarry Smith dm->ops->createfieldis = NULL; 4195552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 4196f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 41970a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 4198552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 4199bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 4200bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 4201b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 42025a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 4203552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 42040a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 42050a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 4206b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 4207d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 42080298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 42090298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 42100298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 42110298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 4212552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 4213552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 42142adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 4215793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 4216552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 42170709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 42180709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 4219bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 42208c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 4221ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 42220709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 4223b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 42242a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 422528d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 42269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 42279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 42289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 42299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 42309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 42319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 42329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 42336bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 42346bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 42359566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 4236c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 4237c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 4238552f7358SJed Brown PetscFunctionReturn(0); 4239552f7358SJed Brown } 4240552f7358SJed Brown 4241d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 4242d71ae5a4SJacob Faibussowitsch { 424363a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 424463a16f15SMatthew G. Knepley 424563a16f15SMatthew G. Knepley PetscFunctionBegin; 424663a16f15SMatthew G. Knepley mesh->refct++; 424763a16f15SMatthew G. Knepley (*newdm)->data = mesh; 42489566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 42499566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 425063a16f15SMatthew G. Knepley PetscFunctionReturn(0); 425163a16f15SMatthew G. Knepley } 425263a16f15SMatthew G. Knepley 42538818961aSMatthew G Knepley /*MC 42548818961aSMatthew G Knepley DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 42558818961aSMatthew G Knepley In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is 42568818961aSMatthew G Knepley specified by a PetscSection object. Ownership in the global representation is determined by 42578818961aSMatthew G Knepley ownership of the underlying DMPlex points. This is specified by another PetscSection object. 42588818961aSMatthew G Knepley 4259e5893cccSMatthew G. Knepley Options Database Keys: 4260250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 4261250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 4262250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 4263250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 4264250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 4265250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 4266250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 4267ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 4268f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 4269f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 4270d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 4271f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 4272250712c9SMatthew G. Knepley . -dm_plex_check_all - Perform all shecks below 4273f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 4274f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 4275f12cf164SMatthew 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 4276f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 4277f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 4278e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 4279e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 4280e5893cccSMatthew G. Knepley 42818818961aSMatthew G Knepley Level: intermediate 42828818961aSMatthew G Knepley 4283db781477SPatrick Sanan .seealso: `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()` 42848818961aSMatthew G Knepley M*/ 42858818961aSMatthew G Knepley 4286d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 4287d71ae5a4SJacob Faibussowitsch { 4288552f7358SJed Brown DM_Plex *mesh; 4289412e9a14SMatthew G. Knepley PetscInt unit; 4290552f7358SJed Brown 4291552f7358SJed Brown PetscFunctionBegin; 4292552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 42934dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 4294552f7358SJed Brown dm->data = mesh; 4295552f7358SJed Brown 4296552f7358SJed Brown mesh->refct = 1; 42979566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 42989566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 4299552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 4300552f7358SJed Brown mesh->refinementLimit = -1.0; 4301e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 43026bc1bd01Sksagiyam mesh->reorderDefault = DMPLEX_REORDER_DEFAULT_NOTSET; 43031d1f2f2aSksagiyam mesh->distributionName = NULL; 43047d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 43057d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 4306552f7358SJed Brown 43079566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 43082e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 4309d9deefdfSMatthew G. Knepley 43108865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 4311552f7358SJed Brown 4312df0420ecSMatthew G. Knepley mesh->depthState = -1; 4313ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 43146113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 4315552f7358SJed Brown 43169566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 4317552f7358SJed Brown PetscFunctionReturn(0); 4318552f7358SJed Brown } 4319552f7358SJed Brown 4320552f7358SJed Brown /*@ 4321552f7358SJed Brown DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 4322552f7358SJed Brown 4323d083f849SBarry Smith Collective 4324552f7358SJed Brown 4325552f7358SJed Brown Input Parameter: 4326552f7358SJed Brown . comm - The communicator for the DMPlex object 4327552f7358SJed Brown 4328552f7358SJed Brown Output Parameter: 4329552f7358SJed Brown . mesh - The DMPlex object 4330552f7358SJed Brown 4331552f7358SJed Brown Level: beginner 4332552f7358SJed Brown 4333552f7358SJed Brown @*/ 4334d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 4335d71ae5a4SJacob Faibussowitsch { 4336552f7358SJed Brown PetscFunctionBegin; 4337552f7358SJed Brown PetscValidPointer(mesh, 2); 43389566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 43399566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 4340552f7358SJed Brown PetscFunctionReturn(0); 4341552f7358SJed Brown } 4342552f7358SJed Brown 4343b09969d6SVaclav Hapla /*@C 4344b09969d6SVaclav Hapla DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output) 4345b09969d6SVaclav Hapla 4346b09969d6SVaclav Hapla Input Parameters: 4347b09969d6SVaclav Hapla + dm - The DM 4348b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4349325d53feSBarry Smith . numVertices - The number of vertices to be owned by this process, or PETSC_DECIDE 4350325d53feSBarry Smith . NVertices - The global number of vertices, or PETSC_DETERMINE 4351b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 43525e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4353b09969d6SVaclav Hapla 4354be8c289dSNicolas Barral Output Parameters: 4355be8c289dSNicolas Barral + vertexSF - (Optional) SF describing complete vertex ownership 4356be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4357b09969d6SVaclav Hapla 4358b09969d6SVaclav Hapla Notes: 4359b09969d6SVaclav Hapla Two triangles sharing a face 4360b09969d6SVaclav Hapla $ 4361b09969d6SVaclav Hapla $ 2 4362b09969d6SVaclav Hapla $ / | \ 4363b09969d6SVaclav Hapla $ / | \ 4364b09969d6SVaclav Hapla $ / | \ 4365b09969d6SVaclav Hapla $ 0 0 | 1 3 4366b09969d6SVaclav Hapla $ \ | / 4367b09969d6SVaclav Hapla $ \ | / 4368b09969d6SVaclav Hapla $ \ | / 4369b09969d6SVaclav Hapla $ 1 4370b09969d6SVaclav Hapla would have input 4371b09969d6SVaclav Hapla $ numCells = 2, numVertices = 4 4372b09969d6SVaclav Hapla $ cells = [0 1 2 1 3 2] 4373b09969d6SVaclav Hapla $ 4374b09969d6SVaclav Hapla which would result in the DMPlex 4375b09969d6SVaclav Hapla $ 4376b09969d6SVaclav Hapla $ 4 4377b09969d6SVaclav Hapla $ / | \ 4378b09969d6SVaclav Hapla $ / | \ 4379b09969d6SVaclav Hapla $ / | \ 4380b09969d6SVaclav Hapla $ 2 0 | 1 5 4381b09969d6SVaclav Hapla $ \ | / 4382b09969d6SVaclav Hapla $ \ | / 4383b09969d6SVaclav Hapla $ \ | / 4384b09969d6SVaclav Hapla $ 3 4385b09969d6SVaclav Hapla 438625b6865aSVaclav Hapla Vertices are implicitly numbered consecutively 0,...,NVertices. 438725b6865aSVaclav Hapla Each rank owns a chunk of numVertices consecutive vertices. 438825b6865aSVaclav Hapla If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout. 4389325d53feSBarry Smith If NVertices is PETSC_DETERMINE and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 4390325d53feSBarry Smith If only NVertices is PETSC_DETERMINE, it is computed as the sum of numVertices over all ranks. 439125b6865aSVaclav Hapla 4392b09969d6SVaclav Hapla The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 4393b09969d6SVaclav Hapla 4394b09969d6SVaclav Hapla Not currently supported in Fortran. 4395b09969d6SVaclav Hapla 4396b09969d6SVaclav Hapla Level: advanced 4397b09969d6SVaclav Hapla 4398db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()` 4399b09969d6SVaclav Hapla @*/ 4400d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved) 4401d71ae5a4SJacob Faibussowitsch { 44022464107aSksagiyam PetscSF sfPoint; 44032464107aSksagiyam PetscLayout layout; 440482fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 4405a47d0d45SMatthew G. Knepley 4406a47d0d45SMatthew G. Knepley PetscFunctionBegin; 440725b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 44089566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 440925b6865aSVaclav Hapla /* Get/check global number of vertices */ 441025b6865aSVaclav Hapla { 441125b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 441225b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 441325b6865aSVaclav Hapla 441425b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 441525b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 44169371c9d4SSatish Balay for (i = 0; i < len; i++) 44179371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 441825b6865aSVaclav Hapla ++NVerticesInCells; 44199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 442025b6865aSVaclav Hapla 442125b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 44229371c9d4SSatish Balay else 44239371c9d4SSatish 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); 442425b6865aSVaclav Hapla } 44259079aca8SVaclav Hapla /* Count locally unique vertices */ 44269079aca8SVaclav Hapla { 44279079aca8SVaclav Hapla PetscHSetI vhash; 44289079aca8SVaclav Hapla PetscInt off = 0; 44299079aca8SVaclav Hapla 44309566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 4431a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 443248a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 4433a47d0d45SMatthew G. Knepley } 44349566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 44359566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 4436ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 44379566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 44389566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 443963a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 4440a47d0d45SMatthew G. Knepley } 44419566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 4442a47d0d45SMatthew G. Knepley /* Create cones */ 44439566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 44449566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 44459566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 44469566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4447a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 4448a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 4449a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 4450a47d0d45SMatthew G. Knepley PetscInt lv; 4451a47d0d45SMatthew G. Knepley 44529079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 44539079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 44549566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 445563a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 4456961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 4457a47d0d45SMatthew G. Knepley } 4458a47d0d45SMatthew G. Knepley } 44592464107aSksagiyam /* Build point sf */ 44609566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 44619566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 44629566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 44639566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 44649566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 44659566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 44669566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 44679566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 44682464107aSksagiyam if (dm->sf) { 44692464107aSksagiyam const char *prefix; 44702464107aSksagiyam 44719566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 44729566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 44732464107aSksagiyam } 44749566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 44759566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 44769566063dSJacob Faibussowitsch if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF")); 4477a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 44789566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 44799566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 44809566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4481a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4482a47d0d45SMatthew G. Knepley } 4483a47d0d45SMatthew G. Knepley 4484b09969d6SVaclav Hapla /*@C 4485b09969d6SVaclav Hapla DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4486b09969d6SVaclav Hapla 4487b09969d6SVaclav Hapla Input Parameters: 4488b09969d6SVaclav Hapla + dm - The DM 4489b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4490b09969d6SVaclav Hapla . sfVert - SF describing complete vertex ownership 4491b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4492b09969d6SVaclav Hapla 4493b09969d6SVaclav Hapla Level: advanced 4494b09969d6SVaclav Hapla 4495b09969d6SVaclav Hapla Notes: 4496b09969d6SVaclav Hapla Not currently supported in Fortran. 4497b09969d6SVaclav Hapla 4498db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 4499b09969d6SVaclav Hapla @*/ 4500d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 4501d71ae5a4SJacob Faibussowitsch { 4502a47d0d45SMatthew G. Knepley PetscSection coordSection; 4503a47d0d45SMatthew G. Knepley Vec coordinates; 4504a47d0d45SMatthew G. Knepley PetscScalar *coords; 45051edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 4506a47d0d45SMatthew G. Knepley 4507a47d0d45SMatthew G. Knepley PetscFunctionBegin; 45089566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 45099566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 45101dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 45119566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 45129566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 45131dca8a05SBarry 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); 45149566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 45159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 45169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 45179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 45181edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 45199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 45209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4521a47d0d45SMatthew G. Knepley } 45229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 45239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 45249566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 45259566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 45269566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 45279566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 45289566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 45299566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 4530a47d0d45SMatthew G. Knepley { 4531a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 4532a47d0d45SMatthew G. Knepley 4533a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 45349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype)); 45359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 453621016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 453721016a8bSBarry Smith { 453821016a8bSBarry Smith PetscScalar *svertexCoords; 453921016a8bSBarry Smith PetscInt i; 45409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 45413612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 45429566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 45439566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 45449566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 454521016a8bSBarry Smith } 454621016a8bSBarry Smith #else 45479566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 45489566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 454921016a8bSBarry Smith #endif 45509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 4551a47d0d45SMatthew G. Knepley } 45529566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 45539566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 45549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 45559566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4556a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4557a47d0d45SMatthew G. Knepley } 4558a47d0d45SMatthew G. Knepley 4559c3edce3dSSatish Balay /*@ 4560b09969d6SVaclav Hapla DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output) 4561a47d0d45SMatthew G. Knepley 4562a47d0d45SMatthew G. Knepley Input Parameters: 4563a47d0d45SMatthew G. Knepley + comm - The communicator 4564a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 4565a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 456625b6865aSVaclav Hapla . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 456725b6865aSVaclav Hapla . NVertices - The global number of vertices, or PETSC_DECIDE 4568a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 4569a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 4570a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4571a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 4572a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4573a47d0d45SMatthew G. Knepley 4574d8d19677SJose E. Roman Output Parameters: 457518d54ad4SMichael Lange + dm - The DM 4576be8c289dSNicolas Barral . vertexSF - (Optional) SF describing complete vertex ownership 4577be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4578a47d0d45SMatthew G. Knepley 4579b09969d6SVaclav Hapla Notes: 4580b09969d6SVaclav Hapla This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), 4581b09969d6SVaclav Hapla DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel() 4582a47d0d45SMatthew G. Knepley 458325b6865aSVaclav Hapla See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters. 458425b6865aSVaclav Hapla See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters. 458525b6865aSVaclav Hapla 4586b09969d6SVaclav Hapla Level: intermediate 4587a47d0d45SMatthew G. Knepley 4588db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 4589a47d0d45SMatthew G. Knepley @*/ 4590d71ae5a4SJacob Faibussowitsch 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) 4591d71ae5a4SJacob Faibussowitsch { 4592a47d0d45SMatthew G. Knepley PetscSF sfVert; 4593a47d0d45SMatthew G. Knepley 4594a47d0d45SMatthew G. Knepley PetscFunctionBegin; 45959566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 45969566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 4597a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 4598064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 45999566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 46009566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 4601a47d0d45SMatthew G. Knepley if (interpolate) { 46025fd9971aSMatthew G. Knepley DM idm; 4603a47d0d45SMatthew G. Knepley 46049566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 46059566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 4606a47d0d45SMatthew G. Knepley *dm = idm; 4607a47d0d45SMatthew G. Knepley } 46089566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 460918d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 46109566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 4611a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4612a47d0d45SMatthew G. Knepley } 4613a47d0d45SMatthew G. Knepley 4614b09969d6SVaclav Hapla /*@C 4615b09969d6SVaclav Hapla DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output) 46169298eaa6SMatthew G Knepley 46179298eaa6SMatthew G Knepley Input Parameters: 4618b09969d6SVaclav Hapla + dm - The DM 4619b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4620325d53feSBarry Smith . numVertices - The number of vertices owned by this process, or PETSC_DETERMINE 46219298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 46225e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 46239298eaa6SMatthew G Knepley 4624b09969d6SVaclav Hapla Level: advanced 46259298eaa6SMatthew G Knepley 4626b09969d6SVaclav Hapla Notes: 4627b09969d6SVaclav Hapla Two triangles sharing a face 46289298eaa6SMatthew G Knepley $ 46299298eaa6SMatthew G Knepley $ 2 46309298eaa6SMatthew G Knepley $ / | \ 46319298eaa6SMatthew G Knepley $ / | \ 46329298eaa6SMatthew G Knepley $ / | \ 46339298eaa6SMatthew G Knepley $ 0 0 | 1 3 46349298eaa6SMatthew G Knepley $ \ | / 46359298eaa6SMatthew G Knepley $ \ | / 46369298eaa6SMatthew G Knepley $ \ | / 46379298eaa6SMatthew G Knepley $ 1 46389298eaa6SMatthew G Knepley would have input 46399298eaa6SMatthew G Knepley $ numCells = 2, numVertices = 4 46409298eaa6SMatthew G Knepley $ cells = [0 1 2 1 3 2] 46419298eaa6SMatthew G Knepley $ 46429298eaa6SMatthew G Knepley which would result in the DMPlex 46439298eaa6SMatthew G Knepley $ 46449298eaa6SMatthew G Knepley $ 4 46459298eaa6SMatthew G Knepley $ / | \ 46469298eaa6SMatthew G Knepley $ / | \ 46479298eaa6SMatthew G Knepley $ / | \ 46489298eaa6SMatthew G Knepley $ 2 0 | 1 5 46499298eaa6SMatthew G Knepley $ \ | / 46509298eaa6SMatthew G Knepley $ \ | / 46519298eaa6SMatthew G Knepley $ \ | / 46529298eaa6SMatthew G Knepley $ 3 46539298eaa6SMatthew G Knepley 4654325d53feSBarry Smith If numVertices is PETSC_DETERMINE, it is computed by PETSc as the maximum vertex index in cells + 1. 465525b6865aSVaclav Hapla 4656b09969d6SVaclav Hapla Not currently supported in Fortran. 46579298eaa6SMatthew G Knepley 4658db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 4659b09969d6SVaclav Hapla @*/ 4660d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 4661d71ae5a4SJacob Faibussowitsch { 4662961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 4663b09969d6SVaclav Hapla 4664b09969d6SVaclav Hapla PetscFunctionBegin; 46659566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 46669566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 466725b6865aSVaclav Hapla /* Get/check global number of vertices */ 466825b6865aSVaclav Hapla { 466925b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 467025b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 467125b6865aSVaclav Hapla 467225b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 467325b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 46749371c9d4SSatish Balay for (i = 0; i < len; i++) 46759371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 467625b6865aSVaclav Hapla ++NVerticesInCells; 467725b6865aSVaclav Hapla 467825b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 46799371c9d4SSatish Balay else 46809371c9d4SSatish 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); 468125b6865aSVaclav Hapla } 46829566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 468348a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 46849566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 46859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4686b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 4687ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 4688b09969d6SVaclav Hapla } 46899566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 46909566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 46919566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4692b09969d6SVaclav Hapla PetscFunctionReturn(0); 4693b09969d6SVaclav Hapla } 4694b09969d6SVaclav Hapla 4695b09969d6SVaclav Hapla /*@C 4696b09969d6SVaclav Hapla DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4697b09969d6SVaclav Hapla 4698b09969d6SVaclav Hapla Input Parameters: 4699b09969d6SVaclav Hapla + dm - The DM 4700b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4701b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4702b09969d6SVaclav Hapla 4703b09969d6SVaclav Hapla Level: advanced 4704b09969d6SVaclav Hapla 4705b09969d6SVaclav Hapla Notes: 4706b09969d6SVaclav Hapla Not currently supported in Fortran. 4707b09969d6SVaclav Hapla 4708db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 4709b09969d6SVaclav Hapla @*/ 4710d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 4711d71ae5a4SJacob Faibussowitsch { 4712b09969d6SVaclav Hapla PetscSection coordSection; 4713b09969d6SVaclav Hapla Vec coordinates; 4714b09969d6SVaclav Hapla DM cdm; 4715b09969d6SVaclav Hapla PetscScalar *coords; 47161edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 4717b09969d6SVaclav Hapla 4718b09969d6SVaclav Hapla PetscFunctionBegin; 47199566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 47209566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 47211dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 47229566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 47239566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 47249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 47259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 47269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 47271edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 47289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 47299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4730b09969d6SVaclav Hapla } 47319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4732b09969d6SVaclav Hapla 47339566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 47349566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 47359566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 47369566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 47379566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 47381edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 4739ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 4740b09969d6SVaclav Hapla } 47419566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 47429566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 47439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 47449566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4745b09969d6SVaclav Hapla PetscFunctionReturn(0); 4746b09969d6SVaclav Hapla } 4747b09969d6SVaclav Hapla 4748b09969d6SVaclav Hapla /*@ 47493df08285SMatthew 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 47503df08285SMatthew G. Knepley 47513df08285SMatthew G. Knepley Collective on comm 4752b09969d6SVaclav Hapla 4753b09969d6SVaclav Hapla Input Parameters: 4754b09969d6SVaclav Hapla + comm - The communicator 4755b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 47563df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 47573df08285SMatthew G. Knepley . numVertices - The number of vertices owned by this process, or PETSC_DECIDE, only on process 0 47583df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 4759b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 47603df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0 4761b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 47623df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0 4763b09969d6SVaclav Hapla 4764b09969d6SVaclav Hapla Output Parameter: 47653df08285SMatthew G. Knepley . dm - The DM, which only has points on process 0 4766b09969d6SVaclav Hapla 4767b09969d6SVaclav Hapla Notes: 4768b09969d6SVaclav Hapla This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(), 4769b09969d6SVaclav Hapla DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList() 4770b09969d6SVaclav Hapla 477125b6865aSVaclav Hapla See DMPlexBuildFromCellList() for an example and details about the topology-related parameters. 477225b6865aSVaclav Hapla See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters. 47733df08285SMatthew G. Knepley See DMPlexCreateFromCellListParallelPetsc() for parallel input 477425b6865aSVaclav Hapla 4775b09969d6SVaclav Hapla Level: intermediate 4776b09969d6SVaclav Hapla 4777db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 47789298eaa6SMatthew G Knepley @*/ 4779d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromCellListPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], DM *dm) 4780d71ae5a4SJacob Faibussowitsch { 47813df08285SMatthew G. Knepley PetscMPIInt rank; 47829298eaa6SMatthew G Knepley 47839298eaa6SMatthew G Knepley PetscFunctionBegin; 478428b400f6SJacob 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."); 47859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 47869566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 47879566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 47889566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 4789c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 47909566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 47919298eaa6SMatthew G Knepley if (interpolate) { 47925fd9971aSMatthew G. Knepley DM idm; 47939298eaa6SMatthew G Knepley 47949566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 47959566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 47969298eaa6SMatthew G Knepley *dm = idm; 47979298eaa6SMatthew G Knepley } 4798c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 47999566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 48009298eaa6SMatthew G Knepley PetscFunctionReturn(0); 48019298eaa6SMatthew G Knepley } 48029298eaa6SMatthew G Knepley 4803939f6067SMatthew G. Knepley /*@ 4804939f6067SMatthew 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 4805939f6067SMatthew G. Knepley 4806939f6067SMatthew G. Knepley Input Parameters: 4807c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension() 4808939f6067SMatthew G. Knepley . depth - The depth of the DAG 4809367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth 4810939f6067SMatthew G. Knepley . coneSize - The cone size of each point 4811939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 4812939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 4813367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim() 4814939f6067SMatthew G. Knepley 4815939f6067SMatthew G. Knepley Output Parameter: 4816939f6067SMatthew G. Knepley . dm - The DM 4817939f6067SMatthew G. Knepley 4818939f6067SMatthew G. Knepley Note: Two triangles sharing a face would have input 4819939f6067SMatthew G. Knepley $ depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 4820939f6067SMatthew G. Knepley $ cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 4821939f6067SMatthew G. Knepley $ vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 4822939f6067SMatthew G. Knepley $ 4823939f6067SMatthew G. Knepley which would result in the DMPlex 4824939f6067SMatthew G. Knepley $ 4825939f6067SMatthew G. Knepley $ 4 4826939f6067SMatthew G. Knepley $ / | \ 4827939f6067SMatthew G. Knepley $ / | \ 4828939f6067SMatthew G. Knepley $ / | \ 4829939f6067SMatthew G. Knepley $ 2 0 | 1 5 4830939f6067SMatthew G. Knepley $ \ | / 4831939f6067SMatthew G. Knepley $ \ | / 4832939f6067SMatthew G. Knepley $ \ | / 4833939f6067SMatthew G. Knepley $ 3 4834939f6067SMatthew G. Knepley $ 4835a4a685f2SJacob Faibussowitsch $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc() 4836939f6067SMatthew G. Knepley 4837939f6067SMatthew G. Knepley Level: advanced 4838939f6067SMatthew G. Knepley 4839db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 4840939f6067SMatthew G. Knepley @*/ 4841d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 4842d71ae5a4SJacob Faibussowitsch { 48439298eaa6SMatthew G Knepley Vec coordinates; 48449298eaa6SMatthew G Knepley PetscSection coordSection; 48459298eaa6SMatthew G Knepley PetscScalar *coords; 4846811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 48479298eaa6SMatthew G Knepley 48489298eaa6SMatthew G Knepley PetscFunctionBegin; 48499566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 48509566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 485163a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 48529298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 48539566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 48549298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 48559566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 4856ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 485797e052ccSToby Isaac } 48581dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 48599566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 48609298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 48619566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 48629566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 48639298eaa6SMatthew G Knepley } 48649566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 48659566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 48669298eaa6SMatthew G Knepley /* Build coordinates */ 48679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 48689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 48699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 48709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 48719298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 48729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 48739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 48749298eaa6SMatthew G Knepley } 48759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 48769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 48779566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 48789566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 48799566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 48809566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dimEmbed)); 48819566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 48829318fe57SMatthew G. Knepley if (vertexCoords) { 48839566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 48849298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 48859298eaa6SMatthew G Knepley PetscInt off; 48869298eaa6SMatthew G Knepley 48879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 4888ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 48899298eaa6SMatthew G Knepley } 48909318fe57SMatthew G. Knepley } 48919566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 48929566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 48939566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 48949298eaa6SMatthew G Knepley PetscFunctionReturn(0); 48959298eaa6SMatthew G Knepley } 48968415267dSToby Isaac 4897ca522641SMatthew G. Knepley /*@C 48988ca92349SMatthew G. Knepley DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file. 48998ca92349SMatthew G. Knepley 49008ca92349SMatthew G. Knepley + comm - The MPI communicator 49018ca92349SMatthew G. Knepley . filename - Name of the .dat file 49028ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 49038ca92349SMatthew G. Knepley 49048ca92349SMatthew G. Knepley Output Parameter: 49058ca92349SMatthew G. Knepley . dm - The DM object representing the mesh 49068ca92349SMatthew G. Knepley 49078ca92349SMatthew G. Knepley Note: The format is the simplest possible: 49088ca92349SMatthew G. Knepley $ Ne 49098ca92349SMatthew G. Knepley $ v0 v1 ... vk 49108ca92349SMatthew G. Knepley $ Nv 49118ca92349SMatthew G. Knepley $ x y z marker 49128ca92349SMatthew G. Knepley 49138ca92349SMatthew G. Knepley Level: beginner 49148ca92349SMatthew G. Knepley 4915db781477SPatrick Sanan .seealso: `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 49168ca92349SMatthew G. Knepley @*/ 4917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 4918d71ae5a4SJacob Faibussowitsch { 49198ca92349SMatthew G. Knepley DMLabel marker; 49208ca92349SMatthew G. Knepley PetscViewer viewer; 49218ca92349SMatthew G. Knepley Vec coordinates; 49228ca92349SMatthew G. Knepley PetscSection coordSection; 49238ca92349SMatthew G. Knepley PetscScalar *coords; 49248ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 49258ca92349SMatthew G. Knepley PetscInt dim = 3, cdim = 3, coordSize, v, c, d; 49268ca92349SMatthew G. Knepley PetscMPIInt rank; 4927f8d5e320SMatthew G. Knepley int snum, Nv, Nc, Ncn, Nl; 49288ca92349SMatthew G. Knepley 49298ca92349SMatthew G. Knepley PetscFunctionBegin; 49309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 49319566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 49329566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 49339566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 49349566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 4935dd400576SPatrick Sanan if (rank == 0) { 49369566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING)); 4937f8d5e320SMatthew G. Knepley snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl); 493808401ef6SPierre Jolivet PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 493925ce1634SJed Brown } else { 4940f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 49418ca92349SMatthew G. Knepley } 49429566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 49439566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 49449566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 49459566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 49469566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 49478ca92349SMatthew G. Knepley /* Read topology */ 4948dd400576SPatrick Sanan if (rank == 0) { 4949f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 4950f8d5e320SMatthew G. Knepley PetscInt cone[8]; 49518ca92349SMatthew G. Knepley int vbuf[8], v; 49528ca92349SMatthew G. Knepley 49539371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 49549371c9d4SSatish Balay format[c * 3 + 0] = '%'; 49559371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 49569371c9d4SSatish Balay format[c * 3 + 2] = ' '; 49579371c9d4SSatish Balay } 4958f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 49599566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 49609566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 49618ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 49629566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 4963f8d5e320SMatthew G. Knepley switch (Ncn) { 4964d71ae5a4SJacob Faibussowitsch case 2: 4965d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 4966d71ae5a4SJacob Faibussowitsch break; 4967d71ae5a4SJacob Faibussowitsch case 3: 4968d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 4969d71ae5a4SJacob Faibussowitsch break; 4970d71ae5a4SJacob Faibussowitsch case 4: 4971d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 4972d71ae5a4SJacob Faibussowitsch break; 4973d71ae5a4SJacob Faibussowitsch case 6: 4974d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 4975d71ae5a4SJacob Faibussowitsch break; 4976d71ae5a4SJacob Faibussowitsch case 8: 4977d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 4978d71ae5a4SJacob Faibussowitsch break; 4979d71ae5a4SJacob Faibussowitsch default: 4980d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 4981f8d5e320SMatthew G. Knepley } 498208401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 4983f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 49848ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 4985f8d5e320SMatthew G. Knepley if (Ncn == 8) { 49868ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 49878ca92349SMatthew G. Knepley cone[1] = cone[3]; 49888ca92349SMatthew G. Knepley cone[3] = tmp; 49898ca92349SMatthew G. Knepley } 49909566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 49918ca92349SMatthew G. Knepley } 49928ca92349SMatthew G. Knepley } 49939566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 49949566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 49958ca92349SMatthew G. Knepley /* Read coordinates */ 49969566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 49979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 49989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 49999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 50008ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 50019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 50029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 50038ca92349SMatthew G. Knepley } 50049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 50059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 50069566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 50079566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 50089566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 50099566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 50109566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 50119566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5012dd400576SPatrick Sanan if (rank == 0) { 5013f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 50148ca92349SMatthew G. Knepley double x[3]; 5015f8d5e320SMatthew G. Knepley int l, val[3]; 50168ca92349SMatthew G. Knepley 5017f8d5e320SMatthew G. Knepley if (Nl) { 50189371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 50199371c9d4SSatish Balay format[l * 3 + 0] = '%'; 50209371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 50219371c9d4SSatish Balay format[l * 3 + 2] = ' '; 50229371c9d4SSatish Balay } 5023f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 50249566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 50259566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 5026f8d5e320SMatthew G. Knepley } 50278ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 50289566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 5029f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 503008401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 5031f8d5e320SMatthew G. Knepley switch (Nl) { 5032d71ae5a4SJacob Faibussowitsch case 0: 5033d71ae5a4SJacob Faibussowitsch snum = 0; 5034d71ae5a4SJacob Faibussowitsch break; 5035d71ae5a4SJacob Faibussowitsch case 1: 5036d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 5037d71ae5a4SJacob Faibussowitsch break; 5038d71ae5a4SJacob Faibussowitsch case 2: 5039d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 5040d71ae5a4SJacob Faibussowitsch break; 5041d71ae5a4SJacob Faibussowitsch case 3: 5042d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 5043d71ae5a4SJacob Faibussowitsch break; 5044d71ae5a4SJacob Faibussowitsch default: 5045d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 5046f8d5e320SMatthew G. Knepley } 504708401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 50488ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 50499566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 50508ca92349SMatthew G. Knepley } 50518ca92349SMatthew G. Knepley } 50529566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 50539566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 50549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 50559566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 50568ca92349SMatthew G. Knepley if (interpolate) { 50578ca92349SMatthew G. Knepley DM idm; 50588ca92349SMatthew G. Knepley DMLabel bdlabel; 50598ca92349SMatthew G. Knepley 50609566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 50619566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 50628ca92349SMatthew G. Knepley *dm = idm; 50638ca92349SMatthew G. Knepley 5064f8d5e320SMatthew G. Knepley if (!Nl) { 50659566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 50669566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 50679566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 50689566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 50698ca92349SMatthew G. Knepley } 5070f8d5e320SMatthew G. Knepley } 50718ca92349SMatthew G. Knepley PetscFunctionReturn(0); 50728ca92349SMatthew G. Knepley } 50738ca92349SMatthew G. Knepley 50748ca92349SMatthew G. Knepley /*@C 5075ca522641SMatthew G. Knepley DMPlexCreateFromFile - This takes a filename and produces a DM 5076ca522641SMatthew G. Knepley 5077ca522641SMatthew G. Knepley Input Parameters: 5078ca522641SMatthew G. Knepley + comm - The communicator 5079ca522641SMatthew G. Knepley . filename - A file name 5080cd7e8a5eSksagiyam . plexname - The object name of the resulting DM, also used for intra-datafile lookup by some formats 5081ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 5082ca522641SMatthew G. Knepley 5083ca522641SMatthew G. Knepley Output Parameter: 5084ca522641SMatthew G. Knepley . dm - The DM 5085ca522641SMatthew G. Knepley 508602ef0d99SVaclav Hapla Options Database Keys: 508702ef0d99SVaclav Hapla . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5 508802ef0d99SVaclav Hapla 5089bca97951SVaclav Hapla Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g. 5090bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 5091bca97951SVaclav Hapla 5092cd7e8a5eSksagiyam Notes: 5093cd7e8a5eSksagiyam Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex 5094cd7e8a5eSksagiyam meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName() 5095cd7e8a5eSksagiyam before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object. 5096cd7e8a5eSksagiyam The input parameter name is thus used to name the DMPlex object when DMPlexCreateFromFile() internally 5097cd7e8a5eSksagiyam calls DMLoad(). Currently, name is ignored for other viewer types and/or formats. 5098cd7e8a5eSksagiyam 5099ca522641SMatthew G. Knepley Level: beginner 5100ca522641SMatthew G. Knepley 5101db781477SPatrick Sanan .seealso: `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 5102ca522641SMatthew G. Knepley @*/ 5103d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 5104d71ae5a4SJacob Faibussowitsch { 5105ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 5106ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 5107ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 5108ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 5109ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 5110ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 5111ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 5112ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 5113ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 5114ef3a5affSJacob Faibussowitsch const char extMed[] = ".med"; 5115ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 5116ef3a5affSJacob Faibussowitsch const char extEGADSLite[] = ".egadslite"; 5117ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 5118ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 5119ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 5120ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 5121ca522641SMatthew G. Knepley size_t len; 5122c1cad2e7SMatthew G. Knepley PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV; 5123ca522641SMatthew G. Knepley PetscMPIInt rank; 5124ca522641SMatthew G. Knepley 5125ca522641SMatthew G. Knepley PetscFunctionBegin; 51265d80c0bfSVaclav Hapla PetscValidCharPointer(filename, 2); 51270d862eaeSPierre Jolivet if (plexname) PetscValidCharPointer(plexname, 3); 5128cd7e8a5eSksagiyam PetscValidPointer(dm, 5); 51299566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 51309566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 51319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 51329566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 513328b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 5134ef3a5affSJacob Faibussowitsch 51359371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 51369371c9d4SSatish Balay do { \ 5137274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 5138274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 5139274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 5140274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 5141ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 5142ef3a5affSJacob Faibussowitsch } else { \ 5143274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 5144ef3a5affSJacob Faibussowitsch } \ 5145ef3a5affSJacob Faibussowitsch } while (0) 5146ef3a5affSJacob Faibussowitsch 5147ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 5148ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 5149ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 5150ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 5151ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 5152ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 5153ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 5154ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 5155ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 5156ef3a5affSJacob Faibussowitsch CheckExtension(extMed, isMed); 5157ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 5158ef3a5affSJacob Faibussowitsch CheckExtension(extEGADSLite, isEGADSLite); 5159ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 5160ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 5161ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 5162ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 5163ef3a5affSJacob Faibussowitsch 5164ef3a5affSJacob Faibussowitsch #undef CheckExtension 5165ef3a5affSJacob Faibussowitsch 5166de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 51679566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 5168ca522641SMatthew G. Knepley } else if (isCGNS) { 51699566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 517090c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 51719566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 51722f0bd6dcSMichael Lange } else if (isFluent) { 51739566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 5174cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 51759c48423bSVaclav Hapla PetscBool load_hdf5_xdmf = PETSC_FALSE; 5176cc2f8f65SMatthew G. Knepley PetscViewer viewer; 5177cc2f8f65SMatthew G. Knepley 517843b242b4SVaclav 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 */ 51799566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf)); 51809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL)); 51819566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 51829566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 51839566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 51849566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 51859566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 51869566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 5187cd7e8a5eSksagiyam 51889566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 51899566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 51909566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 51919566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 51929566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 51939566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer)); 51949566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 51955fd9971aSMatthew G. Knepley 51965fd9971aSMatthew G. Knepley if (interpolate) { 51975fd9971aSMatthew G. Knepley DM idm; 51985fd9971aSMatthew G. Knepley 51999566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 52009566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 52015fd9971aSMatthew G. Knepley *dm = idm; 52025fd9971aSMatthew G. Knepley } 5203707dd687SMichael Lange } else if (isMed) { 52049566063dSJacob Faibussowitsch PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm)); 5205f2801cd6SMatthew G. Knepley } else if (isPLY) { 52069566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 5207c1cad2e7SMatthew G. Knepley } else if (isEGADSLite || isEGADS || isIGES || isSTEP) { 52089566063dSJacob Faibussowitsch if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm)); 52099566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm)); 52107bee2925SMatthew Knepley if (!interpolate) { 52117bee2925SMatthew Knepley DM udm; 52127bee2925SMatthew Knepley 52139566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 52149566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 52157bee2925SMatthew Knepley *dm = udm; 52167bee2925SMatthew Knepley } 52178ca92349SMatthew G. Knepley } else if (isCV) { 52189566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 521998921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 52209566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 52219566063dSJacob Faibussowitsch if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 52229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 5223ca522641SMatthew G. Knepley PetscFunctionReturn(0); 5224ca522641SMatthew G. Knepley } 52259f6c5813SMatthew G. Knepley /*@C 52269f6c5813SMatthew G. Knepley DMPlexCreateEphemeral - This takes a `DMPlexTransform` and a base `DMPlex` and produces an ephemeral `DM`, meaning one that is created on the fly in response to queries. 52279f6c5813SMatthew G. Knepley 52289f6c5813SMatthew G. Knepley Input Parameter: 52299f6c5813SMatthew G. Knepley . tr - The `DMPlexTransform` 52309f6c5813SMatthew G. Knepley 52319f6c5813SMatthew G. Knepley Output Parameter: 52329f6c5813SMatthew G. Knepley . dm - The `DM` 52339f6c5813SMatthew G. Knepley 52349f6c5813SMatthew G. Knepley Notes: 52359f6c5813SMatthew G. Knepley An emphemeral mesh is one that is not stored concretely, as in the default Plex implementation, but rather is produced on the fly in response to queries, using information from the transform and the base mesh. 52369f6c5813SMatthew G. Knepley 52379f6c5813SMatthew G. Knepley Level: beginner 52389f6c5813SMatthew G. Knepley 52399f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 52409f6c5813SMatthew G. Knepley @*/ 52419f6c5813SMatthew G. Knepley PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, DM *dm) 52429f6c5813SMatthew G. Knepley { 52439f6c5813SMatthew G. Knepley DM bdm; 52449f6c5813SMatthew G. Knepley PetscInt Nl; 52459f6c5813SMatthew G. Knepley 52469f6c5813SMatthew G. Knepley PetscFunctionBegin; 52479f6c5813SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm)); 52489f6c5813SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 52499f6c5813SMatthew G. Knepley PetscCall(DMSetFromOptions(*dm)); 52509f6c5813SMatthew G. Knepley 52519f6c5813SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)tr)); 52529f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr)); 52539f6c5813SMatthew G. Knepley ((DM_Plex *)(*dm)->data)->tr = tr; 52549f6c5813SMatthew G. Knepley 52559f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformGetDM(tr, &bdm)); 52569f6c5813SMatthew G. Knepley PetscCall(DMGetNumLabels(bdm, &Nl)); 52579f6c5813SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 52589f6c5813SMatthew G. Knepley DMLabel label, labelNew; 52599f6c5813SMatthew G. Knepley const char *lname; 52609f6c5813SMatthew G. Knepley PetscBool isDepth, isCellType; 52619f6c5813SMatthew G. Knepley 52629f6c5813SMatthew G. Knepley PetscCall(DMGetLabelName(bdm, l, &lname)); 52639f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 52649f6c5813SMatthew G. Knepley if (isDepth) continue; 52659f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "celltype", &isCellType)); 52669f6c5813SMatthew G. Knepley if (isCellType) continue; 52679f6c5813SMatthew G. Knepley PetscCall(DMCreateLabel(*dm, lname)); 52689f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(bdm, lname, &label)); 52699f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(*dm, lname, &labelNew)); 52709f6c5813SMatthew G. Knepley PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL)); 52719f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetLabel(labelNew, label)); 52729f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetTransform(labelNew, tr)); 52739f6c5813SMatthew G. Knepley PetscCall(DMLabelSetUp(labelNew)); 52749f6c5813SMatthew G. Knepley } 52759f6c5813SMatthew G. Knepley PetscFunctionReturn(0); 52769f6c5813SMatthew G. Knepley } 5277