1552f7358SJed Brown #define PETSCDM_DLL 2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h> /*I "petscdmplex.h" I*/ 40c312b8eSJed Brown #include <petscsf.h> 54663dae6SJed Brown #include <petscdmplextransform.h> 6b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h> 7b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h> 8552f7358SJed Brown 9b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 1058cd63d5SVaclav Hapla 119318fe57SMatthew G. Knepley /* External function declarations here */ 129318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm); 139318fe57SMatthew G. Knepley 14e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */ 15d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout) 16d71ae5a4SJacob Faibussowitsch { 174fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 186858538eSMatthew G. Knepley PetscBool dist; 196bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 20e600fa54SMatthew G. Knepley 21e600fa54SMatthew G. Knepley PetscFunctionBegin; 22e600fa54SMatthew G. Knepley if (copyPeriodicity) { 234fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L)); 244fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L)); 25e600fa54SMatthew G. Knepley } 269566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dmin, &dist)); 279566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dmout, dist)); 286bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dmin, &reorder)); 296bc1bd01Sksagiyam PetscCall(DMPlexReorderSetDefault(dmout, reorder)); 30e600fa54SMatthew G. Knepley ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation; 311baa6e33SBarry Smith if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0)); 32e600fa54SMatthew G. Knepley PetscFunctionReturn(0); 33e600fa54SMatthew G. Knepley } 34e600fa54SMatthew G. Knepley 359318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 369318fe57SMatthew G. Knepley - Share the DM_Plex structure 379318fe57SMatthew G. Knepley - Share the coordinates 389318fe57SMatthew G. Knepley - Share the SF 399318fe57SMatthew G. Knepley */ 40d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm) 41d71ae5a4SJacob Faibussowitsch { 429318fe57SMatthew G. Knepley PetscSF sf; 439318fe57SMatthew G. Knepley DM dmNew = *ndm, coordDM, coarseDM; 449318fe57SMatthew G. Knepley Vec coords; 454fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 469318fe57SMatthew G. Knepley PetscInt dim, cdim; 479318fe57SMatthew G. Knepley 489318fe57SMatthew G. Knepley PetscFunctionBegin; 499318fe57SMatthew G. Knepley if (dm == dmNew) { 509566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 519318fe57SMatthew G. Knepley PetscFunctionReturn(0); 529318fe57SMatthew G. Knepley } 539318fe57SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 549566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmNew, &dim)); 559566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmNew, &cdim)); 579566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 589566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sf)); 599566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sf)); 609566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmNew, &coordDM)); 619566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmNew, &coords)); 629566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dm, coordDM)); 639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 646858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM)); 656858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords)); 666858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dm, coordDM)); 676858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 689318fe57SMatthew G. Knepley /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */ 696858538eSMatthew G. Knepley PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 706858538eSMatthew G. Knepley dm->coordinates[0].field = dmNew->coordinates[0].field; 7161a622f3SMatthew G. Knepley ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc; 724fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 734fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 749566063dSJacob Faibussowitsch PetscCall(DMDestroy_Plex(dm)); 759566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 769318fe57SMatthew G. Knepley dm->data = dmNew->data; 779318fe57SMatthew G. Knepley ((DM_Plex *)dmNew->data)->refct++; 789566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 799566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 809566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmNew, &coarseDM)); 819566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 829566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 839318fe57SMatthew G. Knepley PetscFunctionReturn(0); 849318fe57SMatthew G. Knepley } 859318fe57SMatthew G. Knepley 869318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew 879318fe57SMatthew G. Knepley - Swap the DM_Plex structure 889318fe57SMatthew G. Knepley - Swap the coordinates 899318fe57SMatthew G. Knepley - Swap the point PetscSF 909318fe57SMatthew G. Knepley */ 91d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 92d71ae5a4SJacob Faibussowitsch { 939318fe57SMatthew G. Knepley DM coordDMA, coordDMB; 949318fe57SMatthew G. Knepley Vec coordsA, coordsB; 959318fe57SMatthew G. Knepley PetscSF sfA, sfB; 969318fe57SMatthew G. Knepley DMField fieldTmp; 979318fe57SMatthew G. Knepley void *tmp; 989318fe57SMatthew G. Knepley DMLabelLink listTmp; 999318fe57SMatthew G. Knepley DMLabel depthTmp; 1009318fe57SMatthew G. Knepley PetscInt tmpI; 1019318fe57SMatthew G. Knepley 1029318fe57SMatthew G. Knepley PetscFunctionBegin; 1039318fe57SMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 1049566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmA, &sfA)); 1059566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmB, &sfB)); 1069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sfA)); 1079566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmA, sfB)); 1089566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmB, sfA)); 1099566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)sfA)); 1109318fe57SMatthew G. Knepley 1119566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &coordDMA)); 1129566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &coordDMB)); 1139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordDMA)); 1149566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmA, coordDMB)); 1159566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmB, coordDMA)); 1169566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 1179318fe57SMatthew G. Knepley 1189566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordsA)); 1199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmB, &coordsB)); 1209566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordsA)); 1219566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmA, coordsB)); 1229566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordsA)); 1239566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordsA)); 1249318fe57SMatthew G. Knepley 1256858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA)); 1266858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB)); 1276858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordDMA)); 1286858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmA, coordDMB)); 1296858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmB, coordDMA)); 1306858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 1316858538eSMatthew G. Knepley 1326858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA)); 1336858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB)); 1346858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordsA)); 1356858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB)); 1366858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA)); 1376858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordsA)); 1386858538eSMatthew G. Knepley 1396858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[0].field; 1406858538eSMatthew G. Knepley dmA->coordinates[0].field = dmB->coordinates[0].field; 1416858538eSMatthew G. Knepley dmB->coordinates[0].field = fieldTmp; 1426858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[1].field; 1436858538eSMatthew G. Knepley dmA->coordinates[1].field = dmB->coordinates[1].field; 1446858538eSMatthew G. Knepley dmB->coordinates[1].field = fieldTmp; 1459318fe57SMatthew G. Knepley tmp = dmA->data; 1469318fe57SMatthew G. Knepley dmA->data = dmB->data; 1479318fe57SMatthew G. Knepley dmB->data = tmp; 1489318fe57SMatthew G. Knepley listTmp = dmA->labels; 1499318fe57SMatthew G. Knepley dmA->labels = dmB->labels; 1509318fe57SMatthew G. Knepley dmB->labels = listTmp; 1519318fe57SMatthew G. Knepley depthTmp = dmA->depthLabel; 1529318fe57SMatthew G. Knepley dmA->depthLabel = dmB->depthLabel; 1539318fe57SMatthew G. Knepley dmB->depthLabel = depthTmp; 1549318fe57SMatthew G. Knepley depthTmp = dmA->celltypeLabel; 1559318fe57SMatthew G. Knepley dmA->celltypeLabel = dmB->celltypeLabel; 1569318fe57SMatthew G. Knepley dmB->celltypeLabel = depthTmp; 1579318fe57SMatthew G. Knepley tmpI = dmA->levelup; 1589318fe57SMatthew G. Knepley dmA->levelup = dmB->levelup; 1599318fe57SMatthew G. Knepley dmB->levelup = tmpI; 1609318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1619318fe57SMatthew G. Knepley } 1629318fe57SMatthew G. Knepley 163d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) 164d71ae5a4SJacob Faibussowitsch { 1659318fe57SMatthew G. Knepley DM idm; 1669318fe57SMatthew G. Knepley 1679318fe57SMatthew G. Knepley PetscFunctionBegin; 1689566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 1699566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 17069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 1719318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1729318fe57SMatthew G. Knepley } 1739318fe57SMatthew G. Knepley 1749318fe57SMatthew G. Knepley /*@C 1759318fe57SMatthew G. Knepley DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates 1769318fe57SMatthew G. Knepley 177*a1cb98faSBarry Smith Collective on dm 1789318fe57SMatthew G. Knepley 1799318fe57SMatthew G. Knepley Input Parameters: 1809318fe57SMatthew G. Knepley + DM - The DM 1814f9ab2b4SJed Brown . degree - The degree of the finite element or PETSC_DECIDE 1829318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface 1839318fe57SMatthew G. Knepley 1849318fe57SMatthew G. Knepley Level: advanced 1859318fe57SMatthew G. Knepley 186*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscPointFunc`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()` 1879318fe57SMatthew G. Knepley @*/ 188d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc) 189d71ae5a4SJacob Faibussowitsch { 1909318fe57SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1919318fe57SMatthew G. Knepley DM cdm; 1929318fe57SMatthew G. Knepley PetscDS cds; 1939318fe57SMatthew G. Knepley PetscFE fe; 1949318fe57SMatthew G. Knepley PetscClassId id; 1959318fe57SMatthew G. Knepley 1969318fe57SMatthew G. Knepley PetscFunctionBegin; 1979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 1989566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 1999566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, (PetscObject *)&fe)); 2009566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 2019318fe57SMatthew G. Knepley if (id != PETSCFE_CLASSID) { 2029318fe57SMatthew G. Knepley PetscBool simplex; 2039318fe57SMatthew G. Knepley PetscInt dim, dE, qorder; 2049318fe57SMatthew G. Knepley 2059566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 2069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 2079318fe57SMatthew G. Knepley qorder = degree; 208d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)cdm); 2099566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-coord_dm_default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0)); 210d0609cedSBarry Smith PetscOptionsEnd(); 2114f9ab2b4SJed Brown if (degree == PETSC_DECIDE) fe = NULL; 2124f9ab2b4SJed Brown else { 2138c4475acSStefano Zampini PetscCall(DMPlexIsSimplex(dm, &simplex)); 2149566063dSJacob Faibussowitsch PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, degree, qorder, &fe)); 2154f9ab2b4SJed Brown } 2169566063dSJacob Faibussowitsch PetscCall(DMProjectCoordinates(dm, fe)); 2179566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 2189318fe57SMatthew G. Knepley } 2199318fe57SMatthew G. Knepley mesh->coordFunc = coordFunc; 2209318fe57SMatthew G. Knepley PetscFunctionReturn(0); 2219318fe57SMatthew G. Knepley } 2229318fe57SMatthew G. Knepley 2231df5d5c5SMatthew G. Knepley /*@ 2241df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 2251df5d5c5SMatthew G. Knepley 226d083f849SBarry Smith Collective 2271df5d5c5SMatthew G. Knepley 2281df5d5c5SMatthew G. Knepley Input Parameters: 229*a1cb98faSBarry Smith + comm - The communicator for the `DM` object 2301df5d5c5SMatthew G. Knepley . dim - The spatial dimension 2311df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 2321df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 2331df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 2341df5d5c5SMatthew G. Knepley 2351df5d5c5SMatthew G. Knepley Output Parameter: 236*a1cb98faSBarry Smith . dm - The `DM` object 2371df5d5c5SMatthew G. Knepley 2381df5d5c5SMatthew G. Knepley Level: beginner 2391df5d5c5SMatthew G. Knepley 240*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()` 2411df5d5c5SMatthew G. Knepley @*/ 242d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) 243d71ae5a4SJacob Faibussowitsch { 2441df5d5c5SMatthew G. Knepley DM dm; 2451df5d5c5SMatthew G. Knepley PetscMPIInt rank; 2461df5d5c5SMatthew G. Knepley 2471df5d5c5SMatthew G. Knepley PetscFunctionBegin; 2489566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &dm)); 2499566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 2509566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 2519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 252ce78fa2fSMatthew G. Knepley switch (dim) { 253ce78fa2fSMatthew G. Knepley case 2: 2549566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular")); 2559566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral")); 256ce78fa2fSMatthew G. Knepley break; 257ce78fa2fSMatthew G. Knepley case 3: 2589566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral")); 2599566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral")); 260ce78fa2fSMatthew G. Knepley break; 261d71ae5a4SJacob Faibussowitsch default: 262d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 263ce78fa2fSMatthew G. Knepley } 2641df5d5c5SMatthew G. Knepley if (rank) { 2651df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 2669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 2671df5d5c5SMatthew G. Knepley } else { 2681df5d5c5SMatthew G. Knepley switch (dim) { 2691df5d5c5SMatthew G. Knepley case 2: 2701df5d5c5SMatthew G. Knepley if (simplex) { 2711df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 2721df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 2731df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 2741df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 2751df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 2761df5d5c5SMatthew G. Knepley 2779566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2781df5d5c5SMatthew G. Knepley } else { 2791df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 2801df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 2811df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 2821df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2831df5d5c5SMatthew 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}; 2841df5d5c5SMatthew G. Knepley 2859566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2861df5d5c5SMatthew G. Knepley } 2871df5d5c5SMatthew G. Knepley break; 2881df5d5c5SMatthew G. Knepley case 3: 2891df5d5c5SMatthew G. Knepley if (simplex) { 2901df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 2911df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 2921df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 2931df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2941df5d5c5SMatthew 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}; 2951df5d5c5SMatthew G. Knepley 2969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2971df5d5c5SMatthew G. Knepley } else { 2981df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 2991df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 3001df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 3011df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 3029371c9d4SSatish 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}; 3031df5d5c5SMatthew G. Knepley 3049566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 3051df5d5c5SMatthew G. Knepley } 3061df5d5c5SMatthew G. Knepley break; 307d71ae5a4SJacob Faibussowitsch default: 308d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 3091df5d5c5SMatthew G. Knepley } 3101df5d5c5SMatthew G. Knepley } 3111df5d5c5SMatthew G. Knepley *newdm = dm; 3121df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 3131df5d5c5SMatthew G. Knepley DM rdm; 3141df5d5c5SMatthew G. Knepley const char *name; 3151df5d5c5SMatthew G. Knepley 3169566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 3179566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 3189566063dSJacob Faibussowitsch PetscCall(DMRefine(*newdm, comm, &rdm)); 3199566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)*newdm, &name)); 3209566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, name)); 3219566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 3221df5d5c5SMatthew G. Knepley *newdm = rdm; 3231df5d5c5SMatthew G. Knepley } 3241df5d5c5SMatthew G. Knepley if (interpolate) { 3255fd9971aSMatthew G. Knepley DM idm; 3261df5d5c5SMatthew G. Knepley 3279566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*newdm, &idm)); 3289566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 3291df5d5c5SMatthew G. Knepley *newdm = idm; 3301df5d5c5SMatthew G. Knepley } 3311df5d5c5SMatthew G. Knepley PetscFunctionReturn(0); 3321df5d5c5SMatthew G. Knepley } 3331df5d5c5SMatthew G. Knepley 334d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 335d71ae5a4SJacob Faibussowitsch { 3369318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 3379318fe57SMatthew G. Knepley PetscInt markerRight = 1; 3389318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 3399318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 3409318fe57SMatthew G. Knepley Vec coordinates; 3419318fe57SMatthew G. Knepley PetscSection coordSection; 3429318fe57SMatthew G. Knepley PetscScalar *coords; 3439318fe57SMatthew G. Knepley PetscInt coordSize; 3449318fe57SMatthew G. Knepley PetscMPIInt rank; 3459318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 346552f7358SJed Brown 3479318fe57SMatthew G. Knepley PetscFunctionBegin; 3489566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 3499318fe57SMatthew G. Knepley if (markerSeparate) { 3509318fe57SMatthew G. Knepley markerRight = 2; 3519318fe57SMatthew G. Knepley markerLeft = 1; 3529318fe57SMatthew G. Knepley } 3539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 354c5853193SPierre Jolivet if (rank == 0) { 3559566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numVertices)); 3569566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3579566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft)); 3589566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight)); 3599318fe57SMatthew G. Knepley } 3609566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 3619566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 3629318fe57SMatthew G. Knepley /* Build coordinates */ 3639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 3649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 3659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 3669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, 0, numVertices)); 3679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 3689318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 3699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 3709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 3719318fe57SMatthew G. Knepley } 3729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 3739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 3749566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 3759566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 3769566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 3779566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 3789566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 3799566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 3809318fe57SMatthew G. Knepley coords[0] = lower[0]; 3819318fe57SMatthew G. Knepley coords[1] = upper[0]; 3829566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 3839566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 3849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 3859318fe57SMatthew G. Knepley PetscFunctionReturn(0); 3869318fe57SMatthew G. Knepley } 38726492d91SMatthew G. Knepley 388d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 389d71ae5a4SJacob Faibussowitsch { 3901df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0] + 1) * (edges[1] + 1); 3911df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1]; 392552f7358SJed Brown PetscInt markerTop = 1; 393552f7358SJed Brown PetscInt markerBottom = 1; 394552f7358SJed Brown PetscInt markerRight = 1; 395552f7358SJed Brown PetscInt markerLeft = 1; 396552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 397552f7358SJed Brown Vec coordinates; 398552f7358SJed Brown PetscSection coordSection; 399552f7358SJed Brown PetscScalar *coords; 400552f7358SJed Brown PetscInt coordSize; 401552f7358SJed Brown PetscMPIInt rank; 402552f7358SJed Brown PetscInt v, vx, vy; 403552f7358SJed Brown 404552f7358SJed Brown PetscFunctionBegin; 4059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 406552f7358SJed Brown if (markerSeparate) { 4071df21d24SMatthew G. Knepley markerTop = 3; 4081df21d24SMatthew G. Knepley markerBottom = 1; 4091df21d24SMatthew G. Knepley markerRight = 2; 4101df21d24SMatthew G. Knepley markerLeft = 4; 411552f7358SJed Brown } 4129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 413dd400576SPatrick Sanan if (rank == 0) { 414552f7358SJed Brown PetscInt e, ex, ey; 415552f7358SJed Brown 4169566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices)); 41748a46eb9SPierre Jolivet for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 4189566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 419552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 420552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 421552f7358SJed Brown PetscInt edge = vx * edges[1] + ey + edges[0] * (edges[1] + 1); 422552f7358SJed Brown PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges; 423da80777bSKarl Rupp PetscInt cone[2]; 424552f7358SJed Brown 4259371c9d4SSatish Balay cone[0] = vertex; 4269371c9d4SSatish Balay cone[1] = vertex + edges[0] + 1; 4279566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 428552f7358SJed Brown if (vx == edges[0]) { 4299566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 4309566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 431552f7358SJed Brown if (ey == edges[1] - 1) { 4329566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 4339566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 434552f7358SJed Brown } 435552f7358SJed Brown } else if (vx == 0) { 4369566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 4379566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 438552f7358SJed Brown if (ey == edges[1] - 1) { 4399566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 4409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 441552f7358SJed Brown } 442552f7358SJed Brown } 443552f7358SJed Brown } 444552f7358SJed Brown } 445552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 446552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 447552f7358SJed Brown PetscInt edge = vy * edges[0] + ex; 448552f7358SJed Brown PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges; 449da80777bSKarl Rupp PetscInt cone[2]; 450552f7358SJed Brown 4519371c9d4SSatish Balay cone[0] = vertex; 4529371c9d4SSatish Balay cone[1] = vertex + 1; 4539566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 454552f7358SJed Brown if (vy == edges[1]) { 4559566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 4569566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 457552f7358SJed Brown if (ex == edges[0] - 1) { 4589566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 4599566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 460552f7358SJed Brown } 461552f7358SJed Brown } else if (vy == 0) { 4629566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 4639566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 464552f7358SJed Brown if (ex == edges[0] - 1) { 4659566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 4669566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 467552f7358SJed Brown } 468552f7358SJed Brown } 469552f7358SJed Brown } 470552f7358SJed Brown } 471552f7358SJed Brown } 4729566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 4739566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 474552f7358SJed Brown /* Build coordinates */ 4759566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 2)); 4769566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 4779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 4789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 4799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 480552f7358SJed Brown for (v = numEdges; v < numEdges + numVertices; ++v) { 4819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 2)); 4829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 483552f7358SJed Brown } 4849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 4869566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 4879566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 4889566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 4899566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 2)); 4909566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 4919566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 492552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 493552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 494552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx; 495552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy; 496552f7358SJed Brown } 497552f7358SJed Brown } 4989566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 4999566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 5009566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 501552f7358SJed Brown PetscFunctionReturn(0); 502552f7358SJed Brown } 503552f7358SJed Brown 504d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 505d71ae5a4SJacob Faibussowitsch { 5069e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 5077b59f5a9SMichael Lange PetscInt numFaces = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2]; 508c2df9bbfSMatthew G. Knepley PetscInt markerTop = 1; 509c2df9bbfSMatthew G. Knepley PetscInt markerBottom = 1; 510c2df9bbfSMatthew G. Knepley PetscInt markerFront = 1; 511c2df9bbfSMatthew G. Knepley PetscInt markerBack = 1; 512c2df9bbfSMatthew G. Knepley PetscInt markerRight = 1; 513c2df9bbfSMatthew G. Knepley PetscInt markerLeft = 1; 514c2df9bbfSMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 515552f7358SJed Brown Vec coordinates; 516552f7358SJed Brown PetscSection coordSection; 517552f7358SJed Brown PetscScalar *coords; 518552f7358SJed Brown PetscInt coordSize; 519552f7358SJed Brown PetscMPIInt rank; 520552f7358SJed Brown PetscInt v, vx, vy, vz; 5217b59f5a9SMichael Lange PetscInt voffset, iface = 0, cone[4]; 522552f7358SJed Brown 523552f7358SJed Brown PetscFunctionBegin; 5241dca8a05SBarry 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"); 5259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 526c2df9bbfSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 527c2df9bbfSMatthew G. Knepley if (markerSeparate) { 528c2df9bbfSMatthew G. Knepley markerBottom = 1; 529c2df9bbfSMatthew G. Knepley markerTop = 2; 530c2df9bbfSMatthew G. Knepley markerFront = 3; 531c2df9bbfSMatthew G. Knepley markerBack = 4; 532c2df9bbfSMatthew G. Knepley markerRight = 5; 533c2df9bbfSMatthew G. Knepley markerLeft = 6; 534c2df9bbfSMatthew G. Knepley } 5359371c9d4SSatish Balay vertices[0] = faces[0] + 1; 5369371c9d4SSatish Balay vertices[1] = faces[1] + 1; 5379371c9d4SSatish Balay vertices[2] = faces[2] + 1; 5389e8abbc3SMichael Lange numVertices = vertices[0] * vertices[1] * vertices[2]; 539dd400576SPatrick Sanan if (rank == 0) { 540552f7358SJed Brown PetscInt f; 541552f7358SJed Brown 5429566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices)); 54348a46eb9SPierre Jolivet for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 5449566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 5457b59f5a9SMichael Lange 5467b59f5a9SMichael Lange /* Side 0 (Top) */ 5477b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5487b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5497b59f5a9SMichael Lange voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx; 5509371c9d4SSatish Balay cone[0] = voffset; 5519371c9d4SSatish Balay cone[1] = voffset + 1; 5529371c9d4SSatish Balay cone[2] = voffset + vertices[0] + 1; 5539371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 5549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 555c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop)); 556c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop)); 557c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop)); 558c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop)); 559c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop)); 5607b59f5a9SMichael Lange iface++; 561552f7358SJed Brown } 562552f7358SJed Brown } 5637b59f5a9SMichael Lange 5647b59f5a9SMichael Lange /* Side 1 (Bottom) */ 5657b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5667b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5677b59f5a9SMichael Lange voffset = numFaces + vy * (faces[0] + 1) + vx; 5689371c9d4SSatish Balay cone[0] = voffset + 1; 5699371c9d4SSatish Balay cone[1] = voffset; 5709371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 5719371c9d4SSatish Balay cone[3] = voffset + vertices[0] + 1; 5729566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 573c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom)); 574c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom)); 575c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom)); 576c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom)); 577c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom)); 5787b59f5a9SMichael Lange iface++; 579552f7358SJed Brown } 580552f7358SJed Brown } 5817b59f5a9SMichael Lange 5827b59f5a9SMichael Lange /* Side 2 (Front) */ 5837b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 5847b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5857b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vx; 5869371c9d4SSatish Balay cone[0] = voffset; 5879371c9d4SSatish Balay cone[1] = voffset + 1; 5889371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + 1; 5899371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1]; 5909566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 591c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront)); 592c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront)); 593c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront)); 594c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront)); 595c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront)); 5967b59f5a9SMichael Lange iface++; 597552f7358SJed Brown } 5987b59f5a9SMichael Lange } 5997b59f5a9SMichael Lange 6007b59f5a9SMichael Lange /* Side 3 (Back) */ 6017b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6027b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 6037b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx; 6049371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 6059371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1] + 1; 6069371c9d4SSatish Balay cone[2] = voffset + 1; 6079371c9d4SSatish Balay cone[3] = voffset; 6089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 609c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack)); 610c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack)); 611c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack)); 612c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack)); 613c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack)); 6147b59f5a9SMichael Lange iface++; 6157b59f5a9SMichael Lange } 6167b59f5a9SMichael Lange } 6177b59f5a9SMichael Lange 6187b59f5a9SMichael Lange /* Side 4 (Left) */ 6197b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6207b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 6217b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0]; 6229371c9d4SSatish Balay cone[0] = voffset; 6239371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1]; 6249371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + vertices[0]; 6259371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 6269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 627c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft)); 628c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft)); 629c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft)); 630c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft)); 631c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft)); 6327b59f5a9SMichael Lange iface++; 6337b59f5a9SMichael Lange } 6347b59f5a9SMichael Lange } 6357b59f5a9SMichael Lange 6367b59f5a9SMichael Lange /* Side 5 (Right) */ 6377b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6387b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 639aab5bcd8SJed Brown voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0]; 6409371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 6419371c9d4SSatish Balay cone[1] = voffset; 6429371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 6439371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1] + vertices[0]; 6449566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 645c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight)); 646c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight)); 647c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight)); 648c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight)); 649c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight)); 6507b59f5a9SMichael Lange iface++; 6517b59f5a9SMichael Lange } 652552f7358SJed Brown } 653552f7358SJed Brown } 6549566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 6559566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 656552f7358SJed Brown /* Build coordinates */ 6579566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 3)); 6589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 6599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 6619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 662552f7358SJed Brown for (v = numFaces; v < numFaces + numVertices; ++v) { 6639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 3)); 6649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 665552f7358SJed Brown } 6669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 6689566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 6699566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 6709566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6719566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 3)); 6729566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 6739566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 674552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 675552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 676552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 677552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx; 678552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy; 679552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz; 680552f7358SJed Brown } 681552f7358SJed Brown } 682552f7358SJed Brown } 6839566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 6849566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 6859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 686552f7358SJed Brown PetscFunctionReturn(0); 687552f7358SJed Brown } 688552f7358SJed Brown 689d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) 690d71ae5a4SJacob Faibussowitsch { 6919318fe57SMatthew G. Knepley PetscFunctionBegin; 6929318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 6939566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim - 1)); 6949566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim)); 6959318fe57SMatthew G. Knepley switch (dim) { 696d71ae5a4SJacob Faibussowitsch case 1: 697d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); 698d71ae5a4SJacob Faibussowitsch break; 699d71ae5a4SJacob Faibussowitsch case 2: 700d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); 701d71ae5a4SJacob Faibussowitsch break; 702d71ae5a4SJacob Faibussowitsch case 3: 703d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); 704d71ae5a4SJacob Faibussowitsch break; 705d71ae5a4SJacob Faibussowitsch default: 706d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim); 7079318fe57SMatthew G. Knepley } 7089566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 7099318fe57SMatthew G. Knepley PetscFunctionReturn(0); 7109318fe57SMatthew G. Knepley } 7119318fe57SMatthew G. Knepley 7129318fe57SMatthew G. Knepley /*@C 7139318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 7149318fe57SMatthew G. Knepley 7159318fe57SMatthew G. Knepley Collective 7169318fe57SMatthew G. Knepley 7179318fe57SMatthew G. Knepley Input Parameters: 718*a1cb98faSBarry Smith + comm - The communicator for the `DM` object 7199318fe57SMatthew G. Knepley . dim - The spatial dimension of the box, so the resulting mesh is has dimension dim-1 7209318fe57SMatthew 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 7219318fe57SMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 7229318fe57SMatthew G. Knepley . upper - The upper right corner, or NULL for (1, 1, 1) 7239318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 7249318fe57SMatthew G. Knepley 7259318fe57SMatthew G. Knepley Output Parameter: 726*a1cb98faSBarry Smith . dm - The `DM` object 7279318fe57SMatthew G. Knepley 7289318fe57SMatthew G. Knepley Level: beginner 7299318fe57SMatthew G. Knepley 730*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()` 7319318fe57SMatthew G. Knepley @*/ 732d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 733d71ae5a4SJacob Faibussowitsch { 7349318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 7359318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 7369318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 7379318fe57SMatthew G. Knepley 7389318fe57SMatthew G. Knepley PetscFunctionBegin; 7399566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 7409566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 7419566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 7429318fe57SMatthew G. Knepley PetscFunctionReturn(0); 7439318fe57SMatthew G. Knepley } 7449318fe57SMatthew G. Knepley 745d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) 746d71ae5a4SJacob Faibussowitsch { 747fdbf62faSLisandro Dalcin PetscInt i, fStart, fEnd, numCells = 0, numVerts = 0; 748fdbf62faSLisandro Dalcin PetscInt numPoints[2], *coneSize, *cones, *coneOrientations; 749fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 750fdbf62faSLisandro Dalcin PetscReal L, maxCell; 751fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 752fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 753fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 754fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 755fdbf62faSLisandro Dalcin PetscMPIInt rank; 756fdbf62faSLisandro Dalcin 757fdbf62faSLisandro Dalcin PetscFunctionBegin; 7589318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 759fdbf62faSLisandro Dalcin 7609566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, 1)); 7619566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 7629566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 763fdbf62faSLisandro Dalcin 7649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 765dd400576SPatrick Sanan if (rank == 0) numCells = segments; 766dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 767fdbf62faSLisandro Dalcin 7689371c9d4SSatish Balay numPoints[0] = numVerts; 7699371c9d4SSatish Balay numPoints[1] = numCells; 7709566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords)); 7719566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts)); 772ad540459SPierre Jolivet for (i = 0; i < numCells; ++i) coneSize[i] = 2; 773ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0; 7749371c9d4SSatish Balay for (i = 0; i < numCells; ++i) { 7759371c9d4SSatish Balay cones[2 * i] = numCells + i % numVerts; 7769371c9d4SSatish Balay cones[2 * i + 1] = numCells + (i + 1) % numVerts; 7779371c9d4SSatish Balay } 778ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); 7799566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 7809566063dSJacob Faibussowitsch PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords)); 781fdbf62faSLisandro Dalcin 7829566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 7839371c9d4SSatish Balay if (markerSeparate) { 7849371c9d4SSatish Balay markerLeft = faceMarkerLeft; 7859371c9d4SSatish Balay markerRight = faceMarkerRight; 7869371c9d4SSatish Balay } 787dd400576SPatrick Sanan if (!wrap && rank == 0) { 7889566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 7899566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft)); 7909566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight)); 7919566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft)); 7929566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight)); 793fdbf62faSLisandro Dalcin } 794fdbf62faSLisandro Dalcin if (wrap) { 795fdbf62faSLisandro Dalcin L = upper - lower; 796fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments)); 7974fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L)); 798fdbf62faSLisandro Dalcin } 7999566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 800fdbf62faSLisandro Dalcin PetscFunctionReturn(0); 801fdbf62faSLisandro Dalcin } 802fdbf62faSLisandro Dalcin 803d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 804d71ae5a4SJacob Faibussowitsch { 8059318fe57SMatthew G. Knepley DM boundary, vol; 806c22d3578SMatthew G. Knepley DMLabel bdlabel; 807d6218766SMatthew G. Knepley 808d6218766SMatthew G. Knepley PetscFunctionBegin; 8099318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 810c22d3578SMatthew 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"); 8119566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary)); 8129566063dSJacob Faibussowitsch PetscCall(DMSetType(boundary, DMPLEX)); 8139566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 8149566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 815c22d3578SMatthew G. Knepley PetscCall(DMGetLabel(vol, "marker", &bdlabel)); 816c22d3578SMatthew G. Knepley if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel)); 8175de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol)); 81869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 8199566063dSJacob Faibussowitsch PetscCall(DMDestroy(&boundary)); 820d6218766SMatthew G. Knepley PetscFunctionReturn(0); 821d6218766SMatthew G. Knepley } 822d6218766SMatthew G. Knepley 823d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 824d71ae5a4SJacob Faibussowitsch { 825ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 826f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 827f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 828f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 829f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 830f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 831f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 8323dfda0b1SToby Isaac PetscInt dim; 833d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 8343dfda0b1SToby Isaac PetscMPIInt rank; 8353dfda0b1SToby Isaac 8363dfda0b1SToby Isaac PetscFunctionBegin; 8379566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8399566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 8409566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 8419566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 8429371c9d4SSatish 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) { 8439371c9d4SSatish Balay if (cutMarker) { 8449371c9d4SSatish Balay PetscCall(DMCreateLabel(dm, "periodic_cut")); 8459371c9d4SSatish Balay PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 8469371c9d4SSatish Balay } 847d8211ee3SMatthew G. Knepley } 8483dfda0b1SToby Isaac switch (dim) { 8493dfda0b1SToby Isaac case 2: 850f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 851f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 852f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 853f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 8543dfda0b1SToby Isaac break; 8553dfda0b1SToby Isaac case 3: 856f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 857f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 858f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 859f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 860f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 861f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 8623dfda0b1SToby Isaac break; 863d71ae5a4SJacob Faibussowitsch default: 864d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 8653dfda0b1SToby Isaac } 8669566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 867f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 868f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 869f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 870f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 871f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 872f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 873f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 8743dfda0b1SToby Isaac } 8753dfda0b1SToby Isaac { 876dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 877dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 878dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 879dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0; 880dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0; 881dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0; 8823dfda0b1SToby Isaac const PetscInt numCells = numXEdges * numYEdges * numZEdges; 8833dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges * numZEdges; 8843dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges * numZEdges; 8853dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges * numYEdges; 8863dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices * numXFaces; 8873dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices * numYFaces; 8883dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices * numZFaces; 8893dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 8903dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices; 8913dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices; 8923dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices; 8933dfda0b1SToby Isaac const PetscInt numVertices = numXVertices * numYVertices * numZVertices; 8943dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 8953dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 8963dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 8973dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 8983dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 8993dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 9003dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 9013dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 9023dfda0b1SToby Isaac Vec coordinates; 9033dfda0b1SToby Isaac PetscSection coordSection; 9043dfda0b1SToby Isaac PetscScalar *coords; 9053dfda0b1SToby Isaac PetscInt coordSize; 9063dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 9073dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 9083dfda0b1SToby Isaac 9099566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices)); 91048a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 91148a46eb9SPierre Jolivet for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 91248a46eb9SPierre Jolivet for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 9139566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 9143dfda0b1SToby Isaac /* Build cells */ 9153dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 9163dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 9173dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 9183dfda0b1SToby Isaac PetscInt cell = (fz * numYEdges + fy) * numXEdges + fx; 9193dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 9203dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices); 9213dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 9223dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices); 9233dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 9243dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices); 9253dfda0b1SToby Isaac /* B, T, F, K, R, L */ 926b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 92742206facSLisandro Dalcin PetscInt cone[6]; 9283dfda0b1SToby Isaac 9293dfda0b1SToby Isaac /* no boundary twisting in 3D */ 9309371c9d4SSatish Balay cone[0] = faceB; 9319371c9d4SSatish Balay cone[1] = faceT; 9329371c9d4SSatish Balay cone[2] = faceF; 9339371c9d4SSatish Balay cone[3] = faceK; 9349371c9d4SSatish Balay cone[4] = faceR; 9359371c9d4SSatish Balay cone[5] = faceL; 9369566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, cell, cone)); 9379566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, cell, ornt)); 9389566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9399566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9409566063dSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9413dfda0b1SToby Isaac } 9423dfda0b1SToby Isaac } 9433dfda0b1SToby Isaac } 9443dfda0b1SToby Isaac /* Build x faces */ 9453dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 9463dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 9473dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 9483dfda0b1SToby Isaac PetscInt face = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 9493dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 9503dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz; 9513dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 9523dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy; 953b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 9543dfda0b1SToby Isaac PetscInt cone[4]; 9553dfda0b1SToby Isaac 9563dfda0b1SToby Isaac if (dim == 3) { 9573dfda0b1SToby Isaac /* markers */ 9583dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 9593dfda0b1SToby Isaac if (fx == numXVertices - 1) { 9609566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 9619566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerRight)); 9629371c9d4SSatish Balay } else if (fx == 0) { 9639566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 9649566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft)); 9653dfda0b1SToby Isaac } 9663dfda0b1SToby Isaac } 9673dfda0b1SToby Isaac } 9689371c9d4SSatish Balay cone[0] = edgeB; 9699371c9d4SSatish Balay cone[1] = edgeR; 9709371c9d4SSatish Balay cone[2] = edgeT; 9719371c9d4SSatish Balay cone[3] = edgeL; 9729566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 9739566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 9743dfda0b1SToby Isaac } 9753dfda0b1SToby Isaac } 9763dfda0b1SToby Isaac } 9773dfda0b1SToby Isaac /* Build y faces */ 9783dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 97942206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 9803dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 9813dfda0b1SToby Isaac PetscInt face = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 9823dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 9833dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz; 9843dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 9853dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx; 986b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 9873dfda0b1SToby Isaac PetscInt cone[4]; 9883dfda0b1SToby Isaac 9893dfda0b1SToby Isaac if (dim == 3) { 9903dfda0b1SToby Isaac /* markers */ 9913dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 9923dfda0b1SToby Isaac if (fy == numYVertices - 1) { 9939566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 9949566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBack)); 9959371c9d4SSatish Balay } else if (fy == 0) { 9969566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 9979566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerFront)); 9983dfda0b1SToby Isaac } 9993dfda0b1SToby Isaac } 10003dfda0b1SToby Isaac } 10019371c9d4SSatish Balay cone[0] = edgeB; 10029371c9d4SSatish Balay cone[1] = edgeR; 10039371c9d4SSatish Balay cone[2] = edgeT; 10049371c9d4SSatish Balay cone[3] = edgeL; 10059566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 10069566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 10073dfda0b1SToby Isaac } 10083dfda0b1SToby Isaac } 10093dfda0b1SToby Isaac } 10103dfda0b1SToby Isaac /* Build z faces */ 10113dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 10123dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 10133dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 10143dfda0b1SToby Isaac PetscInt face = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 10153dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 10163dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy; 10173dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 10183dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx; 1019b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 10203dfda0b1SToby Isaac PetscInt cone[4]; 10213dfda0b1SToby Isaac 10223dfda0b1SToby Isaac if (dim == 2) { 10239371c9d4SSatish Balay if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) { 10249371c9d4SSatish Balay edgeR += numYEdges - 1 - 2 * fy; 10259371c9d4SSatish Balay ornt[1] = -1; 10269371c9d4SSatish Balay } 10279371c9d4SSatish Balay if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) { 10289371c9d4SSatish Balay edgeT += numXEdges - 1 - 2 * fx; 10299371c9d4SSatish Balay ornt[2] = 0; 10309371c9d4SSatish Balay } 10319566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 10329566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 1033d1c88043SMatthew G. Knepley } else { 10343dfda0b1SToby Isaac /* markers */ 10353dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 10363dfda0b1SToby Isaac if (fz == numZVertices - 1) { 10379566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 10389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerTop)); 10399371c9d4SSatish Balay } else if (fz == 0) { 10409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 10419566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom)); 10423dfda0b1SToby Isaac } 10433dfda0b1SToby Isaac } 10443dfda0b1SToby Isaac } 10459371c9d4SSatish Balay cone[0] = edgeB; 10469371c9d4SSatish Balay cone[1] = edgeR; 10479371c9d4SSatish Balay cone[2] = edgeT; 10489371c9d4SSatish Balay cone[3] = edgeL; 10499566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 10509566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 10513dfda0b1SToby Isaac } 10523dfda0b1SToby Isaac } 10533dfda0b1SToby Isaac } 10543dfda0b1SToby Isaac /* Build Z edges*/ 10553dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 10563dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 10573dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 10583dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez; 10593dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx; 10603dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx; 10613dfda0b1SToby Isaac PetscInt cone[2]; 10623dfda0b1SToby Isaac 10639371c9d4SSatish Balay cone[0] = vertexB; 10649371c9d4SSatish Balay cone[1] = vertexT; 1065c2df9bbfSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, edge, cone)); 10663dfda0b1SToby Isaac if (dim == 3) { 10673dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 10683dfda0b1SToby Isaac if (vx == numXVertices - 1) { 10699566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1070c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1071c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1072c2df9bbfSMatthew G. Knepley } else if (vx == 0) { 10739566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1074c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1075c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 10763dfda0b1SToby Isaac } 10773dfda0b1SToby Isaac } 10783dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 10793dfda0b1SToby Isaac if (vy == numYVertices - 1) { 10809566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1081c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1082c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1083c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 10849566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1085c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1086c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 10873dfda0b1SToby Isaac } 10883dfda0b1SToby Isaac } 10893dfda0b1SToby Isaac } 10903dfda0b1SToby Isaac } 10913dfda0b1SToby Isaac } 10923dfda0b1SToby Isaac } 10933dfda0b1SToby Isaac /* Build Y edges*/ 10943dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 10953dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 10963dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 10973dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx; 10983dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey; 10993dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx; 11003dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 11013dfda0b1SToby Isaac PetscInt cone[2]; 11023dfda0b1SToby Isaac 11039371c9d4SSatish Balay cone[0] = vertexF; 11049371c9d4SSatish Balay cone[1] = vertexK; 11059566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 11063dfda0b1SToby Isaac if (dim == 2) { 11073dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 11083dfda0b1SToby Isaac if (vx == numXVertices - 1) { 11099566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 11109566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 11119566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1112c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1113d8211ee3SMatthew G. Knepley } else if (vx == 0) { 11149566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 11159566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 11169566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1117c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 11183dfda0b1SToby Isaac } 1119d8211ee3SMatthew G. Knepley } else { 11204c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 11219566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 11229566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1123c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 11243dfda0b1SToby Isaac } 1125d8211ee3SMatthew G. Knepley } 1126d8211ee3SMatthew G. Knepley } else { 11273dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 11283dfda0b1SToby Isaac if (vx == numXVertices - 1) { 11299566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1130c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1131c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1132d8211ee3SMatthew G. Knepley } else if (vx == 0) { 11339566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1134c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1135c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 11363dfda0b1SToby Isaac } 11373dfda0b1SToby Isaac } 11383dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 11393dfda0b1SToby Isaac if (vz == numZVertices - 1) { 11409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1141c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1142c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1143d8211ee3SMatthew G. Knepley } else if (vz == 0) { 11449566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1145c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1146c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 11473dfda0b1SToby Isaac } 11483dfda0b1SToby Isaac } 11493dfda0b1SToby Isaac } 11503dfda0b1SToby Isaac } 11513dfda0b1SToby Isaac } 11523dfda0b1SToby Isaac } 11533dfda0b1SToby Isaac /* Build X edges*/ 11543dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 11553dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 11563dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 11573dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices; 11583dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex; 11593dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex; 11603dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 11613dfda0b1SToby Isaac PetscInt cone[2]; 11623dfda0b1SToby Isaac 11639371c9d4SSatish Balay cone[0] = vertexL; 11649371c9d4SSatish Balay cone[1] = vertexR; 11659566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 11663dfda0b1SToby Isaac if (dim == 2) { 11673dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 11683dfda0b1SToby Isaac if (vy == numYVertices - 1) { 11699566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 11709566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 11719566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1172c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1173d8211ee3SMatthew G. Knepley } else if (vy == 0) { 11749566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 11759566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 11769566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1177c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 11783dfda0b1SToby Isaac } 1179d8211ee3SMatthew G. Knepley } else { 11804c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 11819566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 11829566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1183c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 11843dfda0b1SToby Isaac } 1185d8211ee3SMatthew G. Knepley } 1186d8211ee3SMatthew G. Knepley } else { 11873dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 11883dfda0b1SToby Isaac if (vy == numYVertices - 1) { 11899566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1190c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1191c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1192c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 11939566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1194c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1195c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 11963dfda0b1SToby Isaac } 11973dfda0b1SToby Isaac } 11983dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 11993dfda0b1SToby Isaac if (vz == numZVertices - 1) { 12009566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1201c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1202c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1203c2df9bbfSMatthew G. Knepley } else if (vz == 0) { 12049566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1205c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1206c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 12073dfda0b1SToby Isaac } 12083dfda0b1SToby Isaac } 12093dfda0b1SToby Isaac } 12103dfda0b1SToby Isaac } 12113dfda0b1SToby Isaac } 12123dfda0b1SToby Isaac } 12139566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 12149566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 12153dfda0b1SToby Isaac /* Build coordinates */ 12169566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 12179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 12189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 12199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 12203dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex + numVertices; ++v) { 12219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 12229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 12233dfda0b1SToby Isaac } 12249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 12259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 12269566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 12279566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 12289566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 12299566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 12309566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 12319566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12323dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 12333dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 12343dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 12353dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 12363dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1237ad540459SPierre Jolivet if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; 12383dfda0b1SToby Isaac } 12393dfda0b1SToby Isaac } 12403dfda0b1SToby Isaac } 12419566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12429566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 12439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 12443dfda0b1SToby Isaac } 12453dfda0b1SToby Isaac PetscFunctionReturn(0); 12463dfda0b1SToby Isaac } 12473dfda0b1SToby Isaac 1248d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1249d71ae5a4SJacob Faibussowitsch { 12509318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 12519318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1252552f7358SJed Brown 1253552f7358SJed Brown PetscFunctionBegin; 12549318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 12559318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 12569566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 12579371c9d4SSatish Balay for (d = 0; d < dim; ++d) { 12589371c9d4SSatish Balay fac[d] = faces[d]; 12599371c9d4SSatish Balay bdt[d] = periodicity[d]; 12609371c9d4SSatish Balay } 12619566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 12629371c9d4SSatish 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))) { 12636858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 12646858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1265552f7358SJed Brown 12669318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 12676858538eSMatthew G. Knepley if (periodicity[d] != DM_BOUNDARY_NONE) { 12689318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 12699318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1270768d5fceSMatthew G. Knepley } 12716858538eSMatthew G. Knepley } 12724fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1273768d5fceSMatthew G. Knepley } 12749566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 12759318fe57SMatthew G. Knepley PetscFunctionReturn(0); 12769318fe57SMatthew G. Knepley } 12779318fe57SMatthew G. Knepley 1278d71ae5a4SJacob 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) 1279d71ae5a4SJacob Faibussowitsch { 12809318fe57SMatthew G. Knepley PetscFunctionBegin; 12819566063dSJacob Faibussowitsch if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 12829566063dSJacob Faibussowitsch else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 12839566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 12849318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1285768d5fceSMatthew G. Knepley DM udm; 1286768d5fceSMatthew G. Knepley 12879566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 12889566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, udm)); 128969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 1290768d5fceSMatthew G. Knepley } 1291768d5fceSMatthew G. Knepley PetscFunctionReturn(0); 1292c8c68bd8SToby Isaac } 1293c8c68bd8SToby Isaac 1294768d5fceSMatthew G. Knepley /*@C 1295768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1296768d5fceSMatthew G. Knepley 1297d083f849SBarry Smith Collective 1298768d5fceSMatthew G. Knepley 1299768d5fceSMatthew G. Knepley Input Parameters: 1300*a1cb98faSBarry Smith + comm - The communicator for the `DM` object 1301768d5fceSMatthew G. Knepley . dim - The spatial dimension 1302*a1cb98faSBarry Smith . simplex - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells 1303fdbf62faSLisandro Dalcin . faces - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 1304768d5fceSMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 1305768d5fceSMatthew G. Knepley . upper - The upper right corner, or NULL for (1, 1, 1) 1306*a1cb98faSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or NULL for `DM_BOUNDARY_NONE` 1307768d5fceSMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 1308768d5fceSMatthew G. Knepley 1309768d5fceSMatthew G. Knepley Output Parameter: 1310*a1cb98faSBarry Smith . dm - The `DM` object 1311768d5fceSMatthew G. Knepley 1312768d5fceSMatthew G. Knepley Level: beginner 1313768d5fceSMatthew G. Knepley 1314*a1cb98faSBarry Smith Note: 1315*a1cb98faSBarry Smith To customize this mesh using options, use 1316*a1cb98faSBarry Smith .vb 1317*a1cb98faSBarry Smith DMCreate(comm, &dm); 1318*a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 1319*a1cb98faSBarry Smith DMSetFromOptions(dm); 1320*a1cb98faSBarry Smith .ve 1321*a1cb98faSBarry Smith and use the options in `DMSetFromOptions()`. 1322*a1cb98faSBarry Smith 1323*a1cb98faSBarry Smith Here is the numbering returned for 2 faces in each direction for tensor cells: 1324*a1cb98faSBarry Smith .vb 1325*a1cb98faSBarry Smith 10---17---11---18----12 1326*a1cb98faSBarry Smith | | | 1327*a1cb98faSBarry Smith | | | 1328*a1cb98faSBarry Smith 20 2 22 3 24 1329*a1cb98faSBarry Smith | | | 1330*a1cb98faSBarry Smith | | | 1331*a1cb98faSBarry Smith 7---15----8---16----9 1332*a1cb98faSBarry Smith | | | 1333*a1cb98faSBarry Smith | | | 1334*a1cb98faSBarry Smith 19 0 21 1 23 1335*a1cb98faSBarry Smith | | | 1336*a1cb98faSBarry Smith | | | 1337*a1cb98faSBarry Smith 4---13----5---14----6 1338*a1cb98faSBarry Smith .ve 1339*a1cb98faSBarry Smith and for simplicial cells 1340*a1cb98faSBarry Smith .vb 1341*a1cb98faSBarry Smith 14----8---15----9----16 1342*a1cb98faSBarry Smith |\ 5 |\ 7 | 1343*a1cb98faSBarry Smith | \ | \ | 1344*a1cb98faSBarry Smith 13 2 14 3 15 1345*a1cb98faSBarry Smith | 4 \ | 6 \ | 1346*a1cb98faSBarry Smith | \ | \ | 1347*a1cb98faSBarry Smith 11----6---12----7----13 1348*a1cb98faSBarry Smith |\ |\ | 1349*a1cb98faSBarry Smith | \ 1 | \ 3 | 1350*a1cb98faSBarry Smith 10 0 11 1 12 1351*a1cb98faSBarry Smith | 0 \ | 2 \ | 1352*a1cb98faSBarry Smith | \ | \ | 1353*a1cb98faSBarry Smith 8----4----9----5----10 1354*a1cb98faSBarry Smith .ve 1355*a1cb98faSBarry Smith 1356*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 1357768d5fceSMatthew G. Knepley @*/ 1358d71ae5a4SJacob 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) 1359d71ae5a4SJacob Faibussowitsch { 13609318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 1361fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 1362fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 1363fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1364552f7358SJed Brown 1365768d5fceSMatthew G. Knepley PetscFunctionBegin; 13669566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 13679566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 13689566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 13697ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 13709318fe57SMatthew G. Knepley PetscFunctionReturn(0); 13719318fe57SMatthew G. Knepley } 1372fdbf62faSLisandro Dalcin 1373d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1374d71ae5a4SJacob Faibussowitsch { 13759318fe57SMatthew G. Knepley DM bdm, vol; 13769318fe57SMatthew G. Knepley PetscInt i; 13779318fe57SMatthew G. Knepley 13789318fe57SMatthew G. Knepley PetscFunctionBegin; 137908401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 13809566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 13819566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 13829566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 13839566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 13849566063dSJacob Faibussowitsch PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol)); 13859566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 138669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 13879318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 13889318fe57SMatthew G. Knepley Vec v; 13899318fe57SMatthew G. Knepley PetscScalar *x; 13909318fe57SMatthew G. Knepley PetscInt cDim, n; 13919318fe57SMatthew G. Knepley 13929566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 13939566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 13949566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 13959566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 13969318fe57SMatthew G. Knepley x += cDim; 13979318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 13989566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 13999566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 14009318fe57SMatthew G. Knepley } 1401552f7358SJed Brown PetscFunctionReturn(0); 1402552f7358SJed Brown } 1403552f7358SJed Brown 140400dabe28SStefano Zampini /*@ 140500dabe28SStefano Zampini DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells. 140600dabe28SStefano Zampini 1407d083f849SBarry Smith Collective 140800dabe28SStefano Zampini 140900dabe28SStefano Zampini Input Parameters: 1410*a1cb98faSBarry Smith + comm - The communicator for the `DM` object 141100dabe28SStefano Zampini . faces - Number of faces per dimension, or NULL for (1, 1, 1) 141200dabe28SStefano Zampini . lower - The lower left corner, or NULL for (0, 0, 0) 141300dabe28SStefano Zampini . upper - The upper right corner, or NULL for (1, 1, 1) 1414*a1cb98faSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or NULL for `DM_BOUNDARY_NONE` 1415*a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 141600dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 141700dabe28SStefano Zampini 141800dabe28SStefano Zampini Output Parameter: 1419*a1cb98faSBarry Smith . dm - The `DM` object 142000dabe28SStefano Zampini 142100dabe28SStefano Zampini Level: beginner 142200dabe28SStefano Zampini 1423*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 142400dabe28SStefano Zampini @*/ 1425d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 1426d71ae5a4SJacob Faibussowitsch { 14279318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 142800dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 142900dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 143000dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 143100dabe28SStefano Zampini 143200dabe28SStefano Zampini PetscFunctionBegin; 14339566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 14349566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 14359566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 1436d410b0cfSMatthew G. Knepley if (!interpolate) { 1437d410b0cfSMatthew G. Knepley DM udm; 143800dabe28SStefano Zampini 14399566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 144069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 144100dabe28SStefano Zampini } 14427ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 144300dabe28SStefano Zampini PetscFunctionReturn(0); 144400dabe28SStefano Zampini } 144500dabe28SStefano Zampini 1446a9074c1eSMatthew G. Knepley /*@C 1447*a1cb98faSBarry Smith DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database. 1448a9074c1eSMatthew G. Knepley 1449d083f849SBarry Smith Logically Collective on dm 1450a9074c1eSMatthew G. Knepley 1451a9074c1eSMatthew G. Knepley Input Parameters: 1452a9074c1eSMatthew G. Knepley + dm - the DM context 1453a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 1454a9074c1eSMatthew G. Knepley 1455*a1cb98faSBarry Smith Level: advanced 1456*a1cb98faSBarry Smith 1457*a1cb98faSBarry Smith Note: 1458a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 1459a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 1460a9074c1eSMatthew G. Knepley 1461*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()` 1462a9074c1eSMatthew G. Knepley @*/ 1463d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 1464d71ae5a4SJacob Faibussowitsch { 1465a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1466a9074c1eSMatthew G. Knepley 1467a9074c1eSMatthew G. Knepley PetscFunctionBegin; 1468a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14699566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 14709566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 1471a9074c1eSMatthew G. Knepley PetscFunctionReturn(0); 1472a9074c1eSMatthew G. Knepley } 1473a9074c1eSMatthew G. Knepley 14749318fe57SMatthew G. Knepley /* Remap geometry to cylinder 147561a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 147661a622f3SMatthew G. Knepley 14779318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 14789318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 14799318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 14800510c589SMatthew G. Knepley 14819318fe57SMatthew G. Knepley phi = arctan(y/x) 14829318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 14839318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 14840510c589SMatthew G. Knepley 14859318fe57SMatthew G. Knepley so we remap them using 14860510c589SMatthew G. Knepley 14879318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 14889318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 14890510c589SMatthew G. Knepley 14909318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 14919318fe57SMatthew G. Knepley */ 1492d71ae5a4SJacob 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[]) 1493d71ae5a4SJacob Faibussowitsch { 14949318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 14959318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 149622cc497dSMatthew G. Knepley 14979318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 14989318fe57SMatthew G. Knepley f0[0] = u[0]; 14999318fe57SMatthew G. Knepley f0[1] = u[1]; 15009318fe57SMatthew G. Knepley } else { 15019318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 15020510c589SMatthew G. Knepley 15039318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 15049318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 15059318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 15069318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 15079318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 15089318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 15099318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 15109318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 15119318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 15129318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 15139318fe57SMatthew G. Knepley } else { 15149318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 15159318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 15169318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 15179318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 15189318fe57SMatthew G. Knepley } 15199318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 15209318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 15219318fe57SMatthew G. Knepley } 15229318fe57SMatthew G. Knepley f0[2] = u[2]; 15239318fe57SMatthew G. Knepley } 15240510c589SMatthew G. Knepley 1525d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ) 1526d71ae5a4SJacob Faibussowitsch { 15270510c589SMatthew G. Knepley const PetscInt dim = 3; 15289318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 1529d8c47e87SMatthew G. Knepley PetscMPIInt rank; 15300510c589SMatthew G. Knepley 15310510c589SMatthew G. Knepley PetscFunctionBegin; 15329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15339566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 15340510c589SMatthew G. Knepley /* Create topology */ 15350510c589SMatthew G. Knepley { 15360510c589SMatthew G. Knepley PetscInt cone[8], c; 15370510c589SMatthew G. Knepley 1538dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 1539dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 1540006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 1541ae8bcbbbSMatthew G. Knepley numCells *= 3; 1542dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 1543006a8963SMatthew G. Knepley } 15449566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 15459566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 15469566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 1547dd400576SPatrick Sanan if (rank == 0) { 1548006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 15499371c9d4SSatish Balay cone[0] = 15; 15509371c9d4SSatish Balay cone[1] = 18; 15519371c9d4SSatish Balay cone[2] = 17; 15529371c9d4SSatish Balay cone[3] = 16; 15539371c9d4SSatish Balay cone[4] = 31; 15549371c9d4SSatish Balay cone[5] = 32; 15559371c9d4SSatish Balay cone[6] = 33; 15569371c9d4SSatish Balay cone[7] = 34; 15579566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 15589371c9d4SSatish Balay cone[0] = 16; 15599371c9d4SSatish Balay cone[1] = 17; 15609371c9d4SSatish Balay cone[2] = 24; 15619371c9d4SSatish Balay cone[3] = 23; 15629371c9d4SSatish Balay cone[4] = 32; 15639371c9d4SSatish Balay cone[5] = 36; 15649371c9d4SSatish Balay cone[6] = 37; 15659371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 15669566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 15679371c9d4SSatish Balay cone[0] = 18; 15689371c9d4SSatish Balay cone[1] = 27; 15699371c9d4SSatish Balay cone[2] = 24; 15709371c9d4SSatish Balay cone[3] = 17; 15719371c9d4SSatish Balay cone[4] = 34; 15729371c9d4SSatish Balay cone[5] = 33; 15739371c9d4SSatish Balay cone[6] = 37; 15749371c9d4SSatish Balay cone[7] = 38; 15759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 15769371c9d4SSatish Balay cone[0] = 29; 15779371c9d4SSatish Balay cone[1] = 27; 15789371c9d4SSatish Balay cone[2] = 18; 15799371c9d4SSatish Balay cone[3] = 15; 15809371c9d4SSatish Balay cone[4] = 35; 15819371c9d4SSatish Balay cone[5] = 31; 15829371c9d4SSatish Balay cone[6] = 34; 15839371c9d4SSatish Balay cone[7] = 38; 15849566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 15859371c9d4SSatish Balay cone[0] = 29; 15869371c9d4SSatish Balay cone[1] = 15; 15879371c9d4SSatish Balay cone[2] = 16; 15889371c9d4SSatish Balay cone[3] = 23; 15899371c9d4SSatish Balay cone[4] = 35; 15909371c9d4SSatish Balay cone[5] = 36; 15919371c9d4SSatish Balay cone[6] = 32; 15929371c9d4SSatish Balay cone[7] = 31; 15939566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1594006a8963SMatthew G. Knepley 15959371c9d4SSatish Balay cone[0] = 31; 15969371c9d4SSatish Balay cone[1] = 34; 15979371c9d4SSatish Balay cone[2] = 33; 15989371c9d4SSatish Balay cone[3] = 32; 15999371c9d4SSatish Balay cone[4] = 19; 16009371c9d4SSatish Balay cone[5] = 22; 16019371c9d4SSatish Balay cone[6] = 21; 16029371c9d4SSatish Balay cone[7] = 20; 16039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 16049371c9d4SSatish Balay cone[0] = 32; 16059371c9d4SSatish Balay cone[1] = 33; 16069371c9d4SSatish Balay cone[2] = 37; 16079371c9d4SSatish Balay cone[3] = 36; 16089371c9d4SSatish Balay cone[4] = 22; 16099371c9d4SSatish Balay cone[5] = 25; 16109371c9d4SSatish Balay cone[6] = 26; 16119371c9d4SSatish Balay cone[7] = 21; 16129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 16139371c9d4SSatish Balay cone[0] = 34; 16149371c9d4SSatish Balay cone[1] = 38; 16159371c9d4SSatish Balay cone[2] = 37; 16169371c9d4SSatish Balay cone[3] = 33; 16179371c9d4SSatish Balay cone[4] = 20; 16189371c9d4SSatish Balay cone[5] = 21; 16199371c9d4SSatish Balay cone[6] = 26; 16209371c9d4SSatish Balay cone[7] = 28; 16219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 16229371c9d4SSatish Balay cone[0] = 35; 16239371c9d4SSatish Balay cone[1] = 38; 16249371c9d4SSatish Balay cone[2] = 34; 16259371c9d4SSatish Balay cone[3] = 31; 16269371c9d4SSatish Balay cone[4] = 30; 16279371c9d4SSatish Balay cone[5] = 19; 16289371c9d4SSatish Balay cone[6] = 20; 16299371c9d4SSatish Balay cone[7] = 28; 16309566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 16319371c9d4SSatish Balay cone[0] = 35; 16329371c9d4SSatish Balay cone[1] = 31; 16339371c9d4SSatish Balay cone[2] = 32; 16349371c9d4SSatish Balay cone[3] = 36; 16359371c9d4SSatish Balay cone[4] = 30; 16369371c9d4SSatish Balay cone[5] = 25; 16379371c9d4SSatish Balay cone[6] = 22; 16389371c9d4SSatish Balay cone[7] = 19; 16399566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 1640ae8bcbbbSMatthew G. Knepley 16419371c9d4SSatish Balay cone[0] = 19; 16429371c9d4SSatish Balay cone[1] = 20; 16439371c9d4SSatish Balay cone[2] = 21; 16449371c9d4SSatish Balay cone[3] = 22; 16459371c9d4SSatish Balay cone[4] = 15; 16469371c9d4SSatish Balay cone[5] = 16; 16479371c9d4SSatish Balay cone[6] = 17; 16489371c9d4SSatish Balay cone[7] = 18; 16499566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 16509371c9d4SSatish Balay cone[0] = 22; 16519371c9d4SSatish Balay cone[1] = 21; 16529371c9d4SSatish Balay cone[2] = 26; 16539371c9d4SSatish Balay cone[3] = 25; 16549371c9d4SSatish Balay cone[4] = 16; 16559371c9d4SSatish Balay cone[5] = 23; 16569371c9d4SSatish Balay cone[6] = 24; 16579371c9d4SSatish Balay cone[7] = 17; 16589566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 16599371c9d4SSatish Balay cone[0] = 20; 16609371c9d4SSatish Balay cone[1] = 28; 16619371c9d4SSatish Balay cone[2] = 26; 16629371c9d4SSatish Balay cone[3] = 21; 16639371c9d4SSatish Balay cone[4] = 18; 16649371c9d4SSatish Balay cone[5] = 17; 16659371c9d4SSatish Balay cone[6] = 24; 16669371c9d4SSatish Balay cone[7] = 27; 16679566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 16689371c9d4SSatish Balay cone[0] = 30; 16699371c9d4SSatish Balay cone[1] = 28; 16709371c9d4SSatish Balay cone[2] = 20; 16719371c9d4SSatish Balay cone[3] = 19; 16729371c9d4SSatish Balay cone[4] = 29; 16739371c9d4SSatish Balay cone[5] = 15; 16749371c9d4SSatish Balay cone[6] = 18; 16759371c9d4SSatish Balay cone[7] = 27; 16769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 16779371c9d4SSatish Balay cone[0] = 30; 16789371c9d4SSatish Balay cone[1] = 19; 16799371c9d4SSatish Balay cone[2] = 22; 16809371c9d4SSatish Balay cone[3] = 25; 16819371c9d4SSatish Balay cone[4] = 29; 16829371c9d4SSatish Balay cone[5] = 23; 16839371c9d4SSatish Balay cone[6] = 16; 16849371c9d4SSatish Balay cone[7] = 15; 16859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 1686006a8963SMatthew G. Knepley } else { 16879371c9d4SSatish Balay cone[0] = 5; 16889371c9d4SSatish Balay cone[1] = 8; 16899371c9d4SSatish Balay cone[2] = 7; 16909371c9d4SSatish Balay cone[3] = 6; 16919371c9d4SSatish Balay cone[4] = 9; 16929371c9d4SSatish Balay cone[5] = 12; 16939371c9d4SSatish Balay cone[6] = 11; 16949371c9d4SSatish Balay cone[7] = 10; 16959566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 16969371c9d4SSatish Balay cone[0] = 6; 16979371c9d4SSatish Balay cone[1] = 7; 16989371c9d4SSatish Balay cone[2] = 14; 16999371c9d4SSatish Balay cone[3] = 13; 17009371c9d4SSatish Balay cone[4] = 12; 17019371c9d4SSatish Balay cone[5] = 15; 17029371c9d4SSatish Balay cone[6] = 16; 17039371c9d4SSatish Balay cone[7] = 11; 17049566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 17059371c9d4SSatish Balay cone[0] = 8; 17069371c9d4SSatish Balay cone[1] = 17; 17079371c9d4SSatish Balay cone[2] = 14; 17089371c9d4SSatish Balay cone[3] = 7; 17099371c9d4SSatish Balay cone[4] = 10; 17109371c9d4SSatish Balay cone[5] = 11; 17119371c9d4SSatish Balay cone[6] = 16; 17129371c9d4SSatish Balay cone[7] = 18; 17139566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 17149371c9d4SSatish Balay cone[0] = 19; 17159371c9d4SSatish Balay cone[1] = 17; 17169371c9d4SSatish Balay cone[2] = 8; 17179371c9d4SSatish Balay cone[3] = 5; 17189371c9d4SSatish Balay cone[4] = 20; 17199371c9d4SSatish Balay cone[5] = 9; 17209371c9d4SSatish Balay cone[6] = 10; 17219371c9d4SSatish Balay cone[7] = 18; 17229566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 17239371c9d4SSatish Balay cone[0] = 19; 17249371c9d4SSatish Balay cone[1] = 5; 17259371c9d4SSatish Balay cone[2] = 6; 17269371c9d4SSatish Balay cone[3] = 13; 17279371c9d4SSatish Balay cone[4] = 20; 17289371c9d4SSatish Balay cone[5] = 15; 17299371c9d4SSatish Balay cone[6] = 12; 17309371c9d4SSatish Balay cone[7] = 9; 17319566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1732006a8963SMatthew G. Knepley } 1733d8c47e87SMatthew G. Knepley } 17349566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 17359566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 17360510c589SMatthew G. Knepley } 1737dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 17380510c589SMatthew G. Knepley { 17390510c589SMatthew G. Knepley Vec coordinates; 17400510c589SMatthew G. Knepley PetscSection coordSection; 17410510c589SMatthew G. Knepley PetscScalar *coords; 17420510c589SMatthew G. Knepley PetscInt coordSize, v; 17430510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 17440510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 17450510c589SMatthew G. Knepley 17460510c589SMatthew G. Knepley /* Build coordinates */ 17479566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 17489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 17499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 17509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 17510510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 17529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 17539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 17540510c589SMatthew G. Knepley } 17559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 17569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 17579566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 17589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 17599566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 17609566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 17619566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 17629566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 1763dd400576SPatrick Sanan if (rank == 0) { 17649371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 17659371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 17669371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 17679371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 17689371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 17699371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 17709371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 17719371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 17729371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 17739371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 17749371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 17759371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 17769371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 17779371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 17789371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 17799371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 17809371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 17819371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 17829371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 17839371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 17849371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 17859371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 17869371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 17879371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 17889371c9d4SSatish Balay coords[8 * dim + 0] = dis; 17899371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 17909371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 17919371c9d4SSatish Balay coords[9 * dim + 0] = dis; 17929371c9d4SSatish Balay coords[9 * dim + 1] = dis; 17939371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 17949371c9d4SSatish Balay coords[10 * dim + 0] = dis; 17959371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 17969371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 17979371c9d4SSatish Balay coords[11 * dim + 0] = dis; 17989371c9d4SSatish Balay coords[11 * dim + 1] = dis; 17999371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 18009371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 18019371c9d4SSatish Balay coords[12 * dim + 1] = dis; 18029371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 18039371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 18049371c9d4SSatish Balay coords[13 * dim + 1] = dis; 18059371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 18069371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 18079371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 18089371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 18099371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 18109371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 18119371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 1812ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 18139371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 18149371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 18159371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 18169371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 18179371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 18189371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 18199371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 18209371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 18219371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 18229371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 18239371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 18249371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 18259371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 18269371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 18279371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 18289371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 18299371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 18309371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 18319371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 18329371c9d4SSatish Balay coords[22 * dim + 1] = dis; 18339371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 18349371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 18359371c9d4SSatish Balay coords[23 * dim + 1] = dis; 18369371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 1837ae8bcbbbSMatthew G. Knepley } 1838d8c47e87SMatthew G. Knepley } 18399566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 18409566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 18419566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 18420510c589SMatthew G. Knepley } 1843006a8963SMatthew G. Knepley /* Create periodicity */ 1844006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 18456858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 18466858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1847006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 1848ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 18496858538eSMatthew G. Knepley PetscInt numZCells = 3; 1850006a8963SMatthew G. Knepley 18516858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 18526858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 18534fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1854006a8963SMatthew G. Knepley } 1855dbc1dc17SMatthew G. Knepley { 18569318fe57SMatthew G. Knepley DM cdm; 18579318fe57SMatthew G. Knepley PetscDS cds; 18589318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 1859dbc1dc17SMatthew G. Knepley 18609566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder)); 18619566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18629566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 18639566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 1864dbc1dc17SMatthew G. Knepley } 18659318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 18669566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 18670510c589SMatthew G. Knepley PetscFunctionReturn(0); 18680510c589SMatthew G. Knepley } 18690510c589SMatthew G. Knepley 187024119c2aSMatthew G. Knepley /*@ 18719318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 187224119c2aSMatthew G. Knepley 1873d083f849SBarry Smith Collective 187424119c2aSMatthew G. Knepley 187524119c2aSMatthew G. Knepley Input Parameters: 1876*a1cb98faSBarry Smith + comm - The communicator for the `DM` object 18779318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction 187824119c2aSMatthew G. Knepley 187924119c2aSMatthew G. Knepley Output Parameter: 188024119c2aSMatthew G. Knepley . dm - The DM object 188124119c2aSMatthew G. Knepley 188224119c2aSMatthew G. Knepley Level: beginner 188324119c2aSMatthew G. Knepley 1884*a1cb98faSBarry Smith Note: 1885*a1cb98faSBarry Smith Here is the output numbering looking from the bottom of the cylinder: 1886*a1cb98faSBarry Smith .vb 1887*a1cb98faSBarry Smith 17-----14 1888*a1cb98faSBarry Smith | | 1889*a1cb98faSBarry Smith | 2 | 1890*a1cb98faSBarry Smith | | 1891*a1cb98faSBarry Smith 17-----8-----7-----14 1892*a1cb98faSBarry Smith | | | | 1893*a1cb98faSBarry Smith | 3 | 0 | 1 | 1894*a1cb98faSBarry Smith | | | | 1895*a1cb98faSBarry Smith 19-----5-----6-----13 1896*a1cb98faSBarry Smith | | 1897*a1cb98faSBarry Smith | 4 | 1898*a1cb98faSBarry Smith | | 1899*a1cb98faSBarry Smith 19-----13 1900*a1cb98faSBarry Smith 1901*a1cb98faSBarry Smith and up through the top 1902*a1cb98faSBarry Smith 1903*a1cb98faSBarry Smith 18-----16 1904*a1cb98faSBarry Smith | | 1905*a1cb98faSBarry Smith | 2 | 1906*a1cb98faSBarry Smith | | 1907*a1cb98faSBarry Smith 18----10----11-----16 1908*a1cb98faSBarry Smith | | | | 1909*a1cb98faSBarry Smith | 3 | 0 | 1 | 1910*a1cb98faSBarry Smith | | | | 1911*a1cb98faSBarry Smith 20-----9----12-----15 1912*a1cb98faSBarry Smith | | 1913*a1cb98faSBarry Smith | 4 | 1914*a1cb98faSBarry Smith | | 1915*a1cb98faSBarry Smith 20-----15 1916*a1cb98faSBarry Smith .ve 1917*a1cb98faSBarry Smith 1918*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 191924119c2aSMatthew G. Knepley @*/ 1920d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm) 1921d71ae5a4SJacob Faibussowitsch { 19229318fe57SMatthew G. Knepley PetscFunctionBegin; 19239318fe57SMatthew G. Knepley PetscValidPointer(dm, 3); 19249566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 19259566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 19269566063dSJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ)); 19279318fe57SMatthew G. Knepley PetscFunctionReturn(0); 19289318fe57SMatthew G. Knepley } 19299318fe57SMatthew G. Knepley 1930d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 1931d71ae5a4SJacob Faibussowitsch { 193224119c2aSMatthew G. Knepley const PetscInt dim = 3; 1933412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 19349fe9f049SMatthew G. Knepley PetscMPIInt rank; 193524119c2aSMatthew G. Knepley 193624119c2aSMatthew G. Knepley PetscFunctionBegin; 193763a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 19389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 19399566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 1940412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 19419566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 194224119c2aSMatthew G. Knepley /* Create topology */ 194324119c2aSMatthew G. Knepley { 194424119c2aSMatthew G. Knepley PetscInt cone[6], c; 194524119c2aSMatthew G. Knepley 1946dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 1947dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 19489566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 19499566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 19509566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 195124119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 19529371c9d4SSatish Balay cone[0] = c + n * 1; 19539371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 19549371c9d4SSatish Balay cone[2] = 0 + 3 * n; 19559371c9d4SSatish Balay cone[3] = c + n * 2; 19569371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 19579371c9d4SSatish Balay cone[5] = 1 + 3 * n; 19589566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 19599566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 196024119c2aSMatthew G. Knepley } 19619566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 19629566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 196324119c2aSMatthew G. Knepley } 196448a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 196524119c2aSMatthew G. Knepley /* Create cylinder geometry */ 196624119c2aSMatthew G. Knepley { 196724119c2aSMatthew G. Knepley Vec coordinates; 196824119c2aSMatthew G. Knepley PetscSection coordSection; 196924119c2aSMatthew G. Knepley PetscScalar *coords; 1970412e9a14SMatthew G. Knepley PetscInt coordSize, c; 197124119c2aSMatthew G. Knepley 197224119c2aSMatthew G. Knepley /* Build coordinates */ 19739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 19749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 19759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 19769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 197724119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 19789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 19799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 198024119c2aSMatthew G. Knepley } 19819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 19829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 19839566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 19849566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 19859566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 19869566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 19879566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 19889566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 198924119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 19909371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 19919371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 19929371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 19939371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 19949371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 19959371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 199624119c2aSMatthew G. Knepley } 1997dd400576SPatrick Sanan if (rank == 0) { 19989371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 19999371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 20009371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 20019371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 20029371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 20039371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 20049fe9f049SMatthew G. Knepley } 20059566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 20069566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 20079566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 200824119c2aSMatthew G. Knepley } 20099318fe57SMatthew G. Knepley /* Interpolate */ 20109566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 20119318fe57SMatthew G. Knepley PetscFunctionReturn(0); 20129318fe57SMatthew G. Knepley } 20139318fe57SMatthew G. Knepley 20149318fe57SMatthew G. Knepley /*@ 20159318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 20169318fe57SMatthew G. Knepley 20179318fe57SMatthew G. Knepley Collective 20189318fe57SMatthew G. Knepley 20199318fe57SMatthew G. Knepley Input Parameters: 2020*a1cb98faSBarry Smith + comm - The communicator for the `DM` object 20219318fe57SMatthew G. Knepley . n - The number of wedges around the origin 20229318fe57SMatthew G. Knepley - interpolate - Create edges and faces 20239318fe57SMatthew G. Knepley 20249318fe57SMatthew G. Knepley Output Parameter: 2025*a1cb98faSBarry Smith . dm - The `DM` object 20269318fe57SMatthew G. Knepley 20279318fe57SMatthew G. Knepley Level: beginner 20289318fe57SMatthew G. Knepley 2029*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 20309318fe57SMatthew G. Knepley @*/ 2031d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 2032d71ae5a4SJacob Faibussowitsch { 20339318fe57SMatthew G. Knepley PetscFunctionBegin; 20349318fe57SMatthew G. Knepley PetscValidPointer(dm, 4); 20359566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 20369566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 20379566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 203824119c2aSMatthew G. Knepley PetscFunctionReturn(0); 203924119c2aSMatthew G. Knepley } 204024119c2aSMatthew G. Knepley 2041d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2042d71ae5a4SJacob Faibussowitsch { 204365a81367SMatthew G. Knepley PetscReal prod = 0.0; 204465a81367SMatthew G. Knepley PetscInt i; 204565a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 204665a81367SMatthew G. Knepley return PetscSqrtReal(prod); 204765a81367SMatthew G. Knepley } 2048d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2049d71ae5a4SJacob Faibussowitsch { 205065a81367SMatthew G. Knepley PetscReal prod = 0.0; 205165a81367SMatthew G. Knepley PetscInt i; 205265a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i] * y[i]; 205365a81367SMatthew G. Knepley return prod; 205465a81367SMatthew G. Knepley } 205565a81367SMatthew G. Knepley 205651a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 2057d71ae5a4SJacob 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[]) 2058d71ae5a4SJacob Faibussowitsch { 205951a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 206051a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 206151a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 206251a74b61SMatthew G. Knepley 206351a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 206451a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 206551a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 206651a74b61SMatthew G. Knepley } 206751a74b61SMatthew G. Knepley 2068d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 2069d71ae5a4SJacob Faibussowitsch { 207065a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 207165a81367SMatthew G. Knepley PetscSection coordSection; 207265a81367SMatthew G. Knepley Vec coordinates; 207365a81367SMatthew G. Knepley PetscScalar *coords; 207465a81367SMatthew G. Knepley PetscReal *coordsIn; 2075064cae4fSPierre Jolivet PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, c, e; 207665a81367SMatthew G. Knepley PetscMPIInt rank; 207765a81367SMatthew G. Knepley 207865a81367SMatthew G. Knepley PetscFunctionBegin; 20799318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 20809566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 20819566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 20829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 208365a81367SMatthew G. Knepley switch (dim) { 208465a81367SMatthew G. Knepley case 2: 208565a81367SMatthew G. Knepley if (simplex) { 208651a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 208751a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 208865a81367SMatthew G. Knepley const PetscInt degree = 5; 208951a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 209065a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 209165a81367SMatthew G. Knepley PetscInt cone[3]; 209265a81367SMatthew G. Knepley PetscInt *graph, p, i, j, k; 209365a81367SMatthew G. Knepley 20949371c9d4SSatish Balay vertex[0] *= R / radius; 20959371c9d4SSatish Balay vertex[1] *= R / radius; 20969371c9d4SSatish Balay vertex[2] *= R / radius; 2097dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 2098dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 209965a81367SMatthew G. Knepley firstVertex = numCells; 210051a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 210165a81367SMatthew G. Knepley 210265a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 210365a81367SMatthew G. Knepley 210465a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 210551a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 210665a81367SMatthew G. Knepley */ 210765a81367SMatthew G. Knepley /* Construct vertices */ 21089566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2109dd400576SPatrick Sanan if (rank == 0) { 211065a81367SMatthew G. Knepley for (p = 0, i = 0; p < embedDim; ++p) { 211165a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 211265a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 211365a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 211465a81367SMatthew G. Knepley ++i; 211565a81367SMatthew G. Knepley } 211665a81367SMatthew G. Knepley } 211765a81367SMatthew G. Knepley } 211845da822fSValeria Barra } 211965a81367SMatthew G. Knepley /* Construct graph */ 21209566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 212165a81367SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 212265a81367SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 21239371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 21249371c9d4SSatish Balay graph[i * numVerts + j] = 1; 21259371c9d4SSatish Balay ++k; 21269371c9d4SSatish Balay } 212765a81367SMatthew G. Knepley } 212863a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 212965a81367SMatthew G. Knepley } 213065a81367SMatthew G. Knepley /* Build Topology */ 21319566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 213248a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 21339566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 213465a81367SMatthew G. Knepley /* Cells */ 213565a81367SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 213665a81367SMatthew G. Knepley for (j = 0; j < i; ++j) { 213765a81367SMatthew G. Knepley for (k = 0; k < j; ++k) { 213865a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 21399371c9d4SSatish Balay cone[0] = firstVertex + i; 21409371c9d4SSatish Balay cone[1] = firstVertex + j; 21419371c9d4SSatish Balay cone[2] = firstVertex + k; 214265a81367SMatthew G. Knepley /* Check orientation */ 214365a81367SMatthew G. Knepley { 21449371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 21459371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 21469371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 21479371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 21489371c9d4SSatish Balay }; 214965a81367SMatthew G. Knepley PetscReal normal[3]; 215065a81367SMatthew G. Knepley PetscInt e, f; 215165a81367SMatthew G. Knepley 215265a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 215365a81367SMatthew G. Knepley normal[d] = 0.0; 215465a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2155ad540459SPierre 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]); 215665a81367SMatthew G. Knepley } 215765a81367SMatthew G. Knepley } 21589371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 21599371c9d4SSatish Balay PetscInt tmp = cone[1]; 21609371c9d4SSatish Balay cone[1] = cone[2]; 21619371c9d4SSatish Balay cone[2] = tmp; 216265a81367SMatthew G. Knepley } 216365a81367SMatthew G. Knepley } 21649566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 216565a81367SMatthew G. Knepley } 216665a81367SMatthew G. Knepley } 216765a81367SMatthew G. Knepley } 216865a81367SMatthew G. Knepley } 21699566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 21709566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 21719566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 217265a81367SMatthew G. Knepley } else { 21732829fed8SMatthew G. Knepley /* 21742829fed8SMatthew G. Knepley 12-21--13 21752829fed8SMatthew G. Knepley | | 21762829fed8SMatthew G. Knepley 25 4 24 21772829fed8SMatthew G. Knepley | | 21782829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 21792829fed8SMatthew G. Knepley | | | | 21802829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 21812829fed8SMatthew G. Knepley | | | | 21822829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 21832829fed8SMatthew G. Knepley | | 21842829fed8SMatthew G. Knepley 20 1 19 21852829fed8SMatthew G. Knepley | | 21862829fed8SMatthew G. Knepley 10-18--11 21872829fed8SMatthew G. Knepley | | 21882829fed8SMatthew G. Knepley 23 2 22 21892829fed8SMatthew G. Knepley | | 21902829fed8SMatthew G. Knepley 12-21--13 21912829fed8SMatthew G. Knepley */ 21922829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 21932829fed8SMatthew G. Knepley 2194dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 2195dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 2196dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 219765a81367SMatthew G. Knepley firstVertex = numCells; 219865a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 21992829fed8SMatthew G. Knepley /* Build Topology */ 22009566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 220148a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 220248a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 22039566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2204dd400576SPatrick Sanan if (rank == 0) { 22052829fed8SMatthew G. Knepley /* Cell 0 */ 22069371c9d4SSatish Balay cone[0] = 14; 22079371c9d4SSatish Balay cone[1] = 15; 22089371c9d4SSatish Balay cone[2] = 16; 22099371c9d4SSatish Balay cone[3] = 17; 22109566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 22119371c9d4SSatish Balay ornt[0] = 0; 22129371c9d4SSatish Balay ornt[1] = 0; 22139371c9d4SSatish Balay ornt[2] = 0; 22149371c9d4SSatish Balay ornt[3] = 0; 22159566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 22162829fed8SMatthew G. Knepley /* Cell 1 */ 22179371c9d4SSatish Balay cone[0] = 18; 22189371c9d4SSatish Balay cone[1] = 19; 22199371c9d4SSatish Balay cone[2] = 14; 22209371c9d4SSatish Balay cone[3] = 20; 22219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 22229371c9d4SSatish Balay ornt[0] = 0; 22239371c9d4SSatish Balay ornt[1] = 0; 22249371c9d4SSatish Balay ornt[2] = -1; 22259371c9d4SSatish Balay ornt[3] = 0; 22269566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 22272829fed8SMatthew G. Knepley /* Cell 2 */ 22289371c9d4SSatish Balay cone[0] = 21; 22299371c9d4SSatish Balay cone[1] = 22; 22309371c9d4SSatish Balay cone[2] = 18; 22319371c9d4SSatish Balay cone[3] = 23; 22329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 22339371c9d4SSatish Balay ornt[0] = 0; 22349371c9d4SSatish Balay ornt[1] = 0; 22359371c9d4SSatish Balay ornt[2] = -1; 22369371c9d4SSatish Balay ornt[3] = 0; 22379566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 22382829fed8SMatthew G. Knepley /* Cell 3 */ 22399371c9d4SSatish Balay cone[0] = 19; 22409371c9d4SSatish Balay cone[1] = 22; 22419371c9d4SSatish Balay cone[2] = 24; 22429371c9d4SSatish Balay cone[3] = 15; 22439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 22449371c9d4SSatish Balay ornt[0] = -1; 22459371c9d4SSatish Balay ornt[1] = -1; 22469371c9d4SSatish Balay ornt[2] = 0; 22479371c9d4SSatish Balay ornt[3] = -1; 22489566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 22492829fed8SMatthew G. Knepley /* Cell 4 */ 22509371c9d4SSatish Balay cone[0] = 16; 22519371c9d4SSatish Balay cone[1] = 24; 22529371c9d4SSatish Balay cone[2] = 21; 22539371c9d4SSatish Balay cone[3] = 25; 22549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 22559371c9d4SSatish Balay ornt[0] = -1; 22569371c9d4SSatish Balay ornt[1] = -1; 22579371c9d4SSatish Balay ornt[2] = -1; 22589371c9d4SSatish Balay ornt[3] = 0; 22599566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 22602829fed8SMatthew G. Knepley /* Cell 5 */ 22619371c9d4SSatish Balay cone[0] = 20; 22629371c9d4SSatish Balay cone[1] = 17; 22639371c9d4SSatish Balay cone[2] = 25; 22649371c9d4SSatish Balay cone[3] = 23; 22659566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 22669371c9d4SSatish Balay ornt[0] = -1; 22679371c9d4SSatish Balay ornt[1] = -1; 22689371c9d4SSatish Balay ornt[2] = -1; 22699371c9d4SSatish Balay ornt[3] = -1; 22709566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 22712829fed8SMatthew G. Knepley /* Edges */ 22729371c9d4SSatish Balay cone[0] = 6; 22739371c9d4SSatish Balay cone[1] = 7; 22749566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 22759371c9d4SSatish Balay cone[0] = 7; 22769371c9d4SSatish Balay cone[1] = 8; 22779566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 22789371c9d4SSatish Balay cone[0] = 8; 22799371c9d4SSatish Balay cone[1] = 9; 22809566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 22819371c9d4SSatish Balay cone[0] = 9; 22829371c9d4SSatish Balay cone[1] = 6; 22839566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 22849371c9d4SSatish Balay cone[0] = 10; 22859371c9d4SSatish Balay cone[1] = 11; 22869566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 22879371c9d4SSatish Balay cone[0] = 11; 22889371c9d4SSatish Balay cone[1] = 7; 22899566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 22909371c9d4SSatish Balay cone[0] = 6; 22919371c9d4SSatish Balay cone[1] = 10; 22929566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 22939371c9d4SSatish Balay cone[0] = 12; 22949371c9d4SSatish Balay cone[1] = 13; 22959566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 22969371c9d4SSatish Balay cone[0] = 13; 22979371c9d4SSatish Balay cone[1] = 11; 22989566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 22999371c9d4SSatish Balay cone[0] = 10; 23009371c9d4SSatish Balay cone[1] = 12; 23019566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 23029371c9d4SSatish Balay cone[0] = 13; 23039371c9d4SSatish Balay cone[1] = 8; 23049566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 23059371c9d4SSatish Balay cone[0] = 12; 23069371c9d4SSatish Balay cone[1] = 9; 23079566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 230845da822fSValeria Barra } 23099566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 23109566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 23112829fed8SMatthew G. Knepley /* Build coordinates */ 23129566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2313dd400576SPatrick Sanan if (rank == 0) { 23149371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 23159371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 23169371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 23179371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 23189371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 23199371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 23209371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 23219371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 23229371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 23239371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 23249371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 23259371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 23269371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 23279371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 23289371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 23299371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 23309371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 23319371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 23329371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 23339371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 23349371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 23359371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 23369371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 23379371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 233865a81367SMatthew G. Knepley } 233945da822fSValeria Barra } 234065a81367SMatthew G. Knepley break; 234165a81367SMatthew G. Knepley case 3: 2342116ded15SMatthew G. Knepley if (simplex) { 2343116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 234451a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 234551a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 234651a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 2347116ded15SMatthew G. Knepley const PetscInt degree = 12; 2348116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 23499371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 23509371c9d4SSatish Balay {0, 1, 2, 3}, 23519371c9d4SSatish Balay {0, 2, 3, 1}, 23529371c9d4SSatish Balay {0, 3, 1, 2}, 23539371c9d4SSatish Balay {1, 0, 3, 2}, 23549371c9d4SSatish Balay {1, 2, 0, 3}, 23559371c9d4SSatish Balay {1, 3, 2, 0}, 23569371c9d4SSatish Balay {2, 0, 1, 3}, 23579371c9d4SSatish Balay {2, 1, 3, 0}, 23589371c9d4SSatish Balay {2, 3, 0, 1}, 23599371c9d4SSatish Balay {3, 0, 2, 1}, 23609371c9d4SSatish Balay {3, 1, 0, 2}, 23619371c9d4SSatish Balay {3, 2, 1, 0} 23629371c9d4SSatish Balay }; 2363116ded15SMatthew G. Knepley PetscInt cone[4]; 2364116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 2365116ded15SMatthew G. Knepley 23669371c9d4SSatish Balay vertexA[0] *= R; 23679371c9d4SSatish Balay vertexA[1] *= R; 23689371c9d4SSatish Balay vertexA[2] *= R; 23699371c9d4SSatish Balay vertexA[3] *= R; 23709371c9d4SSatish Balay vertexB[0] *= R; 23719371c9d4SSatish Balay vertexB[1] *= R; 23729371c9d4SSatish Balay vertexB[2] *= R; 23739371c9d4SSatish Balay vertexB[3] *= R; 23749371c9d4SSatish Balay vertexC[0] *= R; 23759371c9d4SSatish Balay vertexC[1] *= R; 23769371c9d4SSatish Balay vertexC[2] *= R; 23779371c9d4SSatish Balay vertexC[3] *= R; 2378dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 2379dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 2380116ded15SMatthew G. Knepley firstVertex = numCells; 2381116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 2382116ded15SMatthew G. Knepley 2383116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 2384116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 2385116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 2386116ded15SMatthew G. Knepley 2387116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 23886333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 2389116ded15SMatthew G. Knepley 2390116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 2391116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 2392116ded15SMatthew G. Knepley */ 2393116ded15SMatthew G. Knepley /* Construct vertices */ 23949566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2395116ded15SMatthew G. Knepley i = 0; 2396dd400576SPatrick Sanan if (rank == 0) { 2397116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2398116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2399116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2400116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 2401116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 2402116ded15SMatthew G. Knepley ++i; 2403116ded15SMatthew G. Knepley } 2404116ded15SMatthew G. Knepley } 2405116ded15SMatthew G. Knepley } 2406116ded15SMatthew G. Knepley } 2407116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 2408116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 2409116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2410116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 2411116ded15SMatthew G. Knepley ++i; 2412116ded15SMatthew G. Knepley } 2413116ded15SMatthew G. Knepley } 2414116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 2415116ded15SMatthew G. Knepley s[3] = 1; 2416116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2417116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2418116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2419116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 2420116ded15SMatthew G. Knepley ++i; 2421116ded15SMatthew G. Knepley } 2422116ded15SMatthew G. Knepley } 2423116ded15SMatthew G. Knepley } 2424116ded15SMatthew G. Knepley } 242545da822fSValeria Barra } 242663a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 2427116ded15SMatthew G. Knepley /* Construct graph */ 24289566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 2429116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 2430116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 24319371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 24329371c9d4SSatish Balay graph[i * numVerts + j] = 1; 24339371c9d4SSatish Balay ++k; 24349371c9d4SSatish Balay } 2435116ded15SMatthew G. Knepley } 243663a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 2437116ded15SMatthew G. Knepley } 2438116ded15SMatthew G. Knepley /* Build Topology */ 24399566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 244048a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 24419566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2442116ded15SMatthew G. Knepley /* Cells */ 2443dd400576SPatrick Sanan if (rank == 0) { 2444116ded15SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 2445116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 2446116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 2447116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 24489371c9d4SSatish 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]) { 24499371c9d4SSatish Balay cone[0] = firstVertex + i; 24509371c9d4SSatish Balay cone[1] = firstVertex + j; 24519371c9d4SSatish Balay cone[2] = firstVertex + k; 24529371c9d4SSatish Balay cone[3] = firstVertex + l; 2453116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 2454116ded15SMatthew G. Knepley { 24559371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 24569371c9d4SSatish 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}}}, 2457116ded15SMatthew G. Knepley 24589371c9d4SSatish 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}}}, 2459116ded15SMatthew G. Knepley 24609371c9d4SSatish 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}}}, 2461116ded15SMatthew G. Knepley 24629371c9d4SSatish 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}} } 24639371c9d4SSatish Balay }; 2464116ded15SMatthew G. Knepley PetscReal normal[4]; 2465116ded15SMatthew G. Knepley PetscInt e, f, g; 2466116ded15SMatthew G. Knepley 2467116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 2468116ded15SMatthew G. Knepley normal[d] = 0.0; 2469116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2470116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 2471116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 2472116ded15SMatthew 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]); 2473116ded15SMatthew G. Knepley } 2474116ded15SMatthew G. Knepley } 2475116ded15SMatthew G. Knepley } 2476116ded15SMatthew G. Knepley } 24779371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 24789371c9d4SSatish Balay PetscInt tmp = cone[1]; 24799371c9d4SSatish Balay cone[1] = cone[2]; 24809371c9d4SSatish Balay cone[2] = tmp; 24819371c9d4SSatish Balay } 2482116ded15SMatthew G. Knepley } 24839566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 2484116ded15SMatthew G. Knepley } 2485116ded15SMatthew G. Knepley } 2486116ded15SMatthew G. Knepley } 2487116ded15SMatthew G. Knepley } 2488116ded15SMatthew G. Knepley } 248945da822fSValeria Barra } 24909566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 24919566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 24929566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 2493116ded15SMatthew G. Knepley } 2494f4d061e9SPierre Jolivet break; 2495d71ae5a4SJacob Faibussowitsch default: 2496d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 249765a81367SMatthew G. Knepley } 249865a81367SMatthew G. Knepley /* Create coordinates */ 24999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 25009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 25019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 25029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 25032829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 25049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 25059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 25062829fed8SMatthew G. Knepley } 25079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 25089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 25099566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 25109566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 25119566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 25129566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 25139566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 25149566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 25159371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 2516ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 25179566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 25189566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 25199566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 25209566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 252151a74b61SMatthew G. Knepley { 252251a74b61SMatthew G. Knepley DM cdm; 252351a74b61SMatthew G. Knepley PetscDS cds; 25249318fe57SMatthew G. Knepley PetscScalar c = R; 252551a74b61SMatthew G. Knepley 25269566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere)); 25279566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 25289566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 25299566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 253051a74b61SMatthew G. Knepley } 25319318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 25329566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 25339318fe57SMatthew G. Knepley PetscFunctionReturn(0); 25349318fe57SMatthew G. Knepley } 25359318fe57SMatthew G. Knepley 2536b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 2537b7f5c055SJed Brown 2538b7f5c055SJed Brown /* 2539b7f5c055SJed Brown The Schwarz P implicit surface is 2540b7f5c055SJed Brown 2541b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 2542b7f5c055SJed Brown */ 2543d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2544d71ae5a4SJacob Faibussowitsch { 2545b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 2546b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 2547b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 2548b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2549b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 2550ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 2551b7f5c055SJed Brown } 2552b7f5c055SJed Brown } 2553b7f5c055SJed Brown 25544663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 2555d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 2556d71ae5a4SJacob Faibussowitsch { 2557ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 25584663dae6SJed Brown return 0; 25594663dae6SJed Brown } 25604663dae6SJed Brown 2561b7f5c055SJed Brown /* 2562b7f5c055SJed Brown The Gyroid implicit surface is 2563b7f5c055SJed Brown 2564b7f5c055SJed 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) 2565b7f5c055SJed Brown 2566b7f5c055SJed Brown */ 2567d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2568d71ae5a4SJacob Faibussowitsch { 2569b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 2570b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 2571b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 2572b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 2573b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 2574b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 2575b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 2576b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2577b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2578b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 2579b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2580b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2581b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 2582b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2583b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2584b7f5c055SJed Brown } 2585b7f5c055SJed Brown 25864663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 2587d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 2588d71ae5a4SJacob Faibussowitsch { 25894663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 25904663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 25914663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 25924663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 25934663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 25944663dae6SJed Brown return 0; 25954663dae6SJed Brown } 25964663dae6SJed Brown 2597b7f5c055SJed Brown /* 2598b7f5c055SJed Brown We wish to solve 2599b7f5c055SJed Brown 2600b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 2601b7f5c055SJed Brown 2602b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 2603b7f5c055SJed 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 2604b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 2605b7f5c055SJed Brown 2606b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 2607b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 2608b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 2609b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 2610b7f5c055SJed Brown Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries. 2611b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 2612b7f5c055SJed Brown 2613b7f5c055SJed Brown f(y) = 0 1 equation 2614b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 2615b7f5c055SJed Brown 2616b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 2617b7f5c055SJed Brown */ 2618d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 2619d71ae5a4SJacob Faibussowitsch { 2620b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 2621b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 26222f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 26239371c9d4SSatish Balay PetscReal n_y[3][3] = { 26249371c9d4SSatish Balay {0, 0, 0}, 26259371c9d4SSatish Balay {0, 0, 0}, 26269371c9d4SSatish Balay {0, 0, 0} 26279371c9d4SSatish Balay }; 2628b7f5c055SJed Brown 2629b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 2630b7f5c055SJed Brown 2631b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 2632b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2633ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 2634b7f5c055SJed Brown 2635b7f5c055SJed Brown // Define the Householder reflector 2636b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 2637b7f5c055SJed Brown n[0] += norm * sign; 2638b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 2639b7f5c055SJed Brown 2640b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2641b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 2642b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 2643b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 2644b7f5c055SJed Brown 2645b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2646b7f5c055SJed Brown n[i] /= norm; 2647b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2648b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 2649b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 2650b7f5c055SJed Brown } 2651b7f5c055SJed Brown } 2652b7f5c055SJed Brown 2653b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 2654b7f5c055SJed 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]; 2655b7f5c055SJed Brown 2656b7f5c055SJed Brown res[0] = f; 2657b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 2658b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 2659b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 2660b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2661b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 2662b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 2663b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 2664b7f5c055SJed Brown } 2665b7f5c055SJed Brown } 2666b7f5c055SJed Brown 2667b7f5c055SJed Brown /* 2668b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 2669b7f5c055SJed Brown */ 2670d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 2671d71ae5a4SJacob Faibussowitsch { 2672b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 2673b7f5c055SJed Brown 2674b7f5c055SJed Brown PetscFunctionBegin; 2675b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 2676b7f5c055SJed Brown PetscScalar res[3], J[9]; 2677b7f5c055SJed Brown PetscReal resnorm; 2678b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 2679b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 2680b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 268163a3b9bcSJacob 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]))); 2682b7f5c055SJed Brown } 2683b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 2684b7f5c055SJed Brown 2685b7f5c055SJed Brown // Take the Newton step 26869566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 2687b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 2688b7f5c055SJed Brown } 2689b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 2690b7f5c055SJed Brown PetscFunctionReturn(0); 2691b7f5c055SJed Brown } 2692b7f5c055SJed Brown 2693b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 2694b7f5c055SJed Brown 2695d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 2696d71ae5a4SJacob Faibussowitsch { 2697b7f5c055SJed Brown PetscMPIInt rank; 2698b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 2699b7f5c055SJed Brown PetscInt(*edges)[2] = NULL, *edgeSets = NULL; 2700b7f5c055SJed Brown PetscInt *cells_flat = NULL; 2701b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 2702b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 27034663dae6SJed Brown PetscSimplePointFunc normalFunc = NULL; 2704b7f5c055SJed Brown DMLabel label; 2705b7f5c055SJed Brown 2706b7f5c055SJed Brown PetscFunctionBegin; 27079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 270863a3b9bcSJacob 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); 2709b7f5c055SJed Brown switch (tpstype) { 2710b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 2711b7f5c055SJed 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"); 2712c5853193SPierre Jolivet if (rank == 0) { 2713b7f5c055SJed Brown PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 2714b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 2715b7f5c055SJed Brown PetscReal L = 1; 2716b7f5c055SJed Brown 2717b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 2718b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 2719b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 2720b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 2721b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 2722b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 27239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 27249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 27259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 27269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 2727b7f5c055SJed Brown // x-normal pipes 2728b7f5c055SJed Brown vcount = 0; 2729b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 2730b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2731b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2732b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2733b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 2734b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2735b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2736b7f5c055SJed Brown } 2737b7f5c055SJed Brown } 2738b7f5c055SJed Brown } 2739b7f5c055SJed Brown } 2740b7f5c055SJed Brown // y-normal pipes 2741b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2742b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 2743b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2744b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2745b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2746b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 2747b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2748b7f5c055SJed Brown } 2749b7f5c055SJed Brown } 2750b7f5c055SJed Brown } 2751b7f5c055SJed Brown } 2752b7f5c055SJed Brown // z-normal pipes 2753b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2754b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2755b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 2756b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2757b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2758b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2759b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 2760b7f5c055SJed Brown } 2761b7f5c055SJed Brown } 2762b7f5c055SJed Brown } 2763b7f5c055SJed Brown } 2764b7f5c055SJed Brown // junctions 2765b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2766b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2767b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2768b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 2769b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 2770b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 2771b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 2772b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 2773b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 2774b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 2775b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 2776b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 2777b7f5c055SJed Brown } 2778b7f5c055SJed Brown } 2779b7f5c055SJed Brown } 2780b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 2781b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 2782b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 2783b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 2784b7f5c055SJed Brown }; 2785b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 27869371c9d4SSatish 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}; 2787b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 27889371c9d4SSatish 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}; 2789b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 2790b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 2791b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 2792b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 2793b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 2794b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 2795b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 2796b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 2797b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 2798b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 2799b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 2800b7f5c055SJed Brown if (ijk[dir] == 0) { 2801b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 2802b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 2803b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 2804b7f5c055SJed Brown numEdges++; 2805b7f5c055SJed Brown } 2806b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 2807b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 2808b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 2809b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 2810b7f5c055SJed Brown numEdges++; 2811b7f5c055SJed Brown } 2812b7f5c055SJed Brown } 2813b7f5c055SJed Brown } 2814b7f5c055SJed Brown } 2815b7f5c055SJed Brown } 2816b7f5c055SJed Brown } 281763a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 2818b7f5c055SJed Brown numFaces = 24 * Njunctions; 2819b7f5c055SJed Brown cells_flat = cells[0][0][0]; 2820b7f5c055SJed Brown } 2821b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 28224663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 2823b7f5c055SJed Brown break; 2824b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 2825c5853193SPierre Jolivet if (rank == 0) { 2826b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 2827b7f5c055SJed Brown // 2828b7f5c055SJed 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) 2829b7f5c055SJed Brown // 2830b7f5c055SJed Brown // on the cell [0,2]^3. 2831b7f5c055SJed Brown // 2832b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 2833b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 2834b7f5c055SJed Brown // like a boomerang: 2835b7f5c055SJed Brown // 2836b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 2837b7f5c055SJed Brown // ----- ------- ------- ------- // 2838b7f5c055SJed Brown // // 2839b7f5c055SJed Brown // + + + + + + + \ + // 2840b7f5c055SJed Brown // \ / \ // 2841b7f5c055SJed Brown // \ `-_ _-' / } // 2842b7f5c055SJed Brown // *-_ `-' _-' / // 2843b7f5c055SJed Brown // + `-+ + + +-' + + / + // 2844b7f5c055SJed Brown // // 2845b7f5c055SJed Brown // // 2846b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 2847b7f5c055SJed Brown // ----- ------- ------- ------- // 2848b7f5c055SJed Brown // // 2849b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 2850b7f5c055SJed Brown // `-_ _-_ _-` / // 2851b7f5c055SJed Brown // \ _-' `-_ / { // 2852b7f5c055SJed Brown // \ / \ // 2853b7f5c055SJed Brown // + + + + + + + \ + // 2854b7f5c055SJed Brown // 2855b7f5c055SJed Brown // 2856b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 2857b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 2858b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 2859b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 2860b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 2861b7f5c055SJed Brown // 2862b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 2863b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 2864b7f5c055SJed Brown // 2865b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 2866b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 2867b7f5c055SJed Brown 2868b7f5c055SJed Brown PetscInt facesPerBlock = 64; 2869b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 2870b7f5c055SJed Brown PetscInt extentPlus[3]; 2871b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 28729371c9d4SSatish 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; 28739371c9d4SSatish Balay const PetscInt pattern[64][4] = { 28749371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 2875b7f5c055SJed Brown /* layer 0 */ 28769371c9d4SSatish Balay {A, C, K, G }, 28779371c9d4SSatish Balay {C, B, II, K }, 28789371c9d4SSatish Balay {D, A, H, L }, 28799371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 28809371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 28819371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 28829371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 28839371c9d4SSatish Balay {B, F, M, II }, 2884b7f5c055SJed Brown /* layer 1 */ 28859371c9d4SSatish Balay {G, K, Q, O }, 28869371c9d4SSatish Balay {K, II, P, Q }, 28879371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 28889371c9d4SSatish Balay {J, L, R, P }, 28899371c9d4SSatish Balay {N, J, P, S }, 28909371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 28919371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 28929371c9d4SSatish Balay {II, M, T, P }, 2893b7f5c055SJed Brown /* layer 2 */ 28949371c9d4SSatish Balay {O, Q, Y, U }, 28959371c9d4SSatish Balay {Q, P, W, Y }, 28969371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 28979371c9d4SSatish Balay {P, R, Ap, W }, 28989371c9d4SSatish Balay {S, P, X, Bp }, 28999371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 29009371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 29019371c9d4SSatish Balay {P, T, Z, X }, 2902b7f5c055SJed Brown /* layer 3 */ 29039371c9d4SSatish Balay {U, Y, Ep, Dp }, 29049371c9d4SSatish Balay {Y, W, Cp, Ep }, 29059371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 29069371c9d4SSatish Balay {W, Ap, Gp, Cp }, 29079371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 29089371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 29099371c9d4SSatish Balay {Z, V, Dp, Hp }, 29109371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 2911b7f5c055SJed Brown /* layer 4 */ 29129371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 29139371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 29149371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 29159371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 29169371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 29179371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 29189371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 29199371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 2920b7f5c055SJed Brown /* layer 5 */ 29219371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 29229371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 29239371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 29249371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 29259371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 29269371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 29279371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 29289371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 2929b7f5c055SJed Brown /* layer 6 */ 29309371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 29319371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 29329371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 29339371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 29349371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 29359371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 29369371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 29379371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 2938b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 29399371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 29409371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 29419371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 29429371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 29439371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 29449371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 29459371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 29469371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 2947b7f5c055SJed Brown }; 2948b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 29499371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 2950bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 2951bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 2952bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 2953bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 2954bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 2955bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 2956b7f5c055SJed Brown 2957bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 2958bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 2959bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 2960bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 2961bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 2962bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 2963bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 2964bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 2965b7f5c055SJed Brown 2966bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 2967bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 2968bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 2969bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 2970bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 2971bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 2972b7f5c055SJed Brown 2973bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 2974bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 2975bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 2976bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 2977bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 2978bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 2979bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 2980bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 2981b7f5c055SJed Brown 2982bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 2983bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 2984bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 2985bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 2986bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 2987bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 2988b7f5c055SJed Brown 2989bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 2990bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 2991bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 2992bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 2993bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 2994bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 2995bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 2996bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 2997b7f5c055SJed Brown 2998bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 2999bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 3000bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 3001bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 3002bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 3003bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 3004b7f5c055SJed Brown 3005bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 3006bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 3007bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 3008bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 3009bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 3010bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 3011bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 3012bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 3013b7f5c055SJed Brown }; 3014b7f5c055SJed Brown PetscInt(*cells)[64][4] = NULL; 3015b7f5c055SJed Brown PetscBool *seen; 3016b7f5c055SJed Brown PetscInt *vertToTrueVert; 3017b7f5c055SJed Brown PetscInt count; 3018b7f5c055SJed Brown 3019b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 3020b7f5c055SJed Brown numBlocks = 1; 3021b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 3022b7f5c055SJed Brown numBlocksPlus = 1; 3023b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 3024b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 30259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 30269566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 3027b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3028b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3029b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3030b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3031b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 3032b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 3033b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 3034b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 3035b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 3036b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 3037b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 3038b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 3039b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 3040b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 3041b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 3042b7f5c055SJed Brown 3043b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 3044b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 3045b7f5c055SJed Brown } 3046b7f5c055SJed Brown } 3047b7f5c055SJed Brown } 3048b7f5c055SJed Brown } 3049b7f5c055SJed Brown } 30509371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 30519371c9d4SSatish Balay if (seen[i]) numVertices++; 3052b7f5c055SJed Brown count = 0; 30539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 30549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 3055b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 3056b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 3057b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 3058b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 3059b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 3060b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 3061b7f5c055SJed Brown 3062b7f5c055SJed Brown if (seen[vIdx]) { 3063b7f5c055SJed Brown PetscInt thisVert; 3064b7f5c055SJed Brown 3065b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 3066b7f5c055SJed Brown 3067b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 3068b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 3069b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 3070b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 3071b7f5c055SJed Brown } 3072b7f5c055SJed Brown } 3073b7f5c055SJed Brown } 3074b7f5c055SJed Brown } 3075b7f5c055SJed Brown } 3076b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 3077b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3078ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 3079b7f5c055SJed Brown } 3080b7f5c055SJed Brown } 30819566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 30829566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 3083b7f5c055SJed Brown cells_flat = cells[0][0]; 3084b7f5c055SJed Brown numEdges = 0; 3085b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 3086b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3087b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3088b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3089b7f5c055SJed Brown 3090b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3091b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 3092b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 3093b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 3094b7f5c055SJed Brown } 3095b7f5c055SJed Brown } 3096b7f5c055SJed Brown } 3097b7f5c055SJed Brown } 30989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 30999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 3100b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 3101b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3102b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3103b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3104b7f5c055SJed Brown 3105b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3106b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 3107b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 3108b7f5c055SJed Brown edges[edge][0] = ev[0]; 3109b7f5c055SJed Brown edges[edge][1] = ev[1]; 3110b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 3111b7f5c055SJed Brown } 3112b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 3113b7f5c055SJed Brown edges[edge][0] = ev[0]; 3114b7f5c055SJed Brown edges[edge][1] = ev[1]; 3115b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 3116b7f5c055SJed Brown } 3117b7f5c055SJed Brown } 3118b7f5c055SJed Brown } 3119b7f5c055SJed Brown } 3120b7f5c055SJed Brown } 3121b7f5c055SJed Brown } 3122b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 31234663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 3124b7f5c055SJed Brown break; 3125b7f5c055SJed Brown } 3126b7f5c055SJed Brown 31279566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 3128c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 31299566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 31309566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 3131b7f5c055SJed Brown { 3132b7f5c055SJed Brown DM idm; 31339566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 313469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3135b7f5c055SJed Brown } 3136c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 31379566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 31389566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 3139b7f5c055SJed Brown 31409566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 31419566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 3142b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 3143b7f5c055SJed Brown PetscInt njoin; 3144b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 31459566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 314663a3b9bcSJacob 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]); 31479566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 31489566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 3149b7f5c055SJed Brown } 31509566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 31519566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 31521436d7faSJed Brown if (tps_distribute) { 31531436d7faSJed Brown DM pdm = NULL; 31541436d7faSJed Brown PetscPartitioner part; 31551436d7faSJed Brown 31569566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 31579566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 31589566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 315948a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 31601436d7faSJed Brown // Do not auto-distribute again 31619566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 31621436d7faSJed Brown } 3163b7f5c055SJed Brown 31649566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 3165b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 3166b7f5c055SJed Brown PetscInt m; 3167b7f5c055SJed Brown DM dmf; 3168b7f5c055SJed Brown Vec X; 3169b7f5c055SJed Brown PetscScalar *x; 31709566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 317169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 3172b7f5c055SJed Brown 31739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 31749566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 31759566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 317648a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 31779566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 3178b7f5c055SJed Brown } 3179b7f5c055SJed Brown 3180b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 31819566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 31829566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 3183b7f5c055SJed Brown 3184b7f5c055SJed Brown if (thickness > 0) { 31854663dae6SJed Brown DM edm, cdm, ecdm; 31864663dae6SJed Brown DMPlexTransform tr; 31874663dae6SJed Brown const char *prefix; 31884663dae6SJed Brown PetscOptions options; 31894663dae6SJed Brown // Code from DMPlexExtrude 31904663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 31914663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 31924663dae6SJed Brown PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE)); 31934663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 31944663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 31954663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 31964663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 31974663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 31984663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 31994663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 32004663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 32014663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 32024663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 32034663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 32044663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 32054663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 32064663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 32074663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 32084663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 32094663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 32104663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 32114663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 32124663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 32134663dae6SJed Brown if (edm) { 32144663dae6SJed Brown ((DM_Plex *)edm->data)->printFEM = ((DM_Plex *)dm->data)->printFEM; 32154663dae6SJed Brown ((DM_Plex *)edm->data)->printL2 = ((DM_Plex *)dm->data)->printL2; 3216f5867de0SMatthew G. Knepley ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate; 32174663dae6SJed Brown } 321869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 3219b7f5c055SJed Brown } 3220b7f5c055SJed Brown PetscFunctionReturn(0); 3221b7f5c055SJed Brown } 3222b7f5c055SJed Brown 3223b7f5c055SJed Brown /*@ 3224b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 3225b7f5c055SJed Brown 3226b7f5c055SJed Brown Collective 3227b7f5c055SJed Brown 3228b7f5c055SJed Brown Input Parameters: 3229*a1cb98faSBarry Smith + comm - The communicator for the `DM` object 3230b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 3231b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 3232b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic 32331436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 3234817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 32351436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 3236817da375SSatish Balay - thickness - Thickness in normal direction 3237b7f5c055SJed Brown 3238b7f5c055SJed Brown Output Parameter: 3239*a1cb98faSBarry Smith . dm - The `DM` object 3240*a1cb98faSBarry Smith 3241*a1cb98faSBarry Smith Level: beginner 3242b7f5c055SJed Brown 3243b7f5c055SJed Brown Notes: 3244b7f5c055SJed 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. 3245b7f5c055SJed Brown https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries. 3246b7f5c055SJed 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. 3247b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 3248b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 3249b7f5c055SJed Brown This projection could readily be extended to related surfaces. 3250b7f5c055SJed Brown 3251b7f5c055SJed Brown The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z). 3252b7f5c055SJed Brown When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). Use DMPlexLabelComplete() to propagate to coarse-level vertices. 3253b7f5c055SJed Brown 3254*a1cb98faSBarry Smith Developer Note: 3255b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 3256b7f5c055SJed Brown 3257*a1cb98faSBarry Smith References: 3258*a1cb98faSBarry Smith . * - Maskery et al, Insights into the mechanical properties of several triply periodic minimal surface lattice structures made by polymer additive manufacturing, 2017. 3259*a1cb98faSBarry Smith https://doi.org/10.1016/j.polymer.2017.11.049 3260b7f5c055SJed Brown 3261*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 3262b7f5c055SJed Brown @*/ 3263d71ae5a4SJacob 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) 3264d71ae5a4SJacob Faibussowitsch { 3265b7f5c055SJed Brown PetscFunctionBegin; 32669566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 32679566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 32689566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 3269b7f5c055SJed Brown PetscFunctionReturn(0); 3270b7f5c055SJed Brown } 3271b7f5c055SJed Brown 32729318fe57SMatthew G. Knepley /*@ 32739318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 32749318fe57SMatthew G. Knepley 32759318fe57SMatthew G. Knepley Collective 32769318fe57SMatthew G. Knepley 32779318fe57SMatthew G. Knepley Input Parameters: 3278*a1cb98faSBarry Smith + comm - The communicator for the `DM` object 32799318fe57SMatthew G. Knepley . dim - The dimension 32809318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 32819318fe57SMatthew G. Knepley - R - The radius 32829318fe57SMatthew G. Knepley 32839318fe57SMatthew G. Knepley Output Parameter: 3284*a1cb98faSBarry Smith . dm - The `DM` object 32859318fe57SMatthew G. Knepley 32869318fe57SMatthew G. Knepley Level: beginner 32879318fe57SMatthew G. Knepley 3288*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 32899318fe57SMatthew G. Knepley @*/ 3290d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 3291d71ae5a4SJacob Faibussowitsch { 32929318fe57SMatthew G. Knepley PetscFunctionBegin; 32939318fe57SMatthew G. Knepley PetscValidPointer(dm, 5); 32949566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 32959566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 32969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 32979318fe57SMatthew G. Knepley PetscFunctionReturn(0); 32989318fe57SMatthew G. Knepley } 32999318fe57SMatthew G. Knepley 3300d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 3301d71ae5a4SJacob Faibussowitsch { 33029318fe57SMatthew G. Knepley DM sdm, vol; 33039318fe57SMatthew G. Knepley DMLabel bdlabel; 33049318fe57SMatthew G. Knepley 33059318fe57SMatthew G. Knepley PetscFunctionBegin; 33069566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 33079566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 33089566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_")); 33099566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 33109566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 33119566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 33129566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 33139566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 331469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 33159566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 33169566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 33179566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 33189566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 331951a74b61SMatthew G. Knepley PetscFunctionReturn(0); 332051a74b61SMatthew G. Knepley } 332151a74b61SMatthew G. Knepley 332251a74b61SMatthew G. Knepley /*@ 332351a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 332451a74b61SMatthew G. Knepley 332551a74b61SMatthew G. Knepley Collective 332651a74b61SMatthew G. Knepley 332751a74b61SMatthew G. Knepley Input Parameters: 3328*a1cb98faSBarry Smith + comm - The communicator for the `DM` object 332951a74b61SMatthew G. Knepley . dim - The dimension 333051a74b61SMatthew G. Knepley - R - The radius 333151a74b61SMatthew G. Knepley 333251a74b61SMatthew G. Knepley Output Parameter: 3333*a1cb98faSBarry Smith . dm - The `DM` object 333451a74b61SMatthew G. Knepley 3335*a1cb98faSBarry Smith Options Database Key: 333651a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 333751a74b61SMatthew G. Knepley 333851a74b61SMatthew G. Knepley Level: beginner 333951a74b61SMatthew G. Knepley 3340*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 334151a74b61SMatthew G. Knepley @*/ 3342d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 3343d71ae5a4SJacob Faibussowitsch { 334451a74b61SMatthew G. Knepley PetscFunctionBegin; 33459566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 33469566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 33479566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 33482829fed8SMatthew G. Knepley PetscFunctionReturn(0); 33492829fed8SMatthew G. Knepley } 33502829fed8SMatthew G. Knepley 3351d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 3352d71ae5a4SJacob Faibussowitsch { 33530a6ba040SMatthew G. Knepley PetscFunctionBegin; 33549318fe57SMatthew G. Knepley switch (ct) { 33559371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 33569318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 33579318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 33589318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 33599318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 33609318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 33619318fe57SMatthew G. Knepley 33629566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 33639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33649371c9d4SSatish Balay } break; 33659371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 33669318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 33679318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 33689318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 33699318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 33709318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 33719318fe57SMatthew G. Knepley 33729566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 33739566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33749371c9d4SSatish Balay } break; 33759371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 3376b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 3377b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 3378b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 3379b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 3380b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 3381b5a892a1SMatthew G. Knepley 33829566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 33839566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33849371c9d4SSatish Balay } break; 33859371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 33869318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 33879318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 33889318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 33899318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 33909318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 33919318fe57SMatthew G. Knepley 33929566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 33939566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33949371c9d4SSatish Balay } break; 33959371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 33969318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 33979318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 33989318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 33999318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 34009318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 34019318fe57SMatthew G. Knepley 34029566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 34039566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34049371c9d4SSatish Balay } break; 34059371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 34069318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 34079318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 34089318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 34099318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 34109318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 34119318fe57SMatthew G. Knepley 34129566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 34139566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34149371c9d4SSatish Balay } break; 34159371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 34169318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 34179318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 3418f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 34199318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 3420f0edb160SMatthew 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}; 34219318fe57SMatthew G. Knepley 34229566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34239566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34249371c9d4SSatish Balay } break; 34259371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 34269318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 34279318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 3428f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 34299318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34309371c9d4SSatish 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}; 34319318fe57SMatthew G. Knepley 34329566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34339566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34349371c9d4SSatish Balay } break; 34359371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 34369318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 34379318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 3438f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 34399318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 34409371c9d4SSatish 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}; 34419318fe57SMatthew G. Knepley 34429566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34439566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34449371c9d4SSatish Balay } break; 34459371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 34469318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 34479318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 34489318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 34499318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 34509371c9d4SSatish 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}; 34519318fe57SMatthew G. Knepley 34529566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34539566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34549371c9d4SSatish Balay } break; 34559371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 34569318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 34579318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 34589318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 34599318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34609371c9d4SSatish 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}; 34619318fe57SMatthew G. Knepley 34629566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34649371c9d4SSatish Balay } break; 34659371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 34669318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 34679318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 3468f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 34699318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34709371c9d4SSatish 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}; 34719318fe57SMatthew G. Knepley 34729566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34739566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34749371c9d4SSatish Balay } break; 3475d71ae5a4SJacob Faibussowitsch default: 3476d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 34779318fe57SMatthew G. Knepley } 34789318fe57SMatthew G. Knepley { 34799318fe57SMatthew G. Knepley PetscInt Nv, v; 34809318fe57SMatthew G. Knepley 34819318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 34829566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 34839566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 34849566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 34859566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 34869318fe57SMatthew G. Knepley } 34879566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 34889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 34890a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 34900a6ba040SMatthew G. Knepley } 34910a6ba040SMatthew G. Knepley 34929318fe57SMatthew G. Knepley /*@ 3493*a1cb98faSBarry Smith DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell 34949318fe57SMatthew G. Knepley 34959318fe57SMatthew G. Knepley Collective 34969318fe57SMatthew G. Knepley 34979318fe57SMatthew G. Knepley Input Parameters: 34989318fe57SMatthew G. Knepley + comm - The communicator 34999318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 35009318fe57SMatthew G. Knepley 35019318fe57SMatthew G. Knepley Output Parameter: 35029318fe57SMatthew G. Knepley . refdm - The reference cell 35039318fe57SMatthew G. Knepley 35049318fe57SMatthew G. Knepley Level: intermediate 35059318fe57SMatthew G. Knepley 3506*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()` 35079318fe57SMatthew G. Knepley @*/ 3508d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 3509d71ae5a4SJacob Faibussowitsch { 35100a6ba040SMatthew G. Knepley PetscFunctionBegin; 35119566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 35129566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 35139566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 35149318fe57SMatthew G. Knepley PetscFunctionReturn(0); 35159318fe57SMatthew G. Knepley } 351679a015ccSMatthew G. Knepley 3517d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 3518d71ae5a4SJacob Faibussowitsch { 35199318fe57SMatthew G. Knepley DM plex; 35209318fe57SMatthew G. Knepley DMLabel label; 35219318fe57SMatthew G. Knepley PetscBool hasLabel; 35220a6ba040SMatthew G. Knepley 3523c22d3578SMatthew G. Knepley PetscFunctionBegin; 35249566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 35259318fe57SMatthew G. Knepley if (hasLabel) PetscFunctionReturn(0); 35269566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 35279566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 35289566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 35299566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 35301c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 35319566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 35329318fe57SMatthew G. Knepley PetscFunctionReturn(0); 35339318fe57SMatthew G. Knepley } 3534acdc6f61SToby Isaac 3535669647acSMatthew G. Knepley /* 3536669647acSMatthew 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. 3537669647acSMatthew G. Knepley 3538669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 3539669647acSMatthew G. Knepley */ 3540d71ae5a4SJacob 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[]) 3541d71ae5a4SJacob Faibussowitsch { 3542669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 3543669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 3544669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 3545669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 3546669647acSMatthew G. Knepley 3547669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 3548669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 3549669647acSMatthew G. Knepley } 3550669647acSMatthew G. Knepley 3551669647acSMatthew G. Knepley const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 35529318fe57SMatthew G. Knepley 3553d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 3554d71ae5a4SJacob Faibussowitsch { 35559318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 35569318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 35579318fe57SMatthew G. Knepley PetscInt dim = 2; 35589318fe57SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 3559cd7e8a5eSksagiyam PetscBool flg, flg2, fflg, bdfflg, nameflg; 35609318fe57SMatthew G. Knepley MPI_Comm comm; 3561ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3562ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3563ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 35649318fe57SMatthew G. Knepley 35659318fe57SMatthew G. Knepley PetscFunctionBegin; 35669566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 35679318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 35689566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 35699566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 35709566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 35719566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 35729566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 35739566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 35749566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 357563a3b9bcSJacob Faibussowitsch PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim); 35769566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 35779566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 35789566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 35799566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 35809566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 35819318fe57SMatthew G. Knepley 358261a622f3SMatthew G. Knepley switch (cell) { 358361a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 358461a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 358561a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 358661a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 358761a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 358861a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 3589d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 3590d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 3591d71ae5a4SJacob Faibussowitsch break; 3592d71ae5a4SJacob Faibussowitsch default: 3593d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 3594d71ae5a4SJacob Faibussowitsch break; 359561a622f3SMatthew G. Knepley } 359661a622f3SMatthew G. Knepley 35979318fe57SMatthew G. Knepley if (fflg) { 35989318fe57SMatthew G. Knepley DM dmnew; 35999318fe57SMatthew G. Knepley 36009566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew)); 36015de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 360269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 36039318fe57SMatthew G. Knepley } else if (refDomain) { 36049566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 36059318fe57SMatthew G. Knepley } else if (bdfflg) { 36069318fe57SMatthew G. Knepley DM bdm, dmnew; 36079318fe57SMatthew G. Knepley 36089566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm)); 36099566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 36109566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 36119566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 36129566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 36135de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 361469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 36159318fe57SMatthew G. Knepley } else { 36169566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 36179318fe57SMatthew G. Knepley switch (shape) { 3618669647acSMatthew G. Knepley case DM_SHAPE_BOX: 3619669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 36209318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 36219318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 36229318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 36239318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3624669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 36259318fe57SMatthew G. Knepley PetscInt i, n; 36269318fe57SMatthew G. Knepley 36279318fe57SMatthew G. Knepley n = dim; 36289318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 36299566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 36309318fe57SMatthew G. Knepley n = 3; 36319566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 363263a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 36339318fe57SMatthew G. Knepley n = 3; 36349566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 363563a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 36369318fe57SMatthew G. Knepley n = 3; 36379566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 363863a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 3639669647acSMatthew G. Knepley 3640669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 3641669647acSMatthew G. Knepley if (isAnnular) 3642669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 3643669647acSMatthew G. Knepley 36449318fe57SMatthew G. Knepley switch (cell) { 364561a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 36469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 3647d410b0cfSMatthew G. Knepley if (!interpolate) { 3648d410b0cfSMatthew G. Knepley DM udm; 3649d410b0cfSMatthew G. Knepley 36509566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 365169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3652d410b0cfSMatthew G. Knepley } 36539318fe57SMatthew G. Knepley break; 3654d71ae5a4SJacob Faibussowitsch default: 3655d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate)); 3656d71ae5a4SJacob Faibussowitsch break; 36579318fe57SMatthew G. Knepley } 3658669647acSMatthew G. Knepley if (isAnnular) { 3659669647acSMatthew G. Knepley DM cdm; 3660669647acSMatthew G. Knepley PetscDS cds; 3661669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 3662669647acSMatthew G. Knepley 3663669647acSMatthew G. Knepley // Fix coordinates for annular region 3664669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 3665669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 3666669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 3667669647acSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, NULL)); 3668669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 3669669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 3670669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 3671669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 3672669647acSMatthew G. Knepley } 36739371c9d4SSatish Balay } break; 36749371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 36759318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 36769318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 36779318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 36789318fe57SMatthew G. Knepley PetscInt i, n; 36799318fe57SMatthew G. Knepley 36809318fe57SMatthew G. Knepley n = dim + 1; 36819318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 36829566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 36839318fe57SMatthew G. Knepley n = 3; 36849566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 368563a3b9bcSJacob 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); 36869318fe57SMatthew G. Knepley n = 3; 36879566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 368863a3b9bcSJacob 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); 36899566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 36909371c9d4SSatish Balay } break; 36919371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 36929318fe57SMatthew G. Knepley PetscReal R = 1.0; 36939318fe57SMatthew G. Knepley 36949566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 36959566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 36969371c9d4SSatish Balay } break; 36979371c9d4SSatish Balay case DM_SHAPE_BALL: { 36989318fe57SMatthew G. Knepley PetscReal R = 1.0; 36999318fe57SMatthew G. Knepley 37009566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 37019566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 37029371c9d4SSatish Balay } break; 37039371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 37049318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 37059318fe57SMatthew G. Knepley PetscInt Nw = 6; 37069318fe57SMatthew G. Knepley 37079566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 37089566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 37099318fe57SMatthew G. Knepley switch (cell) { 3710d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 3711d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 3712d71ae5a4SJacob Faibussowitsch break; 3713d71ae5a4SJacob Faibussowitsch default: 3714d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt)); 3715d71ae5a4SJacob Faibussowitsch break; 37169318fe57SMatthew G. Knepley } 37179371c9d4SSatish Balay } break; 3718b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 37199371c9d4SSatish Balay case DM_SHAPE_GYROID: { 3720b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 3721b7f5c055SJed Brown PetscReal thickness = 0.; 3722b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3723b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 37241436d7faSJed Brown PetscBool tps_distribute; 37259566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 37269566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 37279566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 37289566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 37299566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 37309566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 37319566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 37329566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 37339371c9d4SSatish Balay } break; 37349371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 373505bd46c0SStefano Zampini DM dmnew; 373605bd46c0SStefano Zampini PetscReal rl = 0.0; 373705bd46c0SStefano Zampini 373805bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 373905bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 37405de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 374169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 37429371c9d4SSatish Balay } break; 3743d71ae5a4SJacob Faibussowitsch default: 3744d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 37459318fe57SMatthew G. Knepley } 37469318fe57SMatthew G. Knepley } 37479566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 374848a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 37490a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 37500a6ba040SMatthew G. Knepley } 37510a6ba040SMatthew G. Knepley 3752d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 3753d71ae5a4SJacob Faibussowitsch { 37540a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 37557f9d8d6cSVaclav Hapla PetscBool flg, flg2; 37569318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 37570a6ba040SMatthew G. Knepley 37580a6ba040SMatthew G. Knepley PetscFunctionBegin; 37590a6ba040SMatthew G. Knepley /* Handle viewing */ 37609566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 37619566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 37629566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 37639566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 3764f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 37659566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 37669566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 37679318fe57SMatthew G. Knepley /* Labeling */ 37689566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 37699566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 3770953fc75cSMatthew G. Knepley /* Point Location */ 37719566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 37720848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 37739566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 37742e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 37759566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 3776b29cfa1cSToby Isaac /* Projection behavior */ 3777d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 37789566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 3779f12cf164SMatthew G. Knepley /* Checking structure */ 3780f12cf164SMatthew G. Knepley { 37817f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 3782f12cf164SMatthew G. Knepley 37837f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 37847f9d8d6cSVaclav Hapla if (all) { 37857f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 37867f9d8d6cSVaclav Hapla } else { 37879566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 37887f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 37899566063dSJacob 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)); 37907f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 37919566063dSJacob 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)); 37927f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 37939566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 37947f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 37959566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 3796d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 37979566063dSJacob 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)); 37987f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 37997f9d8d6cSVaclav Hapla } 38009566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 38019566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 3802f12cf164SMatthew G. Knepley } 38039318fe57SMatthew G. Knepley { 38049318fe57SMatthew G. Knepley PetscReal scale = 1.0; 38054f3833eaSMatthew G. Knepley 38069566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 38079318fe57SMatthew G. Knepley if (flg) { 38089318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 38099318fe57SMatthew G. Knepley 38109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 38119566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 38129566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 38139566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 38149318fe57SMatthew G. Knepley } 38159318fe57SMatthew G. Knepley } 38169566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 381768d4fef7SMatthew G. Knepley PetscFunctionReturn(0); 381868d4fef7SMatthew G. Knepley } 381968d4fef7SMatthew G. Knepley 3820d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap) 3821d71ae5a4SJacob Faibussowitsch { 3822c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 3823c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 3824c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 3825c506a872SMatthew G. Knepley PetscBool flg; 3826c506a872SMatthew G. Knepley 3827c506a872SMatthew G. Knepley PetscFunctionBegin; 3828c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 3829c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 3830c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 3831c506a872SMatthew G. Knepley if (numOvLabels) { 3832c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 3833c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 3834c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 3835c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 3836c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 3837c506a872SMatthew G. Knepley } 3838c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 3839c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 3840c506a872SMatthew 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); 3841c506a872SMatthew G. Knepley 3842c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 3843c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 3844c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 3845c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 3846c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 3847c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 3848c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 3849c506a872SMatthew G. Knepley } 3850c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 3851c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 3852c506a872SMatthew 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); 3853c506a872SMatthew G. Knepley } 3854c506a872SMatthew G. Knepley PetscFunctionReturn(0); 3855c506a872SMatthew G. Knepley } 3856c506a872SMatthew G. Knepley 3857d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 3858d71ae5a4SJacob Faibussowitsch { 3859bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 3860bdf63967SMatthew G. Knepley char oname[256]; 3861d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 38629318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 3863e600fa54SMatthew 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; 38646bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 386568d4fef7SMatthew G. Knepley 386668d4fef7SMatthew G. Knepley PetscFunctionBegin; 3867d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 38689318fe57SMatthew G. Knepley /* Handle automatic creation */ 38699566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 38706bc1bd01Sksagiyam if (dim < 0) { 38716bc1bd01Sksagiyam PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 38726bc1bd01Sksagiyam created = PETSC_TRUE; 38736bc1bd01Sksagiyam } 38746bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 3875d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 38769566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 3877d89e6e46SMatthew G. Knepley if (flg) { 3878d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 3879d89e6e46SMatthew G. Knepley 38809566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 3881d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 3882d89e6e46SMatthew G. Knepley DM udm; 3883d89e6e46SMatthew G. Knepley 38849566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 388569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3886d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 3887d89e6e46SMatthew G. Knepley DM idm; 3888d89e6e46SMatthew G. Knepley 38899566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 389069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3891d89e6e46SMatthew G. Knepley } 3892d89e6e46SMatthew G. Knepley } 38939b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 38949566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg)); 3895ad540459SPierre Jolivet if (flg) ((DM_Plex *)dm->data)->ignoreModel = ignoreModel; 38969566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 38979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 38989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 38999566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 39009566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 39019566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 39029318fe57SMatthew G. Knepley if (flg) { 39039566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 39049566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 39059318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 39069318fe57SMatthew G. Knepley } 39079b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 39089b44eab4SMatthew G. Knepley DM rdm; 39099b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 39109b44eab4SMatthew G. Knepley 3911dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 39129566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 391369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 3914dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 391561a622f3SMatthew G. Knepley if (coordFunc && remap) { 39169566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 39179b44eab4SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 39189b44eab4SMatthew G. Knepley } 39199b44eab4SMatthew G. Knepley } 39209566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 39219318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 39229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 39239318fe57SMatthew G. Knepley if (extLayers) { 39249318fe57SMatthew G. Knepley DM edm; 39259318fe57SMatthew G. Knepley 39269566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 392769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 392848d16a33SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = NULL; 3929dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3930d410b0cfSMatthew G. Knepley extLayers = 0; 39319318fe57SMatthew G. Knepley } 3932bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 39336bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 39349566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 39356bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 39369566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 39376bc1bd01Sksagiyam if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) { 3938bdf63967SMatthew G. Knepley DM pdm; 3939bdf63967SMatthew G. Knepley IS perm; 3940bdf63967SMatthew G. Knepley 39419566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 39429566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 39439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 394469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 3945dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3946bdf63967SMatthew G. Knepley } 39479b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 39489566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 3949c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 3950dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 39519b44eab4SMatthew G. Knepley if (distribute) { 39529b44eab4SMatthew G. Knepley DM pdm = NULL; 39539b44eab4SMatthew G. Knepley PetscPartitioner part; 39549b44eab4SMatthew G. Knepley 39559566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 39569566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 39579566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm)); 395848a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 39599b44eab4SMatthew G. Knepley } 39609318fe57SMatthew G. Knepley /* Create coordinate space */ 39619318fe57SMatthew G. Knepley if (created) { 396261a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 39639318fe57SMatthew G. Knepley PetscInt degree = 1; 39646858538eSMatthew G. Knepley PetscBool flg; 39659318fe57SMatthew G. Knepley 39669566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg)); 39679566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 39689566063dSJacob Faibussowitsch if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc)); 396961a622f3SMatthew G. Knepley if (flg && !coordSpace) { 397061a622f3SMatthew G. Knepley DM cdm; 397161a622f3SMatthew G. Knepley PetscDS cds; 397261a622f3SMatthew G. Knepley PetscObject obj; 397361a622f3SMatthew G. Knepley PetscClassId id; 397461a622f3SMatthew G. Knepley 39759566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 39769566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 39779566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 39789566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 397961a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 398061a622f3SMatthew G. Knepley PetscContainer dummy; 398161a622f3SMatthew G. Knepley 39829566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 39839566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 39849566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 39859566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 39869566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 398761a622f3SMatthew G. Knepley } 398861a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 398961a622f3SMatthew G. Knepley } 39906858538eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg)); 39919566063dSJacob Faibussowitsch PetscCall(DMLocalizeCoordinates(dm)); 39929318fe57SMatthew G. Knepley } 399368d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 399461a622f3SMatthew G. Knepley remap = PETSC_TRUE; 39959566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 39969566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 39979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 39989566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 399968d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 4000acdc6f61SToby Isaac DM *dms, coarseDM; 400168d4fef7SMatthew G. Knepley 40029566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 40039566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 40049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 40059566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 400668d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 40079566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 400868d4fef7SMatthew G. Knepley if (refine == 1) { 40099566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 40109566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 401168d4fef7SMatthew G. Knepley } else { 40129566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 40139566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 40149566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 40159566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 401668d4fef7SMatthew G. Knepley } 40179566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 40189566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 401968d4fef7SMatthew G. Knepley /* Free DMs */ 402068d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 4021dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 40229566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 402368d4fef7SMatthew G. Knepley } 40249566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 402568d4fef7SMatthew G. Knepley } else { 402668d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 40279318fe57SMatthew G. Knepley DM rdm; 402851a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 402968d4fef7SMatthew G. Knepley 4030dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40319566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 403268d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 403369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 4034dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 403561a622f3SMatthew G. Knepley if (coordFunc && remap) { 40369566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 403751a74b61SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 403851a74b61SMatthew G. Knepley } 403968d4fef7SMatthew G. Knepley } 404068d4fef7SMatthew G. Knepley } 40413cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 40429566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 40439566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 4044b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 4045b653a561SMatthew G. Knepley DM *dms; 4046b653a561SMatthew G. Knepley 40479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 40489566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 4049b653a561SMatthew G. Knepley /* Free DMs */ 4050b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 4051dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 40529566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 4053b653a561SMatthew G. Knepley } 40549566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 4055b653a561SMatthew G. Knepley } else { 4056b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 40579318fe57SMatthew G. Knepley DM cdm; 40589318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 40593cf6fe12SMatthew G. Knepley 4060dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40619566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 40623cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 406369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 4064dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40659318fe57SMatthew G. Knepley if (coordFunc) { 40669566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 40679318fe57SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 40689318fe57SMatthew G. Knepley } 40693cf6fe12SMatthew G. Knepley } 4070b653a561SMatthew G. Knepley } 4071909dfd52SMatthew G. Knepley /* Handle ghost cells */ 40729566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 4073909dfd52SMatthew G. Knepley if (ghostCells) { 4074909dfd52SMatthew G. Knepley DM gdm; 4075909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 4076909dfd52SMatthew G. Knepley 4077909dfd52SMatthew G. Knepley lname[0] = '\0'; 40789566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 40799566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 408069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 4081909dfd52SMatthew G. Knepley } 40826913077dSMatthew G. Knepley /* Handle 1D order */ 40836bc1bd01Sksagiyam if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) { 40846913077dSMatthew G. Knepley DM cdm, rdm; 40856913077dSMatthew G. Knepley PetscDS cds; 40866913077dSMatthew G. Knepley PetscObject obj; 40876913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 40886913077dSMatthew G. Knepley IS perm; 40896bc1bd01Sksagiyam PetscInt Nf; 40906913077dSMatthew G. Knepley PetscBool distributed; 40916913077dSMatthew G. Knepley 40929566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 40939566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 40949566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 40959566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 40966913077dSMatthew G. Knepley if (Nf) { 40979566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 40989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 40996913077dSMatthew G. Knepley } 41006bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 41019566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 41029566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 410369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 41049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 41056913077dSMatthew G. Knepley } 41066913077dSMatthew G. Knepley } 41073cf6fe12SMatthew G. Knepley /* Handle */ 4108dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 4109d0609cedSBarry Smith PetscOptionsHeadEnd(); 41100a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 41110a6ba040SMatthew G. Knepley } 41120a6ba040SMatthew G. Knepley 4113d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 4114d71ae5a4SJacob Faibussowitsch { 4115552f7358SJed Brown PetscFunctionBegin; 41169566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 41179566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 41189566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 41199566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 41209566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 41219566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 4122552f7358SJed Brown PetscFunctionReturn(0); 4123552f7358SJed Brown } 4124552f7358SJed Brown 4125d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 4126d71ae5a4SJacob Faibussowitsch { 4127552f7358SJed Brown PetscFunctionBegin; 41289566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 41299566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 41309566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 4131552f7358SJed Brown PetscFunctionReturn(0); 4132552f7358SJed Brown } 4133552f7358SJed Brown 4134d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4135d71ae5a4SJacob Faibussowitsch { 4136793f3fe5SMatthew G. Knepley PetscInt depth, d; 4137793f3fe5SMatthew G. Knepley 4138793f3fe5SMatthew G. Knepley PetscFunctionBegin; 41399566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4140793f3fe5SMatthew G. Knepley if (depth == 1) { 41419566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 41429566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 41439566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 41449371c9d4SSatish Balay else { 41459371c9d4SSatish Balay *pStart = 0; 41469371c9d4SSatish Balay *pEnd = 0; 41479371c9d4SSatish Balay } 4148793f3fe5SMatthew G. Knepley } else { 41499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 4150793f3fe5SMatthew G. Knepley } 4151793f3fe5SMatthew G. Knepley PetscFunctionReturn(0); 4152793f3fe5SMatthew G. Knepley } 4153793f3fe5SMatthew G. Knepley 4154d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 4155d71ae5a4SJacob Faibussowitsch { 4156502a2867SDave May PetscSF sf; 41570a19bb7dSprj- PetscInt niranks, njranks, n; 41580a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 41590a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 4160502a2867SDave May 41612f356facSMatthew G. Knepley PetscFunctionBegin; 41629566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 41630a19bb7dSprj- if (!data->neighbors) { 41649566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 41659566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 41669566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 41679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 41689566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 41699566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 41700a19bb7dSprj- n = njranks + niranks; 41719566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 41720a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 41739566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 41740a19bb7dSprj- } 41750a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 41760a19bb7dSprj- if (ranks) { 41770a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 41780a19bb7dSprj- else *ranks = NULL; 41790a19bb7dSprj- } 4180502a2867SDave May PetscFunctionReturn(0); 4181502a2867SDave May } 4182502a2867SDave May 41831eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 41841eb70e55SToby Isaac 4185d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 4186d71ae5a4SJacob Faibussowitsch { 4187552f7358SJed Brown PetscFunctionBegin; 4188552f7358SJed Brown dm->ops->view = DMView_Plex; 41892c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 4190552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 419138221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 4192552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 41931bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 419466ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 4195552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 4196552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 4197184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 41980298fd71SBarry Smith dm->ops->createfieldis = NULL; 4199552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 4200f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 42010a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 4202552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 4203bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 4204bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 4205b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 42065a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 4207552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 42080a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 42090a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 4210b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 4211d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 42120298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 42130298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 42140298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 42150298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 4216552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 4217552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 42182adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 4219793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 4220552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 42210709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 42220709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 4223bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 42248c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 4225ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 42260709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 4227b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 42282a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 422928d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 42309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 42319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 42329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 42339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 42349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 42359566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 42369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 42376bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 42386bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 42399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 4240c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 4241c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 4242552f7358SJed Brown PetscFunctionReturn(0); 4243552f7358SJed Brown } 4244552f7358SJed Brown 4245d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 4246d71ae5a4SJacob Faibussowitsch { 424763a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 424863a16f15SMatthew G. Knepley 424963a16f15SMatthew G. Knepley PetscFunctionBegin; 425063a16f15SMatthew G. Knepley mesh->refct++; 425163a16f15SMatthew G. Knepley (*newdm)->data = mesh; 42529566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 42539566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 425463a16f15SMatthew G. Knepley PetscFunctionReturn(0); 425563a16f15SMatthew G. Knepley } 425663a16f15SMatthew G. Knepley 42578818961aSMatthew G Knepley /*MC 4258*a1cb98faSBarry Smith DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 42598818961aSMatthew G Knepley In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is 42608818961aSMatthew G Knepley specified by a PetscSection object. Ownership in the global representation is determined by 4261*a1cb98faSBarry Smith ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object. 42628818961aSMatthew G Knepley 4263e5893cccSMatthew G. Knepley Options Database Keys: 4264250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 4265250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 4266250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 4267250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 4268250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 4269250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 4270250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 4271ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 4272f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 4273f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 4274d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 4275f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 4276250712c9SMatthew G. Knepley . -dm_plex_check_all - Perform all shecks below 4277f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 4278f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 4279f12cf164SMatthew 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 4280f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 4281f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 4282e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 4283e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 4284e5893cccSMatthew G. Knepley 42858818961aSMatthew G Knepley Level: intermediate 42868818961aSMatthew G Knepley 4287*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection` 42888818961aSMatthew G Knepley M*/ 42898818961aSMatthew G Knepley 4290d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 4291d71ae5a4SJacob Faibussowitsch { 4292552f7358SJed Brown DM_Plex *mesh; 4293412e9a14SMatthew G. Knepley PetscInt unit; 4294552f7358SJed Brown 4295552f7358SJed Brown PetscFunctionBegin; 4296552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 42974dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 4298552f7358SJed Brown dm->data = mesh; 4299552f7358SJed Brown 4300552f7358SJed Brown mesh->refct = 1; 43019566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 43029566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 4303552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 4304552f7358SJed Brown mesh->refinementLimit = -1.0; 4305e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 43066bc1bd01Sksagiyam mesh->reorderDefault = DMPLEX_REORDER_DEFAULT_NOTSET; 43071d1f2f2aSksagiyam mesh->distributionName = NULL; 43087d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 43097d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 4310552f7358SJed Brown 43119566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 43122e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 4313d9deefdfSMatthew G. Knepley 43148865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 4315552f7358SJed Brown 4316df0420ecSMatthew G. Knepley mesh->depthState = -1; 4317ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 43186113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 4319552f7358SJed Brown 43209566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 4321552f7358SJed Brown PetscFunctionReturn(0); 4322552f7358SJed Brown } 4323552f7358SJed Brown 4324552f7358SJed Brown /*@ 4325*a1cb98faSBarry Smith DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 4326552f7358SJed Brown 4327d083f849SBarry Smith Collective 4328552f7358SJed Brown 4329552f7358SJed Brown Input Parameter: 4330*a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object 4331552f7358SJed Brown 4332552f7358SJed Brown Output Parameter: 4333*a1cb98faSBarry Smith . mesh - The `DMPLEX` object 4334552f7358SJed Brown 4335552f7358SJed Brown Level: beginner 4336552f7358SJed Brown 4337*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()` 4338552f7358SJed Brown @*/ 4339d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 4340d71ae5a4SJacob Faibussowitsch { 4341552f7358SJed Brown PetscFunctionBegin; 4342552f7358SJed Brown PetscValidPointer(mesh, 2); 43439566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 43449566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 4345552f7358SJed Brown PetscFunctionReturn(0); 4346552f7358SJed Brown } 4347552f7358SJed Brown 4348b09969d6SVaclav Hapla /*@C 4349*a1cb98faSBarry Smith DMPlexBuildFromCellListParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 4350*a1cb98faSBarry Smith 4351*a1cb98faSBarry Smith Collective on dm 4352b09969d6SVaclav Hapla 4353b09969d6SVaclav Hapla Input Parameters: 4354*a1cb98faSBarry Smith + dm - The `DM` 4355b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4356*a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 4357*a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DETERMINE` 4358b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 43595e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4360b09969d6SVaclav Hapla 4361be8c289dSNicolas Barral Output Parameters: 4362*a1cb98faSBarry Smith + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 4363be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4364b09969d6SVaclav Hapla 4365b09969d6SVaclav Hapla Level: advanced 4366b09969d6SVaclav Hapla 4367*a1cb98faSBarry Smith Notes: 4368*a1cb98faSBarry Smith Two triangles sharing a face 4369*a1cb98faSBarry Smith .vb 4370*a1cb98faSBarry Smith 4371*a1cb98faSBarry Smith 2 4372*a1cb98faSBarry Smith / | \ 4373*a1cb98faSBarry Smith / | \ 4374*a1cb98faSBarry Smith / | \ 4375*a1cb98faSBarry Smith 0 0 | 1 3 4376*a1cb98faSBarry Smith \ | / 4377*a1cb98faSBarry Smith \ | / 4378*a1cb98faSBarry Smith \ | / 4379*a1cb98faSBarry Smith 1 4380*a1cb98faSBarry Smith .ve 4381*a1cb98faSBarry Smith would have input 4382*a1cb98faSBarry Smith .vb 4383*a1cb98faSBarry Smith numCells = 2, numVertices = 4 4384*a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 4385*a1cb98faSBarry Smith .ve 4386*a1cb98faSBarry Smith which would result in the `DMPLEX` 4387*a1cb98faSBarry Smith .vb 4388*a1cb98faSBarry Smith 4389*a1cb98faSBarry Smith 4 4390*a1cb98faSBarry Smith / | \ 4391*a1cb98faSBarry Smith / | \ 4392*a1cb98faSBarry Smith / | \ 4393*a1cb98faSBarry Smith 2 0 | 1 5 4394*a1cb98faSBarry Smith \ | / 4395*a1cb98faSBarry Smith \ | / 4396*a1cb98faSBarry Smith \ | / 4397*a1cb98faSBarry Smith 3 4398*a1cb98faSBarry Smith .ve 4399*a1cb98faSBarry Smith 4400*a1cb98faSBarry Smith Vertices are implicitly numbered consecutively 0,...,NVertices. 4401*a1cb98faSBarry Smith Each rank owns a chunk of numVertices consecutive vertices. 4402*a1cb98faSBarry Smith If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 4403*a1cb98faSBarry Smith If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 4404*a1cb98faSBarry Smith If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 4405*a1cb98faSBarry Smith 4406*a1cb98faSBarry Smith The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 4407*a1cb98faSBarry Smith 4408*a1cb98faSBarry Smith Fortran Note: 4409*a1cb98faSBarry Smith Not currently supported in Fortran. 4410*a1cb98faSBarry Smith 4411*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 4412*a1cb98faSBarry Smith `PetscSF` 4413b09969d6SVaclav Hapla @*/ 4414d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved) 4415d71ae5a4SJacob Faibussowitsch { 44162464107aSksagiyam PetscSF sfPoint; 44172464107aSksagiyam PetscLayout layout; 441882fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 4419a47d0d45SMatthew G. Knepley 4420a47d0d45SMatthew G. Knepley PetscFunctionBegin; 442125b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 44229566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 442325b6865aSVaclav Hapla /* Get/check global number of vertices */ 442425b6865aSVaclav Hapla { 442525b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 442625b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 442725b6865aSVaclav Hapla 442825b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 442925b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 44309371c9d4SSatish Balay for (i = 0; i < len; i++) 44319371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 443225b6865aSVaclav Hapla ++NVerticesInCells; 44339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 443425b6865aSVaclav Hapla 443525b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 44369371c9d4SSatish Balay else 44379371c9d4SSatish 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); 443825b6865aSVaclav Hapla } 44399079aca8SVaclav Hapla /* Count locally unique vertices */ 44409079aca8SVaclav Hapla { 44419079aca8SVaclav Hapla PetscHSetI vhash; 44429079aca8SVaclav Hapla PetscInt off = 0; 44439079aca8SVaclav Hapla 44449566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 4445a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 444648a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 4447a47d0d45SMatthew G. Knepley } 44489566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 44499566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 4450ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 44519566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 44529566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 445363a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 4454a47d0d45SMatthew G. Knepley } 44559566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 4456a47d0d45SMatthew G. Knepley /* Create cones */ 44579566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 44589566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 44599566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 44609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4461a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 4462a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 4463a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 4464a47d0d45SMatthew G. Knepley PetscInt lv; 4465a47d0d45SMatthew G. Knepley 44669079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 44679079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 44689566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 446963a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 4470961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 4471a47d0d45SMatthew G. Knepley } 4472a47d0d45SMatthew G. Knepley } 44732464107aSksagiyam /* Build point sf */ 44749566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 44759566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 44769566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 44779566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 44789566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 44799566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 44809566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 44819566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 44822464107aSksagiyam if (dm->sf) { 44832464107aSksagiyam const char *prefix; 44842464107aSksagiyam 44859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 44869566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 44872464107aSksagiyam } 44889566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 44899566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 44909566063dSJacob Faibussowitsch if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF")); 4491a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 44929566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 44939566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 44949566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4495a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4496a47d0d45SMatthew G. Knepley } 4497a47d0d45SMatthew G. Knepley 4498b09969d6SVaclav Hapla /*@C 4499*a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4500*a1cb98faSBarry Smith 4501*a1cb98faSBarry Smith Collective on dm 4502b09969d6SVaclav Hapla 4503b09969d6SVaclav Hapla Input Parameters: 4504*a1cb98faSBarry Smith + dm - The `DM` 4505b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4506*a1cb98faSBarry Smith . sfVert - `PetscSF` describing complete vertex ownership 4507b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4508b09969d6SVaclav Hapla 4509b09969d6SVaclav Hapla Level: advanced 4510b09969d6SVaclav Hapla 4511*a1cb98faSBarry Smith Fortran Note: 4512b09969d6SVaclav Hapla Not currently supported in Fortran. 4513b09969d6SVaclav Hapla 4514*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 4515b09969d6SVaclav Hapla @*/ 4516d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 4517d71ae5a4SJacob Faibussowitsch { 4518a47d0d45SMatthew G. Knepley PetscSection coordSection; 4519a47d0d45SMatthew G. Knepley Vec coordinates; 4520a47d0d45SMatthew G. Knepley PetscScalar *coords; 45211edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 4522a47d0d45SMatthew G. Knepley 4523a47d0d45SMatthew G. Knepley PetscFunctionBegin; 45249566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 45259566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 45261dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 45279566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 45289566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 45291dca8a05SBarry 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); 45309566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 45319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 45329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 45339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 45341edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 45359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 45369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4537a47d0d45SMatthew G. Knepley } 45389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 45399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 45409566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 45419566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 45429566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 45439566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 45449566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 45459566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 4546a47d0d45SMatthew G. Knepley { 4547a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 4548a47d0d45SMatthew G. Knepley 4549a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 45509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype)); 45519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 455221016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 455321016a8bSBarry Smith { 455421016a8bSBarry Smith PetscScalar *svertexCoords; 455521016a8bSBarry Smith PetscInt i; 45569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 45573612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 45589566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 45599566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 45609566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 456121016a8bSBarry Smith } 456221016a8bSBarry Smith #else 45639566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 45649566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 456521016a8bSBarry Smith #endif 45669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 4567a47d0d45SMatthew G. Knepley } 45689566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 45699566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 45709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 45719566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4572a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4573a47d0d45SMatthew G. Knepley } 4574a47d0d45SMatthew G. Knepley 4575c3edce3dSSatish Balay /*@ 4576*a1cb98faSBarry Smith DMPlexCreateFromCellListParallelPetsc - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) 4577*a1cb98faSBarry Smith 4578*a1cb98faSBarry Smith Collective 4579a47d0d45SMatthew G. Knepley 4580a47d0d45SMatthew G. Knepley Input Parameters: 4581a47d0d45SMatthew G. Knepley + comm - The communicator 4582a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 4583a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 4584*a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 4585*a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DECIDE` 4586a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 4587a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 4588a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4589a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 4590a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4591a47d0d45SMatthew G. Knepley 4592d8d19677SJose E. Roman Output Parameters: 4593*a1cb98faSBarry Smith + dm - The `DM` 4594*a1cb98faSBarry Smith . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 4595be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4596a47d0d45SMatthew G. Knepley 4597b09969d6SVaclav Hapla Level: intermediate 4598a47d0d45SMatthew G. Knepley 4599*a1cb98faSBarry Smith Notes: 4600*a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 4601*a1cb98faSBarry Smith `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 4602*a1cb98faSBarry Smith 4603*a1cb98faSBarry Smith See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters. 4604*a1cb98faSBarry Smith 4605*a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 4606*a1cb98faSBarry Smith 4607*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 4608a47d0d45SMatthew G. Knepley @*/ 4609d71ae5a4SJacob 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) 4610d71ae5a4SJacob Faibussowitsch { 4611a47d0d45SMatthew G. Knepley PetscSF sfVert; 4612a47d0d45SMatthew G. Knepley 4613a47d0d45SMatthew G. Knepley PetscFunctionBegin; 46149566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 46159566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 4616a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 4617064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 46189566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 46199566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 4620a47d0d45SMatthew G. Knepley if (interpolate) { 46215fd9971aSMatthew G. Knepley DM idm; 4622a47d0d45SMatthew G. Knepley 46239566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 46249566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 4625a47d0d45SMatthew G. Knepley *dm = idm; 4626a47d0d45SMatthew G. Knepley } 46279566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 462818d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 46299566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 4630a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4631a47d0d45SMatthew G. Knepley } 4632a47d0d45SMatthew G. Knepley 4633b09969d6SVaclav Hapla /*@C 4634*a1cb98faSBarry Smith DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 4635*a1cb98faSBarry Smith 4636*a1cb98faSBarry Smith Collective on dm 46379298eaa6SMatthew G Knepley 46389298eaa6SMatthew G Knepley Input Parameters: 4639*a1cb98faSBarry Smith + dm - The `DM` 4640b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4641*a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE` 46429298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 46435e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 46449298eaa6SMatthew G Knepley 4645b09969d6SVaclav Hapla Level: advanced 46469298eaa6SMatthew G Knepley 4647b09969d6SVaclav Hapla Notes: 4648b09969d6SVaclav Hapla Two triangles sharing a face 4649*a1cb98faSBarry Smith .vb 46509298eaa6SMatthew G Knepley 4651*a1cb98faSBarry Smith 2 4652*a1cb98faSBarry Smith / | \ 4653*a1cb98faSBarry Smith / | \ 4654*a1cb98faSBarry Smith / | \ 4655*a1cb98faSBarry Smith 0 0 | 1 3 4656*a1cb98faSBarry Smith \ | / 4657*a1cb98faSBarry Smith \ | / 4658*a1cb98faSBarry Smith \ | / 4659*a1cb98faSBarry Smith 1 4660*a1cb98faSBarry Smith .ve 4661*a1cb98faSBarry Smith would have input 4662*a1cb98faSBarry Smith .vb 4663*a1cb98faSBarry Smith numCells = 2, numVertices = 4 4664*a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 4665*a1cb98faSBarry Smith .ve 4666*a1cb98faSBarry Smith which would result in the `DMPLEX` 4667*a1cb98faSBarry Smith .vb 4668*a1cb98faSBarry Smith 4669*a1cb98faSBarry Smith 4 4670*a1cb98faSBarry Smith / | \ 4671*a1cb98faSBarry Smith / | \ 4672*a1cb98faSBarry Smith / | \ 4673*a1cb98faSBarry Smith 2 0 | 1 5 4674*a1cb98faSBarry Smith \ | / 4675*a1cb98faSBarry Smith \ | / 4676*a1cb98faSBarry Smith \ | / 4677*a1cb98faSBarry Smith 3 4678*a1cb98faSBarry Smith .ve 4679*a1cb98faSBarry Smith 4680*a1cb98faSBarry Smith If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1. 468125b6865aSVaclav Hapla 4682b09969d6SVaclav Hapla Not currently supported in Fortran. 46839298eaa6SMatthew G Knepley 4684*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 4685b09969d6SVaclav Hapla @*/ 4686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 4687d71ae5a4SJacob Faibussowitsch { 4688961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 4689b09969d6SVaclav Hapla 4690b09969d6SVaclav Hapla PetscFunctionBegin; 46919566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 46929566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 469325b6865aSVaclav Hapla /* Get/check global number of vertices */ 469425b6865aSVaclav Hapla { 469525b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 469625b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 469725b6865aSVaclav Hapla 469825b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 469925b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 47009371c9d4SSatish Balay for (i = 0; i < len; i++) 47019371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 470225b6865aSVaclav Hapla ++NVerticesInCells; 470325b6865aSVaclav Hapla 470425b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 47059371c9d4SSatish Balay else 47069371c9d4SSatish 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); 470725b6865aSVaclav Hapla } 47089566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 470948a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 47109566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 47119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4712b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 4713ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 4714b09969d6SVaclav Hapla } 47159566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 47169566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 47179566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4718b09969d6SVaclav Hapla PetscFunctionReturn(0); 4719b09969d6SVaclav Hapla } 4720b09969d6SVaclav Hapla 4721b09969d6SVaclav Hapla /*@C 4722*a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4723*a1cb98faSBarry Smith 4724*a1cb98faSBarry Smith Collective on dm 4725b09969d6SVaclav Hapla 4726b09969d6SVaclav Hapla Input Parameters: 4727*a1cb98faSBarry Smith + dm - The `DM` 4728b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4729b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4730b09969d6SVaclav Hapla 4731b09969d6SVaclav Hapla Level: advanced 4732b09969d6SVaclav Hapla 4733*a1cb98faSBarry Smith Fortran Note: 4734b09969d6SVaclav Hapla Not currently supported in Fortran. 4735b09969d6SVaclav Hapla 4736*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 4737b09969d6SVaclav Hapla @*/ 4738d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 4739d71ae5a4SJacob Faibussowitsch { 4740b09969d6SVaclav Hapla PetscSection coordSection; 4741b09969d6SVaclav Hapla Vec coordinates; 4742b09969d6SVaclav Hapla DM cdm; 4743b09969d6SVaclav Hapla PetscScalar *coords; 47441edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 4745b09969d6SVaclav Hapla 4746b09969d6SVaclav Hapla PetscFunctionBegin; 47479566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 47489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 47491dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 47509566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 47519566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 47529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 47539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 47549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 47551edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 47569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 47579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4758b09969d6SVaclav Hapla } 47599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4760b09969d6SVaclav Hapla 47619566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 47629566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 47639566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 47649566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 47659566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 47661edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 4767ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 4768b09969d6SVaclav Hapla } 47699566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 47709566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 47719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 47729566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4773b09969d6SVaclav Hapla PetscFunctionReturn(0); 4774b09969d6SVaclav Hapla } 4775b09969d6SVaclav Hapla 4776b09969d6SVaclav Hapla /*@ 4777*a1cb98faSBarry Smith DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 47783df08285SMatthew G. Knepley 4779*a1cb98faSBarry Smith Collective 4780b09969d6SVaclav Hapla 4781b09969d6SVaclav Hapla Input Parameters: 4782b09969d6SVaclav Hapla + comm - The communicator 4783b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 47843df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 4785*a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0 47863df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 4787b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 47883df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0 4789b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 47903df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0 4791b09969d6SVaclav Hapla 4792b09969d6SVaclav Hapla Output Parameter: 4793*a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0 479425b6865aSVaclav Hapla 4795b09969d6SVaclav Hapla Level: intermediate 4796b09969d6SVaclav Hapla 4797*a1cb98faSBarry Smith Notes: 4798*a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`, 4799*a1cb98faSBarry Smith `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()` 4800*a1cb98faSBarry Smith 4801*a1cb98faSBarry Smith See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters. 4802*a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters. 4803*a1cb98faSBarry Smith See `DMPlexCreateFromCellListParallelPetsc()` for parallel input 4804*a1cb98faSBarry Smith 4805*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 48069298eaa6SMatthew G Knepley @*/ 4807d71ae5a4SJacob 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) 4808d71ae5a4SJacob Faibussowitsch { 48093df08285SMatthew G. Knepley PetscMPIInt rank; 48109298eaa6SMatthew G Knepley 48119298eaa6SMatthew G Knepley PetscFunctionBegin; 481228b400f6SJacob 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."); 48139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 48149566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 48159566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 48169566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 4817c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 48189566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 48199298eaa6SMatthew G Knepley if (interpolate) { 48205fd9971aSMatthew G. Knepley DM idm; 48219298eaa6SMatthew G Knepley 48229566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 48239566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 48249298eaa6SMatthew G Knepley *dm = idm; 48259298eaa6SMatthew G Knepley } 4826c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 48279566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 48289298eaa6SMatthew G Knepley PetscFunctionReturn(0); 48299298eaa6SMatthew G Knepley } 48309298eaa6SMatthew G Knepley 4831939f6067SMatthew G. Knepley /*@ 4832939f6067SMatthew 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 4833939f6067SMatthew G. Knepley 4834939f6067SMatthew G. Knepley Input Parameters: 4835c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension() 4836939f6067SMatthew G. Knepley . depth - The depth of the DAG 4837367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth 4838939f6067SMatthew G. Knepley . coneSize - The cone size of each point 4839939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 4840939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 4841367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim() 4842939f6067SMatthew G. Knepley 4843939f6067SMatthew G. Knepley Output Parameter: 4844939f6067SMatthew G. Knepley . dm - The DM 4845939f6067SMatthew G. Knepley 4846*a1cb98faSBarry Smith Note: 4847*a1cb98faSBarry Smith Two triangles sharing a face would have input 4848*a1cb98faSBarry Smith .vb 4849*a1cb98faSBarry Smith depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 4850*a1cb98faSBarry Smith cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 4851*a1cb98faSBarry Smith vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 4852*a1cb98faSBarry Smith .ve 4853939f6067SMatthew G. Knepley which would result in the DMPlex 4854*a1cb98faSBarry Smith .vb 4855*a1cb98faSBarry Smith 4 4856*a1cb98faSBarry Smith / | \ 4857*a1cb98faSBarry Smith / | \ 4858*a1cb98faSBarry Smith / | \ 4859*a1cb98faSBarry Smith 2 0 | 1 5 4860*a1cb98faSBarry Smith \ | / 4861*a1cb98faSBarry Smith \ | / 4862*a1cb98faSBarry Smith \ | / 4863*a1cb98faSBarry Smith 3 4864*a1cb98faSBarry Smith .ve 4865*a1cb98faSBarry Smith Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()` 4866939f6067SMatthew G. Knepley 4867939f6067SMatthew G. Knepley Level: advanced 4868939f6067SMatthew G. Knepley 4869*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 4870939f6067SMatthew G. Knepley @*/ 4871d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 4872d71ae5a4SJacob Faibussowitsch { 48739298eaa6SMatthew G Knepley Vec coordinates; 48749298eaa6SMatthew G Knepley PetscSection coordSection; 48759298eaa6SMatthew G Knepley PetscScalar *coords; 4876811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 48779298eaa6SMatthew G Knepley 48789298eaa6SMatthew G Knepley PetscFunctionBegin; 48799566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 48809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 488163a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 48829298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 48839566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 48849298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 48859566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 4886ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 488797e052ccSToby Isaac } 48881dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 48899566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 48909298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 48919566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 48929566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 48939298eaa6SMatthew G Knepley } 48949566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 48959566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 48969298eaa6SMatthew G Knepley /* Build coordinates */ 48979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 48989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 48999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 49009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 49019298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 49029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 49039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 49049298eaa6SMatthew G Knepley } 49059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 49069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 49079566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 49089566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 49099566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 49109566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dimEmbed)); 49119566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 49129318fe57SMatthew G. Knepley if (vertexCoords) { 49139566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 49149298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 49159298eaa6SMatthew G Knepley PetscInt off; 49169298eaa6SMatthew G Knepley 49179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 4918ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 49199298eaa6SMatthew G Knepley } 49209318fe57SMatthew G. Knepley } 49219566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 49229566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 49239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 49249298eaa6SMatthew G Knepley PetscFunctionReturn(0); 49259298eaa6SMatthew G Knepley } 49268415267dSToby Isaac 4927ca522641SMatthew G. Knepley /*@C 4928*a1cb98faSBarry Smith DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file. 4929*a1cb98faSBarry Smith 4930*a1cb98faSBarry Smith Collective 4931*a1cb98faSBarry Smith 4932*a1cb98faSBarry Smith Collective 49338ca92349SMatthew G. Knepley 49348ca92349SMatthew G. Knepley + comm - The MPI communicator 49358ca92349SMatthew G. Knepley . filename - Name of the .dat file 49368ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 49378ca92349SMatthew G. Knepley 49388ca92349SMatthew G. Knepley Output Parameter: 4939*a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 49408ca92349SMatthew G. Knepley 49418ca92349SMatthew G. Knepley Level: beginner 49428ca92349SMatthew G. Knepley 4943*a1cb98faSBarry Smith Note: 4944*a1cb98faSBarry Smith The format is the simplest possible: 4945*a1cb98faSBarry Smith .vb 4946*a1cb98faSBarry Smith Ne 4947*a1cb98faSBarry Smith v0 v1 ... vk 4948*a1cb98faSBarry Smith Nv 4949*a1cb98faSBarry Smith x y z marker 4950*a1cb98faSBarry Smith .ve 4951*a1cb98faSBarry Smith 4952*a1cb98faSBarry Smith Developer Note: 4953*a1cb98faSBarry Smith Should use a `PetscViewer` not a filename 4954*a1cb98faSBarry Smith 4955*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 49568ca92349SMatthew G. Knepley @*/ 4957d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 4958d71ae5a4SJacob Faibussowitsch { 49598ca92349SMatthew G. Knepley DMLabel marker; 49608ca92349SMatthew G. Knepley PetscViewer viewer; 49618ca92349SMatthew G. Knepley Vec coordinates; 49628ca92349SMatthew G. Knepley PetscSection coordSection; 49638ca92349SMatthew G. Knepley PetscScalar *coords; 49648ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 49658ca92349SMatthew G. Knepley PetscInt dim = 3, cdim = 3, coordSize, v, c, d; 49668ca92349SMatthew G. Knepley PetscMPIInt rank; 4967f8d5e320SMatthew G. Knepley int snum, Nv, Nc, Ncn, Nl; 49688ca92349SMatthew G. Knepley 49698ca92349SMatthew G. Knepley PetscFunctionBegin; 49709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 49719566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 49729566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 49739566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 49749566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 4975dd400576SPatrick Sanan if (rank == 0) { 49769566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING)); 4977f8d5e320SMatthew G. Knepley snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl); 497808401ef6SPierre Jolivet PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 497925ce1634SJed Brown } else { 4980f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 49818ca92349SMatthew G. Knepley } 49829566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 49839566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 49849566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 49859566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 49869566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 49878ca92349SMatthew G. Knepley /* Read topology */ 4988dd400576SPatrick Sanan if (rank == 0) { 4989f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 4990f8d5e320SMatthew G. Knepley PetscInt cone[8]; 49918ca92349SMatthew G. Knepley int vbuf[8], v; 49928ca92349SMatthew G. Knepley 49939371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 49949371c9d4SSatish Balay format[c * 3 + 0] = '%'; 49959371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 49969371c9d4SSatish Balay format[c * 3 + 2] = ' '; 49979371c9d4SSatish Balay } 4998f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 49999566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 50009566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 50018ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 50029566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 5003f8d5e320SMatthew G. Knepley switch (Ncn) { 5004d71ae5a4SJacob Faibussowitsch case 2: 5005d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 5006d71ae5a4SJacob Faibussowitsch break; 5007d71ae5a4SJacob Faibussowitsch case 3: 5008d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 5009d71ae5a4SJacob Faibussowitsch break; 5010d71ae5a4SJacob Faibussowitsch case 4: 5011d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 5012d71ae5a4SJacob Faibussowitsch break; 5013d71ae5a4SJacob Faibussowitsch case 6: 5014d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 5015d71ae5a4SJacob Faibussowitsch break; 5016d71ae5a4SJacob Faibussowitsch case 8: 5017d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 5018d71ae5a4SJacob Faibussowitsch break; 5019d71ae5a4SJacob Faibussowitsch default: 5020d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 5021f8d5e320SMatthew G. Knepley } 502208401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 5023f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 50248ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 5025f8d5e320SMatthew G. Knepley if (Ncn == 8) { 50268ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 50278ca92349SMatthew G. Knepley cone[1] = cone[3]; 50288ca92349SMatthew G. Knepley cone[3] = tmp; 50298ca92349SMatthew G. Knepley } 50309566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 50318ca92349SMatthew G. Knepley } 50328ca92349SMatthew G. Knepley } 50339566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 50349566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 50358ca92349SMatthew G. Knepley /* Read coordinates */ 50369566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 50379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 50389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 50399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 50408ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 50419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 50429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 50438ca92349SMatthew G. Knepley } 50449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 50459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 50469566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 50479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 50489566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 50499566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 50509566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 50519566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5052dd400576SPatrick Sanan if (rank == 0) { 5053f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 50548ca92349SMatthew G. Knepley double x[3]; 5055f8d5e320SMatthew G. Knepley int l, val[3]; 50568ca92349SMatthew G. Knepley 5057f8d5e320SMatthew G. Knepley if (Nl) { 50589371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 50599371c9d4SSatish Balay format[l * 3 + 0] = '%'; 50609371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 50619371c9d4SSatish Balay format[l * 3 + 2] = ' '; 50629371c9d4SSatish Balay } 5063f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 50649566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 50659566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 5066f8d5e320SMatthew G. Knepley } 50678ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 50689566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 5069f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 507008401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 5071f8d5e320SMatthew G. Knepley switch (Nl) { 5072d71ae5a4SJacob Faibussowitsch case 0: 5073d71ae5a4SJacob Faibussowitsch snum = 0; 5074d71ae5a4SJacob Faibussowitsch break; 5075d71ae5a4SJacob Faibussowitsch case 1: 5076d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 5077d71ae5a4SJacob Faibussowitsch break; 5078d71ae5a4SJacob Faibussowitsch case 2: 5079d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 5080d71ae5a4SJacob Faibussowitsch break; 5081d71ae5a4SJacob Faibussowitsch case 3: 5082d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 5083d71ae5a4SJacob Faibussowitsch break; 5084d71ae5a4SJacob Faibussowitsch default: 5085d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 5086f8d5e320SMatthew G. Knepley } 508708401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 50888ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 50899566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 50908ca92349SMatthew G. Knepley } 50918ca92349SMatthew G. Knepley } 50929566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 50939566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 50949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 50959566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 50968ca92349SMatthew G. Knepley if (interpolate) { 50978ca92349SMatthew G. Knepley DM idm; 50988ca92349SMatthew G. Knepley DMLabel bdlabel; 50998ca92349SMatthew G. Knepley 51009566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 51019566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 51028ca92349SMatthew G. Knepley *dm = idm; 51038ca92349SMatthew G. Knepley 5104f8d5e320SMatthew G. Knepley if (!Nl) { 51059566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 51069566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 51079566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 51089566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 51098ca92349SMatthew G. Knepley } 5110f8d5e320SMatthew G. Knepley } 51118ca92349SMatthew G. Knepley PetscFunctionReturn(0); 51128ca92349SMatthew G. Knepley } 51138ca92349SMatthew G. Knepley 51148ca92349SMatthew G. Knepley /*@C 5115*a1cb98faSBarry Smith DMPlexCreateFromFile - This takes a filename and produces a `DM` 5116*a1cb98faSBarry Smith 5117*a1cb98faSBarry Smith Collective 5118ca522641SMatthew G. Knepley 5119ca522641SMatthew G. Knepley Input Parameters: 5120ca522641SMatthew G. Knepley + comm - The communicator 5121ca522641SMatthew G. Knepley . filename - A file name 5122*a1cb98faSBarry Smith . plexname - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats 5123ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 5124ca522641SMatthew G. Knepley 5125ca522641SMatthew G. Knepley Output Parameter: 5126*a1cb98faSBarry Smith . dm - The `DM` 5127ca522641SMatthew G. Knepley 5128*a1cb98faSBarry Smith Options Database Key: 5129*a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5 513002ef0d99SVaclav Hapla 5131bca97951SVaclav Hapla Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g. 5132bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 5133bca97951SVaclav Hapla 5134ca522641SMatthew G. Knepley Level: beginner 5135ca522641SMatthew G. Knepley 5136*a1cb98faSBarry Smith Notes: 5137*a1cb98faSBarry Smith Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX` 5138*a1cb98faSBarry Smith meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()` 5139*a1cb98faSBarry Smith before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object. 5140*a1cb98faSBarry Smith The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally 5141*a1cb98faSBarry Smith calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats. 5142*a1cb98faSBarry Smith 5143*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 5144ca522641SMatthew G. Knepley @*/ 5145d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 5146d71ae5a4SJacob Faibussowitsch { 5147ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 5148ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 5149ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 5150ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 5151ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 5152ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 5153ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 5154ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 5155ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 5156ef3a5affSJacob Faibussowitsch const char extMed[] = ".med"; 5157ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 5158ef3a5affSJacob Faibussowitsch const char extEGADSLite[] = ".egadslite"; 5159ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 5160ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 5161ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 5162ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 5163ca522641SMatthew G. Knepley size_t len; 5164c1cad2e7SMatthew G. Knepley PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV; 5165ca522641SMatthew G. Knepley PetscMPIInt rank; 5166ca522641SMatthew G. Knepley 5167ca522641SMatthew G. Knepley PetscFunctionBegin; 51685d80c0bfSVaclav Hapla PetscValidCharPointer(filename, 2); 51690d862eaeSPierre Jolivet if (plexname) PetscValidCharPointer(plexname, 3); 5170cd7e8a5eSksagiyam PetscValidPointer(dm, 5); 51719566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 51729566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 51739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 51749566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 517528b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 5176ef3a5affSJacob Faibussowitsch 51779371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 51789371c9d4SSatish Balay do { \ 5179274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 5180274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 5181274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 5182274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 5183ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 5184ef3a5affSJacob Faibussowitsch } else { \ 5185274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 5186ef3a5affSJacob Faibussowitsch } \ 5187ef3a5affSJacob Faibussowitsch } while (0) 5188ef3a5affSJacob Faibussowitsch 5189ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 5190ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 5191ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 5192ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 5193ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 5194ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 5195ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 5196ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 5197ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 5198ef3a5affSJacob Faibussowitsch CheckExtension(extMed, isMed); 5199ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 5200ef3a5affSJacob Faibussowitsch CheckExtension(extEGADSLite, isEGADSLite); 5201ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 5202ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 5203ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 5204ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 5205ef3a5affSJacob Faibussowitsch 5206ef3a5affSJacob Faibussowitsch #undef CheckExtension 5207ef3a5affSJacob Faibussowitsch 5208de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 52099566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 5210ca522641SMatthew G. Knepley } else if (isCGNS) { 52119566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 521290c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 52139566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 52142f0bd6dcSMichael Lange } else if (isFluent) { 52159566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 5216cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 52179c48423bSVaclav Hapla PetscBool load_hdf5_xdmf = PETSC_FALSE; 5218cc2f8f65SMatthew G. Knepley PetscViewer viewer; 5219cc2f8f65SMatthew G. Knepley 522043b242b4SVaclav 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 */ 52219566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf)); 52229566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL)); 52239566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 52249566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 52259566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 52269566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 52279566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 52289566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 5229cd7e8a5eSksagiyam 52309566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 52319566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 52329566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 52339566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 52349566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 52359566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer)); 52369566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 52375fd9971aSMatthew G. Knepley 52385fd9971aSMatthew G. Knepley if (interpolate) { 52395fd9971aSMatthew G. Knepley DM idm; 52405fd9971aSMatthew G. Knepley 52419566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 52429566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 52435fd9971aSMatthew G. Knepley *dm = idm; 52445fd9971aSMatthew G. Knepley } 5245707dd687SMichael Lange } else if (isMed) { 52469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm)); 5247f2801cd6SMatthew G. Knepley } else if (isPLY) { 52489566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 5249c1cad2e7SMatthew G. Knepley } else if (isEGADSLite || isEGADS || isIGES || isSTEP) { 52509566063dSJacob Faibussowitsch if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm)); 52519566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm)); 52527bee2925SMatthew Knepley if (!interpolate) { 52537bee2925SMatthew Knepley DM udm; 52547bee2925SMatthew Knepley 52559566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 52569566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 52577bee2925SMatthew Knepley *dm = udm; 52587bee2925SMatthew Knepley } 52598ca92349SMatthew G. Knepley } else if (isCV) { 52609566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 526198921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 52629566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 52639566063dSJacob Faibussowitsch if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 52649566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 5265ca522641SMatthew G. Knepley PetscFunctionReturn(0); 5266ca522641SMatthew G. Knepley } 5267