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 1779318fe57SMatthew G. Knepley Collective 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 186db781477SPatrick Sanan .seealso: `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: 2291df5d5c5SMatthew G. Knepley + 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: 2361df5d5c5SMatthew G. Knepley . dm - The DM object 2371df5d5c5SMatthew G. Knepley 2381df5d5c5SMatthew G. Knepley Level: beginner 2391df5d5c5SMatthew G. Knepley 240db781477SPatrick Sanan .seealso: `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: 7189318fe57SMatthew G. Knepley + 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: 7269318fe57SMatthew G. Knepley . dm - The DM object 7279318fe57SMatthew G. Knepley 7289318fe57SMatthew G. Knepley Level: beginner 7299318fe57SMatthew G. Knepley 730db781477SPatrick Sanan .seealso: `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: 1300768d5fceSMatthew G. Knepley + comm - The communicator for the DM object 1301768d5fceSMatthew G. Knepley . dim - The spatial dimension 1302768d5fceSMatthew G. Knepley . 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) 1306fdbf62faSLisandro Dalcin . 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: 1310768d5fceSMatthew G. Knepley . dm - The DM object 1311768d5fceSMatthew G. Knepley 13129318fe57SMatthew G. Knepley Note: If you want to customize this mesh using options, you just need to 13139318fe57SMatthew G. Knepley $ DMCreate(comm, &dm); 13149318fe57SMatthew G. Knepley $ DMSetType(dm, DMPLEX); 13159318fe57SMatthew G. Knepley $ DMSetFromOptions(dm); 13169318fe57SMatthew G. Knepley and use the options on the DMSetFromOptions() page. 13171367e252SJed Brown 13181367e252SJed Brown Here is the numbering returned for 2 faces in each direction for tensor cells: 1319768d5fceSMatthew G. Knepley $ 10---17---11---18----12 1320768d5fceSMatthew G. Knepley $ | | | 1321768d5fceSMatthew G. Knepley $ | | | 1322768d5fceSMatthew G. Knepley $ 20 2 22 3 24 1323768d5fceSMatthew G. Knepley $ | | | 1324768d5fceSMatthew G. Knepley $ | | | 1325768d5fceSMatthew G. Knepley $ 7---15----8---16----9 1326768d5fceSMatthew G. Knepley $ | | | 1327768d5fceSMatthew G. Knepley $ | | | 1328768d5fceSMatthew G. Knepley $ 19 0 21 1 23 1329768d5fceSMatthew G. Knepley $ | | | 1330768d5fceSMatthew G. Knepley $ | | | 1331768d5fceSMatthew G. Knepley $ 4---13----5---14----6 1332768d5fceSMatthew G. Knepley 1333768d5fceSMatthew G. Knepley and for simplicial cells 1334768d5fceSMatthew G. Knepley 1335768d5fceSMatthew G. Knepley $ 14----8---15----9----16 1336768d5fceSMatthew G. Knepley $ |\ 5 |\ 7 | 1337768d5fceSMatthew G. Knepley $ | \ | \ | 1338768d5fceSMatthew G. Knepley $ 13 2 14 3 15 1339768d5fceSMatthew G. Knepley $ | 4 \ | 6 \ | 1340768d5fceSMatthew G. Knepley $ | \ | \ | 1341768d5fceSMatthew G. Knepley $ 11----6---12----7----13 1342768d5fceSMatthew G. Knepley $ |\ |\ | 1343768d5fceSMatthew G. Knepley $ | \ 1 | \ 3 | 1344768d5fceSMatthew G. Knepley $ 10 0 11 1 12 1345768d5fceSMatthew G. Knepley $ | 0 \ | 2 \ | 1346768d5fceSMatthew G. Knepley $ | \ | \ | 1347768d5fceSMatthew G. Knepley $ 8----4----9----5----10 1348768d5fceSMatthew G. Knepley 1349768d5fceSMatthew G. Knepley Level: beginner 1350768d5fceSMatthew G. Knepley 1351db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 1352768d5fceSMatthew G. Knepley @*/ 1353d71ae5a4SJacob 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) 1354d71ae5a4SJacob Faibussowitsch { 13559318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 1356fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 1357fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 1358fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1359552f7358SJed Brown 1360768d5fceSMatthew G. Knepley PetscFunctionBegin; 13619566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 13629566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 13639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 13647ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 13659318fe57SMatthew G. Knepley PetscFunctionReturn(0); 13669318fe57SMatthew G. Knepley } 1367fdbf62faSLisandro Dalcin 1368d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1369d71ae5a4SJacob Faibussowitsch { 13709318fe57SMatthew G. Knepley DM bdm, vol; 13719318fe57SMatthew G. Knepley PetscInt i; 13729318fe57SMatthew G. Knepley 13739318fe57SMatthew G. Knepley PetscFunctionBegin; 137408401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 13759566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 13769566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 13779566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 13789566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 13799566063dSJacob Faibussowitsch PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol)); 13809566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 138169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 13829318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 13839318fe57SMatthew G. Knepley Vec v; 13849318fe57SMatthew G. Knepley PetscScalar *x; 13859318fe57SMatthew G. Knepley PetscInt cDim, n; 13869318fe57SMatthew G. Knepley 13879566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 13889566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 13899566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 13909566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 13919318fe57SMatthew G. Knepley x += cDim; 13929318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 13939566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 13949566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 13959318fe57SMatthew G. Knepley } 1396552f7358SJed Brown PetscFunctionReturn(0); 1397552f7358SJed Brown } 1398552f7358SJed Brown 139900dabe28SStefano Zampini /*@ 140000dabe28SStefano Zampini DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells. 140100dabe28SStefano Zampini 1402d083f849SBarry Smith Collective 140300dabe28SStefano Zampini 140400dabe28SStefano Zampini Input Parameters: 140500dabe28SStefano Zampini + comm - The communicator for the DM object 140600dabe28SStefano Zampini . faces - Number of faces per dimension, or NULL for (1, 1, 1) 140700dabe28SStefano Zampini . lower - The lower left corner, or NULL for (0, 0, 0) 140800dabe28SStefano Zampini . upper - The upper right corner, or NULL for (1, 1, 1) 140900dabe28SStefano Zampini . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE 1410d0fcb9c2SMatthew G. Knepley . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 141100dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 141200dabe28SStefano Zampini 141300dabe28SStefano Zampini Output Parameter: 141400dabe28SStefano Zampini . dm - The DM object 141500dabe28SStefano Zampini 141600dabe28SStefano Zampini Level: beginner 141700dabe28SStefano Zampini 1418db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 141900dabe28SStefano Zampini @*/ 1420d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 1421d71ae5a4SJacob Faibussowitsch { 14229318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 142300dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 142400dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 142500dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 142600dabe28SStefano Zampini 142700dabe28SStefano Zampini PetscFunctionBegin; 14289566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 14299566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 14309566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 1431d410b0cfSMatthew G. Knepley if (!interpolate) { 1432d410b0cfSMatthew G. Knepley DM udm; 143300dabe28SStefano Zampini 14349566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 143569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 143600dabe28SStefano Zampini } 14377ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 143800dabe28SStefano Zampini PetscFunctionReturn(0); 143900dabe28SStefano Zampini } 144000dabe28SStefano Zampini 1441a9074c1eSMatthew G. Knepley /*@C 1442a9074c1eSMatthew G. Knepley DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database. 1443a9074c1eSMatthew G. Knepley 1444d083f849SBarry Smith Logically Collective on dm 1445a9074c1eSMatthew G. Knepley 1446a9074c1eSMatthew G. Knepley Input Parameters: 1447a9074c1eSMatthew G. Knepley + dm - the DM context 1448a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 1449a9074c1eSMatthew G. Knepley 1450a9074c1eSMatthew G. Knepley Notes: 1451a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 1452a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 1453a9074c1eSMatthew G. Knepley 1454a9074c1eSMatthew G. Knepley Level: advanced 1455a9074c1eSMatthew G. Knepley 1456db781477SPatrick Sanan .seealso: `SNESSetFromOptions()` 1457a9074c1eSMatthew G. Knepley @*/ 1458d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 1459d71ae5a4SJacob Faibussowitsch { 1460a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1461a9074c1eSMatthew G. Knepley 1462a9074c1eSMatthew G. Knepley PetscFunctionBegin; 1463a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14649566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 14659566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 1466a9074c1eSMatthew G. Knepley PetscFunctionReturn(0); 1467a9074c1eSMatthew G. Knepley } 1468a9074c1eSMatthew G. Knepley 14699318fe57SMatthew G. Knepley /* Remap geometry to cylinder 147061a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 147161a622f3SMatthew G. Knepley 14729318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 14739318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 14749318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 14750510c589SMatthew G. Knepley 14769318fe57SMatthew G. Knepley phi = arctan(y/x) 14779318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 14789318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 14790510c589SMatthew G. Knepley 14809318fe57SMatthew G. Knepley so we remap them using 14810510c589SMatthew G. Knepley 14829318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 14839318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 14840510c589SMatthew G. Knepley 14859318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 14869318fe57SMatthew G. Knepley */ 1487d71ae5a4SJacob 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[]) 1488d71ae5a4SJacob Faibussowitsch { 14899318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 14909318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 149122cc497dSMatthew G. Knepley 14929318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 14939318fe57SMatthew G. Knepley f0[0] = u[0]; 14949318fe57SMatthew G. Knepley f0[1] = u[1]; 14959318fe57SMatthew G. Knepley } else { 14969318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 14970510c589SMatthew G. Knepley 14989318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 14999318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 15009318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 15019318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 15029318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 15039318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 15049318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 15059318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 15069318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 15079318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 15089318fe57SMatthew G. Knepley } else { 15099318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 15109318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 15119318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 15129318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 15139318fe57SMatthew G. Knepley } 15149318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 15159318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 15169318fe57SMatthew G. Knepley } 15179318fe57SMatthew G. Knepley f0[2] = u[2]; 15189318fe57SMatthew G. Knepley } 15190510c589SMatthew G. Knepley 1520d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ) 1521d71ae5a4SJacob Faibussowitsch { 15220510c589SMatthew G. Knepley const PetscInt dim = 3; 15239318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 1524d8c47e87SMatthew G. Knepley PetscMPIInt rank; 15250510c589SMatthew G. Knepley 15260510c589SMatthew G. Knepley PetscFunctionBegin; 15279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15289566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 15290510c589SMatthew G. Knepley /* Create topology */ 15300510c589SMatthew G. Knepley { 15310510c589SMatthew G. Knepley PetscInt cone[8], c; 15320510c589SMatthew G. Knepley 1533dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 1534dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 1535006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 1536ae8bcbbbSMatthew G. Knepley numCells *= 3; 1537dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 1538006a8963SMatthew G. Knepley } 15399566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 15409566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 15419566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 1542dd400576SPatrick Sanan if (rank == 0) { 1543006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 15449371c9d4SSatish Balay cone[0] = 15; 15459371c9d4SSatish Balay cone[1] = 18; 15469371c9d4SSatish Balay cone[2] = 17; 15479371c9d4SSatish Balay cone[3] = 16; 15489371c9d4SSatish Balay cone[4] = 31; 15499371c9d4SSatish Balay cone[5] = 32; 15509371c9d4SSatish Balay cone[6] = 33; 15519371c9d4SSatish Balay cone[7] = 34; 15529566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 15539371c9d4SSatish Balay cone[0] = 16; 15549371c9d4SSatish Balay cone[1] = 17; 15559371c9d4SSatish Balay cone[2] = 24; 15569371c9d4SSatish Balay cone[3] = 23; 15579371c9d4SSatish Balay cone[4] = 32; 15589371c9d4SSatish Balay cone[5] = 36; 15599371c9d4SSatish Balay cone[6] = 37; 15609371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 15619566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 15629371c9d4SSatish Balay cone[0] = 18; 15639371c9d4SSatish Balay cone[1] = 27; 15649371c9d4SSatish Balay cone[2] = 24; 15659371c9d4SSatish Balay cone[3] = 17; 15669371c9d4SSatish Balay cone[4] = 34; 15679371c9d4SSatish Balay cone[5] = 33; 15689371c9d4SSatish Balay cone[6] = 37; 15699371c9d4SSatish Balay cone[7] = 38; 15709566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 15719371c9d4SSatish Balay cone[0] = 29; 15729371c9d4SSatish Balay cone[1] = 27; 15739371c9d4SSatish Balay cone[2] = 18; 15749371c9d4SSatish Balay cone[3] = 15; 15759371c9d4SSatish Balay cone[4] = 35; 15769371c9d4SSatish Balay cone[5] = 31; 15779371c9d4SSatish Balay cone[6] = 34; 15789371c9d4SSatish Balay cone[7] = 38; 15799566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 15809371c9d4SSatish Balay cone[0] = 29; 15819371c9d4SSatish Balay cone[1] = 15; 15829371c9d4SSatish Balay cone[2] = 16; 15839371c9d4SSatish Balay cone[3] = 23; 15849371c9d4SSatish Balay cone[4] = 35; 15859371c9d4SSatish Balay cone[5] = 36; 15869371c9d4SSatish Balay cone[6] = 32; 15879371c9d4SSatish Balay cone[7] = 31; 15889566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1589006a8963SMatthew G. Knepley 15909371c9d4SSatish Balay cone[0] = 31; 15919371c9d4SSatish Balay cone[1] = 34; 15929371c9d4SSatish Balay cone[2] = 33; 15939371c9d4SSatish Balay cone[3] = 32; 15949371c9d4SSatish Balay cone[4] = 19; 15959371c9d4SSatish Balay cone[5] = 22; 15969371c9d4SSatish Balay cone[6] = 21; 15979371c9d4SSatish Balay cone[7] = 20; 15989566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 15999371c9d4SSatish Balay cone[0] = 32; 16009371c9d4SSatish Balay cone[1] = 33; 16019371c9d4SSatish Balay cone[2] = 37; 16029371c9d4SSatish Balay cone[3] = 36; 16039371c9d4SSatish Balay cone[4] = 22; 16049371c9d4SSatish Balay cone[5] = 25; 16059371c9d4SSatish Balay cone[6] = 26; 16069371c9d4SSatish Balay cone[7] = 21; 16079566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 16089371c9d4SSatish Balay cone[0] = 34; 16099371c9d4SSatish Balay cone[1] = 38; 16109371c9d4SSatish Balay cone[2] = 37; 16119371c9d4SSatish Balay cone[3] = 33; 16129371c9d4SSatish Balay cone[4] = 20; 16139371c9d4SSatish Balay cone[5] = 21; 16149371c9d4SSatish Balay cone[6] = 26; 16159371c9d4SSatish Balay cone[7] = 28; 16169566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 16179371c9d4SSatish Balay cone[0] = 35; 16189371c9d4SSatish Balay cone[1] = 38; 16199371c9d4SSatish Balay cone[2] = 34; 16209371c9d4SSatish Balay cone[3] = 31; 16219371c9d4SSatish Balay cone[4] = 30; 16229371c9d4SSatish Balay cone[5] = 19; 16239371c9d4SSatish Balay cone[6] = 20; 16249371c9d4SSatish Balay cone[7] = 28; 16259566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 16269371c9d4SSatish Balay cone[0] = 35; 16279371c9d4SSatish Balay cone[1] = 31; 16289371c9d4SSatish Balay cone[2] = 32; 16299371c9d4SSatish Balay cone[3] = 36; 16309371c9d4SSatish Balay cone[4] = 30; 16319371c9d4SSatish Balay cone[5] = 25; 16329371c9d4SSatish Balay cone[6] = 22; 16339371c9d4SSatish Balay cone[7] = 19; 16349566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 1635ae8bcbbbSMatthew G. Knepley 16369371c9d4SSatish Balay cone[0] = 19; 16379371c9d4SSatish Balay cone[1] = 20; 16389371c9d4SSatish Balay cone[2] = 21; 16399371c9d4SSatish Balay cone[3] = 22; 16409371c9d4SSatish Balay cone[4] = 15; 16419371c9d4SSatish Balay cone[5] = 16; 16429371c9d4SSatish Balay cone[6] = 17; 16439371c9d4SSatish Balay cone[7] = 18; 16449566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 16459371c9d4SSatish Balay cone[0] = 22; 16469371c9d4SSatish Balay cone[1] = 21; 16479371c9d4SSatish Balay cone[2] = 26; 16489371c9d4SSatish Balay cone[3] = 25; 16499371c9d4SSatish Balay cone[4] = 16; 16509371c9d4SSatish Balay cone[5] = 23; 16519371c9d4SSatish Balay cone[6] = 24; 16529371c9d4SSatish Balay cone[7] = 17; 16539566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 16549371c9d4SSatish Balay cone[0] = 20; 16559371c9d4SSatish Balay cone[1] = 28; 16569371c9d4SSatish Balay cone[2] = 26; 16579371c9d4SSatish Balay cone[3] = 21; 16589371c9d4SSatish Balay cone[4] = 18; 16599371c9d4SSatish Balay cone[5] = 17; 16609371c9d4SSatish Balay cone[6] = 24; 16619371c9d4SSatish Balay cone[7] = 27; 16629566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 16639371c9d4SSatish Balay cone[0] = 30; 16649371c9d4SSatish Balay cone[1] = 28; 16659371c9d4SSatish Balay cone[2] = 20; 16669371c9d4SSatish Balay cone[3] = 19; 16679371c9d4SSatish Balay cone[4] = 29; 16689371c9d4SSatish Balay cone[5] = 15; 16699371c9d4SSatish Balay cone[6] = 18; 16709371c9d4SSatish Balay cone[7] = 27; 16719566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 16729371c9d4SSatish Balay cone[0] = 30; 16739371c9d4SSatish Balay cone[1] = 19; 16749371c9d4SSatish Balay cone[2] = 22; 16759371c9d4SSatish Balay cone[3] = 25; 16769371c9d4SSatish Balay cone[4] = 29; 16779371c9d4SSatish Balay cone[5] = 23; 16789371c9d4SSatish Balay cone[6] = 16; 16799371c9d4SSatish Balay cone[7] = 15; 16809566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 1681006a8963SMatthew G. Knepley } else { 16829371c9d4SSatish Balay cone[0] = 5; 16839371c9d4SSatish Balay cone[1] = 8; 16849371c9d4SSatish Balay cone[2] = 7; 16859371c9d4SSatish Balay cone[3] = 6; 16869371c9d4SSatish Balay cone[4] = 9; 16879371c9d4SSatish Balay cone[5] = 12; 16889371c9d4SSatish Balay cone[6] = 11; 16899371c9d4SSatish Balay cone[7] = 10; 16909566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 16919371c9d4SSatish Balay cone[0] = 6; 16929371c9d4SSatish Balay cone[1] = 7; 16939371c9d4SSatish Balay cone[2] = 14; 16949371c9d4SSatish Balay cone[3] = 13; 16959371c9d4SSatish Balay cone[4] = 12; 16969371c9d4SSatish Balay cone[5] = 15; 16979371c9d4SSatish Balay cone[6] = 16; 16989371c9d4SSatish Balay cone[7] = 11; 16999566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 17009371c9d4SSatish Balay cone[0] = 8; 17019371c9d4SSatish Balay cone[1] = 17; 17029371c9d4SSatish Balay cone[2] = 14; 17039371c9d4SSatish Balay cone[3] = 7; 17049371c9d4SSatish Balay cone[4] = 10; 17059371c9d4SSatish Balay cone[5] = 11; 17069371c9d4SSatish Balay cone[6] = 16; 17079371c9d4SSatish Balay cone[7] = 18; 17089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 17099371c9d4SSatish Balay cone[0] = 19; 17109371c9d4SSatish Balay cone[1] = 17; 17119371c9d4SSatish Balay cone[2] = 8; 17129371c9d4SSatish Balay cone[3] = 5; 17139371c9d4SSatish Balay cone[4] = 20; 17149371c9d4SSatish Balay cone[5] = 9; 17159371c9d4SSatish Balay cone[6] = 10; 17169371c9d4SSatish Balay cone[7] = 18; 17179566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 17189371c9d4SSatish Balay cone[0] = 19; 17199371c9d4SSatish Balay cone[1] = 5; 17209371c9d4SSatish Balay cone[2] = 6; 17219371c9d4SSatish Balay cone[3] = 13; 17229371c9d4SSatish Balay cone[4] = 20; 17239371c9d4SSatish Balay cone[5] = 15; 17249371c9d4SSatish Balay cone[6] = 12; 17259371c9d4SSatish Balay cone[7] = 9; 17269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1727006a8963SMatthew G. Knepley } 1728d8c47e87SMatthew G. Knepley } 17299566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 17309566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 17310510c589SMatthew G. Knepley } 1732dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 17330510c589SMatthew G. Knepley { 17340510c589SMatthew G. Knepley Vec coordinates; 17350510c589SMatthew G. Knepley PetscSection coordSection; 17360510c589SMatthew G. Knepley PetscScalar *coords; 17370510c589SMatthew G. Knepley PetscInt coordSize, v; 17380510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 17390510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 17400510c589SMatthew G. Knepley 17410510c589SMatthew G. Knepley /* Build coordinates */ 17429566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 17439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 17449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 17459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 17460510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 17479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 17489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 17490510c589SMatthew G. Knepley } 17509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 17519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 17529566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 17539566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 17549566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 17559566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 17569566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 17579566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 1758dd400576SPatrick Sanan if (rank == 0) { 17599371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 17609371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 17619371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 17629371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 17639371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 17649371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 17659371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 17669371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 17679371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 17689371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 17699371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 17709371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 17719371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 17729371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 17739371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 17749371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 17759371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 17769371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 17779371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 17789371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 17799371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 17809371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 17819371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 17829371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 17839371c9d4SSatish Balay coords[8 * dim + 0] = dis; 17849371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 17859371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 17869371c9d4SSatish Balay coords[9 * dim + 0] = dis; 17879371c9d4SSatish Balay coords[9 * dim + 1] = dis; 17889371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 17899371c9d4SSatish Balay coords[10 * dim + 0] = dis; 17909371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 17919371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 17929371c9d4SSatish Balay coords[11 * dim + 0] = dis; 17939371c9d4SSatish Balay coords[11 * dim + 1] = dis; 17949371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 17959371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 17969371c9d4SSatish Balay coords[12 * dim + 1] = dis; 17979371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 17989371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 17999371c9d4SSatish Balay coords[13 * dim + 1] = dis; 18009371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 18019371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 18029371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 18039371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 18049371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 18059371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 18069371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 1807ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 18089371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 18099371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 18109371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 18119371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 18129371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 18139371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 18149371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 18159371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 18169371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 18179371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 18189371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 18199371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 18209371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 18219371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 18229371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 18239371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 18249371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 18259371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 18269371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 18279371c9d4SSatish Balay coords[22 * dim + 1] = dis; 18289371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 18299371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 18309371c9d4SSatish Balay coords[23 * dim + 1] = dis; 18319371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 1832ae8bcbbbSMatthew G. Knepley } 1833d8c47e87SMatthew G. Knepley } 18349566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 18359566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 18369566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 18370510c589SMatthew G. Knepley } 1838006a8963SMatthew G. Knepley /* Create periodicity */ 1839006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 18406858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 18416858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1842006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 1843ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 18446858538eSMatthew G. Knepley PetscInt numZCells = 3; 1845006a8963SMatthew G. Knepley 18466858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 18476858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 18484fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1849006a8963SMatthew G. Knepley } 1850dbc1dc17SMatthew G. Knepley { 18519318fe57SMatthew G. Knepley DM cdm; 18529318fe57SMatthew G. Knepley PetscDS cds; 18539318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 1854dbc1dc17SMatthew G. Knepley 18559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder)); 18569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18579566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 18589566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 1859dbc1dc17SMatthew G. Knepley } 18609318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 18619566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 18620510c589SMatthew G. Knepley PetscFunctionReturn(0); 18630510c589SMatthew G. Knepley } 18640510c589SMatthew G. Knepley 186524119c2aSMatthew G. Knepley /*@ 18669318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 186724119c2aSMatthew G. Knepley 1868d083f849SBarry Smith Collective 186924119c2aSMatthew G. Knepley 187024119c2aSMatthew G. Knepley Input Parameters: 187124119c2aSMatthew G. Knepley + comm - The communicator for the DM object 18729318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction 187324119c2aSMatthew G. Knepley 187424119c2aSMatthew G. Knepley Output Parameter: 187524119c2aSMatthew G. Knepley . dm - The DM object 187624119c2aSMatthew G. Knepley 18779318fe57SMatthew G. Knepley Note: 18789318fe57SMatthew G. Knepley Here is the output numbering looking from the bottom of the cylinder: 18799318fe57SMatthew G. Knepley $ 17-----14 18809318fe57SMatthew G. Knepley $ | | 18819318fe57SMatthew G. Knepley $ | 2 | 18829318fe57SMatthew G. Knepley $ | | 18839318fe57SMatthew G. Knepley $ 17-----8-----7-----14 18849318fe57SMatthew G. Knepley $ | | | | 18859318fe57SMatthew G. Knepley $ | 3 | 0 | 1 | 18869318fe57SMatthew G. Knepley $ | | | | 18879318fe57SMatthew G. Knepley $ 19-----5-----6-----13 18889318fe57SMatthew G. Knepley $ | | 18899318fe57SMatthew G. Knepley $ | 4 | 18909318fe57SMatthew G. Knepley $ | | 18919318fe57SMatthew G. Knepley $ 19-----13 18929318fe57SMatthew G. Knepley $ 18939318fe57SMatthew G. Knepley $ and up through the top 18949318fe57SMatthew G. Knepley $ 18959318fe57SMatthew G. Knepley $ 18-----16 18969318fe57SMatthew G. Knepley $ | | 18979318fe57SMatthew G. Knepley $ | 2 | 18989318fe57SMatthew G. Knepley $ | | 18999318fe57SMatthew G. Knepley $ 18----10----11-----16 19009318fe57SMatthew G. Knepley $ | | | | 19019318fe57SMatthew G. Knepley $ | 3 | 0 | 1 | 19029318fe57SMatthew G. Knepley $ | | | | 19039318fe57SMatthew G. Knepley $ 20-----9----12-----15 19049318fe57SMatthew G. Knepley $ | | 19059318fe57SMatthew G. Knepley $ | 4 | 19069318fe57SMatthew G. Knepley $ | | 19079318fe57SMatthew G. Knepley $ 20-----15 19089318fe57SMatthew G. Knepley 190924119c2aSMatthew G. Knepley Level: beginner 191024119c2aSMatthew G. Knepley 1911db781477SPatrick Sanan .seealso: `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 191224119c2aSMatthew G. Knepley @*/ 1913d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm) 1914d71ae5a4SJacob Faibussowitsch { 19159318fe57SMatthew G. Knepley PetscFunctionBegin; 19169318fe57SMatthew G. Knepley PetscValidPointer(dm, 3); 19179566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 19189566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 19199566063dSJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ)); 19209318fe57SMatthew G. Knepley PetscFunctionReturn(0); 19219318fe57SMatthew G. Knepley } 19229318fe57SMatthew G. Knepley 1923d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 1924d71ae5a4SJacob Faibussowitsch { 192524119c2aSMatthew G. Knepley const PetscInt dim = 3; 1926412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 19279fe9f049SMatthew G. Knepley PetscMPIInt rank; 192824119c2aSMatthew G. Knepley 192924119c2aSMatthew G. Knepley PetscFunctionBegin; 193063a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 19319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 19329566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 1933412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 19349566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 193524119c2aSMatthew G. Knepley /* Create topology */ 193624119c2aSMatthew G. Knepley { 193724119c2aSMatthew G. Knepley PetscInt cone[6], c; 193824119c2aSMatthew G. Knepley 1939dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 1940dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 19419566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 19429566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 19439566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 194424119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 19459371c9d4SSatish Balay cone[0] = c + n * 1; 19469371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 19479371c9d4SSatish Balay cone[2] = 0 + 3 * n; 19489371c9d4SSatish Balay cone[3] = c + n * 2; 19499371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 19509371c9d4SSatish Balay cone[5] = 1 + 3 * n; 19519566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 19529566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 195324119c2aSMatthew G. Knepley } 19549566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 19559566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 195624119c2aSMatthew G. Knepley } 195748a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 195824119c2aSMatthew G. Knepley /* Create cylinder geometry */ 195924119c2aSMatthew G. Knepley { 196024119c2aSMatthew G. Knepley Vec coordinates; 196124119c2aSMatthew G. Knepley PetscSection coordSection; 196224119c2aSMatthew G. Knepley PetscScalar *coords; 1963412e9a14SMatthew G. Knepley PetscInt coordSize, c; 196424119c2aSMatthew G. Knepley 196524119c2aSMatthew G. Knepley /* Build coordinates */ 19669566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 19679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 19689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 19699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 197024119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 19719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 19729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 197324119c2aSMatthew G. Knepley } 19749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 19759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 19769566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 19779566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 19789566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 19799566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 19809566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 19819566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 198224119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 19839371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 19849371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 19859371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 19869371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 19879371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 19889371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 198924119c2aSMatthew G. Knepley } 1990dd400576SPatrick Sanan if (rank == 0) { 19919371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 19929371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 19939371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 19949371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 19959371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 19969371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 19979fe9f049SMatthew G. Knepley } 19989566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 19999566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 20009566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 200124119c2aSMatthew G. Knepley } 20029318fe57SMatthew G. Knepley /* Interpolate */ 20039566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 20049318fe57SMatthew G. Knepley PetscFunctionReturn(0); 20059318fe57SMatthew G. Knepley } 20069318fe57SMatthew G. Knepley 20079318fe57SMatthew G. Knepley /*@ 20089318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 20099318fe57SMatthew G. Knepley 20109318fe57SMatthew G. Knepley Collective 20119318fe57SMatthew G. Knepley 20129318fe57SMatthew G. Knepley Input Parameters: 20139318fe57SMatthew G. Knepley + comm - The communicator for the DM object 20149318fe57SMatthew G. Knepley . n - The number of wedges around the origin 20159318fe57SMatthew G. Knepley - interpolate - Create edges and faces 20169318fe57SMatthew G. Knepley 20179318fe57SMatthew G. Knepley Output Parameter: 20189318fe57SMatthew G. Knepley . dm - The DM object 20199318fe57SMatthew G. Knepley 20209318fe57SMatthew G. Knepley Level: beginner 20219318fe57SMatthew G. Knepley 2022db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 20239318fe57SMatthew G. Knepley @*/ 2024d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 2025d71ae5a4SJacob Faibussowitsch { 20269318fe57SMatthew G. Knepley PetscFunctionBegin; 20279318fe57SMatthew G. Knepley PetscValidPointer(dm, 4); 20289566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 20299566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 20309566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 203124119c2aSMatthew G. Knepley PetscFunctionReturn(0); 203224119c2aSMatthew G. Knepley } 203324119c2aSMatthew G. Knepley 2034d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2035d71ae5a4SJacob Faibussowitsch { 203665a81367SMatthew G. Knepley PetscReal prod = 0.0; 203765a81367SMatthew G. Knepley PetscInt i; 203865a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 203965a81367SMatthew G. Knepley return PetscSqrtReal(prod); 204065a81367SMatthew G. Knepley } 2041d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(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 += x[i] * y[i]; 204665a81367SMatthew G. Knepley return prod; 204765a81367SMatthew G. Knepley } 204865a81367SMatthew G. Knepley 204951a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 2050d71ae5a4SJacob 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[]) 2051d71ae5a4SJacob Faibussowitsch { 205251a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 205351a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 205451a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 205551a74b61SMatthew G. Knepley 205651a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 205751a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 205851a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 205951a74b61SMatthew G. Knepley } 206051a74b61SMatthew G. Knepley 2061d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 2062d71ae5a4SJacob Faibussowitsch { 206365a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 206465a81367SMatthew G. Knepley PetscSection coordSection; 206565a81367SMatthew G. Knepley Vec coordinates; 206665a81367SMatthew G. Knepley PetscScalar *coords; 206765a81367SMatthew G. Knepley PetscReal *coordsIn; 2068064cae4fSPierre Jolivet PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, c, e; 206965a81367SMatthew G. Knepley PetscMPIInt rank; 207065a81367SMatthew G. Knepley 207165a81367SMatthew G. Knepley PetscFunctionBegin; 20729318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 20739566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 20749566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 20759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 207665a81367SMatthew G. Knepley switch (dim) { 207765a81367SMatthew G. Knepley case 2: 207865a81367SMatthew G. Knepley if (simplex) { 207951a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 208051a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 208165a81367SMatthew G. Knepley const PetscInt degree = 5; 208251a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 208365a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 208465a81367SMatthew G. Knepley PetscInt cone[3]; 208565a81367SMatthew G. Knepley PetscInt *graph, p, i, j, k; 208665a81367SMatthew G. Knepley 20879371c9d4SSatish Balay vertex[0] *= R / radius; 20889371c9d4SSatish Balay vertex[1] *= R / radius; 20899371c9d4SSatish Balay vertex[2] *= R / radius; 2090dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 2091dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 209265a81367SMatthew G. Knepley firstVertex = numCells; 209351a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 209465a81367SMatthew G. Knepley 209565a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 209665a81367SMatthew G. Knepley 209765a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 209851a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 209965a81367SMatthew G. Knepley */ 210065a81367SMatthew G. Knepley /* Construct vertices */ 21019566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2102dd400576SPatrick Sanan if (rank == 0) { 210365a81367SMatthew G. Knepley for (p = 0, i = 0; p < embedDim; ++p) { 210465a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 210565a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 210665a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 210765a81367SMatthew G. Knepley ++i; 210865a81367SMatthew G. Knepley } 210965a81367SMatthew G. Knepley } 211065a81367SMatthew G. Knepley } 211145da822fSValeria Barra } 211265a81367SMatthew G. Knepley /* Construct graph */ 21139566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 211465a81367SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 211565a81367SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 21169371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 21179371c9d4SSatish Balay graph[i * numVerts + j] = 1; 21189371c9d4SSatish Balay ++k; 21199371c9d4SSatish Balay } 212065a81367SMatthew G. Knepley } 212163a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 212265a81367SMatthew G. Knepley } 212365a81367SMatthew G. Knepley /* Build Topology */ 21249566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 212548a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 21269566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 212765a81367SMatthew G. Knepley /* Cells */ 212865a81367SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 212965a81367SMatthew G. Knepley for (j = 0; j < i; ++j) { 213065a81367SMatthew G. Knepley for (k = 0; k < j; ++k) { 213165a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 21329371c9d4SSatish Balay cone[0] = firstVertex + i; 21339371c9d4SSatish Balay cone[1] = firstVertex + j; 21349371c9d4SSatish Balay cone[2] = firstVertex + k; 213565a81367SMatthew G. Knepley /* Check orientation */ 213665a81367SMatthew G. Knepley { 21379371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 21389371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 21399371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 21409371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 21419371c9d4SSatish Balay }; 214265a81367SMatthew G. Knepley PetscReal normal[3]; 214365a81367SMatthew G. Knepley PetscInt e, f; 214465a81367SMatthew G. Knepley 214565a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 214665a81367SMatthew G. Knepley normal[d] = 0.0; 214765a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2148ad540459SPierre 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]); 214965a81367SMatthew G. Knepley } 215065a81367SMatthew G. Knepley } 21519371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 21529371c9d4SSatish Balay PetscInt tmp = cone[1]; 21539371c9d4SSatish Balay cone[1] = cone[2]; 21549371c9d4SSatish Balay cone[2] = tmp; 215565a81367SMatthew G. Knepley } 215665a81367SMatthew G. Knepley } 21579566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 215865a81367SMatthew G. Knepley } 215965a81367SMatthew G. Knepley } 216065a81367SMatthew G. Knepley } 216165a81367SMatthew G. Knepley } 21629566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 21639566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 21649566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 216565a81367SMatthew G. Knepley } else { 21662829fed8SMatthew G. Knepley /* 21672829fed8SMatthew G. Knepley 12-21--13 21682829fed8SMatthew G. Knepley | | 21692829fed8SMatthew G. Knepley 25 4 24 21702829fed8SMatthew G. Knepley | | 21712829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 21722829fed8SMatthew G. Knepley | | | | 21732829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 21742829fed8SMatthew G. Knepley | | | | 21752829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 21762829fed8SMatthew G. Knepley | | 21772829fed8SMatthew G. Knepley 20 1 19 21782829fed8SMatthew G. Knepley | | 21792829fed8SMatthew G. Knepley 10-18--11 21802829fed8SMatthew G. Knepley | | 21812829fed8SMatthew G. Knepley 23 2 22 21822829fed8SMatthew G. Knepley | | 21832829fed8SMatthew G. Knepley 12-21--13 21842829fed8SMatthew G. Knepley */ 21852829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 21862829fed8SMatthew G. Knepley 2187dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 2188dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 2189dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 219065a81367SMatthew G. Knepley firstVertex = numCells; 219165a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 21922829fed8SMatthew G. Knepley /* Build Topology */ 21939566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 219448a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 219548a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 21969566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2197dd400576SPatrick Sanan if (rank == 0) { 21982829fed8SMatthew G. Knepley /* Cell 0 */ 21999371c9d4SSatish Balay cone[0] = 14; 22009371c9d4SSatish Balay cone[1] = 15; 22019371c9d4SSatish Balay cone[2] = 16; 22029371c9d4SSatish Balay cone[3] = 17; 22039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 22049371c9d4SSatish Balay ornt[0] = 0; 22059371c9d4SSatish Balay ornt[1] = 0; 22069371c9d4SSatish Balay ornt[2] = 0; 22079371c9d4SSatish Balay ornt[3] = 0; 22089566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 22092829fed8SMatthew G. Knepley /* Cell 1 */ 22109371c9d4SSatish Balay cone[0] = 18; 22119371c9d4SSatish Balay cone[1] = 19; 22129371c9d4SSatish Balay cone[2] = 14; 22139371c9d4SSatish Balay cone[3] = 20; 22149566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 22159371c9d4SSatish Balay ornt[0] = 0; 22169371c9d4SSatish Balay ornt[1] = 0; 22179371c9d4SSatish Balay ornt[2] = -1; 22189371c9d4SSatish Balay ornt[3] = 0; 22199566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 22202829fed8SMatthew G. Knepley /* Cell 2 */ 22219371c9d4SSatish Balay cone[0] = 21; 22229371c9d4SSatish Balay cone[1] = 22; 22239371c9d4SSatish Balay cone[2] = 18; 22249371c9d4SSatish Balay cone[3] = 23; 22259566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 22269371c9d4SSatish Balay ornt[0] = 0; 22279371c9d4SSatish Balay ornt[1] = 0; 22289371c9d4SSatish Balay ornt[2] = -1; 22299371c9d4SSatish Balay ornt[3] = 0; 22309566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 22312829fed8SMatthew G. Knepley /* Cell 3 */ 22329371c9d4SSatish Balay cone[0] = 19; 22339371c9d4SSatish Balay cone[1] = 22; 22349371c9d4SSatish Balay cone[2] = 24; 22359371c9d4SSatish Balay cone[3] = 15; 22369566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 22379371c9d4SSatish Balay ornt[0] = -1; 22389371c9d4SSatish Balay ornt[1] = -1; 22399371c9d4SSatish Balay ornt[2] = 0; 22409371c9d4SSatish Balay ornt[3] = -1; 22419566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 22422829fed8SMatthew G. Knepley /* Cell 4 */ 22439371c9d4SSatish Balay cone[0] = 16; 22449371c9d4SSatish Balay cone[1] = 24; 22459371c9d4SSatish Balay cone[2] = 21; 22469371c9d4SSatish Balay cone[3] = 25; 22479566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 22489371c9d4SSatish Balay ornt[0] = -1; 22499371c9d4SSatish Balay ornt[1] = -1; 22509371c9d4SSatish Balay ornt[2] = -1; 22519371c9d4SSatish Balay ornt[3] = 0; 22529566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 22532829fed8SMatthew G. Knepley /* Cell 5 */ 22549371c9d4SSatish Balay cone[0] = 20; 22559371c9d4SSatish Balay cone[1] = 17; 22569371c9d4SSatish Balay cone[2] = 25; 22579371c9d4SSatish Balay cone[3] = 23; 22589566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 22599371c9d4SSatish Balay ornt[0] = -1; 22609371c9d4SSatish Balay ornt[1] = -1; 22619371c9d4SSatish Balay ornt[2] = -1; 22629371c9d4SSatish Balay ornt[3] = -1; 22639566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 22642829fed8SMatthew G. Knepley /* Edges */ 22659371c9d4SSatish Balay cone[0] = 6; 22669371c9d4SSatish Balay cone[1] = 7; 22679566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 22689371c9d4SSatish Balay cone[0] = 7; 22699371c9d4SSatish Balay cone[1] = 8; 22709566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 22719371c9d4SSatish Balay cone[0] = 8; 22729371c9d4SSatish Balay cone[1] = 9; 22739566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 22749371c9d4SSatish Balay cone[0] = 9; 22759371c9d4SSatish Balay cone[1] = 6; 22769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 22779371c9d4SSatish Balay cone[0] = 10; 22789371c9d4SSatish Balay cone[1] = 11; 22799566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 22809371c9d4SSatish Balay cone[0] = 11; 22819371c9d4SSatish Balay cone[1] = 7; 22829566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 22839371c9d4SSatish Balay cone[0] = 6; 22849371c9d4SSatish Balay cone[1] = 10; 22859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 22869371c9d4SSatish Balay cone[0] = 12; 22879371c9d4SSatish Balay cone[1] = 13; 22889566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 22899371c9d4SSatish Balay cone[0] = 13; 22909371c9d4SSatish Balay cone[1] = 11; 22919566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 22929371c9d4SSatish Balay cone[0] = 10; 22939371c9d4SSatish Balay cone[1] = 12; 22949566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 22959371c9d4SSatish Balay cone[0] = 13; 22969371c9d4SSatish Balay cone[1] = 8; 22979566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 22989371c9d4SSatish Balay cone[0] = 12; 22999371c9d4SSatish Balay cone[1] = 9; 23009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 230145da822fSValeria Barra } 23029566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 23039566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 23042829fed8SMatthew G. Knepley /* Build coordinates */ 23059566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2306dd400576SPatrick Sanan if (rank == 0) { 23079371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 23089371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 23099371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 23109371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 23119371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 23129371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 23139371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 23149371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 23159371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 23169371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 23179371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 23189371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 23199371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 23209371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 23219371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 23229371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 23239371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 23249371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 23259371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 23269371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 23279371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 23289371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 23299371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 23309371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 233165a81367SMatthew G. Knepley } 233245da822fSValeria Barra } 233365a81367SMatthew G. Knepley break; 233465a81367SMatthew G. Knepley case 3: 2335116ded15SMatthew G. Knepley if (simplex) { 2336116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 233751a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 233851a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 233951a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 2340116ded15SMatthew G. Knepley const PetscInt degree = 12; 2341116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 23429371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 23439371c9d4SSatish Balay {0, 1, 2, 3}, 23449371c9d4SSatish Balay {0, 2, 3, 1}, 23459371c9d4SSatish Balay {0, 3, 1, 2}, 23469371c9d4SSatish Balay {1, 0, 3, 2}, 23479371c9d4SSatish Balay {1, 2, 0, 3}, 23489371c9d4SSatish Balay {1, 3, 2, 0}, 23499371c9d4SSatish Balay {2, 0, 1, 3}, 23509371c9d4SSatish Balay {2, 1, 3, 0}, 23519371c9d4SSatish Balay {2, 3, 0, 1}, 23529371c9d4SSatish Balay {3, 0, 2, 1}, 23539371c9d4SSatish Balay {3, 1, 0, 2}, 23549371c9d4SSatish Balay {3, 2, 1, 0} 23559371c9d4SSatish Balay }; 2356116ded15SMatthew G. Knepley PetscInt cone[4]; 2357116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 2358116ded15SMatthew G. Knepley 23599371c9d4SSatish Balay vertexA[0] *= R; 23609371c9d4SSatish Balay vertexA[1] *= R; 23619371c9d4SSatish Balay vertexA[2] *= R; 23629371c9d4SSatish Balay vertexA[3] *= R; 23639371c9d4SSatish Balay vertexB[0] *= R; 23649371c9d4SSatish Balay vertexB[1] *= R; 23659371c9d4SSatish Balay vertexB[2] *= R; 23669371c9d4SSatish Balay vertexB[3] *= R; 23679371c9d4SSatish Balay vertexC[0] *= R; 23689371c9d4SSatish Balay vertexC[1] *= R; 23699371c9d4SSatish Balay vertexC[2] *= R; 23709371c9d4SSatish Balay vertexC[3] *= R; 2371dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 2372dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 2373116ded15SMatthew G. Knepley firstVertex = numCells; 2374116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 2375116ded15SMatthew G. Knepley 2376116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 2377116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 2378116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 2379116ded15SMatthew G. Knepley 2380116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 23816333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 2382116ded15SMatthew G. Knepley 2383116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 2384116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 2385116ded15SMatthew G. Knepley */ 2386116ded15SMatthew G. Knepley /* Construct vertices */ 23879566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2388116ded15SMatthew G. Knepley i = 0; 2389dd400576SPatrick Sanan if (rank == 0) { 2390116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2391116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2392116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2393116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 2394116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 2395116ded15SMatthew G. Knepley ++i; 2396116ded15SMatthew G. Knepley } 2397116ded15SMatthew G. Knepley } 2398116ded15SMatthew G. Knepley } 2399116ded15SMatthew G. Knepley } 2400116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 2401116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 2402116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2403116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 2404116ded15SMatthew G. Knepley ++i; 2405116ded15SMatthew G. Knepley } 2406116ded15SMatthew G. Knepley } 2407116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 2408116ded15SMatthew G. Knepley s[3] = 1; 2409116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2410116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2411116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2412116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 2413116ded15SMatthew G. Knepley ++i; 2414116ded15SMatthew G. Knepley } 2415116ded15SMatthew G. Knepley } 2416116ded15SMatthew G. Knepley } 2417116ded15SMatthew G. Knepley } 241845da822fSValeria Barra } 241963a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 2420116ded15SMatthew G. Knepley /* Construct graph */ 24219566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 2422116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 2423116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 24249371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 24259371c9d4SSatish Balay graph[i * numVerts + j] = 1; 24269371c9d4SSatish Balay ++k; 24279371c9d4SSatish Balay } 2428116ded15SMatthew G. Knepley } 242963a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 2430116ded15SMatthew G. Knepley } 2431116ded15SMatthew G. Knepley /* Build Topology */ 24329566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 243348a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 24349566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2435116ded15SMatthew G. Knepley /* Cells */ 2436dd400576SPatrick Sanan if (rank == 0) { 2437116ded15SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 2438116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 2439116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 2440116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 24419371c9d4SSatish 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]) { 24429371c9d4SSatish Balay cone[0] = firstVertex + i; 24439371c9d4SSatish Balay cone[1] = firstVertex + j; 24449371c9d4SSatish Balay cone[2] = firstVertex + k; 24459371c9d4SSatish Balay cone[3] = firstVertex + l; 2446116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 2447116ded15SMatthew G. Knepley { 24489371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 24499371c9d4SSatish 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}}}, 2450116ded15SMatthew G. Knepley 24519371c9d4SSatish 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}}}, 2452116ded15SMatthew G. Knepley 24539371c9d4SSatish 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}}}, 2454116ded15SMatthew G. Knepley 24559371c9d4SSatish 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}} } 24569371c9d4SSatish Balay }; 2457116ded15SMatthew G. Knepley PetscReal normal[4]; 2458116ded15SMatthew G. Knepley PetscInt e, f, g; 2459116ded15SMatthew G. Knepley 2460116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 2461116ded15SMatthew G. Knepley normal[d] = 0.0; 2462116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2463116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 2464116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 2465116ded15SMatthew 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]); 2466116ded15SMatthew G. Knepley } 2467116ded15SMatthew G. Knepley } 2468116ded15SMatthew G. Knepley } 2469116ded15SMatthew G. Knepley } 24709371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 24719371c9d4SSatish Balay PetscInt tmp = cone[1]; 24729371c9d4SSatish Balay cone[1] = cone[2]; 24739371c9d4SSatish Balay cone[2] = tmp; 24749371c9d4SSatish Balay } 2475116ded15SMatthew G. Knepley } 24769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 2477116ded15SMatthew G. Knepley } 2478116ded15SMatthew G. Knepley } 2479116ded15SMatthew G. Knepley } 2480116ded15SMatthew G. Knepley } 2481116ded15SMatthew G. Knepley } 248245da822fSValeria Barra } 24839566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 24849566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 24859566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 2486116ded15SMatthew G. Knepley } 2487f4d061e9SPierre Jolivet break; 2488d71ae5a4SJacob Faibussowitsch default: 2489d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 249065a81367SMatthew G. Knepley } 249165a81367SMatthew G. Knepley /* Create coordinates */ 24929566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 24939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 24949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 24959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 24962829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 24979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 24989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 24992829fed8SMatthew G. Knepley } 25009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 25019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 25029566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 25039566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 25049566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 25059566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 25069566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 25079566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 25089371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 2509ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 25109566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 25119566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 25129566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 25139566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 251451a74b61SMatthew G. Knepley { 251551a74b61SMatthew G. Knepley DM cdm; 251651a74b61SMatthew G. Knepley PetscDS cds; 25179318fe57SMatthew G. Knepley PetscScalar c = R; 251851a74b61SMatthew G. Knepley 25199566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere)); 25209566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 25219566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 25229566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 252351a74b61SMatthew G. Knepley } 25249318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 25259566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 25269318fe57SMatthew G. Knepley PetscFunctionReturn(0); 25279318fe57SMatthew G. Knepley } 25289318fe57SMatthew G. Knepley 2529b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 2530b7f5c055SJed Brown 2531b7f5c055SJed Brown /* 2532b7f5c055SJed Brown The Schwarz P implicit surface is 2533b7f5c055SJed Brown 2534b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 2535b7f5c055SJed Brown */ 2536d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2537d71ae5a4SJacob Faibussowitsch { 2538b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 2539b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 2540b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 2541b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2542b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 2543ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 2544b7f5c055SJed Brown } 2545b7f5c055SJed Brown } 2546b7f5c055SJed Brown 25474663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 2548d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 2549d71ae5a4SJacob Faibussowitsch { 2550ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 25514663dae6SJed Brown return 0; 25524663dae6SJed Brown } 25534663dae6SJed Brown 2554b7f5c055SJed Brown /* 2555b7f5c055SJed Brown The Gyroid implicit surface is 2556b7f5c055SJed Brown 2557b7f5c055SJed 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) 2558b7f5c055SJed Brown 2559b7f5c055SJed Brown */ 2560d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2561d71ae5a4SJacob Faibussowitsch { 2562b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 2563b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 2564b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 2565b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 2566b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 2567b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 2568b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 2569b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2570b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2571b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 2572b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2573b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2574b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 2575b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2576b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2577b7f5c055SJed Brown } 2578b7f5c055SJed Brown 25794663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 2580d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 2581d71ae5a4SJacob Faibussowitsch { 25824663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 25834663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 25844663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 25854663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 25864663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 25874663dae6SJed Brown return 0; 25884663dae6SJed Brown } 25894663dae6SJed Brown 2590b7f5c055SJed Brown /* 2591b7f5c055SJed Brown We wish to solve 2592b7f5c055SJed Brown 2593b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 2594b7f5c055SJed Brown 2595b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 2596b7f5c055SJed 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 2597b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 2598b7f5c055SJed Brown 2599b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 2600b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 2601b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 2602b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 2603b7f5c055SJed Brown Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries. 2604b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 2605b7f5c055SJed Brown 2606b7f5c055SJed Brown f(y) = 0 1 equation 2607b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 2608b7f5c055SJed Brown 2609b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 2610b7f5c055SJed Brown */ 2611d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 2612d71ae5a4SJacob Faibussowitsch { 2613b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 2614b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 26152f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 26169371c9d4SSatish Balay PetscReal n_y[3][3] = { 26179371c9d4SSatish Balay {0, 0, 0}, 26189371c9d4SSatish Balay {0, 0, 0}, 26199371c9d4SSatish Balay {0, 0, 0} 26209371c9d4SSatish Balay }; 2621b7f5c055SJed Brown 2622b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 2623b7f5c055SJed Brown 2624b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 2625b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2626ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 2627b7f5c055SJed Brown 2628b7f5c055SJed Brown // Define the Householder reflector 2629b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 2630b7f5c055SJed Brown n[0] += norm * sign; 2631b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 2632b7f5c055SJed Brown 2633b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2634b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 2635b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 2636b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 2637b7f5c055SJed Brown 2638b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2639b7f5c055SJed Brown n[i] /= norm; 2640b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2641b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 2642b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 2643b7f5c055SJed Brown } 2644b7f5c055SJed Brown } 2645b7f5c055SJed Brown 2646b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 2647b7f5c055SJed 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]; 2648b7f5c055SJed Brown 2649b7f5c055SJed Brown res[0] = f; 2650b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 2651b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 2652b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 2653b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2654b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 2655b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 2656b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 2657b7f5c055SJed Brown } 2658b7f5c055SJed Brown } 2659b7f5c055SJed Brown 2660b7f5c055SJed Brown /* 2661b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 2662b7f5c055SJed Brown */ 2663d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 2664d71ae5a4SJacob Faibussowitsch { 2665b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 2666b7f5c055SJed Brown 2667b7f5c055SJed Brown PetscFunctionBegin; 2668b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 2669b7f5c055SJed Brown PetscScalar res[3], J[9]; 2670b7f5c055SJed Brown PetscReal resnorm; 2671b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 2672b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 2673b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 267463a3b9bcSJacob 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]))); 2675b7f5c055SJed Brown } 2676b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 2677b7f5c055SJed Brown 2678b7f5c055SJed Brown // Take the Newton step 26799566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 2680b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 2681b7f5c055SJed Brown } 2682b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 2683b7f5c055SJed Brown PetscFunctionReturn(0); 2684b7f5c055SJed Brown } 2685b7f5c055SJed Brown 2686b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 2687b7f5c055SJed Brown 2688d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 2689d71ae5a4SJacob Faibussowitsch { 2690b7f5c055SJed Brown PetscMPIInt rank; 2691b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 2692b7f5c055SJed Brown PetscInt(*edges)[2] = NULL, *edgeSets = NULL; 2693b7f5c055SJed Brown PetscInt *cells_flat = NULL; 2694b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 2695b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 26964663dae6SJed Brown PetscSimplePointFunc normalFunc = NULL; 2697b7f5c055SJed Brown DMLabel label; 2698b7f5c055SJed Brown 2699b7f5c055SJed Brown PetscFunctionBegin; 27009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 270163a3b9bcSJacob 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); 2702b7f5c055SJed Brown switch (tpstype) { 2703b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 2704b7f5c055SJed 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"); 2705c5853193SPierre Jolivet if (rank == 0) { 2706b7f5c055SJed Brown PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 2707b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 2708b7f5c055SJed Brown PetscReal L = 1; 2709b7f5c055SJed Brown 2710b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 2711b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 2712b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 2713b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 2714b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 2715b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 27169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 27179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 27189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 27199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 2720b7f5c055SJed Brown // x-normal pipes 2721b7f5c055SJed Brown vcount = 0; 2722b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 2723b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2724b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2725b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2726b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 2727b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2728b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2729b7f5c055SJed Brown } 2730b7f5c055SJed Brown } 2731b7f5c055SJed Brown } 2732b7f5c055SJed Brown } 2733b7f5c055SJed Brown // y-normal pipes 2734b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2735b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 2736b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2737b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2738b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2739b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 2740b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2741b7f5c055SJed Brown } 2742b7f5c055SJed Brown } 2743b7f5c055SJed Brown } 2744b7f5c055SJed Brown } 2745b7f5c055SJed Brown // z-normal pipes 2746b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2747b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2748b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 2749b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2750b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2751b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2752b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 2753b7f5c055SJed Brown } 2754b7f5c055SJed Brown } 2755b7f5c055SJed Brown } 2756b7f5c055SJed Brown } 2757b7f5c055SJed Brown // junctions 2758b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2759b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2760b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2761b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 2762b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 2763b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 2764b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 2765b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 2766b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 2767b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 2768b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 2769b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 2770b7f5c055SJed Brown } 2771b7f5c055SJed Brown } 2772b7f5c055SJed Brown } 2773b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 2774b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 2775b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 2776b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 2777b7f5c055SJed Brown }; 2778b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 27799371c9d4SSatish 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}; 2780b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 27819371c9d4SSatish 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}; 2782b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 2783b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 2784b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 2785b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 2786b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 2787b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 2788b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 2789b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 2790b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 2791b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 2792b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 2793b7f5c055SJed Brown if (ijk[dir] == 0) { 2794b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 2795b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 2796b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 2797b7f5c055SJed Brown numEdges++; 2798b7f5c055SJed Brown } 2799b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 2800b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 2801b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 2802b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 2803b7f5c055SJed Brown numEdges++; 2804b7f5c055SJed Brown } 2805b7f5c055SJed Brown } 2806b7f5c055SJed Brown } 2807b7f5c055SJed Brown } 2808b7f5c055SJed Brown } 2809b7f5c055SJed Brown } 281063a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 2811b7f5c055SJed Brown numFaces = 24 * Njunctions; 2812b7f5c055SJed Brown cells_flat = cells[0][0][0]; 2813b7f5c055SJed Brown } 2814b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 28154663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 2816b7f5c055SJed Brown break; 2817b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 2818c5853193SPierre Jolivet if (rank == 0) { 2819b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 2820b7f5c055SJed Brown // 2821b7f5c055SJed 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) 2822b7f5c055SJed Brown // 2823b7f5c055SJed Brown // on the cell [0,2]^3. 2824b7f5c055SJed Brown // 2825b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 2826b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 2827b7f5c055SJed Brown // like a boomerang: 2828b7f5c055SJed Brown // 2829b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 2830b7f5c055SJed Brown // ----- ------- ------- ------- // 2831b7f5c055SJed Brown // // 2832b7f5c055SJed Brown // + + + + + + + \ + // 2833b7f5c055SJed Brown // \ / \ // 2834b7f5c055SJed Brown // \ `-_ _-' / } // 2835b7f5c055SJed Brown // *-_ `-' _-' / // 2836b7f5c055SJed Brown // + `-+ + + +-' + + / + // 2837b7f5c055SJed Brown // // 2838b7f5c055SJed Brown // // 2839b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 2840b7f5c055SJed Brown // ----- ------- ------- ------- // 2841b7f5c055SJed Brown // // 2842b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 2843b7f5c055SJed Brown // `-_ _-_ _-` / // 2844b7f5c055SJed Brown // \ _-' `-_ / { // 2845b7f5c055SJed Brown // \ / \ // 2846b7f5c055SJed Brown // + + + + + + + \ + // 2847b7f5c055SJed Brown // 2848b7f5c055SJed Brown // 2849b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 2850b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 2851b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 2852b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 2853b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 2854b7f5c055SJed Brown // 2855b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 2856b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 2857b7f5c055SJed Brown // 2858b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 2859b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 2860b7f5c055SJed Brown 2861b7f5c055SJed Brown PetscInt facesPerBlock = 64; 2862b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 2863b7f5c055SJed Brown PetscInt extentPlus[3]; 2864b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 28659371c9d4SSatish 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; 28669371c9d4SSatish Balay const PetscInt pattern[64][4] = { 28679371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 2868b7f5c055SJed Brown /* layer 0 */ 28699371c9d4SSatish Balay {A, C, K, G }, 28709371c9d4SSatish Balay {C, B, II, K }, 28719371c9d4SSatish Balay {D, A, H, L }, 28729371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 28739371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 28749371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 28759371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 28769371c9d4SSatish Balay {B, F, M, II }, 2877b7f5c055SJed Brown /* layer 1 */ 28789371c9d4SSatish Balay {G, K, Q, O }, 28799371c9d4SSatish Balay {K, II, P, Q }, 28809371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 28819371c9d4SSatish Balay {J, L, R, P }, 28829371c9d4SSatish Balay {N, J, P, S }, 28839371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 28849371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 28859371c9d4SSatish Balay {II, M, T, P }, 2886b7f5c055SJed Brown /* layer 2 */ 28879371c9d4SSatish Balay {O, Q, Y, U }, 28889371c9d4SSatish Balay {Q, P, W, Y }, 28899371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 28909371c9d4SSatish Balay {P, R, Ap, W }, 28919371c9d4SSatish Balay {S, P, X, Bp }, 28929371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 28939371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 28949371c9d4SSatish Balay {P, T, Z, X }, 2895b7f5c055SJed Brown /* layer 3 */ 28969371c9d4SSatish Balay {U, Y, Ep, Dp }, 28979371c9d4SSatish Balay {Y, W, Cp, Ep }, 28989371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 28999371c9d4SSatish Balay {W, Ap, Gp, Cp }, 29009371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 29019371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 29029371c9d4SSatish Balay {Z, V, Dp, Hp }, 29039371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 2904b7f5c055SJed Brown /* layer 4 */ 29059371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 29069371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 29079371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 29089371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 29099371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 29109371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 29119371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 29129371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 2913b7f5c055SJed Brown /* layer 5 */ 29149371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 29159371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 29169371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 29179371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 29189371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 29199371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 29209371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 29219371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 2922b7f5c055SJed Brown /* layer 6 */ 29239371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 29249371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 29259371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 29269371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 29279371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 29289371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 29299371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 29309371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 2931b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 29329371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 29339371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 29349371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 29359371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 29369371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 29379371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 29389371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 29399371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 2940b7f5c055SJed Brown }; 2941b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 29429371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 2943bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 2944bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 2945bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 2946bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 2947bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 2948bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 2949b7f5c055SJed Brown 2950bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 2951bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 2952bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 2953bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 2954bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 2955bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 2956bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 2957bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 2958b7f5c055SJed Brown 2959bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 2960bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 2961bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 2962bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 2963bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 2964bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 2965b7f5c055SJed Brown 2966bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 2967bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 2968bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 2969bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 2970bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 2971bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 2972bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 2973bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 2974b7f5c055SJed Brown 2975bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 2976bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 2977bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 2978bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 2979bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 2980bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 2981b7f5c055SJed Brown 2982bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 2983bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 2984bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 2985bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 2986bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 2987bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 2988bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 2989bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 2990b7f5c055SJed Brown 2991bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 2992bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 2993bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 2994bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 2995bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 2996bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 2997b7f5c055SJed Brown 2998bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 2999bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 3000bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 3001bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 3002bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 3003bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 3004bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 3005bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 3006b7f5c055SJed Brown }; 3007b7f5c055SJed Brown PetscInt(*cells)[64][4] = NULL; 3008b7f5c055SJed Brown PetscBool *seen; 3009b7f5c055SJed Brown PetscInt *vertToTrueVert; 3010b7f5c055SJed Brown PetscInt count; 3011b7f5c055SJed Brown 3012b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 3013b7f5c055SJed Brown numBlocks = 1; 3014b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 3015b7f5c055SJed Brown numBlocksPlus = 1; 3016b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 3017b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 30189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 30199566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 3020b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3021b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3022b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3023b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3024b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 3025b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 3026b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 3027b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 3028b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 3029b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 3030b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 3031b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 3032b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 3033b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 3034b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 3035b7f5c055SJed Brown 3036b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 3037b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 3038b7f5c055SJed Brown } 3039b7f5c055SJed Brown } 3040b7f5c055SJed Brown } 3041b7f5c055SJed Brown } 3042b7f5c055SJed Brown } 30439371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 30449371c9d4SSatish Balay if (seen[i]) numVertices++; 3045b7f5c055SJed Brown count = 0; 30469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 30479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 3048b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 3049b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 3050b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 3051b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 3052b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 3053b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 3054b7f5c055SJed Brown 3055b7f5c055SJed Brown if (seen[vIdx]) { 3056b7f5c055SJed Brown PetscInt thisVert; 3057b7f5c055SJed Brown 3058b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 3059b7f5c055SJed Brown 3060b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 3061b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 3062b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 3063b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 3064b7f5c055SJed Brown } 3065b7f5c055SJed Brown } 3066b7f5c055SJed Brown } 3067b7f5c055SJed Brown } 3068b7f5c055SJed Brown } 3069b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 3070b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3071ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 3072b7f5c055SJed Brown } 3073b7f5c055SJed Brown } 30749566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 30759566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 3076b7f5c055SJed Brown cells_flat = cells[0][0]; 3077b7f5c055SJed Brown numEdges = 0; 3078b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 3079b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3080b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3081b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3082b7f5c055SJed Brown 3083b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3084b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 3085b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 3086b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 3087b7f5c055SJed Brown } 3088b7f5c055SJed Brown } 3089b7f5c055SJed Brown } 3090b7f5c055SJed Brown } 30919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 30929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 3093b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 3094b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3095b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3096b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3097b7f5c055SJed Brown 3098b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3099b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 3100b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 3101b7f5c055SJed Brown edges[edge][0] = ev[0]; 3102b7f5c055SJed Brown edges[edge][1] = ev[1]; 3103b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 3104b7f5c055SJed Brown } 3105b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 3106b7f5c055SJed Brown edges[edge][0] = ev[0]; 3107b7f5c055SJed Brown edges[edge][1] = ev[1]; 3108b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 3109b7f5c055SJed Brown } 3110b7f5c055SJed Brown } 3111b7f5c055SJed Brown } 3112b7f5c055SJed Brown } 3113b7f5c055SJed Brown } 3114b7f5c055SJed Brown } 3115b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 31164663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 3117b7f5c055SJed Brown break; 3118b7f5c055SJed Brown } 3119b7f5c055SJed Brown 31209566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 3121c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 31229566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 31239566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 3124b7f5c055SJed Brown { 3125b7f5c055SJed Brown DM idm; 31269566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 312769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3128b7f5c055SJed Brown } 3129c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 31309566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 31319566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 3132b7f5c055SJed Brown 31339566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 31349566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 3135b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 3136b7f5c055SJed Brown PetscInt njoin; 3137b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 31389566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 313963a3b9bcSJacob 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]); 31409566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 31419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 3142b7f5c055SJed Brown } 31439566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 31449566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 31451436d7faSJed Brown if (tps_distribute) { 31461436d7faSJed Brown DM pdm = NULL; 31471436d7faSJed Brown PetscPartitioner part; 31481436d7faSJed Brown 31499566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 31509566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 31519566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 315248a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 31531436d7faSJed Brown // Do not auto-distribute again 31549566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 31551436d7faSJed Brown } 3156b7f5c055SJed Brown 31579566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 3158b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 3159b7f5c055SJed Brown PetscInt m; 3160b7f5c055SJed Brown DM dmf; 3161b7f5c055SJed Brown Vec X; 3162b7f5c055SJed Brown PetscScalar *x; 31639566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 316469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 3165b7f5c055SJed Brown 31669566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 31679566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 31689566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 316948a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 31709566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 3171b7f5c055SJed Brown } 3172b7f5c055SJed Brown 3173b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 31749566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 31759566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 3176b7f5c055SJed Brown 3177b7f5c055SJed Brown if (thickness > 0) { 31784663dae6SJed Brown DM edm, cdm, ecdm; 31794663dae6SJed Brown DMPlexTransform tr; 31804663dae6SJed Brown const char *prefix; 31814663dae6SJed Brown PetscOptions options; 31824663dae6SJed Brown // Code from DMPlexExtrude 31834663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 31844663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 31854663dae6SJed Brown PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE)); 31864663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 31874663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 31884663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 31894663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 31904663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 31914663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 31924663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 31934663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 31944663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 31954663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 31964663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 31974663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 31984663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 31994663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 32004663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 32014663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 32024663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 32034663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 32044663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 32054663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 32064663dae6SJed Brown if (edm) { 32074663dae6SJed Brown ((DM_Plex *)edm->data)->printFEM = ((DM_Plex *)dm->data)->printFEM; 32084663dae6SJed Brown ((DM_Plex *)edm->data)->printL2 = ((DM_Plex *)dm->data)->printL2; 3209f5867de0SMatthew G. Knepley ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate; 32104663dae6SJed Brown } 321169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 3212b7f5c055SJed Brown } 3213b7f5c055SJed Brown PetscFunctionReturn(0); 3214b7f5c055SJed Brown } 3215b7f5c055SJed Brown 3216b7f5c055SJed Brown /*@ 3217b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 3218b7f5c055SJed Brown 3219b7f5c055SJed Brown Collective 3220b7f5c055SJed Brown 3221b7f5c055SJed Brown Input Parameters: 3222b7f5c055SJed Brown + comm - The communicator for the DM object 3223b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 3224b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 3225b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic 32261436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 3227817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 32281436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 3229817da375SSatish Balay - thickness - Thickness in normal direction 3230b7f5c055SJed Brown 3231b7f5c055SJed Brown Output Parameter: 3232b7f5c055SJed Brown . dm - The DM object 3233b7f5c055SJed Brown 3234b7f5c055SJed Brown Notes: 3235b7f5c055SJed 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. 3236b7f5c055SJed Brown https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries. 3237b7f5c055SJed 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. 3238b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 3239b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 3240b7f5c055SJed Brown This projection could readily be extended to related surfaces. 3241b7f5c055SJed Brown 3242b7f5c055SJed Brown The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z). 3243b7f5c055SJed Brown When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). Use DMPlexLabelComplete() to propagate to coarse-level vertices. 3244b7f5c055SJed Brown 3245b7f5c055SJed Brown References: 3246606c0280SSatish Balay . * - Maskery et al, Insights into the mechanical properties of several triply periodic minimal surface lattice structures made by polymer additive manufacturing, 2017. https://doi.org/10.1016/j.polymer.2017.11.049 3247b7f5c055SJed Brown 3248b7f5c055SJed Brown Developer Notes: 3249b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 3250b7f5c055SJed Brown 3251b7f5c055SJed Brown Level: beginner 3252b7f5c055SJed Brown 3253db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 3254b7f5c055SJed Brown @*/ 3255d71ae5a4SJacob 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) 3256d71ae5a4SJacob Faibussowitsch { 3257b7f5c055SJed Brown PetscFunctionBegin; 32589566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 32599566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 32609566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 3261b7f5c055SJed Brown PetscFunctionReturn(0); 3262b7f5c055SJed Brown } 3263b7f5c055SJed Brown 32649318fe57SMatthew G. Knepley /*@ 32659318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 32669318fe57SMatthew G. Knepley 32679318fe57SMatthew G. Knepley Collective 32689318fe57SMatthew G. Knepley 32699318fe57SMatthew G. Knepley Input Parameters: 32709318fe57SMatthew G. Knepley + comm - The communicator for the DM object 32719318fe57SMatthew G. Knepley . dim - The dimension 32729318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 32739318fe57SMatthew G. Knepley - R - The radius 32749318fe57SMatthew G. Knepley 32759318fe57SMatthew G. Knepley Output Parameter: 32769318fe57SMatthew G. Knepley . dm - The DM object 32779318fe57SMatthew G. Knepley 32789318fe57SMatthew G. Knepley Level: beginner 32799318fe57SMatthew G. Knepley 3280db781477SPatrick Sanan .seealso: `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 32819318fe57SMatthew G. Knepley @*/ 3282d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 3283d71ae5a4SJacob Faibussowitsch { 32849318fe57SMatthew G. Knepley PetscFunctionBegin; 32859318fe57SMatthew G. Knepley PetscValidPointer(dm, 5); 32869566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 32879566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 32889566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 32899318fe57SMatthew G. Knepley PetscFunctionReturn(0); 32909318fe57SMatthew G. Knepley } 32919318fe57SMatthew G. Knepley 3292d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 3293d71ae5a4SJacob Faibussowitsch { 32949318fe57SMatthew G. Knepley DM sdm, vol; 32959318fe57SMatthew G. Knepley DMLabel bdlabel; 32969318fe57SMatthew G. Knepley 32979318fe57SMatthew G. Knepley PetscFunctionBegin; 32989566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 32999566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 33009566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_")); 33019566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 33029566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 33039566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 33049566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 33059566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 330669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 33079566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 33089566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 33099566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 33109566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 331151a74b61SMatthew G. Knepley PetscFunctionReturn(0); 331251a74b61SMatthew G. Knepley } 331351a74b61SMatthew G. Knepley 331451a74b61SMatthew G. Knepley /*@ 331551a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 331651a74b61SMatthew G. Knepley 331751a74b61SMatthew G. Knepley Collective 331851a74b61SMatthew G. Knepley 331951a74b61SMatthew G. Knepley Input Parameters: 332051a74b61SMatthew G. Knepley + comm - The communicator for the DM object 332151a74b61SMatthew G. Knepley . dim - The dimension 332251a74b61SMatthew G. Knepley - R - The radius 332351a74b61SMatthew G. Knepley 332451a74b61SMatthew G. Knepley Output Parameter: 332551a74b61SMatthew G. Knepley . dm - The DM object 332651a74b61SMatthew G. Knepley 332751a74b61SMatthew G. Knepley Options Database Keys: 332851a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 332951a74b61SMatthew G. Knepley 333051a74b61SMatthew G. Knepley Level: beginner 333151a74b61SMatthew G. Knepley 3332db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 333351a74b61SMatthew G. Knepley @*/ 3334d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 3335d71ae5a4SJacob Faibussowitsch { 333651a74b61SMatthew G. Knepley PetscFunctionBegin; 33379566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 33389566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 33399566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 33402829fed8SMatthew G. Knepley PetscFunctionReturn(0); 33412829fed8SMatthew G. Knepley } 33422829fed8SMatthew G. Knepley 3343d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 3344d71ae5a4SJacob Faibussowitsch { 33450a6ba040SMatthew G. Knepley PetscFunctionBegin; 33469318fe57SMatthew G. Knepley switch (ct) { 33479371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 33489318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 33499318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 33509318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 33519318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 33529318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 33539318fe57SMatthew G. Knepley 33549566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 33559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33569371c9d4SSatish Balay } break; 33579371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 33589318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 33599318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 33609318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 33619318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 33629318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 33639318fe57SMatthew G. Knepley 33649566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 33659566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33669371c9d4SSatish Balay } break; 33679371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 3368b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 3369b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 3370b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 3371b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 3372b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 3373b5a892a1SMatthew G. Knepley 33749566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 33759566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33769371c9d4SSatish Balay } break; 33779371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 33789318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 33799318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 33809318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 33819318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 33829318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 33839318fe57SMatthew G. Knepley 33849566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 33859566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33869371c9d4SSatish Balay } break; 33879371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 33889318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 33899318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 33909318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 33919318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 33929318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 33939318fe57SMatthew G. Knepley 33949566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 33959566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33969371c9d4SSatish Balay } break; 33979371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 33989318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 33999318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 34009318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 34019318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 34029318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 34039318fe57SMatthew G. Knepley 34049566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 34059566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34069371c9d4SSatish Balay } break; 34079371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 34089318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 34099318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 3410f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 34119318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 3412f0edb160SMatthew 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}; 34139318fe57SMatthew G. Knepley 34149566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34159566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34169371c9d4SSatish Balay } break; 34179371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 34189318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 34199318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 3420f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 34219318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34229371c9d4SSatish 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}; 34239318fe57SMatthew G. Knepley 34249566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34259566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34269371c9d4SSatish Balay } break; 34279371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 34289318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 34299318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 3430f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 34319318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 34329371c9d4SSatish 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}; 34339318fe57SMatthew G. Knepley 34349566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34359566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34369371c9d4SSatish Balay } break; 34379371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 34389318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 34399318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 34409318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 34419318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 34429371c9d4SSatish 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}; 34439318fe57SMatthew G. Knepley 34449566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34459566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34469371c9d4SSatish Balay } break; 34479371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 34489318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 34499318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 34509318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 34519318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34529371c9d4SSatish 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}; 34539318fe57SMatthew G. Knepley 34549566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34569371c9d4SSatish Balay } break; 34579371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 34589318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 34599318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 3460f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 34619318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34629371c9d4SSatish 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}; 34639318fe57SMatthew G. Knepley 34649566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34659566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34669371c9d4SSatish Balay } break; 3467d71ae5a4SJacob Faibussowitsch default: 3468d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 34699318fe57SMatthew G. Knepley } 34709318fe57SMatthew G. Knepley { 34719318fe57SMatthew G. Knepley PetscInt Nv, v; 34729318fe57SMatthew G. Knepley 34739318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 34749566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 34759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 34769566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 34779566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 34789318fe57SMatthew G. Knepley } 34799566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 34809566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 34810a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 34820a6ba040SMatthew G. Knepley } 34830a6ba040SMatthew G. Knepley 34849318fe57SMatthew G. Knepley /*@ 34859318fe57SMatthew G. Knepley DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell 34869318fe57SMatthew G. Knepley 34879318fe57SMatthew G. Knepley Collective 34889318fe57SMatthew G. Knepley 34899318fe57SMatthew G. Knepley Input Parameters: 34909318fe57SMatthew G. Knepley + comm - The communicator 34919318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 34929318fe57SMatthew G. Knepley 34939318fe57SMatthew G. Knepley Output Parameter: 34949318fe57SMatthew G. Knepley . refdm - The reference cell 34959318fe57SMatthew G. Knepley 34969318fe57SMatthew G. Knepley Level: intermediate 34979318fe57SMatthew G. Knepley 3498db781477SPatrick Sanan .seealso: `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()` 34999318fe57SMatthew G. Knepley @*/ 3500d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 3501d71ae5a4SJacob Faibussowitsch { 35020a6ba040SMatthew G. Knepley PetscFunctionBegin; 35039566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 35049566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 35059566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 35069318fe57SMatthew G. Knepley PetscFunctionReturn(0); 35079318fe57SMatthew G. Knepley } 350879a015ccSMatthew G. Knepley 3509d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 3510d71ae5a4SJacob Faibussowitsch { 35119318fe57SMatthew G. Knepley DM plex; 35129318fe57SMatthew G. Knepley DMLabel label; 35139318fe57SMatthew G. Knepley PetscBool hasLabel; 35140a6ba040SMatthew G. Knepley 3515c22d3578SMatthew G. Knepley PetscFunctionBegin; 35169566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 35179318fe57SMatthew G. Knepley if (hasLabel) PetscFunctionReturn(0); 35189566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 35199566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 35209566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 35219566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 35221c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 35239566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 35249318fe57SMatthew G. Knepley PetscFunctionReturn(0); 35259318fe57SMatthew G. Knepley } 3526acdc6f61SToby Isaac 3527669647acSMatthew G. Knepley /* 3528669647acSMatthew 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. 3529669647acSMatthew G. Knepley 3530669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 3531669647acSMatthew G. Knepley */ 3532d71ae5a4SJacob 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[]) 3533d71ae5a4SJacob Faibussowitsch { 3534669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 3535669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 3536669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 3537669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 3538669647acSMatthew G. Knepley 3539669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 3540669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 3541669647acSMatthew G. Knepley } 3542669647acSMatthew G. Knepley 3543669647acSMatthew G. Knepley const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 35449318fe57SMatthew G. Knepley 3545d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 3546d71ae5a4SJacob Faibussowitsch { 35479318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 35489318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 35499318fe57SMatthew G. Knepley PetscInt dim = 2; 35509318fe57SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 3551cd7e8a5eSksagiyam PetscBool flg, flg2, fflg, bdfflg, nameflg; 35529318fe57SMatthew G. Knepley MPI_Comm comm; 3553ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3554ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3555ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 35569318fe57SMatthew G. Knepley 35579318fe57SMatthew G. Knepley PetscFunctionBegin; 35589566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 35599318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 35609566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 35619566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 35629566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 35639566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 35649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 35659566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 35669566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 356763a3b9bcSJacob Faibussowitsch PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim); 35689566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 35699566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 35709566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 35719566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 35729566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 35739318fe57SMatthew G. Knepley 357461a622f3SMatthew G. Knepley switch (cell) { 357561a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 357661a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 357761a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 357861a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 357961a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 358061a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 3581d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 3582d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 3583d71ae5a4SJacob Faibussowitsch break; 3584d71ae5a4SJacob Faibussowitsch default: 3585d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 3586d71ae5a4SJacob Faibussowitsch break; 358761a622f3SMatthew G. Knepley } 358861a622f3SMatthew G. Knepley 35899318fe57SMatthew G. Knepley if (fflg) { 35909318fe57SMatthew G. Knepley DM dmnew; 35919318fe57SMatthew G. Knepley 35929566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew)); 35935de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 359469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 35959318fe57SMatthew G. Knepley } else if (refDomain) { 35969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 35979318fe57SMatthew G. Knepley } else if (bdfflg) { 35989318fe57SMatthew G. Knepley DM bdm, dmnew; 35999318fe57SMatthew G. Knepley 36009566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm)); 36019566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 36029566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 36039566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 36049566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 36055de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 360669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 36079318fe57SMatthew G. Knepley } else { 36089566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 36099318fe57SMatthew G. Knepley switch (shape) { 3610669647acSMatthew G. Knepley case DM_SHAPE_BOX: 3611669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 36129318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 36139318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 36149318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 36159318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3616669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 36179318fe57SMatthew G. Knepley PetscInt i, n; 36189318fe57SMatthew G. Knepley 36199318fe57SMatthew G. Knepley n = dim; 36209318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 36219566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 36229318fe57SMatthew G. Knepley n = 3; 36239566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 362463a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 36259318fe57SMatthew G. Knepley n = 3; 36269566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 362763a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 36289318fe57SMatthew G. Knepley n = 3; 36299566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 363063a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 3631669647acSMatthew G. Knepley 3632669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 3633669647acSMatthew G. Knepley if (isAnnular) 3634669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 3635669647acSMatthew G. Knepley 36369318fe57SMatthew G. Knepley switch (cell) { 363761a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 36389566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 3639d410b0cfSMatthew G. Knepley if (!interpolate) { 3640d410b0cfSMatthew G. Knepley DM udm; 3641d410b0cfSMatthew G. Knepley 36429566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 364369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3644d410b0cfSMatthew G. Knepley } 36459318fe57SMatthew G. Knepley break; 3646d71ae5a4SJacob Faibussowitsch default: 3647d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate)); 3648d71ae5a4SJacob Faibussowitsch break; 36499318fe57SMatthew G. Knepley } 3650669647acSMatthew G. Knepley if (isAnnular) { 3651669647acSMatthew G. Knepley DM cdm; 3652669647acSMatthew G. Knepley PetscDS cds; 3653669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 3654669647acSMatthew G. Knepley 3655669647acSMatthew G. Knepley // Fix coordinates for annular region 3656669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 3657669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 3658669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 3659669647acSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, NULL)); 3660669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 3661669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 3662669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 3663669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 3664669647acSMatthew G. Knepley } 36659371c9d4SSatish Balay } break; 36669371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 36679318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 36689318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 36699318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 36709318fe57SMatthew G. Knepley PetscInt i, n; 36719318fe57SMatthew G. Knepley 36729318fe57SMatthew G. Knepley n = dim + 1; 36739318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 36749566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 36759318fe57SMatthew G. Knepley n = 3; 36769566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 367763a3b9bcSJacob 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); 36789318fe57SMatthew G. Knepley n = 3; 36799566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 368063a3b9bcSJacob 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); 36819566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 36829371c9d4SSatish Balay } break; 36839371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 36849318fe57SMatthew G. Knepley PetscReal R = 1.0; 36859318fe57SMatthew G. Knepley 36869566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 36879566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 36889371c9d4SSatish Balay } break; 36899371c9d4SSatish Balay case DM_SHAPE_BALL: { 36909318fe57SMatthew G. Knepley PetscReal R = 1.0; 36919318fe57SMatthew G. Knepley 36929566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 36939566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 36949371c9d4SSatish Balay } break; 36959371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 36969318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 36979318fe57SMatthew G. Knepley PetscInt Nw = 6; 36989318fe57SMatthew G. Knepley 36999566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 37009566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 37019318fe57SMatthew G. Knepley switch (cell) { 3702d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 3703d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 3704d71ae5a4SJacob Faibussowitsch break; 3705d71ae5a4SJacob Faibussowitsch default: 3706d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt)); 3707d71ae5a4SJacob Faibussowitsch break; 37089318fe57SMatthew G. Knepley } 37099371c9d4SSatish Balay } break; 3710b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 37119371c9d4SSatish Balay case DM_SHAPE_GYROID: { 3712b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 3713b7f5c055SJed Brown PetscReal thickness = 0.; 3714b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3715b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 37161436d7faSJed Brown PetscBool tps_distribute; 37179566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 37189566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 37199566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 37209566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 37219566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 37229566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 37239566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 37249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 37259371c9d4SSatish Balay } break; 37269371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 372705bd46c0SStefano Zampini DM dmnew; 372805bd46c0SStefano Zampini PetscReal rl = 0.0; 372905bd46c0SStefano Zampini 373005bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 373105bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 37325de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 373369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 37349371c9d4SSatish Balay } break; 3735d71ae5a4SJacob Faibussowitsch default: 3736d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 37379318fe57SMatthew G. Knepley } 37389318fe57SMatthew G. Knepley } 37399566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 374048a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 37410a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 37420a6ba040SMatthew G. Knepley } 37430a6ba040SMatthew G. Knepley 3744d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 3745d71ae5a4SJacob Faibussowitsch { 37460a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 37477f9d8d6cSVaclav Hapla PetscBool flg, flg2; 37489318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 37490a6ba040SMatthew G. Knepley 37500a6ba040SMatthew G. Knepley PetscFunctionBegin; 37510a6ba040SMatthew G. Knepley /* Handle viewing */ 37529566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 37539566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 37549566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 37559566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 3756f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 37579566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 37589566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 37599318fe57SMatthew G. Knepley /* Labeling */ 37609566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 37619566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 3762953fc75cSMatthew G. Knepley /* Point Location */ 37639566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 37640848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 37659566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 37662e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 37679566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 3768b29cfa1cSToby Isaac /* Projection behavior */ 3769*d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 37709566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 3771f12cf164SMatthew G. Knepley /* Checking structure */ 3772f12cf164SMatthew G. Knepley { 37737f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 3774f12cf164SMatthew G. Knepley 37757f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 37767f9d8d6cSVaclav Hapla if (all) { 37777f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 37787f9d8d6cSVaclav Hapla } else { 37799566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 37807f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 37819566063dSJacob 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)); 37827f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 37839566063dSJacob 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)); 37847f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 37859566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 37867f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 37879566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 3788d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 37899566063dSJacob 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)); 37907f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 37917f9d8d6cSVaclav Hapla } 37929566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 37939566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 3794f12cf164SMatthew G. Knepley } 37959318fe57SMatthew G. Knepley { 37969318fe57SMatthew G. Knepley PetscReal scale = 1.0; 37974f3833eaSMatthew G. Knepley 37989566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 37999318fe57SMatthew G. Knepley if (flg) { 38009318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 38019318fe57SMatthew G. Knepley 38029566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 38039566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 38049566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 38059566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 38069318fe57SMatthew G. Knepley } 38079318fe57SMatthew G. Knepley } 38089566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 380968d4fef7SMatthew G. Knepley PetscFunctionReturn(0); 381068d4fef7SMatthew G. Knepley } 381168d4fef7SMatthew G. Knepley 3812d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap) 3813d71ae5a4SJacob Faibussowitsch { 3814c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 3815c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 3816c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 3817c506a872SMatthew G. Knepley PetscBool flg; 3818c506a872SMatthew G. Knepley 3819c506a872SMatthew G. Knepley PetscFunctionBegin; 3820c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 3821c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 3822c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 3823c506a872SMatthew G. Knepley if (numOvLabels) { 3824c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 3825c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 3826c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 3827c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 3828c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 3829c506a872SMatthew G. Knepley } 3830c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 3831c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 3832c506a872SMatthew 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); 3833c506a872SMatthew G. Knepley 3834c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 3835c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 3836c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 3837c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 3838c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 3839c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 3840c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 3841c506a872SMatthew G. Knepley } 3842c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 3843c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 3844c506a872SMatthew 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); 3845c506a872SMatthew G. Knepley } 3846c506a872SMatthew G. Knepley PetscFunctionReturn(0); 3847c506a872SMatthew G. Knepley } 3848c506a872SMatthew G. Knepley 3849d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 3850d71ae5a4SJacob Faibussowitsch { 3851bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 3852bdf63967SMatthew G. Knepley char oname[256]; 3853d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 38549318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 3855e600fa54SMatthew 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; 38566bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 385768d4fef7SMatthew G. Knepley 385868d4fef7SMatthew G. Knepley PetscFunctionBegin; 3859d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 38609318fe57SMatthew G. Knepley /* Handle automatic creation */ 38619566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 38626bc1bd01Sksagiyam if (dim < 0) { 38636bc1bd01Sksagiyam PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 38646bc1bd01Sksagiyam created = PETSC_TRUE; 38656bc1bd01Sksagiyam } 38666bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 3867d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 38689566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 3869d89e6e46SMatthew G. Knepley if (flg) { 3870d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 3871d89e6e46SMatthew G. Knepley 38729566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 3873d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 3874d89e6e46SMatthew G. Knepley DM udm; 3875d89e6e46SMatthew G. Knepley 38769566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 387769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3878d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 3879d89e6e46SMatthew G. Knepley DM idm; 3880d89e6e46SMatthew G. Knepley 38819566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 388269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3883d89e6e46SMatthew G. Knepley } 3884d89e6e46SMatthew G. Knepley } 38859b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 38869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg)); 3887ad540459SPierre Jolivet if (flg) ((DM_Plex *)dm->data)->ignoreModel = ignoreModel; 38889566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 38899566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 38909566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 38919566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 38929566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 38939566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 38949318fe57SMatthew G. Knepley if (flg) { 38959566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 38969566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 38979318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 38989318fe57SMatthew G. Knepley } 38999b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 39009b44eab4SMatthew G. Knepley DM rdm; 39019b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 39029b44eab4SMatthew G. Knepley 3903dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 39049566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 390569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 3906dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 390761a622f3SMatthew G. Knepley if (coordFunc && remap) { 39089566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 39099b44eab4SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 39109b44eab4SMatthew G. Knepley } 39119b44eab4SMatthew G. Knepley } 39129566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 39139318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 39149566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 39159318fe57SMatthew G. Knepley if (extLayers) { 39169318fe57SMatthew G. Knepley DM edm; 39179318fe57SMatthew G. Knepley 39189566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 391969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 392048d16a33SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = NULL; 3921dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3922d410b0cfSMatthew G. Knepley extLayers = 0; 39239318fe57SMatthew G. Knepley } 3924bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 39256bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 39269566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 39276bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 39289566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 39296bc1bd01Sksagiyam if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) { 3930bdf63967SMatthew G. Knepley DM pdm; 3931bdf63967SMatthew G. Knepley IS perm; 3932bdf63967SMatthew G. Knepley 39339566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 39349566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 39359566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 393669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 3937dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3938bdf63967SMatthew G. Knepley } 39399b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 39409566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 3941c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 3942dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 39439b44eab4SMatthew G. Knepley if (distribute) { 39449b44eab4SMatthew G. Knepley DM pdm = NULL; 39459b44eab4SMatthew G. Knepley PetscPartitioner part; 39469b44eab4SMatthew G. Knepley 39479566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 39489566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 39499566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm)); 395048a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 39519b44eab4SMatthew G. Knepley } 39529318fe57SMatthew G. Knepley /* Create coordinate space */ 39539318fe57SMatthew G. Knepley if (created) { 395461a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 39559318fe57SMatthew G. Knepley PetscInt degree = 1; 39566858538eSMatthew G. Knepley PetscBool flg; 39579318fe57SMatthew G. Knepley 39589566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg)); 39599566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 39609566063dSJacob Faibussowitsch if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc)); 396161a622f3SMatthew G. Knepley if (flg && !coordSpace) { 396261a622f3SMatthew G. Knepley DM cdm; 396361a622f3SMatthew G. Knepley PetscDS cds; 396461a622f3SMatthew G. Knepley PetscObject obj; 396561a622f3SMatthew G. Knepley PetscClassId id; 396661a622f3SMatthew G. Knepley 39679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 39689566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 39699566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 39709566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 397161a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 397261a622f3SMatthew G. Knepley PetscContainer dummy; 397361a622f3SMatthew G. Knepley 39749566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 39759566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 39769566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 39779566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 39789566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 397961a622f3SMatthew G. Knepley } 398061a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 398161a622f3SMatthew G. Knepley } 39826858538eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg)); 39839566063dSJacob Faibussowitsch PetscCall(DMLocalizeCoordinates(dm)); 39849318fe57SMatthew G. Knepley } 398568d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 398661a622f3SMatthew G. Knepley remap = PETSC_TRUE; 39879566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 39889566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 39899566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 39909566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 399168d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 3992acdc6f61SToby Isaac DM *dms, coarseDM; 399368d4fef7SMatthew G. Knepley 39949566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 39959566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 39969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 39979566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 399868d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 39999566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 400068d4fef7SMatthew G. Knepley if (refine == 1) { 40019566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 40029566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 400368d4fef7SMatthew G. Knepley } else { 40049566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 40059566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 40069566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 40079566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 400868d4fef7SMatthew G. Knepley } 40099566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 40109566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 401168d4fef7SMatthew G. Knepley /* Free DMs */ 401268d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 4013dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 40149566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 401568d4fef7SMatthew G. Knepley } 40169566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 401768d4fef7SMatthew G. Knepley } else { 401868d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 40199318fe57SMatthew G. Knepley DM rdm; 402051a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 402168d4fef7SMatthew G. Knepley 4022dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40239566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 402468d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 402569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 4026dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 402761a622f3SMatthew G. Knepley if (coordFunc && remap) { 40289566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 402951a74b61SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 403051a74b61SMatthew G. Knepley } 403168d4fef7SMatthew G. Knepley } 403268d4fef7SMatthew G. Knepley } 40333cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 40349566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 40359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 4036b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 4037b653a561SMatthew G. Knepley DM *dms; 4038b653a561SMatthew G. Knepley 40399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 40409566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 4041b653a561SMatthew G. Knepley /* Free DMs */ 4042b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 4043dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 40449566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 4045b653a561SMatthew G. Knepley } 40469566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 4047b653a561SMatthew G. Knepley } else { 4048b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 40499318fe57SMatthew G. Knepley DM cdm; 40509318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 40513cf6fe12SMatthew G. Knepley 4052dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40539566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 40543cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 405569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 4056dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40579318fe57SMatthew G. Knepley if (coordFunc) { 40589566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 40599318fe57SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 40609318fe57SMatthew G. Knepley } 40613cf6fe12SMatthew G. Knepley } 4062b653a561SMatthew G. Knepley } 4063909dfd52SMatthew G. Knepley /* Handle ghost cells */ 40649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 4065909dfd52SMatthew G. Knepley if (ghostCells) { 4066909dfd52SMatthew G. Knepley DM gdm; 4067909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 4068909dfd52SMatthew G. Knepley 4069909dfd52SMatthew G. Knepley lname[0] = '\0'; 40709566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 40719566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 407269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 4073909dfd52SMatthew G. Knepley } 40746913077dSMatthew G. Knepley /* Handle 1D order */ 40756bc1bd01Sksagiyam if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) { 40766913077dSMatthew G. Knepley DM cdm, rdm; 40776913077dSMatthew G. Knepley PetscDS cds; 40786913077dSMatthew G. Knepley PetscObject obj; 40796913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 40806913077dSMatthew G. Knepley IS perm; 40816bc1bd01Sksagiyam PetscInt Nf; 40826913077dSMatthew G. Knepley PetscBool distributed; 40836913077dSMatthew G. Knepley 40849566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 40859566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 40869566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 40879566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 40886913077dSMatthew G. Knepley if (Nf) { 40899566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 40909566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 40916913077dSMatthew G. Knepley } 40926bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 40939566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 40949566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 409569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 40969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 40976913077dSMatthew G. Knepley } 40986913077dSMatthew G. Knepley } 40993cf6fe12SMatthew G. Knepley /* Handle */ 4100dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 4101d0609cedSBarry Smith PetscOptionsHeadEnd(); 41020a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 41030a6ba040SMatthew G. Knepley } 41040a6ba040SMatthew G. Knepley 4105d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 4106d71ae5a4SJacob Faibussowitsch { 4107552f7358SJed Brown PetscFunctionBegin; 41089566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 41099566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 41109566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 41119566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 41129566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 41139566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 4114552f7358SJed Brown PetscFunctionReturn(0); 4115552f7358SJed Brown } 4116552f7358SJed Brown 4117d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 4118d71ae5a4SJacob Faibussowitsch { 4119552f7358SJed Brown PetscFunctionBegin; 41209566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 41219566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 41229566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 4123552f7358SJed Brown PetscFunctionReturn(0); 4124552f7358SJed Brown } 4125552f7358SJed Brown 4126d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4127d71ae5a4SJacob Faibussowitsch { 4128793f3fe5SMatthew G. Knepley PetscInt depth, d; 4129793f3fe5SMatthew G. Knepley 4130793f3fe5SMatthew G. Knepley PetscFunctionBegin; 41319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4132793f3fe5SMatthew G. Knepley if (depth == 1) { 41339566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 41349566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 41359566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 41369371c9d4SSatish Balay else { 41379371c9d4SSatish Balay *pStart = 0; 41389371c9d4SSatish Balay *pEnd = 0; 41399371c9d4SSatish Balay } 4140793f3fe5SMatthew G. Knepley } else { 41419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 4142793f3fe5SMatthew G. Knepley } 4143793f3fe5SMatthew G. Knepley PetscFunctionReturn(0); 4144793f3fe5SMatthew G. Knepley } 4145793f3fe5SMatthew G. Knepley 4146d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 4147d71ae5a4SJacob Faibussowitsch { 4148502a2867SDave May PetscSF sf; 41490a19bb7dSprj- PetscInt niranks, njranks, n; 41500a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 41510a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 4152502a2867SDave May 41532f356facSMatthew G. Knepley PetscFunctionBegin; 41549566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 41550a19bb7dSprj- if (!data->neighbors) { 41569566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 41579566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 41589566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 41599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 41609566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 41619566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 41620a19bb7dSprj- n = njranks + niranks; 41639566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 41640a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 41659566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 41660a19bb7dSprj- } 41670a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 41680a19bb7dSprj- if (ranks) { 41690a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 41700a19bb7dSprj- else *ranks = NULL; 41710a19bb7dSprj- } 4172502a2867SDave May PetscFunctionReturn(0); 4173502a2867SDave May } 4174502a2867SDave May 41751eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 41761eb70e55SToby Isaac 4177d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 4178d71ae5a4SJacob Faibussowitsch { 4179552f7358SJed Brown PetscFunctionBegin; 4180552f7358SJed Brown dm->ops->view = DMView_Plex; 41812c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 4182552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 418338221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 4184552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 41851bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 418666ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 4187552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 4188552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 4189184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 41900298fd71SBarry Smith dm->ops->createfieldis = NULL; 4191552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 4192f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 41930a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 4194552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 4195bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 4196bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 4197b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 41985a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 4199552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 42000a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 42010a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 4202b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 4203d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 42040298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 42050298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 42060298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 42070298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 4208552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 4209552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 42102adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 4211793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 4212552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 42130709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 42140709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 4215bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 42168c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 4217ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 42180709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 4219b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 42202a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 422128d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 42229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 42239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 42249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 42259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 42269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 42279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 42289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 42296bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 42306bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 42319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 4232c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 4233c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 4234552f7358SJed Brown PetscFunctionReturn(0); 4235552f7358SJed Brown } 4236552f7358SJed Brown 4237d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 4238d71ae5a4SJacob Faibussowitsch { 423963a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 424063a16f15SMatthew G. Knepley 424163a16f15SMatthew G. Knepley PetscFunctionBegin; 424263a16f15SMatthew G. Knepley mesh->refct++; 424363a16f15SMatthew G. Knepley (*newdm)->data = mesh; 42449566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 42459566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 424663a16f15SMatthew G. Knepley PetscFunctionReturn(0); 424763a16f15SMatthew G. Knepley } 424863a16f15SMatthew G. Knepley 42498818961aSMatthew G Knepley /*MC 42508818961aSMatthew G Knepley DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 42518818961aSMatthew G Knepley In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is 42528818961aSMatthew G Knepley specified by a PetscSection object. Ownership in the global representation is determined by 42538818961aSMatthew G Knepley ownership of the underlying DMPlex points. This is specified by another PetscSection object. 42548818961aSMatthew G Knepley 4255e5893cccSMatthew G. Knepley Options Database Keys: 4256250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 4257250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 4258250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 4259250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 4260250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 4261250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 4262250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 4263ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 4264f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 4265f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 4266*d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 4267f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 4268250712c9SMatthew G. Knepley . -dm_plex_check_all - Perform all shecks below 4269f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 4270f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 4271f12cf164SMatthew 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 4272f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 4273f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 4274e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 4275e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 4276e5893cccSMatthew G. Knepley 42778818961aSMatthew G Knepley Level: intermediate 42788818961aSMatthew G Knepley 4279db781477SPatrick Sanan .seealso: `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()` 42808818961aSMatthew G Knepley M*/ 42818818961aSMatthew G Knepley 4282d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 4283d71ae5a4SJacob Faibussowitsch { 4284552f7358SJed Brown DM_Plex *mesh; 4285412e9a14SMatthew G. Knepley PetscInt unit; 4286552f7358SJed Brown 4287552f7358SJed Brown PetscFunctionBegin; 4288552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 42894dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 4290552f7358SJed Brown dm->data = mesh; 4291552f7358SJed Brown 4292552f7358SJed Brown mesh->refct = 1; 42939566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 42949566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 4295552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 4296552f7358SJed Brown mesh->refinementLimit = -1.0; 4297e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 42986bc1bd01Sksagiyam mesh->reorderDefault = DMPLEX_REORDER_DEFAULT_NOTSET; 42991d1f2f2aSksagiyam mesh->distributionName = NULL; 43007d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 43017d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 4302552f7358SJed Brown 43039566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 43042e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 4305d9deefdfSMatthew G. Knepley 43068865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 4307552f7358SJed Brown 4308df0420ecSMatthew G. Knepley mesh->depthState = -1; 4309ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 43106113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 4311552f7358SJed Brown 43129566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 4313552f7358SJed Brown PetscFunctionReturn(0); 4314552f7358SJed Brown } 4315552f7358SJed Brown 4316552f7358SJed Brown /*@ 4317552f7358SJed Brown DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 4318552f7358SJed Brown 4319d083f849SBarry Smith Collective 4320552f7358SJed Brown 4321552f7358SJed Brown Input Parameter: 4322552f7358SJed Brown . comm - The communicator for the DMPlex object 4323552f7358SJed Brown 4324552f7358SJed Brown Output Parameter: 4325552f7358SJed Brown . mesh - The DMPlex object 4326552f7358SJed Brown 4327552f7358SJed Brown Level: beginner 4328552f7358SJed Brown 4329552f7358SJed Brown @*/ 4330d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 4331d71ae5a4SJacob Faibussowitsch { 4332552f7358SJed Brown PetscFunctionBegin; 4333552f7358SJed Brown PetscValidPointer(mesh, 2); 43349566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 43359566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 4336552f7358SJed Brown PetscFunctionReturn(0); 4337552f7358SJed Brown } 4338552f7358SJed Brown 4339b09969d6SVaclav Hapla /*@C 4340b09969d6SVaclav Hapla DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output) 4341b09969d6SVaclav Hapla 4342b09969d6SVaclav Hapla Input Parameters: 4343b09969d6SVaclav Hapla + dm - The DM 4344b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4345325d53feSBarry Smith . numVertices - The number of vertices to be owned by this process, or PETSC_DECIDE 4346325d53feSBarry Smith . NVertices - The global number of vertices, or PETSC_DETERMINE 4347b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 43485e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4349b09969d6SVaclav Hapla 4350be8c289dSNicolas Barral Output Parameters: 4351be8c289dSNicolas Barral + vertexSF - (Optional) SF describing complete vertex ownership 4352be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4353b09969d6SVaclav Hapla 4354b09969d6SVaclav Hapla Notes: 4355b09969d6SVaclav Hapla Two triangles sharing a face 4356b09969d6SVaclav Hapla $ 4357b09969d6SVaclav Hapla $ 2 4358b09969d6SVaclav Hapla $ / | \ 4359b09969d6SVaclav Hapla $ / | \ 4360b09969d6SVaclav Hapla $ / | \ 4361b09969d6SVaclav Hapla $ 0 0 | 1 3 4362b09969d6SVaclav Hapla $ \ | / 4363b09969d6SVaclav Hapla $ \ | / 4364b09969d6SVaclav Hapla $ \ | / 4365b09969d6SVaclav Hapla $ 1 4366b09969d6SVaclav Hapla would have input 4367b09969d6SVaclav Hapla $ numCells = 2, numVertices = 4 4368b09969d6SVaclav Hapla $ cells = [0 1 2 1 3 2] 4369b09969d6SVaclav Hapla $ 4370b09969d6SVaclav Hapla which would result in the DMPlex 4371b09969d6SVaclav Hapla $ 4372b09969d6SVaclav Hapla $ 4 4373b09969d6SVaclav Hapla $ / | \ 4374b09969d6SVaclav Hapla $ / | \ 4375b09969d6SVaclav Hapla $ / | \ 4376b09969d6SVaclav Hapla $ 2 0 | 1 5 4377b09969d6SVaclav Hapla $ \ | / 4378b09969d6SVaclav Hapla $ \ | / 4379b09969d6SVaclav Hapla $ \ | / 4380b09969d6SVaclav Hapla $ 3 4381b09969d6SVaclav Hapla 438225b6865aSVaclav Hapla Vertices are implicitly numbered consecutively 0,...,NVertices. 438325b6865aSVaclav Hapla Each rank owns a chunk of numVertices consecutive vertices. 438425b6865aSVaclav Hapla If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout. 4385325d53feSBarry Smith If NVertices is PETSC_DETERMINE and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 4386325d53feSBarry Smith If only NVertices is PETSC_DETERMINE, it is computed as the sum of numVertices over all ranks. 438725b6865aSVaclav Hapla 4388b09969d6SVaclav Hapla The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 4389b09969d6SVaclav Hapla 4390b09969d6SVaclav Hapla Not currently supported in Fortran. 4391b09969d6SVaclav Hapla 4392b09969d6SVaclav Hapla Level: advanced 4393b09969d6SVaclav Hapla 4394db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()` 4395b09969d6SVaclav Hapla @*/ 4396d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved) 4397d71ae5a4SJacob Faibussowitsch { 43982464107aSksagiyam PetscSF sfPoint; 43992464107aSksagiyam PetscLayout layout; 440082fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 4401a47d0d45SMatthew G. Knepley 4402a47d0d45SMatthew G. Knepley PetscFunctionBegin; 440325b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 44049566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 440525b6865aSVaclav Hapla /* Get/check global number of vertices */ 440625b6865aSVaclav Hapla { 440725b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 440825b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 440925b6865aSVaclav Hapla 441025b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 441125b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 44129371c9d4SSatish Balay for (i = 0; i < len; i++) 44139371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 441425b6865aSVaclav Hapla ++NVerticesInCells; 44159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 441625b6865aSVaclav Hapla 441725b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 44189371c9d4SSatish Balay else 44199371c9d4SSatish 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); 442025b6865aSVaclav Hapla } 44219079aca8SVaclav Hapla /* Count locally unique vertices */ 44229079aca8SVaclav Hapla { 44239079aca8SVaclav Hapla PetscHSetI vhash; 44249079aca8SVaclav Hapla PetscInt off = 0; 44259079aca8SVaclav Hapla 44269566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 4427a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 442848a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 4429a47d0d45SMatthew G. Knepley } 44309566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 44319566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 4432ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 44339566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 44349566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 443563a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 4436a47d0d45SMatthew G. Knepley } 44379566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 4438a47d0d45SMatthew G. Knepley /* Create cones */ 44399566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 44409566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 44419566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 44429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4443a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 4444a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 4445a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 4446a47d0d45SMatthew G. Knepley PetscInt lv; 4447a47d0d45SMatthew G. Knepley 44489079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 44499079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 44509566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 445163a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 4452961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 4453a47d0d45SMatthew G. Knepley } 4454a47d0d45SMatthew G. Knepley } 44552464107aSksagiyam /* Build point sf */ 44569566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 44579566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 44589566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 44599566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 44609566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 44619566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 44629566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 44639566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 44642464107aSksagiyam if (dm->sf) { 44652464107aSksagiyam const char *prefix; 44662464107aSksagiyam 44679566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 44689566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 44692464107aSksagiyam } 44709566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 44719566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 44729566063dSJacob Faibussowitsch if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF")); 4473a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 44749566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 44759566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 44769566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4477a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4478a47d0d45SMatthew G. Knepley } 4479a47d0d45SMatthew G. Knepley 4480b09969d6SVaclav Hapla /*@C 4481b09969d6SVaclav Hapla DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4482b09969d6SVaclav Hapla 4483b09969d6SVaclav Hapla Input Parameters: 4484b09969d6SVaclav Hapla + dm - The DM 4485b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4486b09969d6SVaclav Hapla . sfVert - SF describing complete vertex ownership 4487b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4488b09969d6SVaclav Hapla 4489b09969d6SVaclav Hapla Level: advanced 4490b09969d6SVaclav Hapla 4491b09969d6SVaclav Hapla Notes: 4492b09969d6SVaclav Hapla Not currently supported in Fortran. 4493b09969d6SVaclav Hapla 4494db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 4495b09969d6SVaclav Hapla @*/ 4496d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 4497d71ae5a4SJacob Faibussowitsch { 4498a47d0d45SMatthew G. Knepley PetscSection coordSection; 4499a47d0d45SMatthew G. Knepley Vec coordinates; 4500a47d0d45SMatthew G. Knepley PetscScalar *coords; 45011edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 4502a47d0d45SMatthew G. Knepley 4503a47d0d45SMatthew G. Knepley PetscFunctionBegin; 45049566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 45059566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 45061dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 45079566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 45089566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 45091dca8a05SBarry 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); 45109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 45119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 45129566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 45139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 45141edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 45159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 45169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4517a47d0d45SMatthew G. Knepley } 45189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 45199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 45209566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 45219566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 45229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 45239566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 45249566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 45259566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 4526a47d0d45SMatthew G. Knepley { 4527a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 4528a47d0d45SMatthew G. Knepley 4529a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 45309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype)); 45319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 453221016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 453321016a8bSBarry Smith { 453421016a8bSBarry Smith PetscScalar *svertexCoords; 453521016a8bSBarry Smith PetscInt i; 45369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 45373612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 45389566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 45399566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 45409566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 454121016a8bSBarry Smith } 454221016a8bSBarry Smith #else 45439566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 45449566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 454521016a8bSBarry Smith #endif 45469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 4547a47d0d45SMatthew G. Knepley } 45489566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 45499566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 45509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 45519566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4552a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4553a47d0d45SMatthew G. Knepley } 4554a47d0d45SMatthew G. Knepley 4555c3edce3dSSatish Balay /*@ 4556b09969d6SVaclav Hapla DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output) 4557a47d0d45SMatthew G. Knepley 4558a47d0d45SMatthew G. Knepley Input Parameters: 4559a47d0d45SMatthew G. Knepley + comm - The communicator 4560a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 4561a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 456225b6865aSVaclav Hapla . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 456325b6865aSVaclav Hapla . NVertices - The global number of vertices, or PETSC_DECIDE 4564a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 4565a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 4566a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4567a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 4568a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4569a47d0d45SMatthew G. Knepley 4570d8d19677SJose E. Roman Output Parameters: 457118d54ad4SMichael Lange + dm - The DM 4572be8c289dSNicolas Barral . vertexSF - (Optional) SF describing complete vertex ownership 4573be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4574a47d0d45SMatthew G. Knepley 4575b09969d6SVaclav Hapla Notes: 4576b09969d6SVaclav Hapla This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), 4577b09969d6SVaclav Hapla DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel() 4578a47d0d45SMatthew G. Knepley 457925b6865aSVaclav Hapla See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters. 458025b6865aSVaclav Hapla See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters. 458125b6865aSVaclav Hapla 4582b09969d6SVaclav Hapla Level: intermediate 4583a47d0d45SMatthew G. Knepley 4584db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 4585a47d0d45SMatthew G. Knepley @*/ 4586d71ae5a4SJacob 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) 4587d71ae5a4SJacob Faibussowitsch { 4588a47d0d45SMatthew G. Knepley PetscSF sfVert; 4589a47d0d45SMatthew G. Knepley 4590a47d0d45SMatthew G. Knepley PetscFunctionBegin; 45919566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 45929566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 4593a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 4594064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 45959566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 45969566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 4597a47d0d45SMatthew G. Knepley if (interpolate) { 45985fd9971aSMatthew G. Knepley DM idm; 4599a47d0d45SMatthew G. Knepley 46009566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 46019566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 4602a47d0d45SMatthew G. Knepley *dm = idm; 4603a47d0d45SMatthew G. Knepley } 46049566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 460518d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 46069566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 4607a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4608a47d0d45SMatthew G. Knepley } 4609a47d0d45SMatthew G. Knepley 4610b09969d6SVaclav Hapla /*@C 4611b09969d6SVaclav Hapla DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output) 46129298eaa6SMatthew G Knepley 46139298eaa6SMatthew G Knepley Input Parameters: 4614b09969d6SVaclav Hapla + dm - The DM 4615b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4616325d53feSBarry Smith . numVertices - The number of vertices owned by this process, or PETSC_DETERMINE 46179298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 46185e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 46199298eaa6SMatthew G Knepley 4620b09969d6SVaclav Hapla Level: advanced 46219298eaa6SMatthew G Knepley 4622b09969d6SVaclav Hapla Notes: 4623b09969d6SVaclav Hapla Two triangles sharing a face 46249298eaa6SMatthew G Knepley $ 46259298eaa6SMatthew G Knepley $ 2 46269298eaa6SMatthew G Knepley $ / | \ 46279298eaa6SMatthew G Knepley $ / | \ 46289298eaa6SMatthew G Knepley $ / | \ 46299298eaa6SMatthew G Knepley $ 0 0 | 1 3 46309298eaa6SMatthew G Knepley $ \ | / 46319298eaa6SMatthew G Knepley $ \ | / 46329298eaa6SMatthew G Knepley $ \ | / 46339298eaa6SMatthew G Knepley $ 1 46349298eaa6SMatthew G Knepley would have input 46359298eaa6SMatthew G Knepley $ numCells = 2, numVertices = 4 46369298eaa6SMatthew G Knepley $ cells = [0 1 2 1 3 2] 46379298eaa6SMatthew G Knepley $ 46389298eaa6SMatthew G Knepley which would result in the DMPlex 46399298eaa6SMatthew G Knepley $ 46409298eaa6SMatthew G Knepley $ 4 46419298eaa6SMatthew G Knepley $ / | \ 46429298eaa6SMatthew G Knepley $ / | \ 46439298eaa6SMatthew G Knepley $ / | \ 46449298eaa6SMatthew G Knepley $ 2 0 | 1 5 46459298eaa6SMatthew G Knepley $ \ | / 46469298eaa6SMatthew G Knepley $ \ | / 46479298eaa6SMatthew G Knepley $ \ | / 46489298eaa6SMatthew G Knepley $ 3 46499298eaa6SMatthew G Knepley 4650325d53feSBarry Smith If numVertices is PETSC_DETERMINE, it is computed by PETSc as the maximum vertex index in cells + 1. 465125b6865aSVaclav Hapla 4652b09969d6SVaclav Hapla Not currently supported in Fortran. 46539298eaa6SMatthew G Knepley 4654db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 4655b09969d6SVaclav Hapla @*/ 4656d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 4657d71ae5a4SJacob Faibussowitsch { 4658961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 4659b09969d6SVaclav Hapla 4660b09969d6SVaclav Hapla PetscFunctionBegin; 46619566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 46629566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 466325b6865aSVaclav Hapla /* Get/check global number of vertices */ 466425b6865aSVaclav Hapla { 466525b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 466625b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 466725b6865aSVaclav Hapla 466825b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 466925b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 46709371c9d4SSatish Balay for (i = 0; i < len; i++) 46719371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 467225b6865aSVaclav Hapla ++NVerticesInCells; 467325b6865aSVaclav Hapla 467425b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 46759371c9d4SSatish Balay else 46769371c9d4SSatish 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); 467725b6865aSVaclav Hapla } 46789566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 467948a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 46809566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 46819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4682b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 4683ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 4684b09969d6SVaclav Hapla } 46859566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 46869566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 46879566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4688b09969d6SVaclav Hapla PetscFunctionReturn(0); 4689b09969d6SVaclav Hapla } 4690b09969d6SVaclav Hapla 4691b09969d6SVaclav Hapla /*@C 4692b09969d6SVaclav Hapla DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4693b09969d6SVaclav Hapla 4694b09969d6SVaclav Hapla Input Parameters: 4695b09969d6SVaclav Hapla + dm - The DM 4696b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4697b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4698b09969d6SVaclav Hapla 4699b09969d6SVaclav Hapla Level: advanced 4700b09969d6SVaclav Hapla 4701b09969d6SVaclav Hapla Notes: 4702b09969d6SVaclav Hapla Not currently supported in Fortran. 4703b09969d6SVaclav Hapla 4704db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 4705b09969d6SVaclav Hapla @*/ 4706d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 4707d71ae5a4SJacob Faibussowitsch { 4708b09969d6SVaclav Hapla PetscSection coordSection; 4709b09969d6SVaclav Hapla Vec coordinates; 4710b09969d6SVaclav Hapla DM cdm; 4711b09969d6SVaclav Hapla PetscScalar *coords; 47121edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 4713b09969d6SVaclav Hapla 4714b09969d6SVaclav Hapla PetscFunctionBegin; 47159566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 47169566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 47171dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 47189566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 47199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 47209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 47219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 47229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 47231edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 47249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 47259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4726b09969d6SVaclav Hapla } 47279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4728b09969d6SVaclav Hapla 47299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 47309566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 47319566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 47329566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 47339566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 47341edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 4735ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 4736b09969d6SVaclav Hapla } 47379566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 47389566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 47399566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 47409566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4741b09969d6SVaclav Hapla PetscFunctionReturn(0); 4742b09969d6SVaclav Hapla } 4743b09969d6SVaclav Hapla 4744b09969d6SVaclav Hapla /*@ 47453df08285SMatthew G. Knepley DMPlexCreateFromCellListPetsc - Create DMPLEX from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 47463df08285SMatthew G. Knepley 47473df08285SMatthew G. Knepley Collective on comm 4748b09969d6SVaclav Hapla 4749b09969d6SVaclav Hapla Input Parameters: 4750b09969d6SVaclav Hapla + comm - The communicator 4751b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 47523df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 47533df08285SMatthew G. Knepley . numVertices - The number of vertices owned by this process, or PETSC_DECIDE, only on process 0 47543df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 4755b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 47563df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0 4757b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 47583df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0 4759b09969d6SVaclav Hapla 4760b09969d6SVaclav Hapla Output Parameter: 47613df08285SMatthew G. Knepley . dm - The DM, which only has points on process 0 4762b09969d6SVaclav Hapla 4763b09969d6SVaclav Hapla Notes: 4764b09969d6SVaclav Hapla This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(), 4765b09969d6SVaclav Hapla DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList() 4766b09969d6SVaclav Hapla 476725b6865aSVaclav Hapla See DMPlexBuildFromCellList() for an example and details about the topology-related parameters. 476825b6865aSVaclav Hapla See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters. 47693df08285SMatthew G. Knepley See DMPlexCreateFromCellListParallelPetsc() for parallel input 477025b6865aSVaclav Hapla 4771b09969d6SVaclav Hapla Level: intermediate 4772b09969d6SVaclav Hapla 4773db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 47749298eaa6SMatthew G Knepley @*/ 4775d71ae5a4SJacob 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) 4776d71ae5a4SJacob Faibussowitsch { 47773df08285SMatthew G. Knepley PetscMPIInt rank; 47789298eaa6SMatthew G Knepley 47799298eaa6SMatthew G Knepley PetscFunctionBegin; 478028b400f6SJacob 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."); 47819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 47829566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 47839566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 47849566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 4785c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 47869566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 47879298eaa6SMatthew G Knepley if (interpolate) { 47885fd9971aSMatthew G. Knepley DM idm; 47899298eaa6SMatthew G Knepley 47909566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 47919566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 47929298eaa6SMatthew G Knepley *dm = idm; 47939298eaa6SMatthew G Knepley } 4794c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 47959566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 47969298eaa6SMatthew G Knepley PetscFunctionReturn(0); 47979298eaa6SMatthew G Knepley } 47989298eaa6SMatthew G Knepley 4799939f6067SMatthew G. Knepley /*@ 4800939f6067SMatthew 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 4801939f6067SMatthew G. Knepley 4802939f6067SMatthew G. Knepley Input Parameters: 4803c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension() 4804939f6067SMatthew G. Knepley . depth - The depth of the DAG 4805367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth 4806939f6067SMatthew G. Knepley . coneSize - The cone size of each point 4807939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 4808939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 4809367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim() 4810939f6067SMatthew G. Knepley 4811939f6067SMatthew G. Knepley Output Parameter: 4812939f6067SMatthew G. Knepley . dm - The DM 4813939f6067SMatthew G. Knepley 4814939f6067SMatthew G. Knepley Note: Two triangles sharing a face would have input 4815939f6067SMatthew G. Knepley $ depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 4816939f6067SMatthew G. Knepley $ cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 4817939f6067SMatthew G. Knepley $ vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 4818939f6067SMatthew G. Knepley $ 4819939f6067SMatthew G. Knepley which would result in the DMPlex 4820939f6067SMatthew G. Knepley $ 4821939f6067SMatthew G. Knepley $ 4 4822939f6067SMatthew G. Knepley $ / | \ 4823939f6067SMatthew G. Knepley $ / | \ 4824939f6067SMatthew G. Knepley $ / | \ 4825939f6067SMatthew G. Knepley $ 2 0 | 1 5 4826939f6067SMatthew G. Knepley $ \ | / 4827939f6067SMatthew G. Knepley $ \ | / 4828939f6067SMatthew G. Knepley $ \ | / 4829939f6067SMatthew G. Knepley $ 3 4830939f6067SMatthew G. Knepley $ 4831a4a685f2SJacob Faibussowitsch $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc() 4832939f6067SMatthew G. Knepley 4833939f6067SMatthew G. Knepley Level: advanced 4834939f6067SMatthew G. Knepley 4835db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 4836939f6067SMatthew G. Knepley @*/ 4837d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 4838d71ae5a4SJacob Faibussowitsch { 48399298eaa6SMatthew G Knepley Vec coordinates; 48409298eaa6SMatthew G Knepley PetscSection coordSection; 48419298eaa6SMatthew G Knepley PetscScalar *coords; 4842811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 48439298eaa6SMatthew G Knepley 48449298eaa6SMatthew G Knepley PetscFunctionBegin; 48459566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 48469566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 484763a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 48489298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 48499566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 48509298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 48519566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 4852ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 485397e052ccSToby Isaac } 48541dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 48559566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 48569298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 48579566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 48589566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 48599298eaa6SMatthew G Knepley } 48609566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 48619566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 48629298eaa6SMatthew G Knepley /* Build coordinates */ 48639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 48649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 48659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 48669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 48679298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 48689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 48699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 48709298eaa6SMatthew G Knepley } 48719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 48729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 48739566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 48749566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 48759566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 48769566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dimEmbed)); 48779566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 48789318fe57SMatthew G. Knepley if (vertexCoords) { 48799566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 48809298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 48819298eaa6SMatthew G Knepley PetscInt off; 48829298eaa6SMatthew G Knepley 48839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 4884ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 48859298eaa6SMatthew G Knepley } 48869318fe57SMatthew G. Knepley } 48879566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 48889566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 48899566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 48909298eaa6SMatthew G Knepley PetscFunctionReturn(0); 48919298eaa6SMatthew G Knepley } 48928415267dSToby Isaac 4893ca522641SMatthew G. Knepley /*@C 48948ca92349SMatthew G. Knepley DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file. 48958ca92349SMatthew G. Knepley 48968ca92349SMatthew G. Knepley + comm - The MPI communicator 48978ca92349SMatthew G. Knepley . filename - Name of the .dat file 48988ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 48998ca92349SMatthew G. Knepley 49008ca92349SMatthew G. Knepley Output Parameter: 49018ca92349SMatthew G. Knepley . dm - The DM object representing the mesh 49028ca92349SMatthew G. Knepley 49038ca92349SMatthew G. Knepley Note: The format is the simplest possible: 49048ca92349SMatthew G. Knepley $ Ne 49058ca92349SMatthew G. Knepley $ v0 v1 ... vk 49068ca92349SMatthew G. Knepley $ Nv 49078ca92349SMatthew G. Knepley $ x y z marker 49088ca92349SMatthew G. Knepley 49098ca92349SMatthew G. Knepley Level: beginner 49108ca92349SMatthew G. Knepley 4911db781477SPatrick Sanan .seealso: `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 49128ca92349SMatthew G. Knepley @*/ 4913d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 4914d71ae5a4SJacob Faibussowitsch { 49158ca92349SMatthew G. Knepley DMLabel marker; 49168ca92349SMatthew G. Knepley PetscViewer viewer; 49178ca92349SMatthew G. Knepley Vec coordinates; 49188ca92349SMatthew G. Knepley PetscSection coordSection; 49198ca92349SMatthew G. Knepley PetscScalar *coords; 49208ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 49218ca92349SMatthew G. Knepley PetscInt dim = 3, cdim = 3, coordSize, v, c, d; 49228ca92349SMatthew G. Knepley PetscMPIInt rank; 4923f8d5e320SMatthew G. Knepley int snum, Nv, Nc, Ncn, Nl; 49248ca92349SMatthew G. Knepley 49258ca92349SMatthew G. Knepley PetscFunctionBegin; 49269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 49279566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 49289566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 49299566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 49309566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 4931dd400576SPatrick Sanan if (rank == 0) { 49329566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING)); 4933f8d5e320SMatthew G. Knepley snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl); 493408401ef6SPierre Jolivet PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 493525ce1634SJed Brown } else { 4936f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 49378ca92349SMatthew G. Knepley } 49389566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 49399566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 49409566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 49419566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 49429566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 49438ca92349SMatthew G. Knepley /* Read topology */ 4944dd400576SPatrick Sanan if (rank == 0) { 4945f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 4946f8d5e320SMatthew G. Knepley PetscInt cone[8]; 49478ca92349SMatthew G. Knepley int vbuf[8], v; 49488ca92349SMatthew G. Knepley 49499371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 49509371c9d4SSatish Balay format[c * 3 + 0] = '%'; 49519371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 49529371c9d4SSatish Balay format[c * 3 + 2] = ' '; 49539371c9d4SSatish Balay } 4954f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 49559566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 49569566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 49578ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 49589566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 4959f8d5e320SMatthew G. Knepley switch (Ncn) { 4960d71ae5a4SJacob Faibussowitsch case 2: 4961d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 4962d71ae5a4SJacob Faibussowitsch break; 4963d71ae5a4SJacob Faibussowitsch case 3: 4964d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 4965d71ae5a4SJacob Faibussowitsch break; 4966d71ae5a4SJacob Faibussowitsch case 4: 4967d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 4968d71ae5a4SJacob Faibussowitsch break; 4969d71ae5a4SJacob Faibussowitsch case 6: 4970d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 4971d71ae5a4SJacob Faibussowitsch break; 4972d71ae5a4SJacob Faibussowitsch case 8: 4973d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 4974d71ae5a4SJacob Faibussowitsch break; 4975d71ae5a4SJacob Faibussowitsch default: 4976d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 4977f8d5e320SMatthew G. Knepley } 497808401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 4979f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 49808ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 4981f8d5e320SMatthew G. Knepley if (Ncn == 8) { 49828ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 49838ca92349SMatthew G. Knepley cone[1] = cone[3]; 49848ca92349SMatthew G. Knepley cone[3] = tmp; 49858ca92349SMatthew G. Knepley } 49869566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 49878ca92349SMatthew G. Knepley } 49888ca92349SMatthew G. Knepley } 49899566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 49909566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 49918ca92349SMatthew G. Knepley /* Read coordinates */ 49929566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 49939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 49949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 49959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 49968ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 49979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 49989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 49998ca92349SMatthew G. Knepley } 50009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 50019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 50029566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 50039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 50049566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 50059566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 50069566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 50079566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5008dd400576SPatrick Sanan if (rank == 0) { 5009f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 50108ca92349SMatthew G. Knepley double x[3]; 5011f8d5e320SMatthew G. Knepley int l, val[3]; 50128ca92349SMatthew G. Knepley 5013f8d5e320SMatthew G. Knepley if (Nl) { 50149371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 50159371c9d4SSatish Balay format[l * 3 + 0] = '%'; 50169371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 50179371c9d4SSatish Balay format[l * 3 + 2] = ' '; 50189371c9d4SSatish Balay } 5019f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 50209566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 50219566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 5022f8d5e320SMatthew G. Knepley } 50238ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 50249566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 5025f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 502608401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 5027f8d5e320SMatthew G. Knepley switch (Nl) { 5028d71ae5a4SJacob Faibussowitsch case 0: 5029d71ae5a4SJacob Faibussowitsch snum = 0; 5030d71ae5a4SJacob Faibussowitsch break; 5031d71ae5a4SJacob Faibussowitsch case 1: 5032d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 5033d71ae5a4SJacob Faibussowitsch break; 5034d71ae5a4SJacob Faibussowitsch case 2: 5035d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 5036d71ae5a4SJacob Faibussowitsch break; 5037d71ae5a4SJacob Faibussowitsch case 3: 5038d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 5039d71ae5a4SJacob Faibussowitsch break; 5040d71ae5a4SJacob Faibussowitsch default: 5041d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 5042f8d5e320SMatthew G. Knepley } 504308401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 50448ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 50459566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 50468ca92349SMatthew G. Knepley } 50478ca92349SMatthew G. Knepley } 50489566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 50499566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 50509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 50519566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 50528ca92349SMatthew G. Knepley if (interpolate) { 50538ca92349SMatthew G. Knepley DM idm; 50548ca92349SMatthew G. Knepley DMLabel bdlabel; 50558ca92349SMatthew G. Knepley 50569566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 50579566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 50588ca92349SMatthew G. Knepley *dm = idm; 50598ca92349SMatthew G. Knepley 5060f8d5e320SMatthew G. Knepley if (!Nl) { 50619566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 50629566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 50639566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 50649566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 50658ca92349SMatthew G. Knepley } 5066f8d5e320SMatthew G. Knepley } 50678ca92349SMatthew G. Knepley PetscFunctionReturn(0); 50688ca92349SMatthew G. Knepley } 50698ca92349SMatthew G. Knepley 50708ca92349SMatthew G. Knepley /*@C 5071ca522641SMatthew G. Knepley DMPlexCreateFromFile - This takes a filename and produces a DM 5072ca522641SMatthew G. Knepley 5073ca522641SMatthew G. Knepley Input Parameters: 5074ca522641SMatthew G. Knepley + comm - The communicator 5075ca522641SMatthew G. Knepley . filename - A file name 5076cd7e8a5eSksagiyam . plexname - The object name of the resulting DM, also used for intra-datafile lookup by some formats 5077ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 5078ca522641SMatthew G. Knepley 5079ca522641SMatthew G. Knepley Output Parameter: 5080ca522641SMatthew G. Knepley . dm - The DM 5081ca522641SMatthew G. Knepley 508202ef0d99SVaclav Hapla Options Database Keys: 508302ef0d99SVaclav Hapla . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5 508402ef0d99SVaclav Hapla 5085bca97951SVaclav Hapla Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g. 5086bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 5087bca97951SVaclav Hapla 5088cd7e8a5eSksagiyam Notes: 5089cd7e8a5eSksagiyam Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex 5090cd7e8a5eSksagiyam meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName() 5091cd7e8a5eSksagiyam before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object. 5092cd7e8a5eSksagiyam The input parameter name is thus used to name the DMPlex object when DMPlexCreateFromFile() internally 5093cd7e8a5eSksagiyam calls DMLoad(). Currently, name is ignored for other viewer types and/or formats. 5094cd7e8a5eSksagiyam 5095ca522641SMatthew G. Knepley Level: beginner 5096ca522641SMatthew G. Knepley 5097db781477SPatrick Sanan .seealso: `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 5098ca522641SMatthew G. Knepley @*/ 5099d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 5100d71ae5a4SJacob Faibussowitsch { 5101ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 5102ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 5103ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 5104ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 5105ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 5106ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 5107ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 5108ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 5109ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 5110ef3a5affSJacob Faibussowitsch const char extMed[] = ".med"; 5111ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 5112ef3a5affSJacob Faibussowitsch const char extEGADSLite[] = ".egadslite"; 5113ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 5114ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 5115ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 5116ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 5117ca522641SMatthew G. Knepley size_t len; 5118c1cad2e7SMatthew G. Knepley PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV; 5119ca522641SMatthew G. Knepley PetscMPIInt rank; 5120ca522641SMatthew G. Knepley 5121ca522641SMatthew G. Knepley PetscFunctionBegin; 51225d80c0bfSVaclav Hapla PetscValidCharPointer(filename, 2); 51230d862eaeSPierre Jolivet if (plexname) PetscValidCharPointer(plexname, 3); 5124cd7e8a5eSksagiyam PetscValidPointer(dm, 5); 51259566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 51269566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 51279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 51289566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 512928b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 5130ef3a5affSJacob Faibussowitsch 51319371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 51329371c9d4SSatish Balay do { \ 5133274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 5134274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 5135274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 5136274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 5137ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 5138ef3a5affSJacob Faibussowitsch } else { \ 5139274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 5140ef3a5affSJacob Faibussowitsch } \ 5141ef3a5affSJacob Faibussowitsch } while (0) 5142ef3a5affSJacob Faibussowitsch 5143ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 5144ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 5145ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 5146ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 5147ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 5148ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 5149ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 5150ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 5151ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 5152ef3a5affSJacob Faibussowitsch CheckExtension(extMed, isMed); 5153ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 5154ef3a5affSJacob Faibussowitsch CheckExtension(extEGADSLite, isEGADSLite); 5155ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 5156ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 5157ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 5158ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 5159ef3a5affSJacob Faibussowitsch 5160ef3a5affSJacob Faibussowitsch #undef CheckExtension 5161ef3a5affSJacob Faibussowitsch 5162de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 51639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 5164ca522641SMatthew G. Knepley } else if (isCGNS) { 51659566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 516690c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 51679566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 51682f0bd6dcSMichael Lange } else if (isFluent) { 51699566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 5170cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 51719c48423bSVaclav Hapla PetscBool load_hdf5_xdmf = PETSC_FALSE; 5172cc2f8f65SMatthew G. Knepley PetscViewer viewer; 5173cc2f8f65SMatthew G. Knepley 517443b242b4SVaclav 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 */ 51759566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf)); 51769566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL)); 51779566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 51789566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 51799566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 51809566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 51819566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 51829566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 5183cd7e8a5eSksagiyam 51849566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 51859566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 51869566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 51879566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 51889566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 51899566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer)); 51909566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 51915fd9971aSMatthew G. Knepley 51925fd9971aSMatthew G. Knepley if (interpolate) { 51935fd9971aSMatthew G. Knepley DM idm; 51945fd9971aSMatthew G. Knepley 51959566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 51969566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 51975fd9971aSMatthew G. Knepley *dm = idm; 51985fd9971aSMatthew G. Knepley } 5199707dd687SMichael Lange } else if (isMed) { 52009566063dSJacob Faibussowitsch PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm)); 5201f2801cd6SMatthew G. Knepley } else if (isPLY) { 52029566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 5203c1cad2e7SMatthew G. Knepley } else if (isEGADSLite || isEGADS || isIGES || isSTEP) { 52049566063dSJacob Faibussowitsch if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm)); 52059566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm)); 52067bee2925SMatthew Knepley if (!interpolate) { 52077bee2925SMatthew Knepley DM udm; 52087bee2925SMatthew Knepley 52099566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 52109566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 52117bee2925SMatthew Knepley *dm = udm; 52127bee2925SMatthew Knepley } 52138ca92349SMatthew G. Knepley } else if (isCV) { 52149566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 521598921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 52169566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 52179566063dSJacob Faibussowitsch if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 52189566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 5219ca522641SMatthew G. Knepley PetscFunctionReturn(0); 5220ca522641SMatthew G. Knepley } 5221