1552f7358SJed Brown #define PETSCDM_DLL 2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h> /*I "petscdmplex.h" I*/ 40c312b8eSJed Brown #include <petscsf.h> 54663dae6SJed Brown #include <petscdmplextransform.h> 69f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h> 7b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h> 8b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h> 9552f7358SJed Brown 10b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 1158cd63d5SVaclav Hapla 129318fe57SMatthew G. Knepley /* External function declarations here */ 139318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm); 149318fe57SMatthew G. Knepley 15e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */ 16d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout) 17d71ae5a4SJacob Faibussowitsch { 184fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 196858538eSMatthew G. Knepley PetscBool dist; 206bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 21e600fa54SMatthew G. Knepley 22e600fa54SMatthew G. Knepley PetscFunctionBegin; 23e600fa54SMatthew G. Knepley if (copyPeriodicity) { 244fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L)); 254fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L)); 26e600fa54SMatthew G. Knepley } 279566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dmin, &dist)); 289566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dmout, dist)); 296bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dmin, &reorder)); 306bc1bd01Sksagiyam PetscCall(DMPlexReorderSetDefault(dmout, reorder)); 31e600fa54SMatthew G. Knepley ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation; 321baa6e33SBarry Smith if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0)); 33e600fa54SMatthew G. Knepley PetscFunctionReturn(0); 34e600fa54SMatthew G. Knepley } 35e600fa54SMatthew G. Knepley 369318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 379318fe57SMatthew G. Knepley - Share the DM_Plex structure 389318fe57SMatthew G. Knepley - Share the coordinates 399318fe57SMatthew G. Knepley - Share the SF 409318fe57SMatthew G. Knepley */ 41d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm) 42d71ae5a4SJacob Faibussowitsch { 439318fe57SMatthew G. Knepley PetscSF sf; 449318fe57SMatthew G. Knepley DM dmNew = *ndm, coordDM, coarseDM; 459318fe57SMatthew G. Knepley Vec coords; 464fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 479318fe57SMatthew G. Knepley PetscInt dim, cdim; 489318fe57SMatthew G. Knepley 499318fe57SMatthew G. Knepley PetscFunctionBegin; 509318fe57SMatthew G. Knepley if (dm == dmNew) { 519566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 529318fe57SMatthew G. Knepley PetscFunctionReturn(0); 539318fe57SMatthew G. Knepley } 549318fe57SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 559566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmNew, &dim)); 569566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmNew, &cdim)); 589566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 599566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sf)); 609566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sf)); 619566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmNew, &coordDM)); 629566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmNew, &coords)); 639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dm, coordDM)); 649566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 656858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM)); 666858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords)); 676858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dm, coordDM)); 686858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 699318fe57SMatthew G. Knepley /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */ 706858538eSMatthew G. Knepley PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 716858538eSMatthew G. Knepley dm->coordinates[0].field = dmNew->coordinates[0].field; 7261a622f3SMatthew G. Knepley ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc; 734fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 744fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 759566063dSJacob Faibussowitsch PetscCall(DMDestroy_Plex(dm)); 769566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 779318fe57SMatthew G. Knepley dm->data = dmNew->data; 789318fe57SMatthew G. Knepley ((DM_Plex *)dmNew->data)->refct++; 79*5f06a3ddSJed Brown PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &sf)); 80*5f06a3ddSJed Brown PetscCall(DMPlexSetIsoperiodicFaceSF(dm, sf)); // for the compose function effect on dm 819566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 829566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 839566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmNew, &coarseDM)); 849566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 859566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 869318fe57SMatthew G. Knepley PetscFunctionReturn(0); 879318fe57SMatthew G. Knepley } 889318fe57SMatthew G. Knepley 899318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew 909318fe57SMatthew G. Knepley - Swap the DM_Plex structure 919318fe57SMatthew G. Knepley - Swap the coordinates 929318fe57SMatthew G. Knepley - Swap the point PetscSF 939318fe57SMatthew G. Knepley */ 94d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 95d71ae5a4SJacob Faibussowitsch { 969318fe57SMatthew G. Knepley DM coordDMA, coordDMB; 979318fe57SMatthew G. Knepley Vec coordsA, coordsB; 989318fe57SMatthew G. Knepley PetscSF sfA, sfB; 999318fe57SMatthew G. Knepley DMField fieldTmp; 1009318fe57SMatthew G. Knepley void *tmp; 1019318fe57SMatthew G. Knepley DMLabelLink listTmp; 1029318fe57SMatthew G. Knepley DMLabel depthTmp; 1039318fe57SMatthew G. Knepley PetscInt tmpI; 1049318fe57SMatthew G. Knepley 1059318fe57SMatthew G. Knepley PetscFunctionBegin; 1069318fe57SMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 1079566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmA, &sfA)); 1089566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmB, &sfB)); 1099566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sfA)); 1109566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmA, sfB)); 1119566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmB, sfA)); 1129566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)sfA)); 1139318fe57SMatthew G. Knepley 1149566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &coordDMA)); 1159566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &coordDMB)); 1169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordDMA)); 1179566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmA, coordDMB)); 1189566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmB, coordDMA)); 1199566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 1209318fe57SMatthew G. Knepley 1219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordsA)); 1229566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmB, &coordsB)); 1239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordsA)); 1249566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmA, coordsB)); 1259566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordsA)); 1269566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordsA)); 1279318fe57SMatthew G. Knepley 1286858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA)); 1296858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB)); 1306858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordDMA)); 1316858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmA, coordDMB)); 1326858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmB, coordDMA)); 1336858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 1346858538eSMatthew G. Knepley 1356858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA)); 1366858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB)); 1376858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordsA)); 1386858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB)); 1396858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA)); 1406858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordsA)); 1416858538eSMatthew G. Knepley 1426858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[0].field; 1436858538eSMatthew G. Knepley dmA->coordinates[0].field = dmB->coordinates[0].field; 1446858538eSMatthew G. Knepley dmB->coordinates[0].field = fieldTmp; 1456858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[1].field; 1466858538eSMatthew G. Knepley dmA->coordinates[1].field = dmB->coordinates[1].field; 1476858538eSMatthew G. Knepley dmB->coordinates[1].field = fieldTmp; 1489318fe57SMatthew G. Knepley tmp = dmA->data; 1499318fe57SMatthew G. Knepley dmA->data = dmB->data; 1509318fe57SMatthew G. Knepley dmB->data = tmp; 1519318fe57SMatthew G. Knepley listTmp = dmA->labels; 1529318fe57SMatthew G. Knepley dmA->labels = dmB->labels; 1539318fe57SMatthew G. Knepley dmB->labels = listTmp; 1549318fe57SMatthew G. Knepley depthTmp = dmA->depthLabel; 1559318fe57SMatthew G. Knepley dmA->depthLabel = dmB->depthLabel; 1569318fe57SMatthew G. Knepley dmB->depthLabel = depthTmp; 1579318fe57SMatthew G. Knepley depthTmp = dmA->celltypeLabel; 1589318fe57SMatthew G. Knepley dmA->celltypeLabel = dmB->celltypeLabel; 1599318fe57SMatthew G. Knepley dmB->celltypeLabel = depthTmp; 1609318fe57SMatthew G. Knepley tmpI = dmA->levelup; 1619318fe57SMatthew G. Knepley dmA->levelup = dmB->levelup; 1629318fe57SMatthew G. Knepley dmB->levelup = tmpI; 1639318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1649318fe57SMatthew G. Knepley } 1659318fe57SMatthew G. Knepley 1663431e603SJed Brown PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) 167d71ae5a4SJacob Faibussowitsch { 1689318fe57SMatthew G. Knepley DM idm; 1699318fe57SMatthew G. Knepley 1709318fe57SMatthew G. Knepley PetscFunctionBegin; 1719566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 1729566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 17369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 1749318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1759318fe57SMatthew G. Knepley } 1769318fe57SMatthew G. Knepley 1779318fe57SMatthew G. Knepley /*@C 1789318fe57SMatthew G. Knepley DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates 1799318fe57SMatthew G. Knepley 180a1cb98faSBarry Smith Collective on dm 1819318fe57SMatthew G. Knepley 1829318fe57SMatthew G. Knepley Input Parameters: 1839318fe57SMatthew G. Knepley + DM - The DM 1844f9ab2b4SJed Brown . degree - The degree of the finite element or PETSC_DECIDE 1859318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface 1869318fe57SMatthew G. Knepley 1879318fe57SMatthew G. Knepley Level: advanced 1889318fe57SMatthew G. Knepley 189a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscPointFunc`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()` 1909318fe57SMatthew G. Knepley @*/ 191d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc) 192d71ae5a4SJacob Faibussowitsch { 1939318fe57SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1949318fe57SMatthew G. Knepley DM cdm; 1959318fe57SMatthew G. Knepley PetscDS cds; 1969318fe57SMatthew G. Knepley PetscFE fe; 1979318fe57SMatthew G. Knepley PetscClassId id; 1989318fe57SMatthew G. Knepley 1999318fe57SMatthew G. Knepley PetscFunctionBegin; 2009566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 2019566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 2029566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, (PetscObject *)&fe)); 2039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 2049318fe57SMatthew G. Knepley if (id != PETSCFE_CLASSID) { 2059318fe57SMatthew G. Knepley PetscInt dim, dE, qorder; 2069318fe57SMatthew G. Knepley 2079566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 2089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 2099318fe57SMatthew G. Knepley qorder = degree; 210d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)cdm); 211dc431b0cSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0)); 212d0609cedSBarry Smith PetscOptionsEnd(); 2134f9ab2b4SJed Brown if (degree == PETSC_DECIDE) fe = NULL; 2144f9ab2b4SJed Brown else { 215dc431b0cSMatthew G. Knepley DMPolytopeType ct; 216dc431b0cSMatthew G. Knepley PetscInt cStart, cEnd, ctTmp; 217dc431b0cSMatthew G. Knepley 218dc431b0cSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 219dc431b0cSMatthew G. Knepley // Want to match cell types 220dc431b0cSMatthew G. Knepley if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 221dc431b0cSMatthew G. Knepley else ct = DM_POLYTOPE_UNKNOWN; 222dc431b0cSMatthew G. Knepley ctTmp = (PetscInt)ct; 223dc431b0cSMatthew G. Knepley PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &ctTmp, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm))); 224dc431b0cSMatthew G. Knepley ct = (DMPolytopeType)ctTmp; 225dc431b0cSMatthew G. Knepley // Work around current bug 226dc431b0cSMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) fe = NULL; 227dc431b0cSMatthew G. Knepley else PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe)); 2284f9ab2b4SJed Brown } 229dc431b0cSMatthew G. Knepley if (fe) PetscCall(DMProjectCoordinates(dm, fe)); 2309566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 2319318fe57SMatthew G. Knepley } 2329318fe57SMatthew G. Knepley mesh->coordFunc = coordFunc; 2339318fe57SMatthew G. Knepley PetscFunctionReturn(0); 2349318fe57SMatthew G. Knepley } 2359318fe57SMatthew G. Knepley 2361df5d5c5SMatthew G. Knepley /*@ 2371df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 2381df5d5c5SMatthew G. Knepley 239d083f849SBarry Smith Collective 2401df5d5c5SMatthew G. Knepley 2411df5d5c5SMatthew G. Knepley Input Parameters: 242a1cb98faSBarry Smith + comm - The communicator for the `DM` object 2431df5d5c5SMatthew G. Knepley . dim - The spatial dimension 2441df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 2451df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 2461df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 2471df5d5c5SMatthew G. Knepley 2481df5d5c5SMatthew G. Knepley Output Parameter: 249a1cb98faSBarry Smith . dm - The `DM` object 2501df5d5c5SMatthew G. Knepley 2511df5d5c5SMatthew G. Knepley Level: beginner 2521df5d5c5SMatthew G. Knepley 253a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()` 2541df5d5c5SMatthew G. Knepley @*/ 255d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) 256d71ae5a4SJacob Faibussowitsch { 2571df5d5c5SMatthew G. Knepley DM dm; 2581df5d5c5SMatthew G. Knepley PetscMPIInt rank; 2591df5d5c5SMatthew G. Knepley 2601df5d5c5SMatthew G. Knepley PetscFunctionBegin; 2619566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &dm)); 2629566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 2639566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 2649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 265ce78fa2fSMatthew G. Knepley switch (dim) { 266ce78fa2fSMatthew G. Knepley case 2: 2679566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular")); 2689566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral")); 269ce78fa2fSMatthew G. Knepley break; 270ce78fa2fSMatthew G. Knepley case 3: 2719566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral")); 2729566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral")); 273ce78fa2fSMatthew G. Knepley break; 274d71ae5a4SJacob Faibussowitsch default: 275d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 276ce78fa2fSMatthew G. Knepley } 2771df5d5c5SMatthew G. Knepley if (rank) { 2781df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 2799566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 2801df5d5c5SMatthew G. Knepley } else { 2811df5d5c5SMatthew G. Knepley switch (dim) { 2821df5d5c5SMatthew G. Knepley case 2: 2831df5d5c5SMatthew G. Knepley if (simplex) { 2841df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 2851df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 2861df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 2871df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 2881df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 2891df5d5c5SMatthew G. Knepley 2909566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2911df5d5c5SMatthew G. Knepley } else { 2921df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 2931df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 2941df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 2951df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2961df5d5c5SMatthew 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}; 2971df5d5c5SMatthew G. Knepley 2989566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2991df5d5c5SMatthew G. Knepley } 3001df5d5c5SMatthew G. Knepley break; 3011df5d5c5SMatthew G. Knepley case 3: 3021df5d5c5SMatthew G. Knepley if (simplex) { 3031df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 3041df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 3051df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 3061df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 3071df5d5c5SMatthew 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}; 3081df5d5c5SMatthew G. Knepley 3099566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 3101df5d5c5SMatthew G. Knepley } else { 3111df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 3121df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 3131df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 3141df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 3159371c9d4SSatish 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}; 3161df5d5c5SMatthew G. Knepley 3179566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 3181df5d5c5SMatthew G. Knepley } 3191df5d5c5SMatthew G. Knepley break; 320d71ae5a4SJacob Faibussowitsch default: 321d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 3221df5d5c5SMatthew G. Knepley } 3231df5d5c5SMatthew G. Knepley } 3241df5d5c5SMatthew G. Knepley *newdm = dm; 3251df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 3261df5d5c5SMatthew G. Knepley DM rdm; 3271df5d5c5SMatthew G. Knepley const char *name; 3281df5d5c5SMatthew G. Knepley 3299566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 3309566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 3319566063dSJacob Faibussowitsch PetscCall(DMRefine(*newdm, comm, &rdm)); 3329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)*newdm, &name)); 3339566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, name)); 3349566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 3351df5d5c5SMatthew G. Knepley *newdm = rdm; 3361df5d5c5SMatthew G. Knepley } 3371df5d5c5SMatthew G. Knepley if (interpolate) { 3385fd9971aSMatthew G. Knepley DM idm; 3391df5d5c5SMatthew G. Knepley 3409566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*newdm, &idm)); 3419566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 3421df5d5c5SMatthew G. Knepley *newdm = idm; 3431df5d5c5SMatthew G. Knepley } 3441df5d5c5SMatthew G. Knepley PetscFunctionReturn(0); 3451df5d5c5SMatthew G. Knepley } 3461df5d5c5SMatthew G. Knepley 347d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 348d71ae5a4SJacob Faibussowitsch { 3499318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 3509318fe57SMatthew G. Knepley PetscInt markerRight = 1; 3519318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 3529318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 3539318fe57SMatthew G. Knepley Vec coordinates; 3549318fe57SMatthew G. Knepley PetscSection coordSection; 3559318fe57SMatthew G. Knepley PetscScalar *coords; 3569318fe57SMatthew G. Knepley PetscInt coordSize; 3579318fe57SMatthew G. Knepley PetscMPIInt rank; 3589318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 359552f7358SJed Brown 3609318fe57SMatthew G. Knepley PetscFunctionBegin; 3619566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 3629318fe57SMatthew G. Knepley if (markerSeparate) { 3639318fe57SMatthew G. Knepley markerRight = 2; 3649318fe57SMatthew G. Knepley markerLeft = 1; 3659318fe57SMatthew G. Knepley } 3669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 367c5853193SPierre Jolivet if (rank == 0) { 3689566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numVertices)); 3699566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3709566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft)); 3719566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight)); 3729318fe57SMatthew G. Knepley } 3739566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 3749566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 3759318fe57SMatthew G. Knepley /* Build coordinates */ 3769566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 3779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 3789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 3799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, 0, numVertices)); 3809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 3819318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 3829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 3839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 3849318fe57SMatthew G. Knepley } 3859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 3869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 3879566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 3889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 3899566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 3909566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 3919566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 3929566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 3939318fe57SMatthew G. Knepley coords[0] = lower[0]; 3949318fe57SMatthew G. Knepley coords[1] = upper[0]; 3959566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 3969566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 3979566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 3989318fe57SMatthew G. Knepley PetscFunctionReturn(0); 3999318fe57SMatthew G. Knepley } 40026492d91SMatthew G. Knepley 401d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 402d71ae5a4SJacob Faibussowitsch { 4031df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0] + 1) * (edges[1] + 1); 4041df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1]; 405552f7358SJed Brown PetscInt markerTop = 1; 406552f7358SJed Brown PetscInt markerBottom = 1; 407552f7358SJed Brown PetscInt markerRight = 1; 408552f7358SJed Brown PetscInt markerLeft = 1; 409552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 410552f7358SJed Brown Vec coordinates; 411552f7358SJed Brown PetscSection coordSection; 412552f7358SJed Brown PetscScalar *coords; 413552f7358SJed Brown PetscInt coordSize; 414552f7358SJed Brown PetscMPIInt rank; 415552f7358SJed Brown PetscInt v, vx, vy; 416552f7358SJed Brown 417552f7358SJed Brown PetscFunctionBegin; 4189566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 419552f7358SJed Brown if (markerSeparate) { 4201df21d24SMatthew G. Knepley markerTop = 3; 4211df21d24SMatthew G. Knepley markerBottom = 1; 4221df21d24SMatthew G. Knepley markerRight = 2; 4231df21d24SMatthew G. Knepley markerLeft = 4; 424552f7358SJed Brown } 4259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 426dd400576SPatrick Sanan if (rank == 0) { 427552f7358SJed Brown PetscInt e, ex, ey; 428552f7358SJed Brown 4299566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices)); 43048a46eb9SPierre Jolivet for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 4319566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 432552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 433552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 434552f7358SJed Brown PetscInt edge = vx * edges[1] + ey + edges[0] * (edges[1] + 1); 435552f7358SJed Brown PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges; 436da80777bSKarl Rupp PetscInt cone[2]; 437552f7358SJed Brown 4389371c9d4SSatish Balay cone[0] = vertex; 4399371c9d4SSatish Balay cone[1] = vertex + edges[0] + 1; 4409566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 441552f7358SJed Brown if (vx == edges[0]) { 4429566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 4439566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 444552f7358SJed Brown if (ey == edges[1] - 1) { 4459566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 4469566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 447552f7358SJed Brown } 448552f7358SJed Brown } else if (vx == 0) { 4499566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 4509566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 451552f7358SJed Brown if (ey == edges[1] - 1) { 4529566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 4539566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 454552f7358SJed Brown } 455552f7358SJed Brown } 456552f7358SJed Brown } 457552f7358SJed Brown } 458552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 459552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 460552f7358SJed Brown PetscInt edge = vy * edges[0] + ex; 461552f7358SJed Brown PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges; 462da80777bSKarl Rupp PetscInt cone[2]; 463552f7358SJed Brown 4649371c9d4SSatish Balay cone[0] = vertex; 4659371c9d4SSatish Balay cone[1] = vertex + 1; 4669566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 467552f7358SJed Brown if (vy == edges[1]) { 4689566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 4699566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 470552f7358SJed Brown if (ex == edges[0] - 1) { 4719566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 4729566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 473552f7358SJed Brown } 474552f7358SJed Brown } else if (vy == 0) { 4759566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 4769566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 477552f7358SJed Brown if (ex == edges[0] - 1) { 4789566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 4799566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 480552f7358SJed Brown } 481552f7358SJed Brown } 482552f7358SJed Brown } 483552f7358SJed Brown } 484552f7358SJed Brown } 4859566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 4869566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 487552f7358SJed Brown /* Build coordinates */ 4889566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 2)); 4899566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 4909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 4919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 4929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 493552f7358SJed Brown for (v = numEdges; v < numEdges + numVertices; ++v) { 4949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 2)); 4959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 496552f7358SJed Brown } 4979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 4999566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 5009566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 5019566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 5029566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 2)); 5039566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 5049566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 505552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 506552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 507552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx; 508552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy; 509552f7358SJed Brown } 510552f7358SJed Brown } 5119566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 5129566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 5139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 514552f7358SJed Brown PetscFunctionReturn(0); 515552f7358SJed Brown } 516552f7358SJed Brown 517d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 518d71ae5a4SJacob Faibussowitsch { 5199e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 5207b59f5a9SMichael Lange PetscInt numFaces = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2]; 521c2df9bbfSMatthew G. Knepley PetscInt markerTop = 1; 522c2df9bbfSMatthew G. Knepley PetscInt markerBottom = 1; 523c2df9bbfSMatthew G. Knepley PetscInt markerFront = 1; 524c2df9bbfSMatthew G. Knepley PetscInt markerBack = 1; 525c2df9bbfSMatthew G. Knepley PetscInt markerRight = 1; 526c2df9bbfSMatthew G. Knepley PetscInt markerLeft = 1; 527c2df9bbfSMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 528552f7358SJed Brown Vec coordinates; 529552f7358SJed Brown PetscSection coordSection; 530552f7358SJed Brown PetscScalar *coords; 531552f7358SJed Brown PetscInt coordSize; 532552f7358SJed Brown PetscMPIInt rank; 533552f7358SJed Brown PetscInt v, vx, vy, vz; 5347b59f5a9SMichael Lange PetscInt voffset, iface = 0, cone[4]; 535552f7358SJed Brown 536552f7358SJed Brown PetscFunctionBegin; 5371dca8a05SBarry 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"); 5389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 539c2df9bbfSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 540c2df9bbfSMatthew G. Knepley if (markerSeparate) { 541c2df9bbfSMatthew G. Knepley markerBottom = 1; 542c2df9bbfSMatthew G. Knepley markerTop = 2; 543c2df9bbfSMatthew G. Knepley markerFront = 3; 544c2df9bbfSMatthew G. Knepley markerBack = 4; 545c2df9bbfSMatthew G. Knepley markerRight = 5; 546c2df9bbfSMatthew G. Knepley markerLeft = 6; 547c2df9bbfSMatthew G. Knepley } 5489371c9d4SSatish Balay vertices[0] = faces[0] + 1; 5499371c9d4SSatish Balay vertices[1] = faces[1] + 1; 5509371c9d4SSatish Balay vertices[2] = faces[2] + 1; 5519e8abbc3SMichael Lange numVertices = vertices[0] * vertices[1] * vertices[2]; 552dd400576SPatrick Sanan if (rank == 0) { 553552f7358SJed Brown PetscInt f; 554552f7358SJed Brown 5559566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices)); 55648a46eb9SPierre Jolivet for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 5579566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 5587b59f5a9SMichael Lange 5597b59f5a9SMichael Lange /* Side 0 (Top) */ 5607b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5617b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5627b59f5a9SMichael Lange voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx; 5639371c9d4SSatish Balay cone[0] = voffset; 5649371c9d4SSatish Balay cone[1] = voffset + 1; 5659371c9d4SSatish Balay cone[2] = voffset + vertices[0] + 1; 5669371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 5679566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 568c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop)); 569c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop)); 570c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop)); 571c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop)); 572c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop)); 5737b59f5a9SMichael Lange iface++; 574552f7358SJed Brown } 575552f7358SJed Brown } 5767b59f5a9SMichael Lange 5777b59f5a9SMichael Lange /* Side 1 (Bottom) */ 5787b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5797b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5807b59f5a9SMichael Lange voffset = numFaces + vy * (faces[0] + 1) + vx; 5819371c9d4SSatish Balay cone[0] = voffset + 1; 5829371c9d4SSatish Balay cone[1] = voffset; 5839371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 5849371c9d4SSatish Balay cone[3] = voffset + vertices[0] + 1; 5859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 586c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom)); 587c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom)); 588c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom)); 589c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom)); 590c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom)); 5917b59f5a9SMichael Lange iface++; 592552f7358SJed Brown } 593552f7358SJed Brown } 5947b59f5a9SMichael Lange 5957b59f5a9SMichael Lange /* Side 2 (Front) */ 5967b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 5977b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5987b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vx; 5999371c9d4SSatish Balay cone[0] = voffset; 6009371c9d4SSatish Balay cone[1] = voffset + 1; 6019371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + 1; 6029371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1]; 6039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 604c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront)); 605c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront)); 606c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront)); 607c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront)); 608c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront)); 6097b59f5a9SMichael Lange iface++; 610552f7358SJed Brown } 6117b59f5a9SMichael Lange } 6127b59f5a9SMichael Lange 6137b59f5a9SMichael Lange /* Side 3 (Back) */ 6147b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6157b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 6167b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx; 6179371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 6189371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1] + 1; 6199371c9d4SSatish Balay cone[2] = voffset + 1; 6209371c9d4SSatish Balay cone[3] = voffset; 6219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 622c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack)); 623c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack)); 624c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack)); 625c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack)); 626c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack)); 6277b59f5a9SMichael Lange iface++; 6287b59f5a9SMichael Lange } 6297b59f5a9SMichael Lange } 6307b59f5a9SMichael Lange 6317b59f5a9SMichael Lange /* Side 4 (Left) */ 6327b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6337b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 6347b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0]; 6359371c9d4SSatish Balay cone[0] = voffset; 6369371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1]; 6379371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + vertices[0]; 6389371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 6399566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 640c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft)); 641c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft)); 642c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft)); 643c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft)); 644c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft)); 6457b59f5a9SMichael Lange iface++; 6467b59f5a9SMichael Lange } 6477b59f5a9SMichael Lange } 6487b59f5a9SMichael Lange 6497b59f5a9SMichael Lange /* Side 5 (Right) */ 6507b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6517b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 652aab5bcd8SJed Brown voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0]; 6539371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 6549371c9d4SSatish Balay cone[1] = voffset; 6559371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 6569371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1] + vertices[0]; 6579566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 658c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight)); 659c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight)); 660c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight)); 661c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight)); 662c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight)); 6637b59f5a9SMichael Lange iface++; 6647b59f5a9SMichael Lange } 665552f7358SJed Brown } 666552f7358SJed Brown } 6679566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 6689566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 669552f7358SJed Brown /* Build coordinates */ 6709566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 3)); 6719566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 6729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 6749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 675552f7358SJed Brown for (v = numFaces; v < numFaces + numVertices; ++v) { 6769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 3)); 6779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 678552f7358SJed Brown } 6799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 6819566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 6829566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 6839566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6849566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 3)); 6859566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 6869566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 687552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 688552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 689552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 690552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx; 691552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy; 692552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz; 693552f7358SJed Brown } 694552f7358SJed Brown } 695552f7358SJed Brown } 6969566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 6979566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 6989566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 699552f7358SJed Brown PetscFunctionReturn(0); 700552f7358SJed Brown } 701552f7358SJed Brown 702d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) 703d71ae5a4SJacob Faibussowitsch { 7049318fe57SMatthew G. Knepley PetscFunctionBegin; 7059318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 7069566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim - 1)); 7079566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim)); 7089318fe57SMatthew G. Knepley switch (dim) { 709d71ae5a4SJacob Faibussowitsch case 1: 710d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); 711d71ae5a4SJacob Faibussowitsch break; 712d71ae5a4SJacob Faibussowitsch case 2: 713d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); 714d71ae5a4SJacob Faibussowitsch break; 715d71ae5a4SJacob Faibussowitsch case 3: 716d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); 717d71ae5a4SJacob Faibussowitsch break; 718d71ae5a4SJacob Faibussowitsch default: 719d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim); 7209318fe57SMatthew G. Knepley } 7219566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 7229318fe57SMatthew G. Knepley PetscFunctionReturn(0); 7239318fe57SMatthew G. Knepley } 7249318fe57SMatthew G. Knepley 7259318fe57SMatthew G. Knepley /*@C 7269318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 7279318fe57SMatthew G. Knepley 7289318fe57SMatthew G. Knepley Collective 7299318fe57SMatthew G. Knepley 7309318fe57SMatthew G. Knepley Input Parameters: 731a1cb98faSBarry Smith + comm - The communicator for the `DM` object 7329318fe57SMatthew G. Knepley . dim - The spatial dimension of the box, so the resulting mesh is has dimension dim-1 7339318fe57SMatthew 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 7349318fe57SMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 7359318fe57SMatthew G. Knepley . upper - The upper right corner, or NULL for (1, 1, 1) 7369318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 7379318fe57SMatthew G. Knepley 7389318fe57SMatthew G. Knepley Output Parameter: 739a1cb98faSBarry Smith . dm - The `DM` object 7409318fe57SMatthew G. Knepley 7419318fe57SMatthew G. Knepley Level: beginner 7429318fe57SMatthew G. Knepley 743a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()` 7449318fe57SMatthew G. Knepley @*/ 745d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 746d71ae5a4SJacob Faibussowitsch { 7479318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 7489318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 7499318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 7509318fe57SMatthew G. Knepley 7519318fe57SMatthew G. Knepley PetscFunctionBegin; 7529566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 7539566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 7549566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 7559318fe57SMatthew G. Knepley PetscFunctionReturn(0); 7569318fe57SMatthew G. Knepley } 7579318fe57SMatthew G. Knepley 758d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) 759d71ae5a4SJacob Faibussowitsch { 760fdbf62faSLisandro Dalcin PetscInt i, fStart, fEnd, numCells = 0, numVerts = 0; 761fdbf62faSLisandro Dalcin PetscInt numPoints[2], *coneSize, *cones, *coneOrientations; 762fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 763fdbf62faSLisandro Dalcin PetscReal L, maxCell; 764fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 765fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 766fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 767fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 768fdbf62faSLisandro Dalcin PetscMPIInt rank; 769fdbf62faSLisandro Dalcin 770fdbf62faSLisandro Dalcin PetscFunctionBegin; 7719318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 772fdbf62faSLisandro Dalcin 7739566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, 1)); 7749566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 7759566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 776fdbf62faSLisandro Dalcin 7779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 778dd400576SPatrick Sanan if (rank == 0) numCells = segments; 779dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 780fdbf62faSLisandro Dalcin 7819371c9d4SSatish Balay numPoints[0] = numVerts; 7829371c9d4SSatish Balay numPoints[1] = numCells; 7839566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords)); 7849566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts)); 785ad540459SPierre Jolivet for (i = 0; i < numCells; ++i) coneSize[i] = 2; 786ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0; 7879371c9d4SSatish Balay for (i = 0; i < numCells; ++i) { 7889371c9d4SSatish Balay cones[2 * i] = numCells + i % numVerts; 7899371c9d4SSatish Balay cones[2 * i + 1] = numCells + (i + 1) % numVerts; 7909371c9d4SSatish Balay } 791ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); 7929566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 7939566063dSJacob Faibussowitsch PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords)); 794fdbf62faSLisandro Dalcin 7959566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 7969371c9d4SSatish Balay if (markerSeparate) { 7979371c9d4SSatish Balay markerLeft = faceMarkerLeft; 7989371c9d4SSatish Balay markerRight = faceMarkerRight; 7999371c9d4SSatish Balay } 800dd400576SPatrick Sanan if (!wrap && rank == 0) { 8019566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 8029566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft)); 8039566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight)); 8049566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft)); 8059566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight)); 806fdbf62faSLisandro Dalcin } 807fdbf62faSLisandro Dalcin if (wrap) { 808fdbf62faSLisandro Dalcin L = upper - lower; 809fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments)); 8104fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L)); 811fdbf62faSLisandro Dalcin } 8129566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 813fdbf62faSLisandro Dalcin PetscFunctionReturn(0); 814fdbf62faSLisandro Dalcin } 815fdbf62faSLisandro Dalcin 816d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 817d71ae5a4SJacob Faibussowitsch { 8189318fe57SMatthew G. Knepley DM boundary, vol; 819c22d3578SMatthew G. Knepley DMLabel bdlabel; 820d6218766SMatthew G. Knepley 821d6218766SMatthew G. Knepley PetscFunctionBegin; 8229318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 823c22d3578SMatthew 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"); 8249566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary)); 8259566063dSJacob Faibussowitsch PetscCall(DMSetType(boundary, DMPLEX)); 8269566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 8279566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 828c22d3578SMatthew G. Knepley PetscCall(DMGetLabel(vol, "marker", &bdlabel)); 829c22d3578SMatthew G. Knepley if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel)); 8305de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol)); 83169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 8329566063dSJacob Faibussowitsch PetscCall(DMDestroy(&boundary)); 833d6218766SMatthew G. Knepley PetscFunctionReturn(0); 834d6218766SMatthew G. Knepley } 835d6218766SMatthew G. Knepley 836d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 837d71ae5a4SJacob Faibussowitsch { 838ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 839f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 840f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 841f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 842f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 843f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 844f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 8453dfda0b1SToby Isaac PetscInt dim; 846d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 8473dfda0b1SToby Isaac PetscMPIInt rank; 8483dfda0b1SToby Isaac 8493dfda0b1SToby Isaac PetscFunctionBegin; 8509566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8529566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 8539566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 8549566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 8559371c9d4SSatish 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) { 8569371c9d4SSatish Balay if (cutMarker) { 8579371c9d4SSatish Balay PetscCall(DMCreateLabel(dm, "periodic_cut")); 8589371c9d4SSatish Balay PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 8599371c9d4SSatish Balay } 860d8211ee3SMatthew G. Knepley } 8613dfda0b1SToby Isaac switch (dim) { 8623dfda0b1SToby Isaac case 2: 863f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 864f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 865f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 866f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 8673dfda0b1SToby Isaac break; 8683dfda0b1SToby Isaac case 3: 869f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 870f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 871f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 872f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 873f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 874f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 8753dfda0b1SToby Isaac break; 876d71ae5a4SJacob Faibussowitsch default: 877d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 8783dfda0b1SToby Isaac } 8799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 880f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 881f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 882f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 883f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 884f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 885f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 886f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 8873dfda0b1SToby Isaac } 8883dfda0b1SToby Isaac { 889dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 890dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 891dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 892dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0; 893dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0; 894dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0; 8953dfda0b1SToby Isaac const PetscInt numCells = numXEdges * numYEdges * numZEdges; 8963dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges * numZEdges; 8973dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges * numZEdges; 8983dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges * numYEdges; 8993dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices * numXFaces; 9003dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices * numYFaces; 9013dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices * numZFaces; 9023dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 9033dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices; 9043dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices; 9053dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices; 9063dfda0b1SToby Isaac const PetscInt numVertices = numXVertices * numYVertices * numZVertices; 9073dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 9083dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 9093dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 9103dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 9113dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 9123dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 9133dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 9143dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 9153dfda0b1SToby Isaac Vec coordinates; 9163dfda0b1SToby Isaac PetscSection coordSection; 9173dfda0b1SToby Isaac PetscScalar *coords; 9183dfda0b1SToby Isaac PetscInt coordSize; 9193dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 9203dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 9213dfda0b1SToby Isaac 9229566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices)); 92348a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 92448a46eb9SPierre Jolivet for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 92548a46eb9SPierre Jolivet for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 9269566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 9273dfda0b1SToby Isaac /* Build cells */ 9283dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 9293dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 9303dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 9313dfda0b1SToby Isaac PetscInt cell = (fz * numYEdges + fy) * numXEdges + fx; 9323dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 9333dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices); 9343dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 9353dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices); 9363dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 9373dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices); 9383dfda0b1SToby Isaac /* B, T, F, K, R, L */ 939b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 94042206facSLisandro Dalcin PetscInt cone[6]; 9413dfda0b1SToby Isaac 9423dfda0b1SToby Isaac /* no boundary twisting in 3D */ 9439371c9d4SSatish Balay cone[0] = faceB; 9449371c9d4SSatish Balay cone[1] = faceT; 9459371c9d4SSatish Balay cone[2] = faceF; 9469371c9d4SSatish Balay cone[3] = faceK; 9479371c9d4SSatish Balay cone[4] = faceR; 9489371c9d4SSatish Balay cone[5] = faceL; 9499566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, cell, cone)); 9509566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, cell, ornt)); 9519566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9529566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9539566063dSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9543dfda0b1SToby Isaac } 9553dfda0b1SToby Isaac } 9563dfda0b1SToby Isaac } 9573dfda0b1SToby Isaac /* Build x faces */ 9583dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 9593dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 9603dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 9613dfda0b1SToby Isaac PetscInt face = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 9623dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 9633dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz; 9643dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 9653dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy; 966b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 9673dfda0b1SToby Isaac PetscInt cone[4]; 9683dfda0b1SToby Isaac 9693dfda0b1SToby Isaac if (dim == 3) { 9703dfda0b1SToby Isaac /* markers */ 9713dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 9723dfda0b1SToby Isaac if (fx == numXVertices - 1) { 9739566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 9749566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerRight)); 9759371c9d4SSatish Balay } else if (fx == 0) { 9769566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 9779566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft)); 9783dfda0b1SToby Isaac } 9793dfda0b1SToby Isaac } 9803dfda0b1SToby Isaac } 9819371c9d4SSatish Balay cone[0] = edgeB; 9829371c9d4SSatish Balay cone[1] = edgeR; 9839371c9d4SSatish Balay cone[2] = edgeT; 9849371c9d4SSatish Balay cone[3] = edgeL; 9859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 9869566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 9873dfda0b1SToby Isaac } 9883dfda0b1SToby Isaac } 9893dfda0b1SToby Isaac } 9903dfda0b1SToby Isaac /* Build y faces */ 9913dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 99242206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 9933dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 9943dfda0b1SToby Isaac PetscInt face = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 9953dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 9963dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz; 9973dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 9983dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx; 999b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 10003dfda0b1SToby Isaac PetscInt cone[4]; 10013dfda0b1SToby Isaac 10023dfda0b1SToby Isaac if (dim == 3) { 10033dfda0b1SToby Isaac /* markers */ 10043dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 10053dfda0b1SToby Isaac if (fy == numYVertices - 1) { 10069566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 10079566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBack)); 10089371c9d4SSatish Balay } else if (fy == 0) { 10099566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 10109566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerFront)); 10113dfda0b1SToby Isaac } 10123dfda0b1SToby Isaac } 10133dfda0b1SToby Isaac } 10149371c9d4SSatish Balay cone[0] = edgeB; 10159371c9d4SSatish Balay cone[1] = edgeR; 10169371c9d4SSatish Balay cone[2] = edgeT; 10179371c9d4SSatish Balay cone[3] = edgeL; 10189566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 10199566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 10203dfda0b1SToby Isaac } 10213dfda0b1SToby Isaac } 10223dfda0b1SToby Isaac } 10233dfda0b1SToby Isaac /* Build z faces */ 10243dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 10253dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 10263dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 10273dfda0b1SToby Isaac PetscInt face = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 10283dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 10293dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy; 10303dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 10313dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx; 1032b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 10333dfda0b1SToby Isaac PetscInt cone[4]; 10343dfda0b1SToby Isaac 10353dfda0b1SToby Isaac if (dim == 2) { 10369371c9d4SSatish Balay if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) { 10379371c9d4SSatish Balay edgeR += numYEdges - 1 - 2 * fy; 10389371c9d4SSatish Balay ornt[1] = -1; 10399371c9d4SSatish Balay } 10409371c9d4SSatish Balay if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) { 10419371c9d4SSatish Balay edgeT += numXEdges - 1 - 2 * fx; 10429371c9d4SSatish Balay ornt[2] = 0; 10439371c9d4SSatish Balay } 10449566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 10459566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 1046d1c88043SMatthew G. Knepley } else { 10473dfda0b1SToby Isaac /* markers */ 10483dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 10493dfda0b1SToby Isaac if (fz == numZVertices - 1) { 10509566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 10519566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerTop)); 10529371c9d4SSatish Balay } else if (fz == 0) { 10539566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 10549566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom)); 10553dfda0b1SToby Isaac } 10563dfda0b1SToby Isaac } 10573dfda0b1SToby Isaac } 10589371c9d4SSatish Balay cone[0] = edgeB; 10599371c9d4SSatish Balay cone[1] = edgeR; 10609371c9d4SSatish Balay cone[2] = edgeT; 10619371c9d4SSatish Balay cone[3] = edgeL; 10629566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 10639566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 10643dfda0b1SToby Isaac } 10653dfda0b1SToby Isaac } 10663dfda0b1SToby Isaac } 10673dfda0b1SToby Isaac /* Build Z edges*/ 10683dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 10693dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 10703dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 10713dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez; 10723dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx; 10733dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx; 10743dfda0b1SToby Isaac PetscInt cone[2]; 10753dfda0b1SToby Isaac 10769371c9d4SSatish Balay cone[0] = vertexB; 10779371c9d4SSatish Balay cone[1] = vertexT; 1078c2df9bbfSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, edge, cone)); 10793dfda0b1SToby Isaac if (dim == 3) { 10803dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 10813dfda0b1SToby Isaac if (vx == numXVertices - 1) { 10829566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1083c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1084c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1085c2df9bbfSMatthew G. Knepley } else if (vx == 0) { 10869566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1087c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1088c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 10893dfda0b1SToby Isaac } 10903dfda0b1SToby Isaac } 10913dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 10923dfda0b1SToby Isaac if (vy == numYVertices - 1) { 10939566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1094c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1095c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1096c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 10979566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1098c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1099c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 11003dfda0b1SToby Isaac } 11013dfda0b1SToby Isaac } 11023dfda0b1SToby Isaac } 11033dfda0b1SToby Isaac } 11043dfda0b1SToby Isaac } 11053dfda0b1SToby Isaac } 11063dfda0b1SToby Isaac /* Build Y edges*/ 11073dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 11083dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 11093dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 11103dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx; 11113dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey; 11123dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx; 11133dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 11143dfda0b1SToby Isaac PetscInt cone[2]; 11153dfda0b1SToby Isaac 11169371c9d4SSatish Balay cone[0] = vertexF; 11179371c9d4SSatish Balay cone[1] = vertexK; 11189566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 11193dfda0b1SToby Isaac if (dim == 2) { 11203dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 11213dfda0b1SToby Isaac if (vx == numXVertices - 1) { 11229566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 11239566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 11249566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1125c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1126d8211ee3SMatthew G. Knepley } else if (vx == 0) { 11279566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 11289566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 11299566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1130c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 11313dfda0b1SToby Isaac } 1132d8211ee3SMatthew G. Knepley } else { 11334c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 11349566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 11359566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1136c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 11373dfda0b1SToby Isaac } 1138d8211ee3SMatthew G. Knepley } 1139d8211ee3SMatthew G. Knepley } else { 11403dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 11413dfda0b1SToby Isaac if (vx == numXVertices - 1) { 11429566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1143c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1144c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1145d8211ee3SMatthew G. Knepley } else if (vx == 0) { 11469566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1147c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1148c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 11493dfda0b1SToby Isaac } 11503dfda0b1SToby Isaac } 11513dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 11523dfda0b1SToby Isaac if (vz == numZVertices - 1) { 11539566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1154c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1155c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1156d8211ee3SMatthew G. Knepley } else if (vz == 0) { 11579566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1158c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1159c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 11603dfda0b1SToby Isaac } 11613dfda0b1SToby Isaac } 11623dfda0b1SToby Isaac } 11633dfda0b1SToby Isaac } 11643dfda0b1SToby Isaac } 11653dfda0b1SToby Isaac } 11663dfda0b1SToby Isaac /* Build X edges*/ 11673dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 11683dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 11693dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 11703dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices; 11713dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex; 11723dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex; 11733dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 11743dfda0b1SToby Isaac PetscInt cone[2]; 11753dfda0b1SToby Isaac 11769371c9d4SSatish Balay cone[0] = vertexL; 11779371c9d4SSatish Balay cone[1] = vertexR; 11789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 11793dfda0b1SToby Isaac if (dim == 2) { 11803dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 11813dfda0b1SToby Isaac if (vy == numYVertices - 1) { 11829566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 11839566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 11849566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1185c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1186d8211ee3SMatthew G. Knepley } else if (vy == 0) { 11879566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 11889566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 11899566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1190c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 11913dfda0b1SToby Isaac } 1192d8211ee3SMatthew G. Knepley } else { 11934c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 11949566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 11959566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1196c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 11973dfda0b1SToby Isaac } 1198d8211ee3SMatthew G. Knepley } 1199d8211ee3SMatthew G. Knepley } else { 12003dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 12013dfda0b1SToby Isaac if (vy == numYVertices - 1) { 12029566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1203c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1204c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1205c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 12069566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1207c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1208c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 12093dfda0b1SToby Isaac } 12103dfda0b1SToby Isaac } 12113dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 12123dfda0b1SToby Isaac if (vz == numZVertices - 1) { 12139566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1214c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1215c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1216c2df9bbfSMatthew G. Knepley } else if (vz == 0) { 12179566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1218c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1219c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 12203dfda0b1SToby Isaac } 12213dfda0b1SToby Isaac } 12223dfda0b1SToby Isaac } 12233dfda0b1SToby Isaac } 12243dfda0b1SToby Isaac } 12253dfda0b1SToby Isaac } 12269566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 12279566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 12283dfda0b1SToby Isaac /* Build coordinates */ 12299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 12309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 12319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 12329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 12333dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex + numVertices; ++v) { 12349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 12359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 12363dfda0b1SToby Isaac } 12379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 12389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 12399566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 12409566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 12419566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 12429566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 12439566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 12449566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12453dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 12463dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 12473dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 12483dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 12493dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1250ad540459SPierre Jolivet if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; 12513dfda0b1SToby Isaac } 12523dfda0b1SToby Isaac } 12533dfda0b1SToby Isaac } 12549566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12559566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 12569566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 12573dfda0b1SToby Isaac } 12583dfda0b1SToby Isaac PetscFunctionReturn(0); 12593dfda0b1SToby Isaac } 12603dfda0b1SToby Isaac 1261d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1262d71ae5a4SJacob Faibussowitsch { 12639318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 12649318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1265552f7358SJed Brown 1266552f7358SJed Brown PetscFunctionBegin; 12679318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 12689318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 12699566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 12709371c9d4SSatish Balay for (d = 0; d < dim; ++d) { 12719371c9d4SSatish Balay fac[d] = faces[d]; 12729371c9d4SSatish Balay bdt[d] = periodicity[d]; 12739371c9d4SSatish Balay } 12749566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 12759371c9d4SSatish 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))) { 12766858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 12776858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1278552f7358SJed Brown 12799318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 12806858538eSMatthew G. Knepley if (periodicity[d] != DM_BOUNDARY_NONE) { 12819318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 12829318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1283768d5fceSMatthew G. Knepley } 12846858538eSMatthew G. Knepley } 12854fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1286768d5fceSMatthew G. Knepley } 12879566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 12889318fe57SMatthew G. Knepley PetscFunctionReturn(0); 12899318fe57SMatthew G. Knepley } 12909318fe57SMatthew G. Knepley 1291d71ae5a4SJacob 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) 1292d71ae5a4SJacob Faibussowitsch { 12933e72e933SJed Brown PetscBool box_sfc = PETSC_FALSE; 12949318fe57SMatthew G. Knepley PetscFunctionBegin; 12953e72e933SJed Brown PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_box_sfc", &box_sfc, NULL)); 12966725e60dSJed Brown if (box_sfc) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 12976725e60dSJed Brown else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 12989566063dSJacob Faibussowitsch else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 12999566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 13009318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1301768d5fceSMatthew G. Knepley DM udm; 1302768d5fceSMatthew G. Knepley 13039566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 13049566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, udm)); 130569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 1306768d5fceSMatthew G. Knepley } 1307768d5fceSMatthew G. Knepley PetscFunctionReturn(0); 1308c8c68bd8SToby Isaac } 1309c8c68bd8SToby Isaac 1310768d5fceSMatthew G. Knepley /*@C 1311768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1312768d5fceSMatthew G. Knepley 1313d083f849SBarry Smith Collective 1314768d5fceSMatthew G. Knepley 1315768d5fceSMatthew G. Knepley Input Parameters: 1316a1cb98faSBarry Smith + comm - The communicator for the `DM` object 1317768d5fceSMatthew G. Knepley . dim - The spatial dimension 1318a1cb98faSBarry Smith . simplex - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells 1319fdbf62faSLisandro Dalcin . faces - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 1320768d5fceSMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 1321768d5fceSMatthew G. Knepley . upper - The upper right corner, or NULL for (1, 1, 1) 1322a1cb98faSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or NULL for `DM_BOUNDARY_NONE` 1323768d5fceSMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 1324768d5fceSMatthew G. Knepley 1325768d5fceSMatthew G. Knepley Output Parameter: 1326a1cb98faSBarry Smith . dm - The `DM` object 1327768d5fceSMatthew G. Knepley 1328768d5fceSMatthew G. Knepley Level: beginner 1329768d5fceSMatthew G. Knepley 1330a1cb98faSBarry Smith Note: 1331a1cb98faSBarry Smith To customize this mesh using options, use 1332a1cb98faSBarry Smith .vb 1333a1cb98faSBarry Smith DMCreate(comm, &dm); 1334a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 1335a1cb98faSBarry Smith DMSetFromOptions(dm); 1336a1cb98faSBarry Smith .ve 1337a1cb98faSBarry Smith and use the options in `DMSetFromOptions()`. 1338a1cb98faSBarry Smith 1339a1cb98faSBarry Smith Here is the numbering returned for 2 faces in each direction for tensor cells: 1340a1cb98faSBarry Smith .vb 1341a1cb98faSBarry Smith 10---17---11---18----12 1342a1cb98faSBarry Smith | | | 1343a1cb98faSBarry Smith | | | 1344a1cb98faSBarry Smith 20 2 22 3 24 1345a1cb98faSBarry Smith | | | 1346a1cb98faSBarry Smith | | | 1347a1cb98faSBarry Smith 7---15----8---16----9 1348a1cb98faSBarry Smith | | | 1349a1cb98faSBarry Smith | | | 1350a1cb98faSBarry Smith 19 0 21 1 23 1351a1cb98faSBarry Smith | | | 1352a1cb98faSBarry Smith | | | 1353a1cb98faSBarry Smith 4---13----5---14----6 1354a1cb98faSBarry Smith .ve 1355a1cb98faSBarry Smith and for simplicial cells 1356a1cb98faSBarry Smith .vb 1357a1cb98faSBarry Smith 14----8---15----9----16 1358a1cb98faSBarry Smith |\ 5 |\ 7 | 1359a1cb98faSBarry Smith | \ | \ | 1360a1cb98faSBarry Smith 13 2 14 3 15 1361a1cb98faSBarry Smith | 4 \ | 6 \ | 1362a1cb98faSBarry Smith | \ | \ | 1363a1cb98faSBarry Smith 11----6---12----7----13 1364a1cb98faSBarry Smith |\ |\ | 1365a1cb98faSBarry Smith | \ 1 | \ 3 | 1366a1cb98faSBarry Smith 10 0 11 1 12 1367a1cb98faSBarry Smith | 0 \ | 2 \ | 1368a1cb98faSBarry Smith | \ | \ | 1369a1cb98faSBarry Smith 8----4----9----5----10 1370a1cb98faSBarry Smith .ve 1371a1cb98faSBarry Smith 1372a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 1373768d5fceSMatthew G. Knepley @*/ 1374d71ae5a4SJacob 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) 1375d71ae5a4SJacob Faibussowitsch { 13769318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 1377fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 1378fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 1379fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1380552f7358SJed Brown 1381768d5fceSMatthew G. Knepley PetscFunctionBegin; 13829566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 13839566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 13849566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 13857ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 13869318fe57SMatthew G. Knepley PetscFunctionReturn(0); 13879318fe57SMatthew G. Knepley } 1388fdbf62faSLisandro Dalcin 1389d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1390d71ae5a4SJacob Faibussowitsch { 13919318fe57SMatthew G. Knepley DM bdm, vol; 13929318fe57SMatthew G. Knepley PetscInt i; 13939318fe57SMatthew G. Knepley 13949318fe57SMatthew G. Knepley PetscFunctionBegin; 139508401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 13969566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 13979566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 13989566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 13999566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 14009566063dSJacob Faibussowitsch PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol)); 14019566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 140269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 14039318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 14049318fe57SMatthew G. Knepley Vec v; 14059318fe57SMatthew G. Knepley PetscScalar *x; 14069318fe57SMatthew G. Knepley PetscInt cDim, n; 14079318fe57SMatthew G. Knepley 14089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 14099566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 14109566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 14119566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 14129318fe57SMatthew G. Knepley x += cDim; 14139318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 14149566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 14159566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 14169318fe57SMatthew G. Knepley } 1417552f7358SJed Brown PetscFunctionReturn(0); 1418552f7358SJed Brown } 1419552f7358SJed Brown 142000dabe28SStefano Zampini /*@ 142100dabe28SStefano Zampini DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells. 142200dabe28SStefano Zampini 1423d083f849SBarry Smith Collective 142400dabe28SStefano Zampini 142500dabe28SStefano Zampini Input Parameters: 1426a1cb98faSBarry Smith + comm - The communicator for the `DM` object 142700dabe28SStefano Zampini . faces - Number of faces per dimension, or NULL for (1, 1, 1) 142800dabe28SStefano Zampini . lower - The lower left corner, or NULL for (0, 0, 0) 142900dabe28SStefano Zampini . upper - The upper right corner, or NULL for (1, 1, 1) 1430a1cb98faSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or NULL for `DM_BOUNDARY_NONE` 1431a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 143200dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 143300dabe28SStefano Zampini 143400dabe28SStefano Zampini Output Parameter: 1435a1cb98faSBarry Smith . dm - The `DM` object 143600dabe28SStefano Zampini 143700dabe28SStefano Zampini Level: beginner 143800dabe28SStefano Zampini 1439a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 144000dabe28SStefano Zampini @*/ 1441d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 1442d71ae5a4SJacob Faibussowitsch { 14439318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 144400dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 144500dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 144600dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 144700dabe28SStefano Zampini 144800dabe28SStefano Zampini PetscFunctionBegin; 14499566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 14509566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 14519566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 1452d410b0cfSMatthew G. Knepley if (!interpolate) { 1453d410b0cfSMatthew G. Knepley DM udm; 145400dabe28SStefano Zampini 14559566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 145669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 145700dabe28SStefano Zampini } 14587ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 145900dabe28SStefano Zampini PetscFunctionReturn(0); 146000dabe28SStefano Zampini } 146100dabe28SStefano Zampini 1462cfb853baSMatthew G. Knepley /* 1463cfb853baSMatthew G. Knepley DMPlexTensorPointLexicographic_Private - Returns all tuples of size 'len' with nonnegative integers that are all less than or equal to 'max' for that dimension. 1464cfb853baSMatthew G. Knepley Ordering is lexicographic with lowest index as least significant in ordering. 1465cfb853baSMatthew G. Knepley e.g. for len == 2 and max == 2, this will return, in order, {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0,2}, {1,2}, {2,2}. 1466cfb853baSMatthew G. Knepley 1467cfb853baSMatthew G. Knepley Input Parameters: 1468cfb853baSMatthew G. Knepley + len - The length of the tuple 1469cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max) 1470cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 1471cfb853baSMatthew G. Knepley 1472cfb853baSMatthew G. Knepley Output Parameter: 1473cfb853baSMatthew G. Knepley . tup - A tuple of len integers whose entries are at most 'max' 1474cfb853baSMatthew G. Knepley 1475cfb853baSMatthew G. Knepley Level: developer 1476cfb853baSMatthew G. Knepley 1477cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal() 1478cfb853baSMatthew G. Knepley */ 1479cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[]) 1480cfb853baSMatthew G. Knepley { 1481cfb853baSMatthew G. Knepley PetscInt i; 1482cfb853baSMatthew G. Knepley 1483cfb853baSMatthew G. Knepley PetscFunctionBegin; 1484cfb853baSMatthew G. Knepley for (i = 0; i < len; ++i) { 1485cfb853baSMatthew G. Knepley if (tup[i] < max[i] - 1) { 1486cfb853baSMatthew G. Knepley break; 1487cfb853baSMatthew G. Knepley } else { 1488cfb853baSMatthew G. Knepley tup[i] = 0; 1489cfb853baSMatthew G. Knepley } 1490cfb853baSMatthew G. Knepley } 1491cfb853baSMatthew G. Knepley if (i == len) tup[i - 1] = max[i - 1]; 1492cfb853baSMatthew G. Knepley else ++tup[i]; 1493cfb853baSMatthew G. Knepley PetscFunctionReturn(0); 1494cfb853baSMatthew G. Knepley } 1495cfb853baSMatthew G. Knepley 1496cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[]) 1497cfb853baSMatthew G. Knepley { 1498cfb853baSMatthew G. Knepley PetscInt i, idx = tup[len - 1]; 1499cfb853baSMatthew G. Knepley 1500cfb853baSMatthew G. Knepley for (i = len - 2; i >= 0; --i) { 1501cfb853baSMatthew G. Knepley idx *= max[i]; 1502cfb853baSMatthew G. Knepley idx += tup[i]; 1503cfb853baSMatthew G. Knepley } 1504cfb853baSMatthew G. Knepley return idx; 1505cfb853baSMatthew G. Knepley } 1506cfb853baSMatthew G. Knepley 1507cfb853baSMatthew G. Knepley static PetscErrorCode DestroyExtent_Private(void *extent) 1508cfb853baSMatthew G. Knepley { 1509cfb853baSMatthew G. Knepley return PetscFree(extent); 1510cfb853baSMatthew G. Knepley } 1511cfb853baSMatthew G. Knepley 1512cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], const DMBoundaryType bd[]) 1513cfb853baSMatthew G. Knepley { 1514cfb853baSMatthew G. Knepley Vec coordinates; 1515cfb853baSMatthew G. Knepley PetscSection coordSection; 1516cfb853baSMatthew G. Knepley DMLabel cutLabel = NULL; 1517cfb853baSMatthew G. Knepley PetscBool cutMarker = PETSC_FALSE; 1518cfb853baSMatthew G. Knepley PetscBool periodic = PETSC_FALSE; 1519cfb853baSMatthew G. Knepley PetscInt numCells = 1, c; 1520cfb853baSMatthew G. Knepley PetscInt numVertices = 1, v; 1521cfb853baSMatthew G. Knepley PetscScalar *coords; 1522cfb853baSMatthew G. Knepley PetscInt *vertices, *vert, *vtmp, *supp, cone[2]; 1523cfb853baSMatthew G. Knepley PetscInt d, e, cell = 0, coordSize; 1524cfb853baSMatthew G. Knepley PetscMPIInt rank; 1525cfb853baSMatthew G. Knepley 1526cfb853baSMatthew G. Knepley PetscFunctionBegin; 1527cfb853baSMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1528cfb853baSMatthew G. Knepley PetscCall(DMSetDimension(dm, dim)); 1529cfb853baSMatthew G. Knepley PetscCall(PetscCalloc4(dim, &vertices, dim, &vert, dim, &vtmp, 2 * dim, &supp)); 1530cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 1531cfb853baSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 1532cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE; 1533cfb853baSMatthew G. Knepley if (periodic && cutMarker) { 1534cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "periodic_cut")); 1535cfb853baSMatthew G. Knepley PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 1536cfb853baSMatthew G. Knepley } 1537cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Hypercubic mesh must be periodic now"); 1538cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 1539cfb853baSMatthew G. Knepley vertices[d] = edges[d]; 1540cfb853baSMatthew G. Knepley numVertices *= vertices[d]; 1541cfb853baSMatthew G. Knepley } 1542cfb853baSMatthew G. Knepley numCells = numVertices * dim; 1543cfb853baSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 1544cfb853baSMatthew G. Knepley for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2)); 1545cfb853baSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim)); 1546cfb853baSMatthew G. Knepley /* TODO Loop over boundary and reset support sizes */ 1547cfb853baSMatthew G. Knepley PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */ 1548cfb853baSMatthew G. Knepley /* Build cell cones and vertex supports */ 1549cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "celltype")); 1550cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 1551cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells; 1552cfb853baSMatthew G. Knepley PetscInt s = 0; 1553cfb853baSMatthew G. Knepley 1554cfb853baSMatthew G. Knepley PetscPrintf(PETSC_COMM_SELF, "Vertex %" PetscInt_FMT ":", vertex); 1555cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, vert[d]); 1556cfb853baSMatthew G. Knepley PetscPrintf(PETSC_COMM_SELF, "\n"); 1557cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT)); 1558cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 1559cfb853baSMatthew G. Knepley for (e = 0; e < dim; ++e) vtmp[e] = vert[e]; 1560cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + 1) % vertices[d]; 1561cfb853baSMatthew G. Knepley cone[0] = vertex; 1562cfb853baSMatthew G. Knepley cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells; 1563cfb853baSMatthew G. Knepley PetscPrintf(PETSC_COMM_SELF, " Vertex %" PetscInt_FMT ":", cone[1]); 1564cfb853baSMatthew G. Knepley for (e = 0; e < dim; ++e) PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, vtmp[e]); 1565cfb853baSMatthew G. Knepley PetscPrintf(PETSC_COMM_SELF, "\n"); 1566cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, cell, cone)); 1567cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT)); 1568cfb853baSMatthew G. Knepley PetscPrintf(PETSC_COMM_SELF, " Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1]); 1569cfb853baSMatthew G. Knepley ++cell; 1570cfb853baSMatthew G. Knepley } 1571cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 1572cfb853baSMatthew G. Knepley for (e = 0; e < dim; ++e) vtmp[e] = vert[e]; 1573cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + vertices[d] - 1) % vertices[d]; 1574cfb853baSMatthew G. Knepley supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d; 1575cfb853baSMatthew G. Knepley supp[s++] = (vertex - numCells) * dim + d; 1576cfb853baSMatthew G. Knepley PetscCall(DMPlexSetSupport(dm, vertex, supp)); 1577cfb853baSMatthew G. Knepley } 1578cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 1579cfb853baSMatthew G. Knepley } 1580cfb853baSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 1581cfb853baSMatthew G. Knepley /* Build coordinates */ 1582cfb853baSMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 1583cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(coordSection, 1)); 1584cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 1585cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 1586cfb853baSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 1587cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetDof(coordSection, v, dim)); 1588cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 1589cfb853baSMatthew G. Knepley } 1590cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetUp(coordSection)); 1591cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 1592cfb853baSMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 1593cfb853baSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 1594cfb853baSMatthew G. Knepley PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 1595cfb853baSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinates, dim)); 1596cfb853baSMatthew G. Knepley PetscCall(VecSetType(coordinates, VECSTANDARD)); 1597cfb853baSMatthew G. Knepley PetscCall(VecGetArray(coordinates, &coords)); 1598cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) vert[d] = 0; 1599cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 1600cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert); 1601cfb853baSMatthew G. Knepley 1602cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / vertices[d]) * vert[d]; 1603cfb853baSMatthew G. Knepley PetscPrintf(PETSC_COMM_SELF, "Vertex %" PetscInt_FMT ":", vertex); 1604cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, vert[d]); 1605cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) PetscPrintf(PETSC_COMM_SELF, " %g", (double)PetscRealPart(coords[vertex * dim + d])); 1606cfb853baSMatthew G. Knepley PetscPrintf(PETSC_COMM_SELF, "\n"); 1607cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 1608cfb853baSMatthew G. Knepley } 1609cfb853baSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &coords)); 1610cfb853baSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 1611cfb853baSMatthew G. Knepley PetscCall(VecDestroy(&coordinates)); 1612cfb853baSMatthew G. Knepley PetscCall(PetscFree4(vertices, vert, vtmp, supp)); 1613cfb853baSMatthew G. Knepley //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper)); 1614cfb853baSMatthew G. Knepley // Attach the extent 1615cfb853baSMatthew G. Knepley { 1616cfb853baSMatthew G. Knepley PetscContainer c; 1617cfb853baSMatthew G. Knepley PetscInt *extent; 1618cfb853baSMatthew G. Knepley 1619cfb853baSMatthew G. Knepley PetscCall(PetscMalloc1(dim, &extent)); 1620cfb853baSMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) extent[d] = edges[d]; 1621cfb853baSMatthew G. Knepley PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 1622cfb853baSMatthew G. Knepley PetscCall(PetscContainerSetUserDestroy(c, DestroyExtent_Private)); 1623cfb853baSMatthew G. Knepley PetscCall(PetscContainerSetPointer(c, extent)); 1624cfb853baSMatthew G. Knepley PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c)); 1625cfb853baSMatthew G. Knepley PetscCall(PetscContainerDestroy(&c)); 1626cfb853baSMatthew G. Knepley } 1627cfb853baSMatthew G. Knepley PetscFunctionReturn(0); 1628cfb853baSMatthew G. Knepley } 1629cfb853baSMatthew G. Knepley 1630cfb853baSMatthew G. Knepley /*@C 1631cfb853baSMatthew G. Knepley DMPlexCreateHypercubicMesh - Creates a peridoic mesh on the tensor product of unit intervals using only vertices and edges. 1632cfb853baSMatthew G. Knepley 1633cfb853baSMatthew G. Knepley Collective 1634cfb853baSMatthew G. Knepley 1635cfb853baSMatthew G. Knepley Input Parameters: 1636cfb853baSMatthew G. Knepley + comm - The communicator for the DM object 1637cfb853baSMatthew G. Knepley . dim - The spatial dimension 1638cfb853baSMatthew G. Knepley . edges - Number of edges per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 1639cfb853baSMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 1640cfb853baSMatthew G. Knepley - upper - The upper right corner, or NULL for (1, 1, 1) 1641cfb853baSMatthew G. Knepley 1642cfb853baSMatthew G. Knepley Output Parameter: 1643cfb853baSMatthew G. Knepley . dm - The DM object 1644cfb853baSMatthew G. Knepley 1645cfb853baSMatthew G. Knepley Note: If you want to customize this mesh using options, you just need to 1646cfb853baSMatthew G. Knepley $ DMCreate(comm, &dm); 1647cfb853baSMatthew G. Knepley $ DMSetType(dm, DMPLEX); 1648cfb853baSMatthew G. Knepley $ DMSetFromOptions(dm); 1649cfb853baSMatthew G. Knepley and use the options on the DMSetFromOptions() page. 1650cfb853baSMatthew G. Knepley 1651cfb853baSMatthew G. Knepley The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively, 1652cfb853baSMatthew G. Knepley $ 18--0-19--2-20--4-18 1653cfb853baSMatthew G. Knepley $ | | | | 1654cfb853baSMatthew G. Knepley $ 13 15 17 13 1655cfb853baSMatthew G. Knepley $ | | | | 1656cfb853baSMatthew G. Knepley $ 24-12-25-14-26-16-24 1657cfb853baSMatthew G. Knepley $ | | | | 1658cfb853baSMatthew G. Knepley $ 7 9 11 7 1659cfb853baSMatthew G. Knepley $ | | | | 1660cfb853baSMatthew G. Knepley $ 21--6-22--8-23-10-21 1661cfb853baSMatthew G. Knepley $ | | | | 1662cfb853baSMatthew G. Knepley $ 1 3 5 1 1663cfb853baSMatthew G. Knepley $ | | | | 1664cfb853baSMatthew G. Knepley $ 18--0-19--2-20--4-18 1665cfb853baSMatthew G. Knepley 1666cfb853baSMatthew G. Knepley Level: beginner 1667cfb853baSMatthew G. Knepley 1668cfb853baSMatthew G. Knepley .seealso: DMSetFromOptions(), DMPlexCreateFromFile(), DMPlexCreateHexCylinderMesh(), DMSetType(), DMCreate() 1669cfb853baSMatthew G. Knepley @*/ 1670cfb853baSMatthew G. Knepley PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], DM *dm) 1671cfb853baSMatthew G. Knepley { 1672cfb853baSMatthew G. Knepley PetscInt *edg; 1673cfb853baSMatthew G. Knepley PetscReal *low, *upp; 1674cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 1675cfb853baSMatthew G. Knepley PetscInt d; 1676cfb853baSMatthew G. Knepley 1677cfb853baSMatthew G. Knepley PetscFunctionBegin; 1678cfb853baSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 1679cfb853baSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 1680cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt)); 1681cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 1682cfb853baSMatthew G. Knepley edg[d] = edges ? edges[d] : 1; 1683cfb853baSMatthew G. Knepley low[d] = lower ? lower[d] : 0.; 1684cfb853baSMatthew G. Knepley upp[d] = upper ? upper[d] : 1.; 1685cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 1686cfb853baSMatthew G. Knepley } 1687cfb853baSMatthew G. Knepley PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, bdt)); 1688cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edg, low, upp, bdt)); 1689cfb853baSMatthew G. Knepley PetscFunctionReturn(0); 1690cfb853baSMatthew G. Knepley } 1691cfb853baSMatthew G. Knepley 1692a9074c1eSMatthew G. Knepley /*@C 1693a1cb98faSBarry Smith DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database. 1694a9074c1eSMatthew G. Knepley 1695d083f849SBarry Smith Logically Collective on dm 1696a9074c1eSMatthew G. Knepley 1697a9074c1eSMatthew G. Knepley Input Parameters: 1698a9074c1eSMatthew G. Knepley + dm - the DM context 1699a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 1700a9074c1eSMatthew G. Knepley 1701a1cb98faSBarry Smith Level: advanced 1702a1cb98faSBarry Smith 1703a1cb98faSBarry Smith Note: 1704a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 1705a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 1706a9074c1eSMatthew G. Knepley 1707a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()` 1708a9074c1eSMatthew G. Knepley @*/ 1709d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 1710d71ae5a4SJacob Faibussowitsch { 1711a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1712a9074c1eSMatthew G. Knepley 1713a9074c1eSMatthew G. Knepley PetscFunctionBegin; 1714a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 17159566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 17169566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 1717a9074c1eSMatthew G. Knepley PetscFunctionReturn(0); 1718a9074c1eSMatthew G. Knepley } 1719a9074c1eSMatthew G. Knepley 17209318fe57SMatthew G. Knepley /* Remap geometry to cylinder 172161a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 172261a622f3SMatthew G. Knepley 17239318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 17249318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 17259318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 17260510c589SMatthew G. Knepley 17279318fe57SMatthew G. Knepley phi = arctan(y/x) 17289318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 17299318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 17300510c589SMatthew G. Knepley 17319318fe57SMatthew G. Knepley so we remap them using 17320510c589SMatthew G. Knepley 17339318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 17349318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 17350510c589SMatthew G. Knepley 17369318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 17379318fe57SMatthew G. Knepley */ 1738d71ae5a4SJacob 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[]) 1739d71ae5a4SJacob Faibussowitsch { 17409318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 17419318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 174222cc497dSMatthew G. Knepley 17439318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 17449318fe57SMatthew G. Knepley f0[0] = u[0]; 17459318fe57SMatthew G. Knepley f0[1] = u[1]; 17469318fe57SMatthew G. Knepley } else { 17479318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 17480510c589SMatthew G. Knepley 17499318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 17509318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 17519318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 17529318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 17539318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 17549318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 17559318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 17569318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 17579318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 17589318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 17599318fe57SMatthew G. Knepley } else { 17609318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 17619318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 17629318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 17639318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 17649318fe57SMatthew G. Knepley } 17659318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 17669318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 17679318fe57SMatthew G. Knepley } 17689318fe57SMatthew G. Knepley f0[2] = u[2]; 17699318fe57SMatthew G. Knepley } 17700510c589SMatthew G. Knepley 1771d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ) 1772d71ae5a4SJacob Faibussowitsch { 17730510c589SMatthew G. Knepley const PetscInt dim = 3; 17749318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 1775d8c47e87SMatthew G. Knepley PetscMPIInt rank; 17760510c589SMatthew G. Knepley 17770510c589SMatthew G. Knepley PetscFunctionBegin; 17789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17799566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 17800510c589SMatthew G. Knepley /* Create topology */ 17810510c589SMatthew G. Knepley { 17820510c589SMatthew G. Knepley PetscInt cone[8], c; 17830510c589SMatthew G. Knepley 1784dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 1785dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 1786006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 1787ae8bcbbbSMatthew G. Knepley numCells *= 3; 1788dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 1789006a8963SMatthew G. Knepley } 17909566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 17919566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 17929566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 1793dd400576SPatrick Sanan if (rank == 0) { 1794006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 17959371c9d4SSatish Balay cone[0] = 15; 17969371c9d4SSatish Balay cone[1] = 18; 17979371c9d4SSatish Balay cone[2] = 17; 17989371c9d4SSatish Balay cone[3] = 16; 17999371c9d4SSatish Balay cone[4] = 31; 18009371c9d4SSatish Balay cone[5] = 32; 18019371c9d4SSatish Balay cone[6] = 33; 18029371c9d4SSatish Balay cone[7] = 34; 18039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 18049371c9d4SSatish Balay cone[0] = 16; 18059371c9d4SSatish Balay cone[1] = 17; 18069371c9d4SSatish Balay cone[2] = 24; 18079371c9d4SSatish Balay cone[3] = 23; 18089371c9d4SSatish Balay cone[4] = 32; 18099371c9d4SSatish Balay cone[5] = 36; 18109371c9d4SSatish Balay cone[6] = 37; 18119371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 18129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 18139371c9d4SSatish Balay cone[0] = 18; 18149371c9d4SSatish Balay cone[1] = 27; 18159371c9d4SSatish Balay cone[2] = 24; 18169371c9d4SSatish Balay cone[3] = 17; 18179371c9d4SSatish Balay cone[4] = 34; 18189371c9d4SSatish Balay cone[5] = 33; 18199371c9d4SSatish Balay cone[6] = 37; 18209371c9d4SSatish Balay cone[7] = 38; 18219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 18229371c9d4SSatish Balay cone[0] = 29; 18239371c9d4SSatish Balay cone[1] = 27; 18249371c9d4SSatish Balay cone[2] = 18; 18259371c9d4SSatish Balay cone[3] = 15; 18269371c9d4SSatish Balay cone[4] = 35; 18279371c9d4SSatish Balay cone[5] = 31; 18289371c9d4SSatish Balay cone[6] = 34; 18299371c9d4SSatish Balay cone[7] = 38; 18309566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 18319371c9d4SSatish Balay cone[0] = 29; 18329371c9d4SSatish Balay cone[1] = 15; 18339371c9d4SSatish Balay cone[2] = 16; 18349371c9d4SSatish Balay cone[3] = 23; 18359371c9d4SSatish Balay cone[4] = 35; 18369371c9d4SSatish Balay cone[5] = 36; 18379371c9d4SSatish Balay cone[6] = 32; 18389371c9d4SSatish Balay cone[7] = 31; 18399566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1840006a8963SMatthew G. Knepley 18419371c9d4SSatish Balay cone[0] = 31; 18429371c9d4SSatish Balay cone[1] = 34; 18439371c9d4SSatish Balay cone[2] = 33; 18449371c9d4SSatish Balay cone[3] = 32; 18459371c9d4SSatish Balay cone[4] = 19; 18469371c9d4SSatish Balay cone[5] = 22; 18479371c9d4SSatish Balay cone[6] = 21; 18489371c9d4SSatish Balay cone[7] = 20; 18499566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 18509371c9d4SSatish Balay cone[0] = 32; 18519371c9d4SSatish Balay cone[1] = 33; 18529371c9d4SSatish Balay cone[2] = 37; 18539371c9d4SSatish Balay cone[3] = 36; 18549371c9d4SSatish Balay cone[4] = 22; 18559371c9d4SSatish Balay cone[5] = 25; 18569371c9d4SSatish Balay cone[6] = 26; 18579371c9d4SSatish Balay cone[7] = 21; 18589566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 18599371c9d4SSatish Balay cone[0] = 34; 18609371c9d4SSatish Balay cone[1] = 38; 18619371c9d4SSatish Balay cone[2] = 37; 18629371c9d4SSatish Balay cone[3] = 33; 18639371c9d4SSatish Balay cone[4] = 20; 18649371c9d4SSatish Balay cone[5] = 21; 18659371c9d4SSatish Balay cone[6] = 26; 18669371c9d4SSatish Balay cone[7] = 28; 18679566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 18689371c9d4SSatish Balay cone[0] = 35; 18699371c9d4SSatish Balay cone[1] = 38; 18709371c9d4SSatish Balay cone[2] = 34; 18719371c9d4SSatish Balay cone[3] = 31; 18729371c9d4SSatish Balay cone[4] = 30; 18739371c9d4SSatish Balay cone[5] = 19; 18749371c9d4SSatish Balay cone[6] = 20; 18759371c9d4SSatish Balay cone[7] = 28; 18769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 18779371c9d4SSatish Balay cone[0] = 35; 18789371c9d4SSatish Balay cone[1] = 31; 18799371c9d4SSatish Balay cone[2] = 32; 18809371c9d4SSatish Balay cone[3] = 36; 18819371c9d4SSatish Balay cone[4] = 30; 18829371c9d4SSatish Balay cone[5] = 25; 18839371c9d4SSatish Balay cone[6] = 22; 18849371c9d4SSatish Balay cone[7] = 19; 18859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 1886ae8bcbbbSMatthew G. Knepley 18879371c9d4SSatish Balay cone[0] = 19; 18889371c9d4SSatish Balay cone[1] = 20; 18899371c9d4SSatish Balay cone[2] = 21; 18909371c9d4SSatish Balay cone[3] = 22; 18919371c9d4SSatish Balay cone[4] = 15; 18929371c9d4SSatish Balay cone[5] = 16; 18939371c9d4SSatish Balay cone[6] = 17; 18949371c9d4SSatish Balay cone[7] = 18; 18959566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 18969371c9d4SSatish Balay cone[0] = 22; 18979371c9d4SSatish Balay cone[1] = 21; 18989371c9d4SSatish Balay cone[2] = 26; 18999371c9d4SSatish Balay cone[3] = 25; 19009371c9d4SSatish Balay cone[4] = 16; 19019371c9d4SSatish Balay cone[5] = 23; 19029371c9d4SSatish Balay cone[6] = 24; 19039371c9d4SSatish Balay cone[7] = 17; 19049566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 19059371c9d4SSatish Balay cone[0] = 20; 19069371c9d4SSatish Balay cone[1] = 28; 19079371c9d4SSatish Balay cone[2] = 26; 19089371c9d4SSatish Balay cone[3] = 21; 19099371c9d4SSatish Balay cone[4] = 18; 19109371c9d4SSatish Balay cone[5] = 17; 19119371c9d4SSatish Balay cone[6] = 24; 19129371c9d4SSatish Balay cone[7] = 27; 19139566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 19149371c9d4SSatish Balay cone[0] = 30; 19159371c9d4SSatish Balay cone[1] = 28; 19169371c9d4SSatish Balay cone[2] = 20; 19179371c9d4SSatish Balay cone[3] = 19; 19189371c9d4SSatish Balay cone[4] = 29; 19199371c9d4SSatish Balay cone[5] = 15; 19209371c9d4SSatish Balay cone[6] = 18; 19219371c9d4SSatish Balay cone[7] = 27; 19229566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 19239371c9d4SSatish Balay cone[0] = 30; 19249371c9d4SSatish Balay cone[1] = 19; 19259371c9d4SSatish Balay cone[2] = 22; 19269371c9d4SSatish Balay cone[3] = 25; 19279371c9d4SSatish Balay cone[4] = 29; 19289371c9d4SSatish Balay cone[5] = 23; 19299371c9d4SSatish Balay cone[6] = 16; 19309371c9d4SSatish Balay cone[7] = 15; 19319566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 1932006a8963SMatthew G. Knepley } else { 19339371c9d4SSatish Balay cone[0] = 5; 19349371c9d4SSatish Balay cone[1] = 8; 19359371c9d4SSatish Balay cone[2] = 7; 19369371c9d4SSatish Balay cone[3] = 6; 19379371c9d4SSatish Balay cone[4] = 9; 19389371c9d4SSatish Balay cone[5] = 12; 19399371c9d4SSatish Balay cone[6] = 11; 19409371c9d4SSatish Balay cone[7] = 10; 19419566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 19429371c9d4SSatish Balay cone[0] = 6; 19439371c9d4SSatish Balay cone[1] = 7; 19449371c9d4SSatish Balay cone[2] = 14; 19459371c9d4SSatish Balay cone[3] = 13; 19469371c9d4SSatish Balay cone[4] = 12; 19479371c9d4SSatish Balay cone[5] = 15; 19489371c9d4SSatish Balay cone[6] = 16; 19499371c9d4SSatish Balay cone[7] = 11; 19509566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 19519371c9d4SSatish Balay cone[0] = 8; 19529371c9d4SSatish Balay cone[1] = 17; 19539371c9d4SSatish Balay cone[2] = 14; 19549371c9d4SSatish Balay cone[3] = 7; 19559371c9d4SSatish Balay cone[4] = 10; 19569371c9d4SSatish Balay cone[5] = 11; 19579371c9d4SSatish Balay cone[6] = 16; 19589371c9d4SSatish Balay cone[7] = 18; 19599566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 19609371c9d4SSatish Balay cone[0] = 19; 19619371c9d4SSatish Balay cone[1] = 17; 19629371c9d4SSatish Balay cone[2] = 8; 19639371c9d4SSatish Balay cone[3] = 5; 19649371c9d4SSatish Balay cone[4] = 20; 19659371c9d4SSatish Balay cone[5] = 9; 19669371c9d4SSatish Balay cone[6] = 10; 19679371c9d4SSatish Balay cone[7] = 18; 19689566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 19699371c9d4SSatish Balay cone[0] = 19; 19709371c9d4SSatish Balay cone[1] = 5; 19719371c9d4SSatish Balay cone[2] = 6; 19729371c9d4SSatish Balay cone[3] = 13; 19739371c9d4SSatish Balay cone[4] = 20; 19749371c9d4SSatish Balay cone[5] = 15; 19759371c9d4SSatish Balay cone[6] = 12; 19769371c9d4SSatish Balay cone[7] = 9; 19779566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1978006a8963SMatthew G. Knepley } 1979d8c47e87SMatthew G. Knepley } 19809566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 19819566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 19820510c589SMatthew G. Knepley } 1983dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 19840510c589SMatthew G. Knepley { 19850510c589SMatthew G. Knepley Vec coordinates; 19860510c589SMatthew G. Knepley PetscSection coordSection; 19870510c589SMatthew G. Knepley PetscScalar *coords; 19880510c589SMatthew G. Knepley PetscInt coordSize, v; 19890510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 19900510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 19910510c589SMatthew G. Knepley 19920510c589SMatthew G. Knepley /* Build coordinates */ 19939566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 19949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 19959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 19969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 19970510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 19989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 19999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 20000510c589SMatthew G. Knepley } 20019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 20029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 20039566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 20049566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 20059566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 20069566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 20079566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 20089566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 2009dd400576SPatrick Sanan if (rank == 0) { 20109371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 20119371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 20129371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 20139371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 20149371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 20159371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 20169371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 20179371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 20189371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 20199371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 20209371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 20219371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 20229371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 20239371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 20249371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 20259371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 20269371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 20279371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 20289371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 20299371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 20309371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 20319371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 20329371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 20339371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 20349371c9d4SSatish Balay coords[8 * dim + 0] = dis; 20359371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 20369371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 20379371c9d4SSatish Balay coords[9 * dim + 0] = dis; 20389371c9d4SSatish Balay coords[9 * dim + 1] = dis; 20399371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 20409371c9d4SSatish Balay coords[10 * dim + 0] = dis; 20419371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 20429371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 20439371c9d4SSatish Balay coords[11 * dim + 0] = dis; 20449371c9d4SSatish Balay coords[11 * dim + 1] = dis; 20459371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 20469371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 20479371c9d4SSatish Balay coords[12 * dim + 1] = dis; 20489371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 20499371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 20509371c9d4SSatish Balay coords[13 * dim + 1] = dis; 20519371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 20529371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 20539371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 20549371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 20559371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 20569371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 20579371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 2058ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 20599371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 20609371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 20619371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 20629371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 20639371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 20649371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 20659371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 20669371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 20679371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 20689371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 20699371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 20709371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 20719371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 20729371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 20739371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 20749371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 20759371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 20769371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 20779371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 20789371c9d4SSatish Balay coords[22 * dim + 1] = dis; 20799371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 20809371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 20819371c9d4SSatish Balay coords[23 * dim + 1] = dis; 20829371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 2083ae8bcbbbSMatthew G. Knepley } 2084d8c47e87SMatthew G. Knepley } 20859566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 20869566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 20879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 20880510c589SMatthew G. Knepley } 2089006a8963SMatthew G. Knepley /* Create periodicity */ 2090006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 20916858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 20926858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 2093006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 2094ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 20956858538eSMatthew G. Knepley PetscInt numZCells = 3; 2096006a8963SMatthew G. Knepley 20976858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 20986858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 20994fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 2100006a8963SMatthew G. Knepley } 2101dbc1dc17SMatthew G. Knepley { 21029318fe57SMatthew G. Knepley DM cdm; 21039318fe57SMatthew G. Knepley PetscDS cds; 21049318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 2105dbc1dc17SMatthew G. Knepley 21069566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder)); 21079566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 21089566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 21099566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 2110dbc1dc17SMatthew G. Knepley } 21119318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 21129566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 21130510c589SMatthew G. Knepley PetscFunctionReturn(0); 21140510c589SMatthew G. Knepley } 21150510c589SMatthew G. Knepley 211624119c2aSMatthew G. Knepley /*@ 21179318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 211824119c2aSMatthew G. Knepley 2119d083f849SBarry Smith Collective 212024119c2aSMatthew G. Knepley 212124119c2aSMatthew G. Knepley Input Parameters: 2122a1cb98faSBarry Smith + comm - The communicator for the `DM` object 21239318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction 212424119c2aSMatthew G. Knepley 212524119c2aSMatthew G. Knepley Output Parameter: 212624119c2aSMatthew G. Knepley . dm - The DM object 212724119c2aSMatthew G. Knepley 212824119c2aSMatthew G. Knepley Level: beginner 212924119c2aSMatthew G. Knepley 2130a1cb98faSBarry Smith Note: 2131a1cb98faSBarry Smith Here is the output numbering looking from the bottom of the cylinder: 2132a1cb98faSBarry Smith .vb 2133a1cb98faSBarry Smith 17-----14 2134a1cb98faSBarry Smith | | 2135a1cb98faSBarry Smith | 2 | 2136a1cb98faSBarry Smith | | 2137a1cb98faSBarry Smith 17-----8-----7-----14 2138a1cb98faSBarry Smith | | | | 2139a1cb98faSBarry Smith | 3 | 0 | 1 | 2140a1cb98faSBarry Smith | | | | 2141a1cb98faSBarry Smith 19-----5-----6-----13 2142a1cb98faSBarry Smith | | 2143a1cb98faSBarry Smith | 4 | 2144a1cb98faSBarry Smith | | 2145a1cb98faSBarry Smith 19-----13 2146a1cb98faSBarry Smith 2147a1cb98faSBarry Smith and up through the top 2148a1cb98faSBarry Smith 2149a1cb98faSBarry Smith 18-----16 2150a1cb98faSBarry Smith | | 2151a1cb98faSBarry Smith | 2 | 2152a1cb98faSBarry Smith | | 2153a1cb98faSBarry Smith 18----10----11-----16 2154a1cb98faSBarry Smith | | | | 2155a1cb98faSBarry Smith | 3 | 0 | 1 | 2156a1cb98faSBarry Smith | | | | 2157a1cb98faSBarry Smith 20-----9----12-----15 2158a1cb98faSBarry Smith | | 2159a1cb98faSBarry Smith | 4 | 2160a1cb98faSBarry Smith | | 2161a1cb98faSBarry Smith 20-----15 2162a1cb98faSBarry Smith .ve 2163a1cb98faSBarry Smith 2164a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 216524119c2aSMatthew G. Knepley @*/ 2166d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm) 2167d71ae5a4SJacob Faibussowitsch { 21689318fe57SMatthew G. Knepley PetscFunctionBegin; 21699318fe57SMatthew G. Knepley PetscValidPointer(dm, 3); 21709566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 21719566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 21729566063dSJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ)); 21739318fe57SMatthew G. Knepley PetscFunctionReturn(0); 21749318fe57SMatthew G. Knepley } 21759318fe57SMatthew G. Knepley 2176d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 2177d71ae5a4SJacob Faibussowitsch { 217824119c2aSMatthew G. Knepley const PetscInt dim = 3; 2179412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 21809fe9f049SMatthew G. Knepley PetscMPIInt rank; 218124119c2aSMatthew G. Knepley 218224119c2aSMatthew G. Knepley PetscFunctionBegin; 218363a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 21849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 21859566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 2186412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 21879566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 218824119c2aSMatthew G. Knepley /* Create topology */ 218924119c2aSMatthew G. Knepley { 219024119c2aSMatthew G. Knepley PetscInt cone[6], c; 219124119c2aSMatthew G. Knepley 2192dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 2193dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 21949566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 21959566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 21969566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 219724119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 21989371c9d4SSatish Balay cone[0] = c + n * 1; 21999371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 22009371c9d4SSatish Balay cone[2] = 0 + 3 * n; 22019371c9d4SSatish Balay cone[3] = c + n * 2; 22029371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 22039371c9d4SSatish Balay cone[5] = 1 + 3 * n; 22049566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 22059566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 220624119c2aSMatthew G. Knepley } 22079566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 22089566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 220924119c2aSMatthew G. Knepley } 221048a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 221124119c2aSMatthew G. Knepley /* Create cylinder geometry */ 221224119c2aSMatthew G. Knepley { 221324119c2aSMatthew G. Knepley Vec coordinates; 221424119c2aSMatthew G. Knepley PetscSection coordSection; 221524119c2aSMatthew G. Knepley PetscScalar *coords; 2216412e9a14SMatthew G. Knepley PetscInt coordSize, c; 221724119c2aSMatthew G. Knepley 221824119c2aSMatthew G. Knepley /* Build coordinates */ 22199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 22209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 22219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 22229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 222324119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 22249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 22259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 222624119c2aSMatthew G. Knepley } 22279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 22289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 22299566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 22309566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 22319566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 22329566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 22339566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 22349566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 223524119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 22369371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 22379371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 22389371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 22399371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 22409371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 22419371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 224224119c2aSMatthew G. Knepley } 2243dd400576SPatrick Sanan if (rank == 0) { 22449371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 22459371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 22469371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 22479371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 22489371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 22499371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 22509fe9f049SMatthew G. Knepley } 22519566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 22529566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 22539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 225424119c2aSMatthew G. Knepley } 22559318fe57SMatthew G. Knepley /* Interpolate */ 22569566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 22579318fe57SMatthew G. Knepley PetscFunctionReturn(0); 22589318fe57SMatthew G. Knepley } 22599318fe57SMatthew G. Knepley 22609318fe57SMatthew G. Knepley /*@ 22619318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 22629318fe57SMatthew G. Knepley 22639318fe57SMatthew G. Knepley Collective 22649318fe57SMatthew G. Knepley 22659318fe57SMatthew G. Knepley Input Parameters: 2266a1cb98faSBarry Smith + comm - The communicator for the `DM` object 22679318fe57SMatthew G. Knepley . n - The number of wedges around the origin 22689318fe57SMatthew G. Knepley - interpolate - Create edges and faces 22699318fe57SMatthew G. Knepley 22709318fe57SMatthew G. Knepley Output Parameter: 2271a1cb98faSBarry Smith . dm - The `DM` object 22729318fe57SMatthew G. Knepley 22739318fe57SMatthew G. Knepley Level: beginner 22749318fe57SMatthew G. Knepley 2275a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 22769318fe57SMatthew G. Knepley @*/ 2277d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 2278d71ae5a4SJacob Faibussowitsch { 22799318fe57SMatthew G. Knepley PetscFunctionBegin; 22809318fe57SMatthew G. Knepley PetscValidPointer(dm, 4); 22819566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 22829566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 22839566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 228424119c2aSMatthew G. Knepley PetscFunctionReturn(0); 228524119c2aSMatthew G. Knepley } 228624119c2aSMatthew G. Knepley 2287d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2288d71ae5a4SJacob Faibussowitsch { 228965a81367SMatthew G. Knepley PetscReal prod = 0.0; 229065a81367SMatthew G. Knepley PetscInt i; 229165a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 229265a81367SMatthew G. Knepley return PetscSqrtReal(prod); 229365a81367SMatthew G. Knepley } 2294d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2295d71ae5a4SJacob Faibussowitsch { 229665a81367SMatthew G. Knepley PetscReal prod = 0.0; 229765a81367SMatthew G. Knepley PetscInt i; 229865a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i] * y[i]; 229965a81367SMatthew G. Knepley return prod; 230065a81367SMatthew G. Knepley } 230165a81367SMatthew G. Knepley 230251a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 2303d71ae5a4SJacob 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[]) 2304d71ae5a4SJacob Faibussowitsch { 230551a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 230651a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 230751a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 230851a74b61SMatthew G. Knepley 230951a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 231051a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 231151a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 231251a74b61SMatthew G. Knepley } 231351a74b61SMatthew G. Knepley 2314d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 2315d71ae5a4SJacob Faibussowitsch { 231665a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 231765a81367SMatthew G. Knepley PetscSection coordSection; 231865a81367SMatthew G. Knepley Vec coordinates; 231965a81367SMatthew G. Knepley PetscScalar *coords; 232065a81367SMatthew G. Knepley PetscReal *coordsIn; 2321064cae4fSPierre Jolivet PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, c, e; 232265a81367SMatthew G. Knepley PetscMPIInt rank; 232365a81367SMatthew G. Knepley 232465a81367SMatthew G. Knepley PetscFunctionBegin; 23259318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 23269566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 23279566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 23289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 232965a81367SMatthew G. Knepley switch (dim) { 233065a81367SMatthew G. Knepley case 2: 233165a81367SMatthew G. Knepley if (simplex) { 233251a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 233351a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 233465a81367SMatthew G. Knepley const PetscInt degree = 5; 233551a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 233665a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 233765a81367SMatthew G. Knepley PetscInt cone[3]; 233865a81367SMatthew G. Knepley PetscInt *graph, p, i, j, k; 233965a81367SMatthew G. Knepley 23409371c9d4SSatish Balay vertex[0] *= R / radius; 23419371c9d4SSatish Balay vertex[1] *= R / radius; 23429371c9d4SSatish Balay vertex[2] *= R / radius; 2343dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 2344dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 234565a81367SMatthew G. Knepley firstVertex = numCells; 234651a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 234765a81367SMatthew G. Knepley 234865a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 234965a81367SMatthew G. Knepley 235065a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 235151a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 235265a81367SMatthew G. Knepley */ 235365a81367SMatthew G. Knepley /* Construct vertices */ 23549566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2355dd400576SPatrick Sanan if (rank == 0) { 235665a81367SMatthew G. Knepley for (p = 0, i = 0; p < embedDim; ++p) { 235765a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 235865a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 235965a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 236065a81367SMatthew G. Knepley ++i; 236165a81367SMatthew G. Knepley } 236265a81367SMatthew G. Knepley } 236365a81367SMatthew G. Knepley } 236445da822fSValeria Barra } 236565a81367SMatthew G. Knepley /* Construct graph */ 23669566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 236765a81367SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 236865a81367SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 23699371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 23709371c9d4SSatish Balay graph[i * numVerts + j] = 1; 23719371c9d4SSatish Balay ++k; 23729371c9d4SSatish Balay } 237365a81367SMatthew G. Knepley } 237463a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 237565a81367SMatthew G. Knepley } 237665a81367SMatthew G. Knepley /* Build Topology */ 23779566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 237848a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 23799566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 238065a81367SMatthew G. Knepley /* Cells */ 238165a81367SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 238265a81367SMatthew G. Knepley for (j = 0; j < i; ++j) { 238365a81367SMatthew G. Knepley for (k = 0; k < j; ++k) { 238465a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 23859371c9d4SSatish Balay cone[0] = firstVertex + i; 23869371c9d4SSatish Balay cone[1] = firstVertex + j; 23879371c9d4SSatish Balay cone[2] = firstVertex + k; 238865a81367SMatthew G. Knepley /* Check orientation */ 238965a81367SMatthew G. Knepley { 23909371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 23919371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 23929371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 23939371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 23949371c9d4SSatish Balay }; 239565a81367SMatthew G. Knepley PetscReal normal[3]; 239665a81367SMatthew G. Knepley PetscInt e, f; 239765a81367SMatthew G. Knepley 239865a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 239965a81367SMatthew G. Knepley normal[d] = 0.0; 240065a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2401ad540459SPierre 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]); 240265a81367SMatthew G. Knepley } 240365a81367SMatthew G. Knepley } 24049371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 24059371c9d4SSatish Balay PetscInt tmp = cone[1]; 24069371c9d4SSatish Balay cone[1] = cone[2]; 24079371c9d4SSatish Balay cone[2] = tmp; 240865a81367SMatthew G. Knepley } 240965a81367SMatthew G. Knepley } 24109566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 241165a81367SMatthew G. Knepley } 241265a81367SMatthew G. Knepley } 241365a81367SMatthew G. Knepley } 241465a81367SMatthew G. Knepley } 24159566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 24169566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 24179566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 241865a81367SMatthew G. Knepley } else { 24192829fed8SMatthew G. Knepley /* 24202829fed8SMatthew G. Knepley 12-21--13 24212829fed8SMatthew G. Knepley | | 24222829fed8SMatthew G. Knepley 25 4 24 24232829fed8SMatthew G. Knepley | | 24242829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 24252829fed8SMatthew G. Knepley | | | | 24262829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 24272829fed8SMatthew G. Knepley | | | | 24282829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 24292829fed8SMatthew G. Knepley | | 24302829fed8SMatthew G. Knepley 20 1 19 24312829fed8SMatthew G. Knepley | | 24322829fed8SMatthew G. Knepley 10-18--11 24332829fed8SMatthew G. Knepley | | 24342829fed8SMatthew G. Knepley 23 2 22 24352829fed8SMatthew G. Knepley | | 24362829fed8SMatthew G. Knepley 12-21--13 24372829fed8SMatthew G. Knepley */ 24382829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 24392829fed8SMatthew G. Knepley 2440dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 2441dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 2442dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 244365a81367SMatthew G. Knepley firstVertex = numCells; 244465a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 24452829fed8SMatthew G. Knepley /* Build Topology */ 24469566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 244748a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 244848a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 24499566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2450dd400576SPatrick Sanan if (rank == 0) { 24512829fed8SMatthew G. Knepley /* Cell 0 */ 24529371c9d4SSatish Balay cone[0] = 14; 24539371c9d4SSatish Balay cone[1] = 15; 24549371c9d4SSatish Balay cone[2] = 16; 24559371c9d4SSatish Balay cone[3] = 17; 24569566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 24579371c9d4SSatish Balay ornt[0] = 0; 24589371c9d4SSatish Balay ornt[1] = 0; 24599371c9d4SSatish Balay ornt[2] = 0; 24609371c9d4SSatish Balay ornt[3] = 0; 24619566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 24622829fed8SMatthew G. Knepley /* Cell 1 */ 24639371c9d4SSatish Balay cone[0] = 18; 24649371c9d4SSatish Balay cone[1] = 19; 24659371c9d4SSatish Balay cone[2] = 14; 24669371c9d4SSatish Balay cone[3] = 20; 24679566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 24689371c9d4SSatish Balay ornt[0] = 0; 24699371c9d4SSatish Balay ornt[1] = 0; 24709371c9d4SSatish Balay ornt[2] = -1; 24719371c9d4SSatish Balay ornt[3] = 0; 24729566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 24732829fed8SMatthew G. Knepley /* Cell 2 */ 24749371c9d4SSatish Balay cone[0] = 21; 24759371c9d4SSatish Balay cone[1] = 22; 24769371c9d4SSatish Balay cone[2] = 18; 24779371c9d4SSatish Balay cone[3] = 23; 24789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 24799371c9d4SSatish Balay ornt[0] = 0; 24809371c9d4SSatish Balay ornt[1] = 0; 24819371c9d4SSatish Balay ornt[2] = -1; 24829371c9d4SSatish Balay ornt[3] = 0; 24839566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 24842829fed8SMatthew G. Knepley /* Cell 3 */ 24859371c9d4SSatish Balay cone[0] = 19; 24869371c9d4SSatish Balay cone[1] = 22; 24879371c9d4SSatish Balay cone[2] = 24; 24889371c9d4SSatish Balay cone[3] = 15; 24899566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 24909371c9d4SSatish Balay ornt[0] = -1; 24919371c9d4SSatish Balay ornt[1] = -1; 24929371c9d4SSatish Balay ornt[2] = 0; 24939371c9d4SSatish Balay ornt[3] = -1; 24949566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 24952829fed8SMatthew G. Knepley /* Cell 4 */ 24969371c9d4SSatish Balay cone[0] = 16; 24979371c9d4SSatish Balay cone[1] = 24; 24989371c9d4SSatish Balay cone[2] = 21; 24999371c9d4SSatish Balay cone[3] = 25; 25009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 25019371c9d4SSatish Balay ornt[0] = -1; 25029371c9d4SSatish Balay ornt[1] = -1; 25039371c9d4SSatish Balay ornt[2] = -1; 25049371c9d4SSatish Balay ornt[3] = 0; 25059566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 25062829fed8SMatthew G. Knepley /* Cell 5 */ 25079371c9d4SSatish Balay cone[0] = 20; 25089371c9d4SSatish Balay cone[1] = 17; 25099371c9d4SSatish Balay cone[2] = 25; 25109371c9d4SSatish Balay cone[3] = 23; 25119566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 25129371c9d4SSatish Balay ornt[0] = -1; 25139371c9d4SSatish Balay ornt[1] = -1; 25149371c9d4SSatish Balay ornt[2] = -1; 25159371c9d4SSatish Balay ornt[3] = -1; 25169566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 25172829fed8SMatthew G. Knepley /* Edges */ 25189371c9d4SSatish Balay cone[0] = 6; 25199371c9d4SSatish Balay cone[1] = 7; 25209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 25219371c9d4SSatish Balay cone[0] = 7; 25229371c9d4SSatish Balay cone[1] = 8; 25239566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 25249371c9d4SSatish Balay cone[0] = 8; 25259371c9d4SSatish Balay cone[1] = 9; 25269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 25279371c9d4SSatish Balay cone[0] = 9; 25289371c9d4SSatish Balay cone[1] = 6; 25299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 25309371c9d4SSatish Balay cone[0] = 10; 25319371c9d4SSatish Balay cone[1] = 11; 25329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 25339371c9d4SSatish Balay cone[0] = 11; 25349371c9d4SSatish Balay cone[1] = 7; 25359566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 25369371c9d4SSatish Balay cone[0] = 6; 25379371c9d4SSatish Balay cone[1] = 10; 25389566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 25399371c9d4SSatish Balay cone[0] = 12; 25409371c9d4SSatish Balay cone[1] = 13; 25419566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 25429371c9d4SSatish Balay cone[0] = 13; 25439371c9d4SSatish Balay cone[1] = 11; 25449566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 25459371c9d4SSatish Balay cone[0] = 10; 25469371c9d4SSatish Balay cone[1] = 12; 25479566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 25489371c9d4SSatish Balay cone[0] = 13; 25499371c9d4SSatish Balay cone[1] = 8; 25509566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 25519371c9d4SSatish Balay cone[0] = 12; 25529371c9d4SSatish Balay cone[1] = 9; 25539566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 255445da822fSValeria Barra } 25559566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 25569566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 25572829fed8SMatthew G. Knepley /* Build coordinates */ 25589566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2559dd400576SPatrick Sanan if (rank == 0) { 25609371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 25619371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 25629371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 25639371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 25649371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 25659371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 25669371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 25679371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 25689371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 25699371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 25709371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 25719371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 25729371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 25739371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 25749371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 25759371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 25769371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 25779371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 25789371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 25799371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 25809371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 25819371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 25829371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 25839371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 258465a81367SMatthew G. Knepley } 258545da822fSValeria Barra } 258665a81367SMatthew G. Knepley break; 258765a81367SMatthew G. Knepley case 3: 2588116ded15SMatthew G. Knepley if (simplex) { 2589116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 259051a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 259151a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 259251a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 2593116ded15SMatthew G. Knepley const PetscInt degree = 12; 2594116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 25959371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 25969371c9d4SSatish Balay {0, 1, 2, 3}, 25979371c9d4SSatish Balay {0, 2, 3, 1}, 25989371c9d4SSatish Balay {0, 3, 1, 2}, 25999371c9d4SSatish Balay {1, 0, 3, 2}, 26009371c9d4SSatish Balay {1, 2, 0, 3}, 26019371c9d4SSatish Balay {1, 3, 2, 0}, 26029371c9d4SSatish Balay {2, 0, 1, 3}, 26039371c9d4SSatish Balay {2, 1, 3, 0}, 26049371c9d4SSatish Balay {2, 3, 0, 1}, 26059371c9d4SSatish Balay {3, 0, 2, 1}, 26069371c9d4SSatish Balay {3, 1, 0, 2}, 26079371c9d4SSatish Balay {3, 2, 1, 0} 26089371c9d4SSatish Balay }; 2609116ded15SMatthew G. Knepley PetscInt cone[4]; 2610116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 2611116ded15SMatthew G. Knepley 26129371c9d4SSatish Balay vertexA[0] *= R; 26139371c9d4SSatish Balay vertexA[1] *= R; 26149371c9d4SSatish Balay vertexA[2] *= R; 26159371c9d4SSatish Balay vertexA[3] *= R; 26169371c9d4SSatish Balay vertexB[0] *= R; 26179371c9d4SSatish Balay vertexB[1] *= R; 26189371c9d4SSatish Balay vertexB[2] *= R; 26199371c9d4SSatish Balay vertexB[3] *= R; 26209371c9d4SSatish Balay vertexC[0] *= R; 26219371c9d4SSatish Balay vertexC[1] *= R; 26229371c9d4SSatish Balay vertexC[2] *= R; 26239371c9d4SSatish Balay vertexC[3] *= R; 2624dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 2625dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 2626116ded15SMatthew G. Knepley firstVertex = numCells; 2627116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 2628116ded15SMatthew G. Knepley 2629116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 2630116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 2631116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 2632116ded15SMatthew G. Knepley 2633116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 26346333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 2635116ded15SMatthew G. Knepley 2636116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 2637116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 2638116ded15SMatthew G. Knepley */ 2639116ded15SMatthew G. Knepley /* Construct vertices */ 26409566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2641116ded15SMatthew G. Knepley i = 0; 2642dd400576SPatrick Sanan if (rank == 0) { 2643116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2644116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2645116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2646116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 2647116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 2648116ded15SMatthew G. Knepley ++i; 2649116ded15SMatthew G. Knepley } 2650116ded15SMatthew G. Knepley } 2651116ded15SMatthew G. Knepley } 2652116ded15SMatthew G. Knepley } 2653116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 2654116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 2655116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2656116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 2657116ded15SMatthew G. Knepley ++i; 2658116ded15SMatthew G. Knepley } 2659116ded15SMatthew G. Knepley } 2660116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 2661116ded15SMatthew G. Knepley s[3] = 1; 2662116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2663116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2664116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2665116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 2666116ded15SMatthew G. Knepley ++i; 2667116ded15SMatthew G. Knepley } 2668116ded15SMatthew G. Knepley } 2669116ded15SMatthew G. Knepley } 2670116ded15SMatthew G. Knepley } 267145da822fSValeria Barra } 267263a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 2673116ded15SMatthew G. Knepley /* Construct graph */ 26749566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 2675116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 2676116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 26779371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 26789371c9d4SSatish Balay graph[i * numVerts + j] = 1; 26799371c9d4SSatish Balay ++k; 26809371c9d4SSatish Balay } 2681116ded15SMatthew G. Knepley } 268263a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 2683116ded15SMatthew G. Knepley } 2684116ded15SMatthew G. Knepley /* Build Topology */ 26859566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 268648a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 26879566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2688116ded15SMatthew G. Knepley /* Cells */ 2689dd400576SPatrick Sanan if (rank == 0) { 2690116ded15SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 2691116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 2692116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 2693116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 26949371c9d4SSatish 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]) { 26959371c9d4SSatish Balay cone[0] = firstVertex + i; 26969371c9d4SSatish Balay cone[1] = firstVertex + j; 26979371c9d4SSatish Balay cone[2] = firstVertex + k; 26989371c9d4SSatish Balay cone[3] = firstVertex + l; 2699116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 2700116ded15SMatthew G. Knepley { 27019371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 27029371c9d4SSatish 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}}}, 2703116ded15SMatthew G. Knepley 27049371c9d4SSatish 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}}}, 2705116ded15SMatthew G. Knepley 27069371c9d4SSatish 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}}}, 2707116ded15SMatthew G. Knepley 27089371c9d4SSatish 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}} } 27099371c9d4SSatish Balay }; 2710116ded15SMatthew G. Knepley PetscReal normal[4]; 2711116ded15SMatthew G. Knepley PetscInt e, f, g; 2712116ded15SMatthew G. Knepley 2713116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 2714116ded15SMatthew G. Knepley normal[d] = 0.0; 2715116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2716116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 2717116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 2718116ded15SMatthew 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]); 2719116ded15SMatthew G. Knepley } 2720116ded15SMatthew G. Knepley } 2721116ded15SMatthew G. Knepley } 2722116ded15SMatthew G. Knepley } 27239371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 27249371c9d4SSatish Balay PetscInt tmp = cone[1]; 27259371c9d4SSatish Balay cone[1] = cone[2]; 27269371c9d4SSatish Balay cone[2] = tmp; 27279371c9d4SSatish Balay } 2728116ded15SMatthew G. Knepley } 27299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 2730116ded15SMatthew G. Knepley } 2731116ded15SMatthew G. Knepley } 2732116ded15SMatthew G. Knepley } 2733116ded15SMatthew G. Knepley } 2734116ded15SMatthew G. Knepley } 273545da822fSValeria Barra } 27369566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 27379566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 27389566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 2739116ded15SMatthew G. Knepley } 2740f4d061e9SPierre Jolivet break; 2741d71ae5a4SJacob Faibussowitsch default: 2742d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 274365a81367SMatthew G. Knepley } 274465a81367SMatthew G. Knepley /* Create coordinates */ 27459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 27469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 27479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 27489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 27492829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 27509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 27519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 27522829fed8SMatthew G. Knepley } 27539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 27549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 27559566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 27569566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 27579566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 27589566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 27599566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 27609566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 27619371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 2762ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 27639566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 27649566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 27659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 27669566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 276751a74b61SMatthew G. Knepley { 276851a74b61SMatthew G. Knepley DM cdm; 276951a74b61SMatthew G. Knepley PetscDS cds; 27709318fe57SMatthew G. Knepley PetscScalar c = R; 277151a74b61SMatthew G. Knepley 27729566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere)); 27739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 27749566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 27759566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 277651a74b61SMatthew G. Knepley } 27779318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 27789566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 27799318fe57SMatthew G. Knepley PetscFunctionReturn(0); 27809318fe57SMatthew G. Knepley } 27819318fe57SMatthew G. Knepley 2782b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 2783b7f5c055SJed Brown 2784b7f5c055SJed Brown /* 2785b7f5c055SJed Brown The Schwarz P implicit surface is 2786b7f5c055SJed Brown 2787b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 2788b7f5c055SJed Brown */ 2789d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2790d71ae5a4SJacob Faibussowitsch { 2791b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 2792b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 2793b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 2794b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2795b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 2796ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 2797b7f5c055SJed Brown } 2798b7f5c055SJed Brown } 2799b7f5c055SJed Brown 28004663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 2801d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 2802d71ae5a4SJacob Faibussowitsch { 2803ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 28044663dae6SJed Brown return 0; 28054663dae6SJed Brown } 28064663dae6SJed Brown 2807b7f5c055SJed Brown /* 2808b7f5c055SJed Brown The Gyroid implicit surface is 2809b7f5c055SJed Brown 2810b7f5c055SJed 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) 2811b7f5c055SJed Brown 2812b7f5c055SJed Brown */ 2813d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2814d71ae5a4SJacob Faibussowitsch { 2815b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 2816b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 2817b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 2818b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 2819b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 2820b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 2821b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 2822b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2823b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2824b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 2825b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2826b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2827b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 2828b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2829b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2830b7f5c055SJed Brown } 2831b7f5c055SJed Brown 28324663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 2833d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 2834d71ae5a4SJacob Faibussowitsch { 28354663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 28364663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 28374663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 28384663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 28394663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 28404663dae6SJed Brown return 0; 28414663dae6SJed Brown } 28424663dae6SJed Brown 2843b7f5c055SJed Brown /* 2844b7f5c055SJed Brown We wish to solve 2845b7f5c055SJed Brown 2846b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 2847b7f5c055SJed Brown 2848b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 2849b7f5c055SJed 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 2850b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 2851b7f5c055SJed Brown 2852b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 2853b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 2854b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 2855b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 2856b7f5c055SJed Brown Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries. 2857b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 2858b7f5c055SJed Brown 2859b7f5c055SJed Brown f(y) = 0 1 equation 2860b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 2861b7f5c055SJed Brown 2862b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 2863b7f5c055SJed Brown */ 2864d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 2865d71ae5a4SJacob Faibussowitsch { 2866b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 2867b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 28682f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 28699371c9d4SSatish Balay PetscReal n_y[3][3] = { 28709371c9d4SSatish Balay {0, 0, 0}, 28719371c9d4SSatish Balay {0, 0, 0}, 28729371c9d4SSatish Balay {0, 0, 0} 28739371c9d4SSatish Balay }; 2874b7f5c055SJed Brown 2875b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 2876b7f5c055SJed Brown 2877b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 2878b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2879ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 2880b7f5c055SJed Brown 2881b7f5c055SJed Brown // Define the Householder reflector 2882b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 2883b7f5c055SJed Brown n[0] += norm * sign; 2884b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 2885b7f5c055SJed Brown 2886b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2887b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 2888b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 2889b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 2890b7f5c055SJed Brown 2891b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2892b7f5c055SJed Brown n[i] /= norm; 2893b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2894b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 2895b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 2896b7f5c055SJed Brown } 2897b7f5c055SJed Brown } 2898b7f5c055SJed Brown 2899b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 2900b7f5c055SJed 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]; 2901b7f5c055SJed Brown 2902b7f5c055SJed Brown res[0] = f; 2903b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 2904b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 2905b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 2906b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2907b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 2908b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 2909b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 2910b7f5c055SJed Brown } 2911b7f5c055SJed Brown } 2912b7f5c055SJed Brown 2913b7f5c055SJed Brown /* 2914b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 2915b7f5c055SJed Brown */ 2916d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 2917d71ae5a4SJacob Faibussowitsch { 2918b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 2919b7f5c055SJed Brown 2920b7f5c055SJed Brown PetscFunctionBegin; 2921b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 2922b7f5c055SJed Brown PetscScalar res[3], J[9]; 2923b7f5c055SJed Brown PetscReal resnorm; 2924b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 2925b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 2926b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 292763a3b9bcSJacob 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]))); 2928b7f5c055SJed Brown } 2929b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 2930b7f5c055SJed Brown 2931b7f5c055SJed Brown // Take the Newton step 29329566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 2933b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 2934b7f5c055SJed Brown } 2935b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 2936b7f5c055SJed Brown PetscFunctionReturn(0); 2937b7f5c055SJed Brown } 2938b7f5c055SJed Brown 2939b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 2940b7f5c055SJed Brown 2941d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 2942d71ae5a4SJacob Faibussowitsch { 2943b7f5c055SJed Brown PetscMPIInt rank; 2944b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 2945b7f5c055SJed Brown PetscInt(*edges)[2] = NULL, *edgeSets = NULL; 2946b7f5c055SJed Brown PetscInt *cells_flat = NULL; 2947b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 2948b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 29494663dae6SJed Brown PetscSimplePointFunc normalFunc = NULL; 2950b7f5c055SJed Brown DMLabel label; 2951b7f5c055SJed Brown 2952b7f5c055SJed Brown PetscFunctionBegin; 29539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 295463a3b9bcSJacob 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); 2955b7f5c055SJed Brown switch (tpstype) { 2956b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 2957b7f5c055SJed 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"); 2958c5853193SPierre Jolivet if (rank == 0) { 2959b7f5c055SJed Brown PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 2960b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 2961b7f5c055SJed Brown PetscReal L = 1; 2962b7f5c055SJed Brown 2963b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 2964b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 2965b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 2966b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 2967b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 2968b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 29699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 29709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 29719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 29729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 2973b7f5c055SJed Brown // x-normal pipes 2974b7f5c055SJed Brown vcount = 0; 2975b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 2976b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2977b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2978b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2979b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 2980b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2981b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2982b7f5c055SJed Brown } 2983b7f5c055SJed Brown } 2984b7f5c055SJed Brown } 2985b7f5c055SJed Brown } 2986b7f5c055SJed Brown // y-normal pipes 2987b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2988b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 2989b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2990b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2991b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2992b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 2993b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2994b7f5c055SJed Brown } 2995b7f5c055SJed Brown } 2996b7f5c055SJed Brown } 2997b7f5c055SJed Brown } 2998b7f5c055SJed Brown // z-normal pipes 2999b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3000b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3001b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 3002b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3003b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3004b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3005b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 3006b7f5c055SJed Brown } 3007b7f5c055SJed Brown } 3008b7f5c055SJed Brown } 3009b7f5c055SJed Brown } 3010b7f5c055SJed Brown // junctions 3011b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3012b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3013b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3014b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 3015b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 3016b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 3017b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 3018b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 3019b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 3020b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 3021b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 3022b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 3023b7f5c055SJed Brown } 3024b7f5c055SJed Brown } 3025b7f5c055SJed Brown } 3026b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 3027b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 3028b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 3029b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 3030b7f5c055SJed Brown }; 3031b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 30329371c9d4SSatish 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}; 3033b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 30349371c9d4SSatish 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}; 3035b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 3036b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 3037b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 3038b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 3039b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 3040b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 3041b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 3042b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 3043b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 3044b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 3045b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 3046b7f5c055SJed Brown if (ijk[dir] == 0) { 3047b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 3048b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 3049b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 3050b7f5c055SJed Brown numEdges++; 3051b7f5c055SJed Brown } 3052b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 3053b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 3054b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 3055b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 3056b7f5c055SJed Brown numEdges++; 3057b7f5c055SJed Brown } 3058b7f5c055SJed Brown } 3059b7f5c055SJed Brown } 3060b7f5c055SJed Brown } 3061b7f5c055SJed Brown } 3062b7f5c055SJed Brown } 306363a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 3064b7f5c055SJed Brown numFaces = 24 * Njunctions; 3065b7f5c055SJed Brown cells_flat = cells[0][0][0]; 3066b7f5c055SJed Brown } 3067b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 30684663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 3069b7f5c055SJed Brown break; 3070b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 3071c5853193SPierre Jolivet if (rank == 0) { 3072b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 3073b7f5c055SJed Brown // 3074b7f5c055SJed 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) 3075b7f5c055SJed Brown // 3076b7f5c055SJed Brown // on the cell [0,2]^3. 3077b7f5c055SJed Brown // 3078b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 3079b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 3080b7f5c055SJed Brown // like a boomerang: 3081b7f5c055SJed Brown // 3082b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 3083b7f5c055SJed Brown // ----- ------- ------- ------- // 3084b7f5c055SJed Brown // // 3085b7f5c055SJed Brown // + + + + + + + \ + // 3086b7f5c055SJed Brown // \ / \ // 3087b7f5c055SJed Brown // \ `-_ _-' / } // 3088b7f5c055SJed Brown // *-_ `-' _-' / // 3089b7f5c055SJed Brown // + `-+ + + +-' + + / + // 3090b7f5c055SJed Brown // // 3091b7f5c055SJed Brown // // 3092b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 3093b7f5c055SJed Brown // ----- ------- ------- ------- // 3094b7f5c055SJed Brown // // 3095b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 3096b7f5c055SJed Brown // `-_ _-_ _-` / // 3097b7f5c055SJed Brown // \ _-' `-_ / { // 3098b7f5c055SJed Brown // \ / \ // 3099b7f5c055SJed Brown // + + + + + + + \ + // 3100b7f5c055SJed Brown // 3101b7f5c055SJed Brown // 3102b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 3103b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 3104b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 3105b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 3106b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 3107b7f5c055SJed Brown // 3108b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 3109b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 3110b7f5c055SJed Brown // 3111b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 3112b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 3113b7f5c055SJed Brown 3114b7f5c055SJed Brown PetscInt facesPerBlock = 64; 3115b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 3116b7f5c055SJed Brown PetscInt extentPlus[3]; 3117b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 31189371c9d4SSatish 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; 31199371c9d4SSatish Balay const PetscInt pattern[64][4] = { 31209371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 3121b7f5c055SJed Brown /* layer 0 */ 31229371c9d4SSatish Balay {A, C, K, G }, 31239371c9d4SSatish Balay {C, B, II, K }, 31249371c9d4SSatish Balay {D, A, H, L }, 31259371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 31269371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 31279371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 31289371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 31299371c9d4SSatish Balay {B, F, M, II }, 3130b7f5c055SJed Brown /* layer 1 */ 31319371c9d4SSatish Balay {G, K, Q, O }, 31329371c9d4SSatish Balay {K, II, P, Q }, 31339371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 31349371c9d4SSatish Balay {J, L, R, P }, 31359371c9d4SSatish Balay {N, J, P, S }, 31369371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 31379371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 31389371c9d4SSatish Balay {II, M, T, P }, 3139b7f5c055SJed Brown /* layer 2 */ 31409371c9d4SSatish Balay {O, Q, Y, U }, 31419371c9d4SSatish Balay {Q, P, W, Y }, 31429371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 31439371c9d4SSatish Balay {P, R, Ap, W }, 31449371c9d4SSatish Balay {S, P, X, Bp }, 31459371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 31469371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 31479371c9d4SSatish Balay {P, T, Z, X }, 3148b7f5c055SJed Brown /* layer 3 */ 31499371c9d4SSatish Balay {U, Y, Ep, Dp }, 31509371c9d4SSatish Balay {Y, W, Cp, Ep }, 31519371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 31529371c9d4SSatish Balay {W, Ap, Gp, Cp }, 31539371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 31549371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 31559371c9d4SSatish Balay {Z, V, Dp, Hp }, 31569371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 3157b7f5c055SJed Brown /* layer 4 */ 31589371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 31599371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 31609371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 31619371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 31629371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 31639371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 31649371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 31659371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 3166b7f5c055SJed Brown /* layer 5 */ 31679371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 31689371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 31699371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 31709371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 31719371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 31729371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 31739371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 31749371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 3175b7f5c055SJed Brown /* layer 6 */ 31769371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 31779371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 31789371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 31799371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 31809371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 31819371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 31829371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 31839371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 3184b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 31859371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 31869371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 31879371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 31889371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 31899371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 31909371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 31919371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 31929371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 3193b7f5c055SJed Brown }; 3194b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 31959371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 3196bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 3197bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 3198bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 3199bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 3200bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 3201bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 3202b7f5c055SJed Brown 3203bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 3204bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 3205bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 3206bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 3207bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 3208bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 3209bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 3210bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 3211b7f5c055SJed Brown 3212bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 3213bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 3214bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 3215bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 3216bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 3217bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 3218b7f5c055SJed Brown 3219bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 3220bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 3221bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 3222bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 3223bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 3224bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 3225bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 3226bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 3227b7f5c055SJed Brown 3228bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 3229bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 3230bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 3231bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 3232bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 3233bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 3234b7f5c055SJed Brown 3235bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 3236bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 3237bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 3238bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 3239bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 3240bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 3241bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 3242bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 3243b7f5c055SJed Brown 3244bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 3245bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 3246bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 3247bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 3248bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 3249bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 3250b7f5c055SJed Brown 3251bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 3252bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 3253bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 3254bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 3255bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 3256bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 3257bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 3258bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 3259b7f5c055SJed Brown }; 3260b7f5c055SJed Brown PetscInt(*cells)[64][4] = NULL; 3261b7f5c055SJed Brown PetscBool *seen; 3262b7f5c055SJed Brown PetscInt *vertToTrueVert; 3263b7f5c055SJed Brown PetscInt count; 3264b7f5c055SJed Brown 3265b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 3266b7f5c055SJed Brown numBlocks = 1; 3267b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 3268b7f5c055SJed Brown numBlocksPlus = 1; 3269b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 3270b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 32719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 32729566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 3273b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3274b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3275b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3276b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3277b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 3278b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 3279b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 3280b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 3281b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 3282b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 3283b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 3284b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 3285b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 3286b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 3287b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 3288b7f5c055SJed Brown 3289b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 3290b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 3291b7f5c055SJed Brown } 3292b7f5c055SJed Brown } 3293b7f5c055SJed Brown } 3294b7f5c055SJed Brown } 3295b7f5c055SJed Brown } 32969371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 32979371c9d4SSatish Balay if (seen[i]) numVertices++; 3298b7f5c055SJed Brown count = 0; 32999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 33009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 3301b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 3302b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 3303b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 3304b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 3305b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 3306b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 3307b7f5c055SJed Brown 3308b7f5c055SJed Brown if (seen[vIdx]) { 3309b7f5c055SJed Brown PetscInt thisVert; 3310b7f5c055SJed Brown 3311b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 3312b7f5c055SJed Brown 3313b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 3314b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 3315b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 3316b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 3317b7f5c055SJed Brown } 3318b7f5c055SJed Brown } 3319b7f5c055SJed Brown } 3320b7f5c055SJed Brown } 3321b7f5c055SJed Brown } 3322b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 3323b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3324ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 3325b7f5c055SJed Brown } 3326b7f5c055SJed Brown } 33279566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 33289566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 3329b7f5c055SJed Brown cells_flat = cells[0][0]; 3330b7f5c055SJed Brown numEdges = 0; 3331b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 3332b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3333b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3334b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3335b7f5c055SJed Brown 3336b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3337b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 3338b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 3339b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 3340b7f5c055SJed Brown } 3341b7f5c055SJed Brown } 3342b7f5c055SJed Brown } 3343b7f5c055SJed Brown } 33449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 33459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 3346b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 3347b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3348b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3349b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3350b7f5c055SJed Brown 3351b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3352b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 3353b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 3354b7f5c055SJed Brown edges[edge][0] = ev[0]; 3355b7f5c055SJed Brown edges[edge][1] = ev[1]; 3356b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 3357b7f5c055SJed Brown } 3358b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 3359b7f5c055SJed Brown edges[edge][0] = ev[0]; 3360b7f5c055SJed Brown edges[edge][1] = ev[1]; 3361b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 3362b7f5c055SJed Brown } 3363b7f5c055SJed Brown } 3364b7f5c055SJed Brown } 3365b7f5c055SJed Brown } 3366b7f5c055SJed Brown } 3367b7f5c055SJed Brown } 3368b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 33694663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 3370b7f5c055SJed Brown break; 3371b7f5c055SJed Brown } 3372b7f5c055SJed Brown 33739566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 3374c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 33759566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 33769566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 3377b7f5c055SJed Brown { 3378b7f5c055SJed Brown DM idm; 33799566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 338069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3381b7f5c055SJed Brown } 3382c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 33839566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 33849566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 3385b7f5c055SJed Brown 33869566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 33879566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 3388b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 3389b7f5c055SJed Brown PetscInt njoin; 3390b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 33919566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 339263a3b9bcSJacob 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]); 33939566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 33949566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 3395b7f5c055SJed Brown } 33969566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 33979566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 33981436d7faSJed Brown if (tps_distribute) { 33991436d7faSJed Brown DM pdm = NULL; 34001436d7faSJed Brown PetscPartitioner part; 34011436d7faSJed Brown 34029566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 34039566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 34049566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 340548a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 34061436d7faSJed Brown // Do not auto-distribute again 34079566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 34081436d7faSJed Brown } 3409b7f5c055SJed Brown 34109566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 3411b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 3412b7f5c055SJed Brown PetscInt m; 3413b7f5c055SJed Brown DM dmf; 3414b7f5c055SJed Brown Vec X; 3415b7f5c055SJed Brown PetscScalar *x; 34169566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 341769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 3418b7f5c055SJed Brown 34199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 34209566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 34219566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 342248a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 34239566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 3424b7f5c055SJed Brown } 3425b7f5c055SJed Brown 3426b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 34279566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 34289566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 3429b7f5c055SJed Brown 3430b7f5c055SJed Brown if (thickness > 0) { 34314663dae6SJed Brown DM edm, cdm, ecdm; 34324663dae6SJed Brown DMPlexTransform tr; 34334663dae6SJed Brown const char *prefix; 34344663dae6SJed Brown PetscOptions options; 34354663dae6SJed Brown // Code from DMPlexExtrude 34364663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 34374663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 34384663dae6SJed Brown PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE)); 34394663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 34404663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 34414663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 34424663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 34434663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 34444663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 34454663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 34464663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 34474663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 34484663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 34494663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 34504663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 34514663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 34524663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 34534663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 34544663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 34554663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 34564663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 34574663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 34584663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 34594663dae6SJed Brown if (edm) { 34604663dae6SJed Brown ((DM_Plex *)edm->data)->printFEM = ((DM_Plex *)dm->data)->printFEM; 34614663dae6SJed Brown ((DM_Plex *)edm->data)->printL2 = ((DM_Plex *)dm->data)->printL2; 3462f5867de0SMatthew G. Knepley ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate; 34634663dae6SJed Brown } 346469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 3465b7f5c055SJed Brown } 3466b7f5c055SJed Brown PetscFunctionReturn(0); 3467b7f5c055SJed Brown } 3468b7f5c055SJed Brown 3469b7f5c055SJed Brown /*@ 3470b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 3471b7f5c055SJed Brown 3472b7f5c055SJed Brown Collective 3473b7f5c055SJed Brown 3474b7f5c055SJed Brown Input Parameters: 3475a1cb98faSBarry Smith + comm - The communicator for the `DM` object 3476b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 3477b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 3478b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic 34791436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 3480817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 34811436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 3482817da375SSatish Balay - thickness - Thickness in normal direction 3483b7f5c055SJed Brown 3484b7f5c055SJed Brown Output Parameter: 3485a1cb98faSBarry Smith . dm - The `DM` object 3486a1cb98faSBarry Smith 3487a1cb98faSBarry Smith Level: beginner 3488b7f5c055SJed Brown 3489b7f5c055SJed Brown Notes: 3490b7f5c055SJed 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. 3491b7f5c055SJed Brown https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries. 3492b7f5c055SJed 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. 3493b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 3494b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 3495b7f5c055SJed Brown This projection could readily be extended to related surfaces. 3496b7f5c055SJed Brown 3497b7f5c055SJed Brown The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z). 3498b7f5c055SJed Brown When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). Use DMPlexLabelComplete() to propagate to coarse-level vertices. 3499b7f5c055SJed Brown 3500a1cb98faSBarry Smith Developer Note: 3501b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 3502b7f5c055SJed Brown 3503a1cb98faSBarry Smith References: 3504a1cb98faSBarry Smith . * - Maskery et al, Insights into the mechanical properties of several triply periodic minimal surface lattice structures made by polymer additive manufacturing, 2017. 3505a1cb98faSBarry Smith https://doi.org/10.1016/j.polymer.2017.11.049 3506b7f5c055SJed Brown 3507a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 3508b7f5c055SJed Brown @*/ 3509d71ae5a4SJacob 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) 3510d71ae5a4SJacob Faibussowitsch { 3511b7f5c055SJed Brown PetscFunctionBegin; 35129566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 35139566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 35149566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 3515b7f5c055SJed Brown PetscFunctionReturn(0); 3516b7f5c055SJed Brown } 3517b7f5c055SJed Brown 35189318fe57SMatthew G. Knepley /*@ 35199318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 35209318fe57SMatthew G. Knepley 35219318fe57SMatthew G. Knepley Collective 35229318fe57SMatthew G. Knepley 35239318fe57SMatthew G. Knepley Input Parameters: 3524a1cb98faSBarry Smith + comm - The communicator for the `DM` object 35259318fe57SMatthew G. Knepley . dim - The dimension 35269318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 35279318fe57SMatthew G. Knepley - R - The radius 35289318fe57SMatthew G. Knepley 35299318fe57SMatthew G. Knepley Output Parameter: 3530a1cb98faSBarry Smith . dm - The `DM` object 35319318fe57SMatthew G. Knepley 35329318fe57SMatthew G. Knepley Level: beginner 35339318fe57SMatthew G. Knepley 3534a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 35359318fe57SMatthew G. Knepley @*/ 3536d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 3537d71ae5a4SJacob Faibussowitsch { 35389318fe57SMatthew G. Knepley PetscFunctionBegin; 35399318fe57SMatthew G. Knepley PetscValidPointer(dm, 5); 35409566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 35419566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 35429566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 35439318fe57SMatthew G. Knepley PetscFunctionReturn(0); 35449318fe57SMatthew G. Knepley } 35459318fe57SMatthew G. Knepley 3546d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 3547d71ae5a4SJacob Faibussowitsch { 35489318fe57SMatthew G. Knepley DM sdm, vol; 35499318fe57SMatthew G. Knepley DMLabel bdlabel; 35509318fe57SMatthew G. Knepley 35519318fe57SMatthew G. Knepley PetscFunctionBegin; 35529566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 35539566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 35549566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_")); 35559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 35569566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 35579566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 35589566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 35599566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 356069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 35619566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 35629566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 35639566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 35649566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 356551a74b61SMatthew G. Knepley PetscFunctionReturn(0); 356651a74b61SMatthew G. Knepley } 356751a74b61SMatthew G. Knepley 356851a74b61SMatthew G. Knepley /*@ 356951a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 357051a74b61SMatthew G. Knepley 357151a74b61SMatthew G. Knepley Collective 357251a74b61SMatthew G. Knepley 357351a74b61SMatthew G. Knepley Input Parameters: 3574a1cb98faSBarry Smith + comm - The communicator for the `DM` object 357551a74b61SMatthew G. Knepley . dim - The dimension 357651a74b61SMatthew G. Knepley - R - The radius 357751a74b61SMatthew G. Knepley 357851a74b61SMatthew G. Knepley Output Parameter: 3579a1cb98faSBarry Smith . dm - The `DM` object 358051a74b61SMatthew G. Knepley 3581a1cb98faSBarry Smith Options Database Key: 358251a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 358351a74b61SMatthew G. Knepley 358451a74b61SMatthew G. Knepley Level: beginner 358551a74b61SMatthew G. Knepley 3586a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 358751a74b61SMatthew G. Knepley @*/ 3588d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 3589d71ae5a4SJacob Faibussowitsch { 359051a74b61SMatthew G. Knepley PetscFunctionBegin; 35919566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 35929566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 35939566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 35942829fed8SMatthew G. Knepley PetscFunctionReturn(0); 35952829fed8SMatthew G. Knepley } 35962829fed8SMatthew G. Knepley 3597d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 3598d71ae5a4SJacob Faibussowitsch { 35990a6ba040SMatthew G. Knepley PetscFunctionBegin; 36009318fe57SMatthew G. Knepley switch (ct) { 36019371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 36029318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 36039318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 36049318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 36059318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 36069318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 36079318fe57SMatthew G. Knepley 36089566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 36099566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 36109371c9d4SSatish Balay } break; 36119371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 36129318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 36139318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 36149318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 36159318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 36169318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 36179318fe57SMatthew G. Knepley 36189566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 36199566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 36209371c9d4SSatish Balay } break; 36219371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 3622b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 3623b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 3624b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 3625b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 3626b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 3627b5a892a1SMatthew G. Knepley 36289566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 36299566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 36309371c9d4SSatish Balay } break; 36319371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 36329318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 36339318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 36349318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 36359318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 36369318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 36379318fe57SMatthew G. Knepley 36389566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 36399566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 36409371c9d4SSatish Balay } break; 36419371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 36429318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 36439318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 36449318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 36459318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 36469318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 36479318fe57SMatthew G. Knepley 36489566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 36499566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 36509371c9d4SSatish Balay } break; 36519371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 36529318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 36539318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 36549318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 36559318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 36569318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 36579318fe57SMatthew G. Knepley 36589566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 36599566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 36609371c9d4SSatish Balay } break; 36619371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 36629318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 36639318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 3664f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 36659318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 3666f0edb160SMatthew 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}; 36679318fe57SMatthew G. Knepley 36689566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 36699566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 36709371c9d4SSatish Balay } break; 36719371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 36729318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 36739318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 3674f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 36759318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 36769371c9d4SSatish 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}; 36779318fe57SMatthew G. Knepley 36789566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 36799566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 36809371c9d4SSatish Balay } break; 36819371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 36829318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 36839318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 3684f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 36859318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 36869371c9d4SSatish 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}; 36879318fe57SMatthew G. Knepley 36889566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 36899566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 36909371c9d4SSatish Balay } break; 36919371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 36929318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 36939318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 36949318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 36959318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 36969371c9d4SSatish 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}; 36979318fe57SMatthew G. Knepley 36989566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 36999566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 37009371c9d4SSatish Balay } break; 37019371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 37029318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 37039318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 37049318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 37059318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 37069371c9d4SSatish 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}; 37079318fe57SMatthew G. Knepley 37089566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 37099566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 37109371c9d4SSatish Balay } break; 37119371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 37129318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 37139318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 3714f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 37159318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 37169371c9d4SSatish 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}; 37179318fe57SMatthew G. Knepley 37189566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 37199566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 37209371c9d4SSatish Balay } break; 3721d71ae5a4SJacob Faibussowitsch default: 3722d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 37239318fe57SMatthew G. Knepley } 37249318fe57SMatthew G. Knepley { 37259318fe57SMatthew G. Knepley PetscInt Nv, v; 37269318fe57SMatthew G. Knepley 37279318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 37289566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 37299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 37309566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 37319566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 37329318fe57SMatthew G. Knepley } 37339566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 37349566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 37350a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 37360a6ba040SMatthew G. Knepley } 37370a6ba040SMatthew G. Knepley 37389318fe57SMatthew G. Knepley /*@ 3739a1cb98faSBarry Smith DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell 37409318fe57SMatthew G. Knepley 37419318fe57SMatthew G. Knepley Collective 37429318fe57SMatthew G. Knepley 37439318fe57SMatthew G. Knepley Input Parameters: 37449318fe57SMatthew G. Knepley + comm - The communicator 37459318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 37469318fe57SMatthew G. Knepley 37479318fe57SMatthew G. Knepley Output Parameter: 37489318fe57SMatthew G. Knepley . refdm - The reference cell 37499318fe57SMatthew G. Knepley 37509318fe57SMatthew G. Knepley Level: intermediate 37519318fe57SMatthew G. Knepley 3752a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()` 37539318fe57SMatthew G. Knepley @*/ 3754d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 3755d71ae5a4SJacob Faibussowitsch { 37560a6ba040SMatthew G. Knepley PetscFunctionBegin; 37579566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 37589566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 37599566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 37609318fe57SMatthew G. Knepley PetscFunctionReturn(0); 37619318fe57SMatthew G. Knepley } 376279a015ccSMatthew G. Knepley 3763d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 3764d71ae5a4SJacob Faibussowitsch { 37659318fe57SMatthew G. Knepley DM plex; 37669318fe57SMatthew G. Knepley DMLabel label; 37679318fe57SMatthew G. Knepley PetscBool hasLabel; 37680a6ba040SMatthew G. Knepley 3769c22d3578SMatthew G. Knepley PetscFunctionBegin; 37709566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 37719318fe57SMatthew G. Knepley if (hasLabel) PetscFunctionReturn(0); 37729566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 37739566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 37749566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 37759566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 37761c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 37779566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 37789318fe57SMatthew G. Knepley PetscFunctionReturn(0); 37799318fe57SMatthew G. Knepley } 3780acdc6f61SToby Isaac 3781669647acSMatthew G. Knepley /* 3782669647acSMatthew 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. 3783669647acSMatthew G. Knepley 3784669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 3785669647acSMatthew G. Knepley */ 3786d71ae5a4SJacob 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[]) 3787d71ae5a4SJacob Faibussowitsch { 3788669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 3789669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 3790669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 3791669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 3792669647acSMatthew G. Knepley 3793669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 3794669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 3795669647acSMatthew G. Knepley } 3796669647acSMatthew G. Knepley 3797cfb853baSMatthew G. Knepley const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 37989318fe57SMatthew G. Knepley 3799d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 3800d71ae5a4SJacob Faibussowitsch { 38019318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 38029318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 38039318fe57SMatthew G. Knepley PetscInt dim = 2; 38049318fe57SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 3805cd7e8a5eSksagiyam PetscBool flg, flg2, fflg, bdfflg, nameflg; 38069318fe57SMatthew G. Knepley MPI_Comm comm; 3807ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3808ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3809ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 38109318fe57SMatthew G. Knepley 38119318fe57SMatthew G. Knepley PetscFunctionBegin; 38129566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 38139318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 38149566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 38159566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 38169566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 38179566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 38189566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 38199566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 38209566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 3821cfb853baSMatthew G. Knepley PetscCheck(dim >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [0, infinity)", dim); 38229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 38239566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 38249566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 38259566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 38269566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 38279318fe57SMatthew G. Knepley 382861a622f3SMatthew G. Knepley switch (cell) { 382961a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 383061a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 383161a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 383261a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 383361a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 383461a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 3835d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 3836d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 3837d71ae5a4SJacob Faibussowitsch break; 3838d71ae5a4SJacob Faibussowitsch default: 3839d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 3840d71ae5a4SJacob Faibussowitsch break; 384161a622f3SMatthew G. Knepley } 384261a622f3SMatthew G. Knepley 38439318fe57SMatthew G. Knepley if (fflg) { 38449318fe57SMatthew G. Knepley DM dmnew; 38459318fe57SMatthew G. Knepley 38469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew)); 38475de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 384869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 38499318fe57SMatthew G. Knepley } else if (refDomain) { 38509566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 38519318fe57SMatthew G. Knepley } else if (bdfflg) { 38529318fe57SMatthew G. Knepley DM bdm, dmnew; 38539318fe57SMatthew G. Knepley 38549566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm)); 38559566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 38569566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 38579566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 38589566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 38595de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 386069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 38619318fe57SMatthew G. Knepley } else { 38629566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 38639318fe57SMatthew G. Knepley switch (shape) { 3864669647acSMatthew G. Knepley case DM_SHAPE_BOX: 3865669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 38669318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 38679318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 38689318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 38699318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3870669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 38719318fe57SMatthew G. Knepley PetscInt i, n; 38729318fe57SMatthew G. Knepley 38739318fe57SMatthew G. Knepley n = dim; 38749318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 38759566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 38769318fe57SMatthew G. Knepley n = 3; 38779566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 387863a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 38799318fe57SMatthew G. Knepley n = 3; 38809566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 388163a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 38829318fe57SMatthew G. Knepley n = 3; 38839566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 388463a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 3885669647acSMatthew G. Knepley 3886669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 3887669647acSMatthew G. Knepley if (isAnnular) 3888669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 3889669647acSMatthew G. Knepley 38909318fe57SMatthew G. Knepley switch (cell) { 389161a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 38929566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 3893d410b0cfSMatthew G. Knepley if (!interpolate) { 3894d410b0cfSMatthew G. Knepley DM udm; 3895d410b0cfSMatthew G. Knepley 38969566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 389769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3898d410b0cfSMatthew G. Knepley } 38999318fe57SMatthew G. Knepley break; 3900d71ae5a4SJacob Faibussowitsch default: 3901d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate)); 3902d71ae5a4SJacob Faibussowitsch break; 39039318fe57SMatthew G. Knepley } 3904669647acSMatthew G. Knepley if (isAnnular) { 3905669647acSMatthew G. Knepley DM cdm; 3906669647acSMatthew G. Knepley PetscDS cds; 3907669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 3908669647acSMatthew G. Knepley 3909669647acSMatthew G. Knepley // Fix coordinates for annular region 3910669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 3911669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 3912669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 3913669647acSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, NULL)); 3914669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 3915669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 3916669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 3917669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 3918669647acSMatthew G. Knepley } 39199371c9d4SSatish Balay } break; 39209371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 39219318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 39229318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 39239318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 39249318fe57SMatthew G. Knepley PetscInt i, n; 39259318fe57SMatthew G. Knepley 39269318fe57SMatthew G. Knepley n = dim + 1; 39279318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 39289566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 39299318fe57SMatthew G. Knepley n = 3; 39309566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 393163a3b9bcSJacob 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); 39329318fe57SMatthew G. Knepley n = 3; 39339566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 393463a3b9bcSJacob 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); 39359566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 39369371c9d4SSatish Balay } break; 39379371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 39389318fe57SMatthew G. Knepley PetscReal R = 1.0; 39399318fe57SMatthew G. Knepley 39409566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 39419566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 39429371c9d4SSatish Balay } break; 39439371c9d4SSatish Balay case DM_SHAPE_BALL: { 39449318fe57SMatthew G. Knepley PetscReal R = 1.0; 39459318fe57SMatthew G. Knepley 39469566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 39479566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 39489371c9d4SSatish Balay } break; 39499371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 39509318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 39519318fe57SMatthew G. Knepley PetscInt Nw = 6; 39529318fe57SMatthew G. Knepley 39539566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 39549566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 39559318fe57SMatthew G. Knepley switch (cell) { 3956d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 3957d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 3958d71ae5a4SJacob Faibussowitsch break; 3959d71ae5a4SJacob Faibussowitsch default: 3960d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt)); 3961d71ae5a4SJacob Faibussowitsch break; 39629318fe57SMatthew G. Knepley } 39639371c9d4SSatish Balay } break; 3964b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 39659371c9d4SSatish Balay case DM_SHAPE_GYROID: { 3966b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 3967b7f5c055SJed Brown PetscReal thickness = 0.; 3968b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3969b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 39701436d7faSJed Brown PetscBool tps_distribute; 39719566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 39729566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 39739566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 39749566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 39759566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 39769566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 39779566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 39789566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 39799371c9d4SSatish Balay } break; 39809371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 398105bd46c0SStefano Zampini DM dmnew; 398205bd46c0SStefano Zampini PetscReal rl = 0.0; 398305bd46c0SStefano Zampini 398405bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 398505bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 39865de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 398769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 39889371c9d4SSatish Balay } break; 3989cfb853baSMatthew G. Knepley case DM_SHAPE_HYPERCUBIC: { 3990cfb853baSMatthew G. Knepley PetscInt *edges; 3991cfb853baSMatthew G. Knepley PetscReal *lower, *upper; 3992cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 3993cfb853baSMatthew G. Knepley PetscInt n, d; 3994cfb853baSMatthew G. Knepley 3995cfb853baSMatthew G. Knepley *useCoordSpace = PETSC_FALSE; 3996cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt)); 3997cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 3998cfb853baSMatthew G. Knepley edges[d] = 1; 3999cfb853baSMatthew G. Knepley lower[d] = 0.; 4000cfb853baSMatthew G. Knepley upper[d] = 1.; 4001cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 4002cfb853baSMatthew G. Knepley } 4003cfb853baSMatthew G. Knepley n = dim; 4004cfb853baSMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg)); 4005cfb853baSMatthew G. Knepley n = dim; 4006cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 4007cfb853baSMatthew G. Knepley PetscCheck(!flg || n == dim, comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 4008cfb853baSMatthew G. Knepley n = dim; 4009cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 4010cfb853baSMatthew G. Knepley PetscCheck(!flg || n == dim, comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 4011cfb853baSMatthew G. Knepley n = dim; 4012cfb853baSMatthew G. Knepley PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 4013cfb853baSMatthew G. Knepley PetscCheck(!flg || n == dim, comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 4014cfb853baSMatthew G. Knepley PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, bdt)); 4015cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edges, lower, upper, bdt)); 4016cfb853baSMatthew G. Knepley } break; 4017d71ae5a4SJacob Faibussowitsch default: 4018d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 40199318fe57SMatthew G. Knepley } 40209318fe57SMatthew G. Knepley } 40219566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 402248a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 40230a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 40240a6ba040SMatthew G. Knepley } 40250a6ba040SMatthew G. Knepley 4026d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 4027d71ae5a4SJacob Faibussowitsch { 40280a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 40297f9d8d6cSVaclav Hapla PetscBool flg, flg2; 40309318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 40310a6ba040SMatthew G. Knepley 40320a6ba040SMatthew G. Knepley PetscFunctionBegin; 40330a6ba040SMatthew G. Knepley /* Handle viewing */ 40349566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 40359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 40369566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 40379566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 4038f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 40399566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 40409566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 40419318fe57SMatthew G. Knepley /* Labeling */ 40429566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 40439566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 4044953fc75cSMatthew G. Knepley /* Point Location */ 40459566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 40460848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 40479566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 40482e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 40499566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 4050b29cfa1cSToby Isaac /* Projection behavior */ 4051d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 40529566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 4053f12cf164SMatthew G. Knepley /* Checking structure */ 4054f12cf164SMatthew G. Knepley { 40557f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 4056f12cf164SMatthew G. Knepley 40577f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 40587f9d8d6cSVaclav Hapla if (all) { 40597f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 40607f9d8d6cSVaclav Hapla } else { 40619566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 40627f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 40639566063dSJacob 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)); 40647f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 40659566063dSJacob 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)); 40667f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 40679566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 40687f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 40699566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 4070d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 40719566063dSJacob 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)); 40727f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 40737f9d8d6cSVaclav Hapla } 40749566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 40759566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 4076f12cf164SMatthew G. Knepley } 40779318fe57SMatthew G. Knepley { 40789318fe57SMatthew G. Knepley PetscReal scale = 1.0; 40794f3833eaSMatthew G. Knepley 40809566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 40819318fe57SMatthew G. Knepley if (flg) { 40829318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 40839318fe57SMatthew G. Knepley 40849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 40859566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 40869566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 40879566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 40889318fe57SMatthew G. Knepley } 40899318fe57SMatthew G. Knepley } 40909566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 409168d4fef7SMatthew G. Knepley PetscFunctionReturn(0); 409268d4fef7SMatthew G. Knepley } 409368d4fef7SMatthew G. Knepley 4094d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap) 4095d71ae5a4SJacob Faibussowitsch { 4096c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 4097c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 4098c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 4099c506a872SMatthew G. Knepley PetscBool flg; 4100c506a872SMatthew G. Knepley 4101c506a872SMatthew G. Knepley PetscFunctionBegin; 4102c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 4103c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 4104c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 4105c506a872SMatthew G. Knepley if (numOvLabels) { 4106c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 4107c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 4108c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 4109c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 4110c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 4111c506a872SMatthew G. Knepley } 4112c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 4113c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 4114c506a872SMatthew 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); 4115c506a872SMatthew G. Knepley 4116c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 4117c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 4118c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 4119c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 4120c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 4121c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 4122c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 4123c506a872SMatthew G. Knepley } 4124c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 4125c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 4126c506a872SMatthew 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); 4127c506a872SMatthew G. Knepley } 4128c506a872SMatthew G. Knepley PetscFunctionReturn(0); 4129c506a872SMatthew G. Knepley } 4130c506a872SMatthew G. Knepley 4131d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 4132d71ae5a4SJacob Faibussowitsch { 4133bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 4134bdf63967SMatthew G. Knepley char oname[256]; 4135d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 41369318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 4137e600fa54SMatthew 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; 41386bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 413968d4fef7SMatthew G. Knepley 414068d4fef7SMatthew G. Knepley PetscFunctionBegin; 4141d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 4142dd4c3f67SMatthew G. Knepley if (dm->cloneOpts) goto non_refine; 41439318fe57SMatthew G. Knepley /* Handle automatic creation */ 41449566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 41456bc1bd01Sksagiyam if (dim < 0) { 41466bc1bd01Sksagiyam PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 41476bc1bd01Sksagiyam created = PETSC_TRUE; 41486bc1bd01Sksagiyam } 41496bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 4150d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 41519566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 4152d89e6e46SMatthew G. Knepley if (flg) { 4153d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 4154d89e6e46SMatthew G. Knepley 41559566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 4156d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 4157d89e6e46SMatthew G. Knepley DM udm; 4158d89e6e46SMatthew G. Knepley 41599566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 416069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 4161d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 4162d89e6e46SMatthew G. Knepley DM idm; 4163d89e6e46SMatthew G. Knepley 41649566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 416569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 4166d89e6e46SMatthew G. Knepley } 4167d89e6e46SMatthew G. Knepley } 41689b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 41699566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg)); 4170ad540459SPierre Jolivet if (flg) ((DM_Plex *)dm->data)->ignoreModel = ignoreModel; 41719566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 41729566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 41739566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 41749566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 41759566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 41769566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 41779318fe57SMatthew G. Knepley if (flg) { 41789566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 41799566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 41809318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 41819318fe57SMatthew G. Knepley } 41829b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 41839b44eab4SMatthew G. Knepley DM rdm; 41849b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 41859b44eab4SMatthew G. Knepley 4186dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 41879566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 418869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 4189dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 419061a622f3SMatthew G. Knepley if (coordFunc && remap) { 41919566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 41929b44eab4SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 41939b44eab4SMatthew G. Knepley } 41949b44eab4SMatthew G. Knepley } 41959566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 41969318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 41979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 41989318fe57SMatthew G. Knepley if (extLayers) { 41999318fe57SMatthew G. Knepley DM edm; 42009318fe57SMatthew G. Knepley 42019566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 420269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 420348d16a33SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = NULL; 4204dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 4205d410b0cfSMatthew G. Knepley extLayers = 0; 42065e17fc22SAidan Hamilton PetscCall(DMGetDimension(dm, &dim)); 42079318fe57SMatthew G. Knepley } 4208bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 42096bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 42109566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 42116bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 42129566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 42136bc1bd01Sksagiyam if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) { 4214bdf63967SMatthew G. Knepley DM pdm; 4215bdf63967SMatthew G. Knepley IS perm; 4216bdf63967SMatthew G. Knepley 42179566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 42189566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 42199566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 422069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 4221dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 4222bdf63967SMatthew G. Knepley } 42239b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 42249566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 4225c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 4226dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 42279b44eab4SMatthew G. Knepley if (distribute) { 42289b44eab4SMatthew G. Knepley DM pdm = NULL; 42299b44eab4SMatthew G. Knepley PetscPartitioner part; 42309b44eab4SMatthew G. Knepley 42319566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 42329566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 42339566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm)); 423448a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 42359b44eab4SMatthew G. Knepley } 42369318fe57SMatthew G. Knepley /* Create coordinate space */ 42379318fe57SMatthew G. Knepley if (created) { 423861a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 42399318fe57SMatthew G. Knepley PetscInt degree = 1; 42405515ebd3SMatthew G. Knepley PetscInt height = 0; 42415515ebd3SMatthew G. Knepley DM cdm; 42426858538eSMatthew G. Knepley PetscBool flg; 42439318fe57SMatthew G. Knepley 42449566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg)); 42459566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 42469566063dSJacob Faibussowitsch if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc)); 42475515ebd3SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 424861a622f3SMatthew G. Knepley if (flg && !coordSpace) { 424961a622f3SMatthew G. Knepley PetscDS cds; 425061a622f3SMatthew G. Knepley PetscObject obj; 425161a622f3SMatthew G. Knepley PetscClassId id; 425261a622f3SMatthew G. Knepley 42539566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 42549566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 42559566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 425661a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 425761a622f3SMatthew G. Knepley PetscContainer dummy; 425861a622f3SMatthew G. Knepley 42599566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 42609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 42619566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 42629566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 42639566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 426461a622f3SMatthew G. Knepley } 426561a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 426661a622f3SMatthew G. Knepley } 42676858538eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg)); 42685515ebd3SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg)); 42695515ebd3SMatthew G. Knepley if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height)); 42709566063dSJacob Faibussowitsch PetscCall(DMLocalizeCoordinates(dm)); 42719318fe57SMatthew G. Knepley } 427268d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 427361a622f3SMatthew G. Knepley remap = PETSC_TRUE; 42749566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 42759566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 42769566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 42779566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 427868d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 4279acdc6f61SToby Isaac DM *dms, coarseDM; 428068d4fef7SMatthew G. Knepley 42819566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 42829566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 42839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 42849566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 428568d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 42869566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 428768d4fef7SMatthew G. Knepley if (refine == 1) { 42889566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 42899566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 429068d4fef7SMatthew G. Knepley } else { 42919566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 42929566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 42939566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 42949566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 429568d4fef7SMatthew G. Knepley } 42969566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 42979566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 429868d4fef7SMatthew G. Knepley /* Free DMs */ 429968d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 4300dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 43019566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 430268d4fef7SMatthew G. Knepley } 43039566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 430468d4fef7SMatthew G. Knepley } else { 430568d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 43069318fe57SMatthew G. Knepley DM rdm; 430751a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 430868d4fef7SMatthew G. Knepley 4309dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 43109566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 431168d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 431269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 4313dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 431461a622f3SMatthew G. Knepley if (coordFunc && remap) { 43159566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 431651a74b61SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 431751a74b61SMatthew G. Knepley } 431868d4fef7SMatthew G. Knepley } 431968d4fef7SMatthew G. Knepley } 43203cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 43219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 43229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 4323b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 4324b653a561SMatthew G. Knepley DM *dms; 4325b653a561SMatthew G. Knepley 43269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 43279566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 4328b653a561SMatthew G. Knepley /* Free DMs */ 4329b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 4330dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 43319566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 4332b653a561SMatthew G. Knepley } 43339566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 4334b653a561SMatthew G. Knepley } else { 4335b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 43369318fe57SMatthew G. Knepley DM cdm; 43379318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 43383cf6fe12SMatthew G. Knepley 4339dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 43409566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 43413cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 434269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 4343dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 43449318fe57SMatthew G. Knepley if (coordFunc) { 43459566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 43469318fe57SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 43479318fe57SMatthew G. Knepley } 43483cf6fe12SMatthew G. Knepley } 4349b653a561SMatthew G. Knepley } 4350909dfd52SMatthew G. Knepley /* Handle ghost cells */ 43519566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 4352909dfd52SMatthew G. Knepley if (ghostCells) { 4353909dfd52SMatthew G. Knepley DM gdm; 4354909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 4355909dfd52SMatthew G. Knepley 4356909dfd52SMatthew G. Knepley lname[0] = '\0'; 43579566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 43589566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 435969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 4360909dfd52SMatthew G. Knepley } 43616913077dSMatthew G. Knepley /* Handle 1D order */ 43626bc1bd01Sksagiyam if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) { 43636913077dSMatthew G. Knepley DM cdm, rdm; 43646913077dSMatthew G. Knepley PetscDS cds; 43656913077dSMatthew G. Knepley PetscObject obj; 43666913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 43676913077dSMatthew G. Knepley IS perm; 43686bc1bd01Sksagiyam PetscInt Nf; 43696913077dSMatthew G. Knepley PetscBool distributed; 43706913077dSMatthew G. Knepley 43719566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 43729566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 43739566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 43749566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 43756913077dSMatthew G. Knepley if (Nf) { 43769566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 43779566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 43786913077dSMatthew G. Knepley } 43796bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 43809566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 43819566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 438269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 43839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 43846913077dSMatthew G. Knepley } 43856913077dSMatthew G. Knepley } 43863cf6fe12SMatthew G. Knepley /* Handle */ 4387dd4c3f67SMatthew G. Knepley non_refine: 4388dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 4389d0609cedSBarry Smith PetscOptionsHeadEnd(); 43900a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 43910a6ba040SMatthew G. Knepley } 43920a6ba040SMatthew G. Knepley 4393d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 4394d71ae5a4SJacob Faibussowitsch { 4395552f7358SJed Brown PetscFunctionBegin; 43969566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 43979566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 43989566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 43999566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 44009566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 44019566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 4402552f7358SJed Brown PetscFunctionReturn(0); 4403552f7358SJed Brown } 4404552f7358SJed Brown 4405d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 4406d71ae5a4SJacob Faibussowitsch { 4407552f7358SJed Brown PetscFunctionBegin; 44089566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 44099566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 44109566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 4411552f7358SJed Brown PetscFunctionReturn(0); 4412552f7358SJed Brown } 4413552f7358SJed Brown 4414d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4415d71ae5a4SJacob Faibussowitsch { 4416793f3fe5SMatthew G. Knepley PetscInt depth, d; 4417793f3fe5SMatthew G. Knepley 4418793f3fe5SMatthew G. Knepley PetscFunctionBegin; 44199566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4420793f3fe5SMatthew G. Knepley if (depth == 1) { 44219566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 44229566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 44239566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 44249371c9d4SSatish Balay else { 44259371c9d4SSatish Balay *pStart = 0; 44269371c9d4SSatish Balay *pEnd = 0; 44279371c9d4SSatish Balay } 4428793f3fe5SMatthew G. Knepley } else { 44299566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 4430793f3fe5SMatthew G. Knepley } 4431793f3fe5SMatthew G. Knepley PetscFunctionReturn(0); 4432793f3fe5SMatthew G. Knepley } 4433793f3fe5SMatthew G. Knepley 4434d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 4435d71ae5a4SJacob Faibussowitsch { 4436502a2867SDave May PetscSF sf; 44370a19bb7dSprj- PetscInt niranks, njranks, n; 44380a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 44390a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 4440502a2867SDave May 44412f356facSMatthew G. Knepley PetscFunctionBegin; 44429566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 44430a19bb7dSprj- if (!data->neighbors) { 44449566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 44459566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 44469566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 44479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 44489566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 44499566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 44500a19bb7dSprj- n = njranks + niranks; 44519566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 44520a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 44539566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 44540a19bb7dSprj- } 44550a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 44560a19bb7dSprj- if (ranks) { 44570a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 44580a19bb7dSprj- else *ranks = NULL; 44590a19bb7dSprj- } 4460502a2867SDave May PetscFunctionReturn(0); 4461502a2867SDave May } 4462502a2867SDave May 44631eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 44641eb70e55SToby Isaac 4465d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 4466d71ae5a4SJacob Faibussowitsch { 4467552f7358SJed Brown PetscFunctionBegin; 4468552f7358SJed Brown dm->ops->view = DMView_Plex; 44692c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 4470552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 447138221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 4472552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 44731bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 447466ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 4475552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 4476552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 4477184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 44780298fd71SBarry Smith dm->ops->createfieldis = NULL; 4479552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 4480f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 44810a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 4482552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 4483bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 4484bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 4485b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 44865a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 4487552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 44880a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 44890a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 4490b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 4491d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 44920298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 44930298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 44940298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 44950298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 4496552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 4497552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 44982adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 4499793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 4500552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 45010709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 45020709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 4503bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 45048c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 4505ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 45060709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 4507b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 45082a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 450928d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 45109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 45119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 45129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 45139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 45149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 45159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 45169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 45176bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 45186bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 45199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 4520c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 4521c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 4522552f7358SJed Brown PetscFunctionReturn(0); 4523552f7358SJed Brown } 4524552f7358SJed Brown 4525d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 4526d71ae5a4SJacob Faibussowitsch { 452763a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 45286725e60dSJed Brown PetscSF face_sf; 452963a16f15SMatthew G. Knepley 453063a16f15SMatthew G. Knepley PetscFunctionBegin; 453163a16f15SMatthew G. Knepley mesh->refct++; 453263a16f15SMatthew G. Knepley (*newdm)->data = mesh; 4533*5f06a3ddSJed Brown PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &face_sf)); 4534*5f06a3ddSJed Brown PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, face_sf)); 45359566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 45369566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 453763a16f15SMatthew G. Knepley PetscFunctionReturn(0); 453863a16f15SMatthew G. Knepley } 453963a16f15SMatthew G. Knepley 45408818961aSMatthew G Knepley /*MC 4541a1cb98faSBarry Smith DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 45428818961aSMatthew G Knepley In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is 45438818961aSMatthew G Knepley specified by a PetscSection object. Ownership in the global representation is determined by 4544a1cb98faSBarry Smith ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object. 45458818961aSMatthew G Knepley 4546e5893cccSMatthew G. Knepley Options Database Keys: 4547250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 4548250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 4549250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 4550250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 4551250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 4552250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 4553250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 4554ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 4555f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 4556f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 4557d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 4558f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 4559250712c9SMatthew G. Knepley . -dm_plex_check_all - Perform all shecks below 4560f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 4561f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 4562f12cf164SMatthew 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 4563f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 4564f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 4565e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 4566e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 4567e5893cccSMatthew G. Knepley 45688818961aSMatthew G Knepley Level: intermediate 45698818961aSMatthew G Knepley 4570a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection` 45718818961aSMatthew G Knepley M*/ 45728818961aSMatthew G Knepley 4573d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 4574d71ae5a4SJacob Faibussowitsch { 4575552f7358SJed Brown DM_Plex *mesh; 4576412e9a14SMatthew G. Knepley PetscInt unit; 4577552f7358SJed Brown 4578552f7358SJed Brown PetscFunctionBegin; 4579552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 45804dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 4581552f7358SJed Brown dm->data = mesh; 4582552f7358SJed Brown 4583552f7358SJed Brown mesh->refct = 1; 45849566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 45859566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 4586552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 4587552f7358SJed Brown mesh->refinementLimit = -1.0; 4588e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 45896bc1bd01Sksagiyam mesh->reorderDefault = DMPLEX_REORDER_DEFAULT_NOTSET; 45901d1f2f2aSksagiyam mesh->distributionName = NULL; 45917d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 45927d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 4593552f7358SJed Brown 45949566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 45952e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 4596d9deefdfSMatthew G. Knepley 45978865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 4598552f7358SJed Brown 4599df0420ecSMatthew G. Knepley mesh->depthState = -1; 4600ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 46016113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 4602552f7358SJed Brown 46039566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 4604552f7358SJed Brown PetscFunctionReturn(0); 4605552f7358SJed Brown } 4606552f7358SJed Brown 4607552f7358SJed Brown /*@ 4608a1cb98faSBarry Smith DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 4609552f7358SJed Brown 4610d083f849SBarry Smith Collective 4611552f7358SJed Brown 4612552f7358SJed Brown Input Parameter: 4613a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object 4614552f7358SJed Brown 4615552f7358SJed Brown Output Parameter: 4616a1cb98faSBarry Smith . mesh - The `DMPLEX` object 4617552f7358SJed Brown 4618552f7358SJed Brown Level: beginner 4619552f7358SJed Brown 4620a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()` 4621552f7358SJed Brown @*/ 4622d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 4623d71ae5a4SJacob Faibussowitsch { 4624552f7358SJed Brown PetscFunctionBegin; 4625552f7358SJed Brown PetscValidPointer(mesh, 2); 46269566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 46279566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 4628552f7358SJed Brown PetscFunctionReturn(0); 4629552f7358SJed Brown } 4630552f7358SJed Brown 4631b09969d6SVaclav Hapla /*@C 4632a1cb98faSBarry Smith DMPlexBuildFromCellListParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 4633a1cb98faSBarry Smith 4634a1cb98faSBarry Smith Collective on dm 4635b09969d6SVaclav Hapla 4636b09969d6SVaclav Hapla Input Parameters: 4637a1cb98faSBarry Smith + dm - The `DM` 4638b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4639a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 4640a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DETERMINE` 4641b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 46425e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4643b09969d6SVaclav Hapla 4644be8c289dSNicolas Barral Output Parameters: 4645a1cb98faSBarry Smith + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 4646be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4647b09969d6SVaclav Hapla 4648b09969d6SVaclav Hapla Level: advanced 4649b09969d6SVaclav Hapla 4650a1cb98faSBarry Smith Notes: 4651a1cb98faSBarry Smith Two triangles sharing a face 4652a1cb98faSBarry Smith .vb 4653a1cb98faSBarry Smith 4654a1cb98faSBarry Smith 2 4655a1cb98faSBarry Smith / | \ 4656a1cb98faSBarry Smith / | \ 4657a1cb98faSBarry Smith / | \ 4658a1cb98faSBarry Smith 0 0 | 1 3 4659a1cb98faSBarry Smith \ | / 4660a1cb98faSBarry Smith \ | / 4661a1cb98faSBarry Smith \ | / 4662a1cb98faSBarry Smith 1 4663a1cb98faSBarry Smith .ve 4664a1cb98faSBarry Smith would have input 4665a1cb98faSBarry Smith .vb 4666a1cb98faSBarry Smith numCells = 2, numVertices = 4 4667a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 4668a1cb98faSBarry Smith .ve 4669a1cb98faSBarry Smith which would result in the `DMPLEX` 4670a1cb98faSBarry Smith .vb 4671a1cb98faSBarry Smith 4672a1cb98faSBarry Smith 4 4673a1cb98faSBarry Smith / | \ 4674a1cb98faSBarry Smith / | \ 4675a1cb98faSBarry Smith / | \ 4676a1cb98faSBarry Smith 2 0 | 1 5 4677a1cb98faSBarry Smith \ | / 4678a1cb98faSBarry Smith \ | / 4679a1cb98faSBarry Smith \ | / 4680a1cb98faSBarry Smith 3 4681a1cb98faSBarry Smith .ve 4682a1cb98faSBarry Smith 4683a1cb98faSBarry Smith Vertices are implicitly numbered consecutively 0,...,NVertices. 4684a1cb98faSBarry Smith Each rank owns a chunk of numVertices consecutive vertices. 4685a1cb98faSBarry Smith If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 4686a1cb98faSBarry Smith If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 4687a1cb98faSBarry Smith If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 4688a1cb98faSBarry Smith 4689a1cb98faSBarry Smith The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 4690a1cb98faSBarry Smith 4691a1cb98faSBarry Smith Fortran Note: 4692a1cb98faSBarry Smith Not currently supported in Fortran. 4693a1cb98faSBarry Smith 4694a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 4695a1cb98faSBarry Smith `PetscSF` 4696b09969d6SVaclav Hapla @*/ 4697d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved) 4698d71ae5a4SJacob Faibussowitsch { 46992464107aSksagiyam PetscSF sfPoint; 47002464107aSksagiyam PetscLayout layout; 470182fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 4702a47d0d45SMatthew G. Knepley 4703a47d0d45SMatthew G. Knepley PetscFunctionBegin; 470425b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 47059566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 470625b6865aSVaclav Hapla /* Get/check global number of vertices */ 470725b6865aSVaclav Hapla { 470825b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 470925b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 471025b6865aSVaclav Hapla 471125b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 471225b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 47139371c9d4SSatish Balay for (i = 0; i < len; i++) 47149371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 471525b6865aSVaclav Hapla ++NVerticesInCells; 47169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 471725b6865aSVaclav Hapla 471825b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 47199371c9d4SSatish Balay else 47209371c9d4SSatish 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); 472125b6865aSVaclav Hapla } 47229079aca8SVaclav Hapla /* Count locally unique vertices */ 47239079aca8SVaclav Hapla { 47249079aca8SVaclav Hapla PetscHSetI vhash; 47259079aca8SVaclav Hapla PetscInt off = 0; 47269079aca8SVaclav Hapla 47279566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 4728a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 472948a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 4730a47d0d45SMatthew G. Knepley } 47319566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 47329566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 4733ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 47349566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 47359566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 473663a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 4737a47d0d45SMatthew G. Knepley } 47389566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 4739a47d0d45SMatthew G. Knepley /* Create cones */ 47409566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 47419566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 47429566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 47439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4744a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 4745a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 4746a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 4747a47d0d45SMatthew G. Knepley PetscInt lv; 4748a47d0d45SMatthew G. Knepley 47499079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 47509079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 47519566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 475263a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 4753961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 4754a47d0d45SMatthew G. Knepley } 4755a47d0d45SMatthew G. Knepley } 47562464107aSksagiyam /* Build point sf */ 47579566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 47589566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 47599566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 47609566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 47619566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 47629566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 47639566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 47649566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 47652464107aSksagiyam if (dm->sf) { 47662464107aSksagiyam const char *prefix; 47672464107aSksagiyam 47689566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 47699566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 47702464107aSksagiyam } 47719566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 47729566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 47739566063dSJacob Faibussowitsch if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF")); 4774a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 47759566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 47769566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 47779566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4778a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4779a47d0d45SMatthew G. Knepley } 4780a47d0d45SMatthew G. Knepley 4781b09969d6SVaclav Hapla /*@C 4782a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4783a1cb98faSBarry Smith 4784a1cb98faSBarry Smith Collective on dm 4785b09969d6SVaclav Hapla 4786b09969d6SVaclav Hapla Input Parameters: 4787a1cb98faSBarry Smith + dm - The `DM` 4788b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4789a1cb98faSBarry Smith . sfVert - `PetscSF` describing complete vertex ownership 4790b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4791b09969d6SVaclav Hapla 4792b09969d6SVaclav Hapla Level: advanced 4793b09969d6SVaclav Hapla 4794a1cb98faSBarry Smith Fortran Note: 4795b09969d6SVaclav Hapla Not currently supported in Fortran. 4796b09969d6SVaclav Hapla 4797a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 4798b09969d6SVaclav Hapla @*/ 4799d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 4800d71ae5a4SJacob Faibussowitsch { 4801a47d0d45SMatthew G. Knepley PetscSection coordSection; 4802a47d0d45SMatthew G. Knepley Vec coordinates; 4803a47d0d45SMatthew G. Knepley PetscScalar *coords; 48041edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 4805a47d0d45SMatthew G. Knepley 4806a47d0d45SMatthew G. Knepley PetscFunctionBegin; 48079566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 48089566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 48091dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 48109566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 48119566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 48121dca8a05SBarry 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); 48139566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 48149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 48159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 48169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 48171edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 48189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 48199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4820a47d0d45SMatthew G. Knepley } 48219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 48229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 48239566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 48249566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 48259566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 48269566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 48279566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 48289566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 4829a47d0d45SMatthew G. Knepley { 4830a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 4831a47d0d45SMatthew G. Knepley 4832a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 48339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype)); 48349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 483521016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 483621016a8bSBarry Smith { 483721016a8bSBarry Smith PetscScalar *svertexCoords; 483821016a8bSBarry Smith PetscInt i; 48399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 48403612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 48419566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 48429566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 48439566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 484421016a8bSBarry Smith } 484521016a8bSBarry Smith #else 48469566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 48479566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 484821016a8bSBarry Smith #endif 48499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 4850a47d0d45SMatthew G. Knepley } 48519566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 48529566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 48539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 48549566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4855a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4856a47d0d45SMatthew G. Knepley } 4857a47d0d45SMatthew G. Knepley 4858c3edce3dSSatish Balay /*@ 4859a1cb98faSBarry Smith DMPlexCreateFromCellListParallelPetsc - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) 4860a1cb98faSBarry Smith 4861a1cb98faSBarry Smith Collective 4862a47d0d45SMatthew G. Knepley 4863a47d0d45SMatthew G. Knepley Input Parameters: 4864a47d0d45SMatthew G. Knepley + comm - The communicator 4865a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 4866a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 4867a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 4868a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DECIDE` 4869a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 4870a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 4871a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4872a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 4873a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4874a47d0d45SMatthew G. Knepley 4875d8d19677SJose E. Roman Output Parameters: 4876a1cb98faSBarry Smith + dm - The `DM` 4877a1cb98faSBarry Smith . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 4878be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4879a47d0d45SMatthew G. Knepley 4880b09969d6SVaclav Hapla Level: intermediate 4881a47d0d45SMatthew G. Knepley 4882a1cb98faSBarry Smith Notes: 4883a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 4884a1cb98faSBarry Smith `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 4885a1cb98faSBarry Smith 4886a1cb98faSBarry Smith See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters. 4887a1cb98faSBarry Smith 4888a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 4889a1cb98faSBarry Smith 4890a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 4891a47d0d45SMatthew G. Knepley @*/ 4892d71ae5a4SJacob 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) 4893d71ae5a4SJacob Faibussowitsch { 4894a47d0d45SMatthew G. Knepley PetscSF sfVert; 4895a47d0d45SMatthew G. Knepley 4896a47d0d45SMatthew G. Knepley PetscFunctionBegin; 48979566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 48989566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 4899a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 4900064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 49019566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 49029566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 4903a47d0d45SMatthew G. Knepley if (interpolate) { 49045fd9971aSMatthew G. Knepley DM idm; 4905a47d0d45SMatthew G. Knepley 49069566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 49079566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 4908a47d0d45SMatthew G. Knepley *dm = idm; 4909a47d0d45SMatthew G. Knepley } 49109566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 491118d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 49129566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 4913a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4914a47d0d45SMatthew G. Knepley } 4915a47d0d45SMatthew G. Knepley 4916b09969d6SVaclav Hapla /*@C 4917a1cb98faSBarry Smith DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 4918a1cb98faSBarry Smith 4919a1cb98faSBarry Smith Collective on dm 49209298eaa6SMatthew G Knepley 49219298eaa6SMatthew G Knepley Input Parameters: 4922a1cb98faSBarry Smith + dm - The `DM` 4923b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4924a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE` 49259298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 49265e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 49279298eaa6SMatthew G Knepley 4928b09969d6SVaclav Hapla Level: advanced 49299298eaa6SMatthew G Knepley 4930b09969d6SVaclav Hapla Notes: 4931b09969d6SVaclav Hapla Two triangles sharing a face 4932a1cb98faSBarry Smith .vb 49339298eaa6SMatthew G Knepley 4934a1cb98faSBarry Smith 2 4935a1cb98faSBarry Smith / | \ 4936a1cb98faSBarry Smith / | \ 4937a1cb98faSBarry Smith / | \ 4938a1cb98faSBarry Smith 0 0 | 1 3 4939a1cb98faSBarry Smith \ | / 4940a1cb98faSBarry Smith \ | / 4941a1cb98faSBarry Smith \ | / 4942a1cb98faSBarry Smith 1 4943a1cb98faSBarry Smith .ve 4944a1cb98faSBarry Smith would have input 4945a1cb98faSBarry Smith .vb 4946a1cb98faSBarry Smith numCells = 2, numVertices = 4 4947a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 4948a1cb98faSBarry Smith .ve 4949a1cb98faSBarry Smith which would result in the `DMPLEX` 4950a1cb98faSBarry Smith .vb 4951a1cb98faSBarry Smith 4952a1cb98faSBarry Smith 4 4953a1cb98faSBarry Smith / | \ 4954a1cb98faSBarry Smith / | \ 4955a1cb98faSBarry Smith / | \ 4956a1cb98faSBarry Smith 2 0 | 1 5 4957a1cb98faSBarry Smith \ | / 4958a1cb98faSBarry Smith \ | / 4959a1cb98faSBarry Smith \ | / 4960a1cb98faSBarry Smith 3 4961a1cb98faSBarry Smith .ve 4962a1cb98faSBarry Smith 4963a1cb98faSBarry Smith If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1. 496425b6865aSVaclav Hapla 4965b09969d6SVaclav Hapla Not currently supported in Fortran. 49669298eaa6SMatthew G Knepley 4967a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 4968b09969d6SVaclav Hapla @*/ 4969d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 4970d71ae5a4SJacob Faibussowitsch { 4971961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 4972b09969d6SVaclav Hapla 4973b09969d6SVaclav Hapla PetscFunctionBegin; 49749566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 49759566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 497625b6865aSVaclav Hapla /* Get/check global number of vertices */ 497725b6865aSVaclav Hapla { 497825b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 497925b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 498025b6865aSVaclav Hapla 498125b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 498225b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 49839371c9d4SSatish Balay for (i = 0; i < len; i++) 49849371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 498525b6865aSVaclav Hapla ++NVerticesInCells; 498625b6865aSVaclav Hapla 498725b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 49889371c9d4SSatish Balay else 49899371c9d4SSatish 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); 499025b6865aSVaclav Hapla } 49919566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 499248a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 49939566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 49949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4995b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 4996ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 4997b09969d6SVaclav Hapla } 49989566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 49999566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 50009566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 5001b09969d6SVaclav Hapla PetscFunctionReturn(0); 5002b09969d6SVaclav Hapla } 5003b09969d6SVaclav Hapla 5004b09969d6SVaclav Hapla /*@C 5005a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 5006a1cb98faSBarry Smith 5007a1cb98faSBarry Smith Collective on dm 5008b09969d6SVaclav Hapla 5009b09969d6SVaclav Hapla Input Parameters: 5010a1cb98faSBarry Smith + dm - The `DM` 5011b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 5012b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 5013b09969d6SVaclav Hapla 5014b09969d6SVaclav Hapla Level: advanced 5015b09969d6SVaclav Hapla 5016a1cb98faSBarry Smith Fortran Note: 5017b09969d6SVaclav Hapla Not currently supported in Fortran. 5018b09969d6SVaclav Hapla 5019a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 5020b09969d6SVaclav Hapla @*/ 5021d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 5022d71ae5a4SJacob Faibussowitsch { 5023b09969d6SVaclav Hapla PetscSection coordSection; 5024b09969d6SVaclav Hapla Vec coordinates; 5025b09969d6SVaclav Hapla DM cdm; 5026b09969d6SVaclav Hapla PetscScalar *coords; 50271edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 5028b09969d6SVaclav Hapla 5029b09969d6SVaclav Hapla PetscFunctionBegin; 50309566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 50319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 50321dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 50339566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 50349566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 50359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 50369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 50379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 50381edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 50399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 50409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 5041b09969d6SVaclav Hapla } 50429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 5043b09969d6SVaclav Hapla 50449566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 50459566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 50469566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 50479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 50489566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 50491edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 5050ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 5051b09969d6SVaclav Hapla } 50529566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 50539566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 50549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 50559566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 5056b09969d6SVaclav Hapla PetscFunctionReturn(0); 5057b09969d6SVaclav Hapla } 5058b09969d6SVaclav Hapla 5059b09969d6SVaclav Hapla /*@ 5060a1cb98faSBarry Smith DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 50613df08285SMatthew G. Knepley 5062a1cb98faSBarry Smith Collective 5063b09969d6SVaclav Hapla 5064b09969d6SVaclav Hapla Input Parameters: 5065b09969d6SVaclav Hapla + comm - The communicator 5066b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 50673df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 5068a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0 50693df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 5070b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 50713df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0 5072b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 50733df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0 5074b09969d6SVaclav Hapla 5075b09969d6SVaclav Hapla Output Parameter: 5076a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0 507725b6865aSVaclav Hapla 5078b09969d6SVaclav Hapla Level: intermediate 5079b09969d6SVaclav Hapla 5080a1cb98faSBarry Smith Notes: 5081a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`, 5082a1cb98faSBarry Smith `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()` 5083a1cb98faSBarry Smith 5084a1cb98faSBarry Smith See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters. 5085a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters. 5086a1cb98faSBarry Smith See `DMPlexCreateFromCellListParallelPetsc()` for parallel input 5087a1cb98faSBarry Smith 5088a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 50899298eaa6SMatthew G Knepley @*/ 5090d71ae5a4SJacob 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) 5091d71ae5a4SJacob Faibussowitsch { 50923df08285SMatthew G. Knepley PetscMPIInt rank; 50939298eaa6SMatthew G Knepley 50949298eaa6SMatthew G Knepley PetscFunctionBegin; 509528b400f6SJacob 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."); 50969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 50979566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 50989566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 50999566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 5100c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 51019566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 51029298eaa6SMatthew G Knepley if (interpolate) { 51035fd9971aSMatthew G. Knepley DM idm; 51049298eaa6SMatthew G Knepley 51059566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 51069566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 51079298eaa6SMatthew G Knepley *dm = idm; 51089298eaa6SMatthew G Knepley } 5109c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 51109566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 51119298eaa6SMatthew G Knepley PetscFunctionReturn(0); 51129298eaa6SMatthew G Knepley } 51139298eaa6SMatthew G Knepley 5114939f6067SMatthew G. Knepley /*@ 5115939f6067SMatthew 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 5116939f6067SMatthew G. Knepley 5117939f6067SMatthew G. Knepley Input Parameters: 5118c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension() 5119939f6067SMatthew G. Knepley . depth - The depth of the DAG 5120367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth 5121939f6067SMatthew G. Knepley . coneSize - The cone size of each point 5122939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 5123939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 5124367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim() 5125939f6067SMatthew G. Knepley 5126939f6067SMatthew G. Knepley Output Parameter: 5127939f6067SMatthew G. Knepley . dm - The DM 5128939f6067SMatthew G. Knepley 5129a1cb98faSBarry Smith Note: 5130a1cb98faSBarry Smith Two triangles sharing a face would have input 5131a1cb98faSBarry Smith .vb 5132a1cb98faSBarry Smith depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 5133a1cb98faSBarry Smith cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 5134a1cb98faSBarry Smith vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 5135a1cb98faSBarry Smith .ve 5136939f6067SMatthew G. Knepley which would result in the DMPlex 5137a1cb98faSBarry Smith .vb 5138a1cb98faSBarry Smith 4 5139a1cb98faSBarry Smith / | \ 5140a1cb98faSBarry Smith / | \ 5141a1cb98faSBarry Smith / | \ 5142a1cb98faSBarry Smith 2 0 | 1 5 5143a1cb98faSBarry Smith \ | / 5144a1cb98faSBarry Smith \ | / 5145a1cb98faSBarry Smith \ | / 5146a1cb98faSBarry Smith 3 5147a1cb98faSBarry Smith .ve 5148a1cb98faSBarry Smith Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()` 5149939f6067SMatthew G. Knepley 5150939f6067SMatthew G. Knepley Level: advanced 5151939f6067SMatthew G. Knepley 5152a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 5153939f6067SMatthew G. Knepley @*/ 5154d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 5155d71ae5a4SJacob Faibussowitsch { 51569298eaa6SMatthew G Knepley Vec coordinates; 51579298eaa6SMatthew G Knepley PetscSection coordSection; 51589298eaa6SMatthew G Knepley PetscScalar *coords; 5159811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 51609298eaa6SMatthew G Knepley 51619298eaa6SMatthew G Knepley PetscFunctionBegin; 51629566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 51639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 516463a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 51659298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 51669566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 51679298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 51689566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 5169ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 517097e052ccSToby Isaac } 51711dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 51729566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 51739298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 51749566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 51759566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 51769298eaa6SMatthew G Knepley } 51779566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 51789566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 51799298eaa6SMatthew G Knepley /* Build coordinates */ 51809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 51819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 51829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 51839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 51849298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 51859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 51869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 51879298eaa6SMatthew G Knepley } 51889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 51899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 51909566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 51919566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 51929566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 51939566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dimEmbed)); 51949566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 51959318fe57SMatthew G. Knepley if (vertexCoords) { 51969566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 51979298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 51989298eaa6SMatthew G Knepley PetscInt off; 51999298eaa6SMatthew G Knepley 52009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 5201ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 52029298eaa6SMatthew G Knepley } 52039318fe57SMatthew G. Knepley } 52049566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 52059566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 52069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 52079298eaa6SMatthew G Knepley PetscFunctionReturn(0); 52089298eaa6SMatthew G Knepley } 52098415267dSToby Isaac 5210ca522641SMatthew G. Knepley /*@C 5211a1cb98faSBarry Smith DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file. 5212a1cb98faSBarry Smith 5213a1cb98faSBarry Smith Collective 52148ca92349SMatthew G. Knepley 52158ca92349SMatthew G. Knepley + comm - The MPI communicator 52168ca92349SMatthew G. Knepley . filename - Name of the .dat file 52178ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 52188ca92349SMatthew G. Knepley 52198ca92349SMatthew G. Knepley Output Parameter: 5220a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 52218ca92349SMatthew G. Knepley 52228ca92349SMatthew G. Knepley Level: beginner 52238ca92349SMatthew G. Knepley 5224a1cb98faSBarry Smith Note: 5225a1cb98faSBarry Smith The format is the simplest possible: 5226a1cb98faSBarry Smith .vb 5227a1cb98faSBarry Smith Ne 5228a1cb98faSBarry Smith v0 v1 ... vk 5229a1cb98faSBarry Smith Nv 5230a1cb98faSBarry Smith x y z marker 5231a1cb98faSBarry Smith .ve 5232a1cb98faSBarry Smith 5233a1cb98faSBarry Smith Developer Note: 5234a1cb98faSBarry Smith Should use a `PetscViewer` not a filename 5235a1cb98faSBarry Smith 5236a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 52378ca92349SMatthew G. Knepley @*/ 5238d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 5239d71ae5a4SJacob Faibussowitsch { 52408ca92349SMatthew G. Knepley DMLabel marker; 52418ca92349SMatthew G. Knepley PetscViewer viewer; 52428ca92349SMatthew G. Knepley Vec coordinates; 52438ca92349SMatthew G. Knepley PetscSection coordSection; 52448ca92349SMatthew G. Knepley PetscScalar *coords; 52458ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 52468ca92349SMatthew G. Knepley PetscInt dim = 3, cdim = 3, coordSize, v, c, d; 52478ca92349SMatthew G. Knepley PetscMPIInt rank; 5248f8d5e320SMatthew G. Knepley int snum, Nv, Nc, Ncn, Nl; 52498ca92349SMatthew G. Knepley 52508ca92349SMatthew G. Knepley PetscFunctionBegin; 52519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 52529566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 52539566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 52549566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 52559566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 5256dd400576SPatrick Sanan if (rank == 0) { 52579566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING)); 5258f8d5e320SMatthew G. Knepley snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl); 525908401ef6SPierre Jolivet PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 526025ce1634SJed Brown } else { 5261f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 52628ca92349SMatthew G. Knepley } 52639566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 52649566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 52659566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 52669566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 52679566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 52688ca92349SMatthew G. Knepley /* Read topology */ 5269dd400576SPatrick Sanan if (rank == 0) { 5270f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 5271f8d5e320SMatthew G. Knepley PetscInt cone[8]; 52728ca92349SMatthew G. Knepley int vbuf[8], v; 52738ca92349SMatthew G. Knepley 52749371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 52759371c9d4SSatish Balay format[c * 3 + 0] = '%'; 52769371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 52779371c9d4SSatish Balay format[c * 3 + 2] = ' '; 52789371c9d4SSatish Balay } 5279f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 52809566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 52819566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 52828ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 52839566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 5284f8d5e320SMatthew G. Knepley switch (Ncn) { 5285d71ae5a4SJacob Faibussowitsch case 2: 5286d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 5287d71ae5a4SJacob Faibussowitsch break; 5288d71ae5a4SJacob Faibussowitsch case 3: 5289d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 5290d71ae5a4SJacob Faibussowitsch break; 5291d71ae5a4SJacob Faibussowitsch case 4: 5292d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 5293d71ae5a4SJacob Faibussowitsch break; 5294d71ae5a4SJacob Faibussowitsch case 6: 5295d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 5296d71ae5a4SJacob Faibussowitsch break; 5297d71ae5a4SJacob Faibussowitsch case 8: 5298d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 5299d71ae5a4SJacob Faibussowitsch break; 5300d71ae5a4SJacob Faibussowitsch default: 5301d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 5302f8d5e320SMatthew G. Knepley } 530308401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 5304f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 53058ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 5306f8d5e320SMatthew G. Knepley if (Ncn == 8) { 53078ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 53088ca92349SMatthew G. Knepley cone[1] = cone[3]; 53098ca92349SMatthew G. Knepley cone[3] = tmp; 53108ca92349SMatthew G. Knepley } 53119566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 53128ca92349SMatthew G. Knepley } 53138ca92349SMatthew G. Knepley } 53149566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 53159566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 53168ca92349SMatthew G. Knepley /* Read coordinates */ 53179566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 53189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 53199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 53209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 53218ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 53229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 53239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 53248ca92349SMatthew G. Knepley } 53259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 53269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 53279566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 53289566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 53299566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 53309566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 53319566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 53329566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5333dd400576SPatrick Sanan if (rank == 0) { 5334f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 53358ca92349SMatthew G. Knepley double x[3]; 5336f8d5e320SMatthew G. Knepley int l, val[3]; 53378ca92349SMatthew G. Knepley 5338f8d5e320SMatthew G. Knepley if (Nl) { 53399371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 53409371c9d4SSatish Balay format[l * 3 + 0] = '%'; 53419371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 53429371c9d4SSatish Balay format[l * 3 + 2] = ' '; 53439371c9d4SSatish Balay } 5344f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 53459566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 53469566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 5347f8d5e320SMatthew G. Knepley } 53488ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 53499566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 5350f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 535108401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 5352f8d5e320SMatthew G. Knepley switch (Nl) { 5353d71ae5a4SJacob Faibussowitsch case 0: 5354d71ae5a4SJacob Faibussowitsch snum = 0; 5355d71ae5a4SJacob Faibussowitsch break; 5356d71ae5a4SJacob Faibussowitsch case 1: 5357d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 5358d71ae5a4SJacob Faibussowitsch break; 5359d71ae5a4SJacob Faibussowitsch case 2: 5360d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 5361d71ae5a4SJacob Faibussowitsch break; 5362d71ae5a4SJacob Faibussowitsch case 3: 5363d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 5364d71ae5a4SJacob Faibussowitsch break; 5365d71ae5a4SJacob Faibussowitsch default: 5366d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 5367f8d5e320SMatthew G. Knepley } 536808401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 53698ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 53709566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 53718ca92349SMatthew G. Knepley } 53728ca92349SMatthew G. Knepley } 53739566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 53749566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 53759566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 53769566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 53778ca92349SMatthew G. Knepley if (interpolate) { 53788ca92349SMatthew G. Knepley DM idm; 53798ca92349SMatthew G. Knepley DMLabel bdlabel; 53808ca92349SMatthew G. Knepley 53819566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 53829566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 53838ca92349SMatthew G. Knepley *dm = idm; 53848ca92349SMatthew G. Knepley 5385f8d5e320SMatthew G. Knepley if (!Nl) { 53869566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 53879566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 53889566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 53899566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 53908ca92349SMatthew G. Knepley } 5391f8d5e320SMatthew G. Knepley } 53928ca92349SMatthew G. Knepley PetscFunctionReturn(0); 53938ca92349SMatthew G. Knepley } 53948ca92349SMatthew G. Knepley 53958ca92349SMatthew G. Knepley /*@C 5396a1cb98faSBarry Smith DMPlexCreateFromFile - This takes a filename and produces a `DM` 5397a1cb98faSBarry Smith 5398a1cb98faSBarry Smith Collective 5399ca522641SMatthew G. Knepley 5400ca522641SMatthew G. Knepley Input Parameters: 5401ca522641SMatthew G. Knepley + comm - The communicator 5402ca522641SMatthew G. Knepley . filename - A file name 5403a1cb98faSBarry Smith . plexname - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats 5404ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 5405ca522641SMatthew G. Knepley 5406ca522641SMatthew G. Knepley Output Parameter: 5407a1cb98faSBarry Smith . dm - The `DM` 5408ca522641SMatthew G. Knepley 5409a1cb98faSBarry Smith Options Database Key: 5410a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5 541102ef0d99SVaclav Hapla 5412bca97951SVaclav Hapla Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g. 5413bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 5414bca97951SVaclav Hapla 5415ca522641SMatthew G. Knepley Level: beginner 5416ca522641SMatthew G. Knepley 5417a1cb98faSBarry Smith Notes: 5418a1cb98faSBarry Smith Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX` 5419a1cb98faSBarry Smith meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()` 5420a1cb98faSBarry Smith before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object. 5421a1cb98faSBarry Smith The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally 5422a1cb98faSBarry Smith calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats. 5423a1cb98faSBarry Smith 5424a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 5425ca522641SMatthew G. Knepley @*/ 5426d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 5427d71ae5a4SJacob Faibussowitsch { 5428ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 5429ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 5430ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 5431ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 5432ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 5433ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 5434ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 5435ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 5436ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 5437ef3a5affSJacob Faibussowitsch const char extMed[] = ".med"; 5438ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 5439ef3a5affSJacob Faibussowitsch const char extEGADSLite[] = ".egadslite"; 5440ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 5441ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 5442ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 5443ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 5444ca522641SMatthew G. Knepley size_t len; 5445c1cad2e7SMatthew G. Knepley PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV; 5446ca522641SMatthew G. Knepley PetscMPIInt rank; 5447ca522641SMatthew G. Knepley 5448ca522641SMatthew G. Knepley PetscFunctionBegin; 54495d80c0bfSVaclav Hapla PetscValidCharPointer(filename, 2); 54500d862eaeSPierre Jolivet if (plexname) PetscValidCharPointer(plexname, 3); 5451cd7e8a5eSksagiyam PetscValidPointer(dm, 5); 54529566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 54539566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 54549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 54559566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 545628b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 5457ef3a5affSJacob Faibussowitsch 54589371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 54599371c9d4SSatish Balay do { \ 5460274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 5461274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 5462274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 5463274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 5464ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 5465ef3a5affSJacob Faibussowitsch } else { \ 5466274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 5467ef3a5affSJacob Faibussowitsch } \ 5468ef3a5affSJacob Faibussowitsch } while (0) 5469ef3a5affSJacob Faibussowitsch 5470ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 5471ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 5472ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 5473ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 5474ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 5475ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 5476ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 5477ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 5478ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 5479ef3a5affSJacob Faibussowitsch CheckExtension(extMed, isMed); 5480ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 5481ef3a5affSJacob Faibussowitsch CheckExtension(extEGADSLite, isEGADSLite); 5482ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 5483ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 5484ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 5485ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 5486ef3a5affSJacob Faibussowitsch 5487ef3a5affSJacob Faibussowitsch #undef CheckExtension 5488ef3a5affSJacob Faibussowitsch 5489de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 54909566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 5491ca522641SMatthew G. Knepley } else if (isCGNS) { 54929566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 549390c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 54949566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 54952f0bd6dcSMichael Lange } else if (isFluent) { 54969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 5497cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 54989c48423bSVaclav Hapla PetscBool load_hdf5_xdmf = PETSC_FALSE; 5499cc2f8f65SMatthew G. Knepley PetscViewer viewer; 5500cc2f8f65SMatthew G. Knepley 550143b242b4SVaclav 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 */ 55029566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf)); 55039566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL)); 55049566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 55059566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 55069566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 55079566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 55089566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 55099566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 5510cd7e8a5eSksagiyam 55119566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 55129566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 55139566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 55149566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 55159566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 55169566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer)); 55179566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 55185fd9971aSMatthew G. Knepley 55195fd9971aSMatthew G. Knepley if (interpolate) { 55205fd9971aSMatthew G. Knepley DM idm; 55215fd9971aSMatthew G. Knepley 55229566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 55239566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 55245fd9971aSMatthew G. Knepley *dm = idm; 55255fd9971aSMatthew G. Knepley } 5526707dd687SMichael Lange } else if (isMed) { 55279566063dSJacob Faibussowitsch PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm)); 5528f2801cd6SMatthew G. Knepley } else if (isPLY) { 55299566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 5530c1cad2e7SMatthew G. Knepley } else if (isEGADSLite || isEGADS || isIGES || isSTEP) { 55319566063dSJacob Faibussowitsch if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm)); 55329566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm)); 55337bee2925SMatthew Knepley if (!interpolate) { 55347bee2925SMatthew Knepley DM udm; 55357bee2925SMatthew Knepley 55369566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 55379566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 55387bee2925SMatthew Knepley *dm = udm; 55397bee2925SMatthew Knepley } 55408ca92349SMatthew G. Knepley } else if (isCV) { 55419566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 554298921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 55439566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 55449566063dSJacob Faibussowitsch if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 55459566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 5546ca522641SMatthew G. Knepley PetscFunctionReturn(0); 5547ca522641SMatthew G. Knepley } 55489f6c5813SMatthew G. Knepley /*@C 55499f6c5813SMatthew G. Knepley DMPlexCreateEphemeral - This takes a `DMPlexTransform` and a base `DMPlex` and produces an ephemeral `DM`, meaning one that is created on the fly in response to queries. 55509f6c5813SMatthew G. Knepley 55519f6c5813SMatthew G. Knepley Input Parameter: 55529f6c5813SMatthew G. Knepley . tr - The `DMPlexTransform` 55539f6c5813SMatthew G. Knepley 55549f6c5813SMatthew G. Knepley Output Parameter: 55559f6c5813SMatthew G. Knepley . dm - The `DM` 55569f6c5813SMatthew G. Knepley 55579f6c5813SMatthew G. Knepley Notes: 55589f6c5813SMatthew G. Knepley An emphemeral mesh is one that is not stored concretely, as in the default Plex implementation, but rather is produced on the fly in response to queries, using information from the transform and the base mesh. 55599f6c5813SMatthew G. Knepley 55609f6c5813SMatthew G. Knepley Level: beginner 55619f6c5813SMatthew G. Knepley 55629f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 55639f6c5813SMatthew G. Knepley @*/ 55649f6c5813SMatthew G. Knepley PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, DM *dm) 55659f6c5813SMatthew G. Knepley { 55669f6c5813SMatthew G. Knepley DM bdm; 55679f6c5813SMatthew G. Knepley PetscInt Nl; 55689f6c5813SMatthew G. Knepley 55699f6c5813SMatthew G. Knepley PetscFunctionBegin; 55709f6c5813SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm)); 55719f6c5813SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 55729f6c5813SMatthew G. Knepley PetscCall(DMSetFromOptions(*dm)); 55739f6c5813SMatthew G. Knepley 55749f6c5813SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)tr)); 55759f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr)); 55769f6c5813SMatthew G. Knepley ((DM_Plex *)(*dm)->data)->tr = tr; 55779f6c5813SMatthew G. Knepley 55789f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformGetDM(tr, &bdm)); 55799f6c5813SMatthew G. Knepley PetscCall(DMGetNumLabels(bdm, &Nl)); 55809f6c5813SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 55819f6c5813SMatthew G. Knepley DMLabel label, labelNew; 55829f6c5813SMatthew G. Knepley const char *lname; 55839f6c5813SMatthew G. Knepley PetscBool isDepth, isCellType; 55849f6c5813SMatthew G. Knepley 55859f6c5813SMatthew G. Knepley PetscCall(DMGetLabelName(bdm, l, &lname)); 55869f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 55879f6c5813SMatthew G. Knepley if (isDepth) continue; 55889f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "celltype", &isCellType)); 55899f6c5813SMatthew G. Knepley if (isCellType) continue; 55909f6c5813SMatthew G. Knepley PetscCall(DMCreateLabel(*dm, lname)); 55919f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(bdm, lname, &label)); 55929f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(*dm, lname, &labelNew)); 55939f6c5813SMatthew G. Knepley PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL)); 55949f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetLabel(labelNew, label)); 55959f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetTransform(labelNew, tr)); 55969f6c5813SMatthew G. Knepley PetscCall(DMLabelSetUp(labelNew)); 55979f6c5813SMatthew G. Knepley } 55989f6c5813SMatthew G. Knepley PetscFunctionReturn(0); 55999f6c5813SMatthew G. Knepley } 5600