1552f7358SJed Brown #define PETSCDM_DLL 2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h> /*I "petscdmplex.h" I*/ 40c312b8eSJed Brown #include <petscsf.h> 54663dae6SJed Brown #include <petscdmplextransform.h> 69f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h> 7b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h> 8b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h> 9552f7358SJed Brown 10b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 1158cd63d5SVaclav Hapla 129318fe57SMatthew G. Knepley /* External function declarations here */ 139318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm); 149318fe57SMatthew G. Knepley 15e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */ 16d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout) 17d71ae5a4SJacob Faibussowitsch { 184fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 196858538eSMatthew G. Knepley PetscBool dist; 206bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 21e600fa54SMatthew G. Knepley 22e600fa54SMatthew G. Knepley PetscFunctionBegin; 23e600fa54SMatthew G. Knepley if (copyPeriodicity) { 244fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L)); 254fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L)); 26e600fa54SMatthew G. Knepley } 279566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dmin, &dist)); 289566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dmout, dist)); 296bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dmin, &reorder)); 306bc1bd01Sksagiyam PetscCall(DMPlexReorderSetDefault(dmout, reorder)); 31e600fa54SMatthew G. Knepley ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation; 321baa6e33SBarry Smith if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0)); 33e600fa54SMatthew G. Knepley PetscFunctionReturn(0); 34e600fa54SMatthew G. Knepley } 35e600fa54SMatthew G. Knepley 369318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 379318fe57SMatthew G. Knepley - Share the DM_Plex structure 389318fe57SMatthew G. Knepley - Share the coordinates 399318fe57SMatthew G. Knepley - Share the SF 409318fe57SMatthew G. Knepley */ 41d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm) 42d71ae5a4SJacob Faibussowitsch { 439318fe57SMatthew G. Knepley PetscSF sf; 449318fe57SMatthew G. Knepley DM dmNew = *ndm, coordDM, coarseDM; 459318fe57SMatthew G. Knepley Vec coords; 464fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 479318fe57SMatthew G. Knepley PetscInt dim, cdim; 489318fe57SMatthew G. Knepley 499318fe57SMatthew G. Knepley PetscFunctionBegin; 509318fe57SMatthew G. Knepley if (dm == dmNew) { 519566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 529318fe57SMatthew G. Knepley PetscFunctionReturn(0); 539318fe57SMatthew G. Knepley } 549318fe57SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 559566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmNew, &dim)); 569566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmNew, &cdim)); 589566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 599566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sf)); 609566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sf)); 619566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmNew, &coordDM)); 629566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmNew, &coords)); 639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dm, coordDM)); 649566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 656858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM)); 666858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords)); 676858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dm, coordDM)); 686858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 699318fe57SMatthew G. Knepley /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */ 706858538eSMatthew G. Knepley PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 716858538eSMatthew G. Knepley dm->coordinates[0].field = dmNew->coordinates[0].field; 7261a622f3SMatthew G. Knepley ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc; 734fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 744fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 759566063dSJacob Faibussowitsch PetscCall(DMDestroy_Plex(dm)); 769566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 779318fe57SMatthew G. Knepley dm->data = dmNew->data; 789318fe57SMatthew G. Knepley ((DM_Plex *)dmNew->data)->refct++; 799566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 809566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 819566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmNew, &coarseDM)); 829566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 839566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 849318fe57SMatthew G. Knepley PetscFunctionReturn(0); 859318fe57SMatthew G. Knepley } 869318fe57SMatthew G. Knepley 879318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew 889318fe57SMatthew G. Knepley - Swap the DM_Plex structure 899318fe57SMatthew G. Knepley - Swap the coordinates 909318fe57SMatthew G. Knepley - Swap the point PetscSF 919318fe57SMatthew G. Knepley */ 92d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 93d71ae5a4SJacob Faibussowitsch { 949318fe57SMatthew G. Knepley DM coordDMA, coordDMB; 959318fe57SMatthew G. Knepley Vec coordsA, coordsB; 969318fe57SMatthew G. Knepley PetscSF sfA, sfB; 979318fe57SMatthew G. Knepley DMField fieldTmp; 989318fe57SMatthew G. Knepley void *tmp; 999318fe57SMatthew G. Knepley DMLabelLink listTmp; 1009318fe57SMatthew G. Knepley DMLabel depthTmp; 1019318fe57SMatthew G. Knepley PetscInt tmpI; 1029318fe57SMatthew G. Knepley 1039318fe57SMatthew G. Knepley PetscFunctionBegin; 1049318fe57SMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 1059566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmA, &sfA)); 1069566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmB, &sfB)); 1079566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sfA)); 1089566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmA, sfB)); 1099566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmB, sfA)); 1109566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)sfA)); 1119318fe57SMatthew G. Knepley 1129566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &coordDMA)); 1139566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &coordDMB)); 1149566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordDMA)); 1159566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmA, coordDMB)); 1169566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmB, coordDMA)); 1179566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 1189318fe57SMatthew G. Knepley 1199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordsA)); 1209566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmB, &coordsB)); 1219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordsA)); 1229566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmA, coordsB)); 1239566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordsA)); 1249566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordsA)); 1259318fe57SMatthew G. Knepley 1266858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA)); 1276858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB)); 1286858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordDMA)); 1296858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmA, coordDMB)); 1306858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmB, coordDMA)); 1316858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 1326858538eSMatthew G. Knepley 1336858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA)); 1346858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB)); 1356858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordsA)); 1366858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB)); 1376858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA)); 1386858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordsA)); 1396858538eSMatthew G. Knepley 1406858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[0].field; 1416858538eSMatthew G. Knepley dmA->coordinates[0].field = dmB->coordinates[0].field; 1426858538eSMatthew G. Knepley dmB->coordinates[0].field = fieldTmp; 1436858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[1].field; 1446858538eSMatthew G. Knepley dmA->coordinates[1].field = dmB->coordinates[1].field; 1456858538eSMatthew G. Knepley dmB->coordinates[1].field = fieldTmp; 1469318fe57SMatthew G. Knepley tmp = dmA->data; 1479318fe57SMatthew G. Knepley dmA->data = dmB->data; 1489318fe57SMatthew G. Knepley dmB->data = tmp; 1499318fe57SMatthew G. Knepley listTmp = dmA->labels; 1509318fe57SMatthew G. Knepley dmA->labels = dmB->labels; 1519318fe57SMatthew G. Knepley dmB->labels = listTmp; 1529318fe57SMatthew G. Knepley depthTmp = dmA->depthLabel; 1539318fe57SMatthew G. Knepley dmA->depthLabel = dmB->depthLabel; 1549318fe57SMatthew G. Knepley dmB->depthLabel = depthTmp; 1559318fe57SMatthew G. Knepley depthTmp = dmA->celltypeLabel; 1569318fe57SMatthew G. Knepley dmA->celltypeLabel = dmB->celltypeLabel; 1579318fe57SMatthew G. Knepley dmB->celltypeLabel = depthTmp; 1589318fe57SMatthew G. Knepley tmpI = dmA->levelup; 1599318fe57SMatthew G. Knepley dmA->levelup = dmB->levelup; 1609318fe57SMatthew G. Knepley dmB->levelup = tmpI; 1619318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1629318fe57SMatthew G. Knepley } 1639318fe57SMatthew G. Knepley 164d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) 165d71ae5a4SJacob Faibussowitsch { 1669318fe57SMatthew G. Knepley DM idm; 1679318fe57SMatthew G. Knepley 1689318fe57SMatthew G. Knepley PetscFunctionBegin; 1699566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 1709566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 17169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 1729318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1739318fe57SMatthew G. Knepley } 1749318fe57SMatthew G. Knepley 1759318fe57SMatthew G. Knepley /*@C 1769318fe57SMatthew G. Knepley DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates 1779318fe57SMatthew G. Knepley 178a1cb98faSBarry Smith Collective on dm 1799318fe57SMatthew G. Knepley 1809318fe57SMatthew G. Knepley Input Parameters: 1819318fe57SMatthew G. Knepley + DM - The DM 1824f9ab2b4SJed Brown . degree - The degree of the finite element or PETSC_DECIDE 1839318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface 1849318fe57SMatthew G. Knepley 1859318fe57SMatthew G. Knepley Level: advanced 1869318fe57SMatthew G. Knepley 187a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscPointFunc`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()` 1889318fe57SMatthew G. Knepley @*/ 189d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc) 190d71ae5a4SJacob Faibussowitsch { 1919318fe57SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1929318fe57SMatthew G. Knepley DM cdm; 1939318fe57SMatthew G. Knepley PetscDS cds; 1949318fe57SMatthew G. Knepley PetscFE fe; 1959318fe57SMatthew G. Knepley PetscClassId id; 1969318fe57SMatthew G. Knepley 1979318fe57SMatthew G. Knepley PetscFunctionBegin; 1989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 1999566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 2009566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, (PetscObject *)&fe)); 2019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 2029318fe57SMatthew G. Knepley if (id != PETSCFE_CLASSID) { 2039318fe57SMatthew G. Knepley PetscInt dim, dE, qorder; 2049318fe57SMatthew G. Knepley 2059566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 2069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 2079318fe57SMatthew G. Knepley qorder = degree; 208d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)cdm); 209dc431b0cSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0)); 210d0609cedSBarry Smith PetscOptionsEnd(); 2114f9ab2b4SJed Brown if (degree == PETSC_DECIDE) fe = NULL; 2124f9ab2b4SJed Brown else { 213dc431b0cSMatthew G. Knepley DMPolytopeType ct; 214dc431b0cSMatthew G. Knepley PetscInt cStart, cEnd, ctTmp; 215dc431b0cSMatthew G. Knepley 216dc431b0cSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 217dc431b0cSMatthew G. Knepley // Want to match cell types 218dc431b0cSMatthew G. Knepley if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 219dc431b0cSMatthew G. Knepley else ct = DM_POLYTOPE_UNKNOWN; 220dc431b0cSMatthew G. Knepley ctTmp = (PetscInt)ct; 221dc431b0cSMatthew G. Knepley PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &ctTmp, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm))); 222dc431b0cSMatthew G. Knepley ct = (DMPolytopeType)ctTmp; 223dc431b0cSMatthew G. Knepley // Work around current bug 224dc431b0cSMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) fe = NULL; 225dc431b0cSMatthew G. Knepley else PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe)); 2264f9ab2b4SJed Brown } 227dc431b0cSMatthew G. Knepley if (fe) PetscCall(DMProjectCoordinates(dm, fe)); 2289566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 2299318fe57SMatthew G. Knepley } 2309318fe57SMatthew G. Knepley mesh->coordFunc = coordFunc; 2319318fe57SMatthew G. Knepley PetscFunctionReturn(0); 2329318fe57SMatthew G. Knepley } 2339318fe57SMatthew G. Knepley 2341df5d5c5SMatthew G. Knepley /*@ 2351df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 2361df5d5c5SMatthew G. Knepley 237d083f849SBarry Smith Collective 2381df5d5c5SMatthew G. Knepley 2391df5d5c5SMatthew G. Knepley Input Parameters: 240a1cb98faSBarry Smith + comm - The communicator for the `DM` object 2411df5d5c5SMatthew G. Knepley . dim - The spatial dimension 2421df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 2431df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 2441df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 2451df5d5c5SMatthew G. Knepley 2461df5d5c5SMatthew G. Knepley Output Parameter: 247a1cb98faSBarry Smith . dm - The `DM` object 2481df5d5c5SMatthew G. Knepley 2491df5d5c5SMatthew G. Knepley Level: beginner 2501df5d5c5SMatthew G. Knepley 251a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()` 2521df5d5c5SMatthew G. Knepley @*/ 253d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) 254d71ae5a4SJacob Faibussowitsch { 2551df5d5c5SMatthew G. Knepley DM dm; 2561df5d5c5SMatthew G. Knepley PetscMPIInt rank; 2571df5d5c5SMatthew G. Knepley 2581df5d5c5SMatthew G. Knepley PetscFunctionBegin; 2599566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &dm)); 2609566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 2619566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 2629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 263ce78fa2fSMatthew G. Knepley switch (dim) { 264ce78fa2fSMatthew G. Knepley case 2: 2659566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular")); 2669566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral")); 267ce78fa2fSMatthew G. Knepley break; 268ce78fa2fSMatthew G. Knepley case 3: 2699566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral")); 2709566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral")); 271ce78fa2fSMatthew G. Knepley break; 272d71ae5a4SJacob Faibussowitsch default: 273d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 274ce78fa2fSMatthew G. Knepley } 2751df5d5c5SMatthew G. Knepley if (rank) { 2761df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 2779566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 2781df5d5c5SMatthew G. Knepley } else { 2791df5d5c5SMatthew G. Knepley switch (dim) { 2801df5d5c5SMatthew G. Knepley case 2: 2811df5d5c5SMatthew G. Knepley if (simplex) { 2821df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 2831df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 2841df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 2851df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 2861df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 2871df5d5c5SMatthew G. Knepley 2889566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2891df5d5c5SMatthew G. Knepley } else { 2901df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 2911df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 2921df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 2931df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2941df5d5c5SMatthew 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}; 2951df5d5c5SMatthew G. Knepley 2969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2971df5d5c5SMatthew G. Knepley } 2981df5d5c5SMatthew G. Knepley break; 2991df5d5c5SMatthew G. Knepley case 3: 3001df5d5c5SMatthew G. Knepley if (simplex) { 3011df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 3021df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 3031df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 3041df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 3051df5d5c5SMatthew 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}; 3061df5d5c5SMatthew G. Knepley 3079566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 3081df5d5c5SMatthew G. Knepley } else { 3091df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 3101df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 3111df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 3121df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 3139371c9d4SSatish 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}; 3141df5d5c5SMatthew G. Knepley 3159566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 3161df5d5c5SMatthew G. Knepley } 3171df5d5c5SMatthew G. Knepley break; 318d71ae5a4SJacob Faibussowitsch default: 319d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 3201df5d5c5SMatthew G. Knepley } 3211df5d5c5SMatthew G. Knepley } 3221df5d5c5SMatthew G. Knepley *newdm = dm; 3231df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 3241df5d5c5SMatthew G. Knepley DM rdm; 3251df5d5c5SMatthew G. Knepley const char *name; 3261df5d5c5SMatthew G. Knepley 3279566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 3289566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 3299566063dSJacob Faibussowitsch PetscCall(DMRefine(*newdm, comm, &rdm)); 3309566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)*newdm, &name)); 3319566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, name)); 3329566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 3331df5d5c5SMatthew G. Knepley *newdm = rdm; 3341df5d5c5SMatthew G. Knepley } 3351df5d5c5SMatthew G. Knepley if (interpolate) { 3365fd9971aSMatthew G. Knepley DM idm; 3371df5d5c5SMatthew G. Knepley 3389566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*newdm, &idm)); 3399566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 3401df5d5c5SMatthew G. Knepley *newdm = idm; 3411df5d5c5SMatthew G. Knepley } 3421df5d5c5SMatthew G. Knepley PetscFunctionReturn(0); 3431df5d5c5SMatthew G. Knepley } 3441df5d5c5SMatthew G. Knepley 345d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 346d71ae5a4SJacob Faibussowitsch { 3479318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 3489318fe57SMatthew G. Knepley PetscInt markerRight = 1; 3499318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 3509318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 3519318fe57SMatthew G. Knepley Vec coordinates; 3529318fe57SMatthew G. Knepley PetscSection coordSection; 3539318fe57SMatthew G. Knepley PetscScalar *coords; 3549318fe57SMatthew G. Knepley PetscInt coordSize; 3559318fe57SMatthew G. Knepley PetscMPIInt rank; 3569318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 357552f7358SJed Brown 3589318fe57SMatthew G. Knepley PetscFunctionBegin; 3599566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 3609318fe57SMatthew G. Knepley if (markerSeparate) { 3619318fe57SMatthew G. Knepley markerRight = 2; 3629318fe57SMatthew G. Knepley markerLeft = 1; 3639318fe57SMatthew G. Knepley } 3649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 365c5853193SPierre Jolivet if (rank == 0) { 3669566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numVertices)); 3679566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3689566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft)); 3699566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight)); 3709318fe57SMatthew G. Knepley } 3719566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 3729566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 3739318fe57SMatthew G. Knepley /* Build coordinates */ 3749566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 3759566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 3769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 3779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, 0, numVertices)); 3789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 3799318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 3809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 3819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 3829318fe57SMatthew G. Knepley } 3839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 3849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 3859566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 3869566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 3879566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 3889566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 3899566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 3909566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 3919318fe57SMatthew G. Knepley coords[0] = lower[0]; 3929318fe57SMatthew G. Knepley coords[1] = upper[0]; 3939566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 3949566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 3959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 3969318fe57SMatthew G. Knepley PetscFunctionReturn(0); 3979318fe57SMatthew G. Knepley } 39826492d91SMatthew G. Knepley 399d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 400d71ae5a4SJacob Faibussowitsch { 4011df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0] + 1) * (edges[1] + 1); 4021df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1]; 403552f7358SJed Brown PetscInt markerTop = 1; 404552f7358SJed Brown PetscInt markerBottom = 1; 405552f7358SJed Brown PetscInt markerRight = 1; 406552f7358SJed Brown PetscInt markerLeft = 1; 407552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 408552f7358SJed Brown Vec coordinates; 409552f7358SJed Brown PetscSection coordSection; 410552f7358SJed Brown PetscScalar *coords; 411552f7358SJed Brown PetscInt coordSize; 412552f7358SJed Brown PetscMPIInt rank; 413552f7358SJed Brown PetscInt v, vx, vy; 414552f7358SJed Brown 415552f7358SJed Brown PetscFunctionBegin; 4169566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 417552f7358SJed Brown if (markerSeparate) { 4181df21d24SMatthew G. Knepley markerTop = 3; 4191df21d24SMatthew G. Knepley markerBottom = 1; 4201df21d24SMatthew G. Knepley markerRight = 2; 4211df21d24SMatthew G. Knepley markerLeft = 4; 422552f7358SJed Brown } 4239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 424dd400576SPatrick Sanan if (rank == 0) { 425552f7358SJed Brown PetscInt e, ex, ey; 426552f7358SJed Brown 4279566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices)); 42848a46eb9SPierre Jolivet for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 4299566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 430552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 431552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 432552f7358SJed Brown PetscInt edge = vx * edges[1] + ey + edges[0] * (edges[1] + 1); 433552f7358SJed Brown PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges; 434da80777bSKarl Rupp PetscInt cone[2]; 435552f7358SJed Brown 4369371c9d4SSatish Balay cone[0] = vertex; 4379371c9d4SSatish Balay cone[1] = vertex + edges[0] + 1; 4389566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 439552f7358SJed Brown if (vx == edges[0]) { 4409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 4419566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 442552f7358SJed Brown if (ey == edges[1] - 1) { 4439566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 4449566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 445552f7358SJed Brown } 446552f7358SJed Brown } else if (vx == 0) { 4479566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 4489566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 449552f7358SJed Brown if (ey == edges[1] - 1) { 4509566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 4519566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 452552f7358SJed Brown } 453552f7358SJed Brown } 454552f7358SJed Brown } 455552f7358SJed Brown } 456552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 457552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 458552f7358SJed Brown PetscInt edge = vy * edges[0] + ex; 459552f7358SJed Brown PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges; 460da80777bSKarl Rupp PetscInt cone[2]; 461552f7358SJed Brown 4629371c9d4SSatish Balay cone[0] = vertex; 4639371c9d4SSatish Balay cone[1] = vertex + 1; 4649566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 465552f7358SJed Brown if (vy == edges[1]) { 4669566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 4679566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 468552f7358SJed Brown if (ex == edges[0] - 1) { 4699566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 4709566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 471552f7358SJed Brown } 472552f7358SJed Brown } else if (vy == 0) { 4739566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 4749566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 475552f7358SJed Brown if (ex == edges[0] - 1) { 4769566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 4779566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 478552f7358SJed Brown } 479552f7358SJed Brown } 480552f7358SJed Brown } 481552f7358SJed Brown } 482552f7358SJed Brown } 4839566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 4849566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 485552f7358SJed Brown /* Build coordinates */ 4869566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 2)); 4879566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 4889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 4899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 4909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 491552f7358SJed Brown for (v = numEdges; v < numEdges + numVertices; ++v) { 4929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 2)); 4939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 494552f7358SJed Brown } 4959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 4979566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 4989566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 4999566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 5009566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 2)); 5019566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 5029566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 503552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 504552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 505552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx; 506552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy; 507552f7358SJed Brown } 508552f7358SJed Brown } 5099566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 5109566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 5119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 512552f7358SJed Brown PetscFunctionReturn(0); 513552f7358SJed Brown } 514552f7358SJed Brown 515d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 516d71ae5a4SJacob Faibussowitsch { 5179e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 5187b59f5a9SMichael Lange PetscInt numFaces = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2]; 519c2df9bbfSMatthew G. Knepley PetscInt markerTop = 1; 520c2df9bbfSMatthew G. Knepley PetscInt markerBottom = 1; 521c2df9bbfSMatthew G. Knepley PetscInt markerFront = 1; 522c2df9bbfSMatthew G. Knepley PetscInt markerBack = 1; 523c2df9bbfSMatthew G. Knepley PetscInt markerRight = 1; 524c2df9bbfSMatthew G. Knepley PetscInt markerLeft = 1; 525c2df9bbfSMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 526552f7358SJed Brown Vec coordinates; 527552f7358SJed Brown PetscSection coordSection; 528552f7358SJed Brown PetscScalar *coords; 529552f7358SJed Brown PetscInt coordSize; 530552f7358SJed Brown PetscMPIInt rank; 531552f7358SJed Brown PetscInt v, vx, vy, vz; 5327b59f5a9SMichael Lange PetscInt voffset, iface = 0, cone[4]; 533552f7358SJed Brown 534552f7358SJed Brown PetscFunctionBegin; 5351dca8a05SBarry 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"); 5369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 537c2df9bbfSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 538c2df9bbfSMatthew G. Knepley if (markerSeparate) { 539c2df9bbfSMatthew G. Knepley markerBottom = 1; 540c2df9bbfSMatthew G. Knepley markerTop = 2; 541c2df9bbfSMatthew G. Knepley markerFront = 3; 542c2df9bbfSMatthew G. Knepley markerBack = 4; 543c2df9bbfSMatthew G. Knepley markerRight = 5; 544c2df9bbfSMatthew G. Knepley markerLeft = 6; 545c2df9bbfSMatthew G. Knepley } 5469371c9d4SSatish Balay vertices[0] = faces[0] + 1; 5479371c9d4SSatish Balay vertices[1] = faces[1] + 1; 5489371c9d4SSatish Balay vertices[2] = faces[2] + 1; 5499e8abbc3SMichael Lange numVertices = vertices[0] * vertices[1] * vertices[2]; 550dd400576SPatrick Sanan if (rank == 0) { 551552f7358SJed Brown PetscInt f; 552552f7358SJed Brown 5539566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices)); 55448a46eb9SPierre Jolivet for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 5559566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 5567b59f5a9SMichael Lange 5577b59f5a9SMichael Lange /* Side 0 (Top) */ 5587b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5597b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5607b59f5a9SMichael Lange voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx; 5619371c9d4SSatish Balay cone[0] = voffset; 5629371c9d4SSatish Balay cone[1] = voffset + 1; 5639371c9d4SSatish Balay cone[2] = voffset + vertices[0] + 1; 5649371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 5659566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 566c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop)); 567c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop)); 568c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop)); 569c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop)); 570c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop)); 5717b59f5a9SMichael Lange iface++; 572552f7358SJed Brown } 573552f7358SJed Brown } 5747b59f5a9SMichael Lange 5757b59f5a9SMichael Lange /* Side 1 (Bottom) */ 5767b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5777b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5787b59f5a9SMichael Lange voffset = numFaces + vy * (faces[0] + 1) + vx; 5799371c9d4SSatish Balay cone[0] = voffset + 1; 5809371c9d4SSatish Balay cone[1] = voffset; 5819371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 5829371c9d4SSatish Balay cone[3] = voffset + vertices[0] + 1; 5839566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 584c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom)); 585c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom)); 586c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom)); 587c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom)); 588c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom)); 5897b59f5a9SMichael Lange iface++; 590552f7358SJed Brown } 591552f7358SJed Brown } 5927b59f5a9SMichael Lange 5937b59f5a9SMichael Lange /* Side 2 (Front) */ 5947b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 5957b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5967b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vx; 5979371c9d4SSatish Balay cone[0] = voffset; 5989371c9d4SSatish Balay cone[1] = voffset + 1; 5999371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + 1; 6009371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1]; 6019566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 602c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront)); 603c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront)); 604c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront)); 605c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront)); 606c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront)); 6077b59f5a9SMichael Lange iface++; 608552f7358SJed Brown } 6097b59f5a9SMichael Lange } 6107b59f5a9SMichael Lange 6117b59f5a9SMichael Lange /* Side 3 (Back) */ 6127b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6137b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 6147b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx; 6159371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 6169371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1] + 1; 6179371c9d4SSatish Balay cone[2] = voffset + 1; 6189371c9d4SSatish Balay cone[3] = voffset; 6199566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 620c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack)); 621c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack)); 622c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack)); 623c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack)); 624c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack)); 6257b59f5a9SMichael Lange iface++; 6267b59f5a9SMichael Lange } 6277b59f5a9SMichael Lange } 6287b59f5a9SMichael Lange 6297b59f5a9SMichael Lange /* Side 4 (Left) */ 6307b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6317b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 6327b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0]; 6339371c9d4SSatish Balay cone[0] = voffset; 6349371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1]; 6359371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + vertices[0]; 6369371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 6379566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 638c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft)); 639c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft)); 640c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft)); 641c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft)); 642c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft)); 6437b59f5a9SMichael Lange iface++; 6447b59f5a9SMichael Lange } 6457b59f5a9SMichael Lange } 6467b59f5a9SMichael Lange 6477b59f5a9SMichael Lange /* Side 5 (Right) */ 6487b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6497b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 650aab5bcd8SJed Brown voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0]; 6519371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 6529371c9d4SSatish Balay cone[1] = voffset; 6539371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 6549371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1] + vertices[0]; 6559566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 656c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight)); 657c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight)); 658c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight)); 659c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight)); 660c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight)); 6617b59f5a9SMichael Lange iface++; 6627b59f5a9SMichael Lange } 663552f7358SJed Brown } 664552f7358SJed Brown } 6659566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 6669566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 667552f7358SJed Brown /* Build coordinates */ 6689566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 3)); 6699566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 6709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 6729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 673552f7358SJed Brown for (v = numFaces; v < numFaces + numVertices; ++v) { 6749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 3)); 6759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 676552f7358SJed Brown } 6779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 6799566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 6809566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 6819566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6829566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 3)); 6839566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 6849566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 685552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 686552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 687552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 688552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx; 689552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy; 690552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz; 691552f7358SJed Brown } 692552f7358SJed Brown } 693552f7358SJed Brown } 6949566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 6959566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 6969566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 697552f7358SJed Brown PetscFunctionReturn(0); 698552f7358SJed Brown } 699552f7358SJed Brown 700d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) 701d71ae5a4SJacob Faibussowitsch { 7029318fe57SMatthew G. Knepley PetscFunctionBegin; 7039318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 7049566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim - 1)); 7059566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim)); 7069318fe57SMatthew G. Knepley switch (dim) { 707d71ae5a4SJacob Faibussowitsch case 1: 708d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); 709d71ae5a4SJacob Faibussowitsch break; 710d71ae5a4SJacob Faibussowitsch case 2: 711d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); 712d71ae5a4SJacob Faibussowitsch break; 713d71ae5a4SJacob Faibussowitsch case 3: 714d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); 715d71ae5a4SJacob Faibussowitsch break; 716d71ae5a4SJacob Faibussowitsch default: 717d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim); 7189318fe57SMatthew G. Knepley } 7199566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 7209318fe57SMatthew G. Knepley PetscFunctionReturn(0); 7219318fe57SMatthew G. Knepley } 7229318fe57SMatthew G. Knepley 7239318fe57SMatthew G. Knepley /*@C 7249318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 7259318fe57SMatthew G. Knepley 7269318fe57SMatthew G. Knepley Collective 7279318fe57SMatthew G. Knepley 7289318fe57SMatthew G. Knepley Input Parameters: 729a1cb98faSBarry Smith + comm - The communicator for the `DM` object 7309318fe57SMatthew G. Knepley . dim - The spatial dimension of the box, so the resulting mesh is has dimension dim-1 7319318fe57SMatthew 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 7329318fe57SMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 7339318fe57SMatthew G. Knepley . upper - The upper right corner, or NULL for (1, 1, 1) 7349318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 7359318fe57SMatthew G. Knepley 7369318fe57SMatthew G. Knepley Output Parameter: 737a1cb98faSBarry Smith . dm - The `DM` object 7389318fe57SMatthew G. Knepley 7399318fe57SMatthew G. Knepley Level: beginner 7409318fe57SMatthew G. Knepley 741a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()` 7429318fe57SMatthew G. Knepley @*/ 743d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 744d71ae5a4SJacob Faibussowitsch { 7459318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 7469318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 7479318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 7489318fe57SMatthew G. Knepley 7499318fe57SMatthew G. Knepley PetscFunctionBegin; 7509566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 7519566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 7529566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 7539318fe57SMatthew G. Knepley PetscFunctionReturn(0); 7549318fe57SMatthew G. Knepley } 7559318fe57SMatthew G. Knepley 756d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) 757d71ae5a4SJacob Faibussowitsch { 758fdbf62faSLisandro Dalcin PetscInt i, fStart, fEnd, numCells = 0, numVerts = 0; 759fdbf62faSLisandro Dalcin PetscInt numPoints[2], *coneSize, *cones, *coneOrientations; 760fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 761fdbf62faSLisandro Dalcin PetscReal L, maxCell; 762fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 763fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 764fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 765fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 766fdbf62faSLisandro Dalcin PetscMPIInt rank; 767fdbf62faSLisandro Dalcin 768fdbf62faSLisandro Dalcin PetscFunctionBegin; 7699318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 770fdbf62faSLisandro Dalcin 7719566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, 1)); 7729566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 7739566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 774fdbf62faSLisandro Dalcin 7759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 776dd400576SPatrick Sanan if (rank == 0) numCells = segments; 777dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 778fdbf62faSLisandro Dalcin 7799371c9d4SSatish Balay numPoints[0] = numVerts; 7809371c9d4SSatish Balay numPoints[1] = numCells; 7819566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords)); 7829566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts)); 783ad540459SPierre Jolivet for (i = 0; i < numCells; ++i) coneSize[i] = 2; 784ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0; 7859371c9d4SSatish Balay for (i = 0; i < numCells; ++i) { 7869371c9d4SSatish Balay cones[2 * i] = numCells + i % numVerts; 7879371c9d4SSatish Balay cones[2 * i + 1] = numCells + (i + 1) % numVerts; 7889371c9d4SSatish Balay } 789ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); 7909566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 7919566063dSJacob Faibussowitsch PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords)); 792fdbf62faSLisandro Dalcin 7939566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 7949371c9d4SSatish Balay if (markerSeparate) { 7959371c9d4SSatish Balay markerLeft = faceMarkerLeft; 7969371c9d4SSatish Balay markerRight = faceMarkerRight; 7979371c9d4SSatish Balay } 798dd400576SPatrick Sanan if (!wrap && rank == 0) { 7999566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 8009566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft)); 8019566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight)); 8029566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft)); 8039566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight)); 804fdbf62faSLisandro Dalcin } 805fdbf62faSLisandro Dalcin if (wrap) { 806fdbf62faSLisandro Dalcin L = upper - lower; 807fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments)); 8084fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L)); 809fdbf62faSLisandro Dalcin } 8109566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 811fdbf62faSLisandro Dalcin PetscFunctionReturn(0); 812fdbf62faSLisandro Dalcin } 813fdbf62faSLisandro Dalcin 814d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 815d71ae5a4SJacob Faibussowitsch { 8169318fe57SMatthew G. Knepley DM boundary, vol; 817c22d3578SMatthew G. Knepley DMLabel bdlabel; 818d6218766SMatthew G. Knepley 819d6218766SMatthew G. Knepley PetscFunctionBegin; 8209318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 821c22d3578SMatthew 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"); 8229566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary)); 8239566063dSJacob Faibussowitsch PetscCall(DMSetType(boundary, DMPLEX)); 8249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 8259566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 826c22d3578SMatthew G. Knepley PetscCall(DMGetLabel(vol, "marker", &bdlabel)); 827c22d3578SMatthew G. Knepley if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel)); 8285de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol)); 82969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 8309566063dSJacob Faibussowitsch PetscCall(DMDestroy(&boundary)); 831d6218766SMatthew G. Knepley PetscFunctionReturn(0); 832d6218766SMatthew G. Knepley } 833d6218766SMatthew G. Knepley 834d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 835d71ae5a4SJacob Faibussowitsch { 836ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 837f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 838f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 839f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 840f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 841f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 842f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 8433dfda0b1SToby Isaac PetscInt dim; 844d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 8453dfda0b1SToby Isaac PetscMPIInt rank; 8463dfda0b1SToby Isaac 8473dfda0b1SToby Isaac PetscFunctionBegin; 8489566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8509566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 8519566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 8529566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 8539371c9d4SSatish 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) { 8549371c9d4SSatish Balay if (cutMarker) { 8559371c9d4SSatish Balay PetscCall(DMCreateLabel(dm, "periodic_cut")); 8569371c9d4SSatish Balay PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 8579371c9d4SSatish Balay } 858d8211ee3SMatthew G. Knepley } 8593dfda0b1SToby Isaac switch (dim) { 8603dfda0b1SToby Isaac case 2: 861f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 862f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 863f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 864f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 8653dfda0b1SToby Isaac break; 8663dfda0b1SToby Isaac case 3: 867f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 868f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 869f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 870f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 871f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 872f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 8733dfda0b1SToby Isaac break; 874d71ae5a4SJacob Faibussowitsch default: 875d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 8763dfda0b1SToby Isaac } 8779566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 878f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 879f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 880f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 881f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 882f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 883f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 884f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 8853dfda0b1SToby Isaac } 8863dfda0b1SToby Isaac { 887dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 888dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 889dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 890dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0; 891dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0; 892dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0; 8933dfda0b1SToby Isaac const PetscInt numCells = numXEdges * numYEdges * numZEdges; 8943dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges * numZEdges; 8953dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges * numZEdges; 8963dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges * numYEdges; 8973dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices * numXFaces; 8983dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices * numYFaces; 8993dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices * numZFaces; 9003dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 9013dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices; 9023dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices; 9033dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices; 9043dfda0b1SToby Isaac const PetscInt numVertices = numXVertices * numYVertices * numZVertices; 9053dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 9063dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 9073dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 9083dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 9093dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 9103dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 9113dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 9123dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 9133dfda0b1SToby Isaac Vec coordinates; 9143dfda0b1SToby Isaac PetscSection coordSection; 9153dfda0b1SToby Isaac PetscScalar *coords; 9163dfda0b1SToby Isaac PetscInt coordSize; 9173dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 9183dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 9193dfda0b1SToby Isaac 9209566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices)); 92148a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 92248a46eb9SPierre Jolivet for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 92348a46eb9SPierre Jolivet for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 9249566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 9253dfda0b1SToby Isaac /* Build cells */ 9263dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 9273dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 9283dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 9293dfda0b1SToby Isaac PetscInt cell = (fz * numYEdges + fy) * numXEdges + fx; 9303dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 9313dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices); 9323dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 9333dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices); 9343dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 9353dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices); 9363dfda0b1SToby Isaac /* B, T, F, K, R, L */ 937b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 93842206facSLisandro Dalcin PetscInt cone[6]; 9393dfda0b1SToby Isaac 9403dfda0b1SToby Isaac /* no boundary twisting in 3D */ 9419371c9d4SSatish Balay cone[0] = faceB; 9429371c9d4SSatish Balay cone[1] = faceT; 9439371c9d4SSatish Balay cone[2] = faceF; 9449371c9d4SSatish Balay cone[3] = faceK; 9459371c9d4SSatish Balay cone[4] = faceR; 9469371c9d4SSatish Balay cone[5] = faceL; 9479566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, cell, cone)); 9489566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, cell, ornt)); 9499566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9509566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9519566063dSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 9523dfda0b1SToby Isaac } 9533dfda0b1SToby Isaac } 9543dfda0b1SToby Isaac } 9553dfda0b1SToby Isaac /* Build x faces */ 9563dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 9573dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 9583dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 9593dfda0b1SToby Isaac PetscInt face = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 9603dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 9613dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz; 9623dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 9633dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy; 964b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 9653dfda0b1SToby Isaac PetscInt cone[4]; 9663dfda0b1SToby Isaac 9673dfda0b1SToby Isaac if (dim == 3) { 9683dfda0b1SToby Isaac /* markers */ 9693dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 9703dfda0b1SToby Isaac if (fx == numXVertices - 1) { 9719566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 9729566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerRight)); 9739371c9d4SSatish Balay } else if (fx == 0) { 9749566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 9759566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft)); 9763dfda0b1SToby Isaac } 9773dfda0b1SToby Isaac } 9783dfda0b1SToby Isaac } 9799371c9d4SSatish Balay cone[0] = edgeB; 9809371c9d4SSatish Balay cone[1] = edgeR; 9819371c9d4SSatish Balay cone[2] = edgeT; 9829371c9d4SSatish Balay cone[3] = edgeL; 9839566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 9849566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 9853dfda0b1SToby Isaac } 9863dfda0b1SToby Isaac } 9873dfda0b1SToby Isaac } 9883dfda0b1SToby Isaac /* Build y faces */ 9893dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 99042206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 9913dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 9923dfda0b1SToby Isaac PetscInt face = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 9933dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 9943dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz; 9953dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 9963dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx; 997b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 9983dfda0b1SToby Isaac PetscInt cone[4]; 9993dfda0b1SToby Isaac 10003dfda0b1SToby Isaac if (dim == 3) { 10013dfda0b1SToby Isaac /* markers */ 10023dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 10033dfda0b1SToby Isaac if (fy == numYVertices - 1) { 10049566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 10059566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBack)); 10069371c9d4SSatish Balay } else if (fy == 0) { 10079566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 10089566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerFront)); 10093dfda0b1SToby Isaac } 10103dfda0b1SToby Isaac } 10113dfda0b1SToby Isaac } 10129371c9d4SSatish Balay cone[0] = edgeB; 10139371c9d4SSatish Balay cone[1] = edgeR; 10149371c9d4SSatish Balay cone[2] = edgeT; 10159371c9d4SSatish Balay cone[3] = edgeL; 10169566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 10179566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 10183dfda0b1SToby Isaac } 10193dfda0b1SToby Isaac } 10203dfda0b1SToby Isaac } 10213dfda0b1SToby Isaac /* Build z faces */ 10223dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 10233dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 10243dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 10253dfda0b1SToby Isaac PetscInt face = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 10263dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 10273dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy; 10283dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 10293dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx; 1030b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 10313dfda0b1SToby Isaac PetscInt cone[4]; 10323dfda0b1SToby Isaac 10333dfda0b1SToby Isaac if (dim == 2) { 10349371c9d4SSatish Balay if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) { 10359371c9d4SSatish Balay edgeR += numYEdges - 1 - 2 * fy; 10369371c9d4SSatish Balay ornt[1] = -1; 10379371c9d4SSatish Balay } 10389371c9d4SSatish Balay if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) { 10399371c9d4SSatish Balay edgeT += numXEdges - 1 - 2 * fx; 10409371c9d4SSatish Balay ornt[2] = 0; 10419371c9d4SSatish Balay } 10429566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 10439566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 1044d1c88043SMatthew G. Knepley } else { 10453dfda0b1SToby Isaac /* markers */ 10463dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 10473dfda0b1SToby Isaac if (fz == numZVertices - 1) { 10489566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 10499566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerTop)); 10509371c9d4SSatish Balay } else if (fz == 0) { 10519566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 10529566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom)); 10533dfda0b1SToby Isaac } 10543dfda0b1SToby Isaac } 10553dfda0b1SToby Isaac } 10569371c9d4SSatish Balay cone[0] = edgeB; 10579371c9d4SSatish Balay cone[1] = edgeR; 10589371c9d4SSatish Balay cone[2] = edgeT; 10599371c9d4SSatish Balay cone[3] = edgeL; 10609566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 10619566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 10623dfda0b1SToby Isaac } 10633dfda0b1SToby Isaac } 10643dfda0b1SToby Isaac } 10653dfda0b1SToby Isaac /* Build Z edges*/ 10663dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 10673dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 10683dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 10693dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez; 10703dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx; 10713dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx; 10723dfda0b1SToby Isaac PetscInt cone[2]; 10733dfda0b1SToby Isaac 10749371c9d4SSatish Balay cone[0] = vertexB; 10759371c9d4SSatish Balay cone[1] = vertexT; 1076c2df9bbfSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, edge, cone)); 10773dfda0b1SToby Isaac if (dim == 3) { 10783dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 10793dfda0b1SToby Isaac if (vx == numXVertices - 1) { 10809566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1081c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1082c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1083c2df9bbfSMatthew G. Knepley } else if (vx == 0) { 10849566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1085c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1086c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 10873dfda0b1SToby Isaac } 10883dfda0b1SToby Isaac } 10893dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 10903dfda0b1SToby Isaac if (vy == numYVertices - 1) { 10919566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1092c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1093c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1094c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 10959566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1096c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1097c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 10983dfda0b1SToby Isaac } 10993dfda0b1SToby Isaac } 11003dfda0b1SToby Isaac } 11013dfda0b1SToby Isaac } 11023dfda0b1SToby Isaac } 11033dfda0b1SToby Isaac } 11043dfda0b1SToby Isaac /* Build Y edges*/ 11053dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 11063dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 11073dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 11083dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx; 11093dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey; 11103dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx; 11113dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 11123dfda0b1SToby Isaac PetscInt cone[2]; 11133dfda0b1SToby Isaac 11149371c9d4SSatish Balay cone[0] = vertexF; 11159371c9d4SSatish Balay cone[1] = vertexK; 11169566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 11173dfda0b1SToby Isaac if (dim == 2) { 11183dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 11193dfda0b1SToby Isaac if (vx == numXVertices - 1) { 11209566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 11219566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 11229566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1123c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1124d8211ee3SMatthew G. Knepley } else if (vx == 0) { 11259566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 11269566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 11279566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1128c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 11293dfda0b1SToby Isaac } 1130d8211ee3SMatthew G. Knepley } else { 11314c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 11329566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 11339566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1134c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 11353dfda0b1SToby Isaac } 1136d8211ee3SMatthew G. Knepley } 1137d8211ee3SMatthew G. Knepley } else { 11383dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 11393dfda0b1SToby Isaac if (vx == numXVertices - 1) { 11409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1141c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1142c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1143d8211ee3SMatthew G. Knepley } else if (vx == 0) { 11449566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1145c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1146c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 11473dfda0b1SToby Isaac } 11483dfda0b1SToby Isaac } 11493dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 11503dfda0b1SToby Isaac if (vz == numZVertices - 1) { 11519566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1152c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1153c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1154d8211ee3SMatthew G. Knepley } else if (vz == 0) { 11559566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1156c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1157c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 11583dfda0b1SToby Isaac } 11593dfda0b1SToby Isaac } 11603dfda0b1SToby Isaac } 11613dfda0b1SToby Isaac } 11623dfda0b1SToby Isaac } 11633dfda0b1SToby Isaac } 11643dfda0b1SToby Isaac /* Build X edges*/ 11653dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 11663dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 11673dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 11683dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices; 11693dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex; 11703dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex; 11713dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 11723dfda0b1SToby Isaac PetscInt cone[2]; 11733dfda0b1SToby Isaac 11749371c9d4SSatish Balay cone[0] = vertexL; 11759371c9d4SSatish Balay cone[1] = vertexR; 11769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 11773dfda0b1SToby Isaac if (dim == 2) { 11783dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 11793dfda0b1SToby Isaac if (vy == numYVertices - 1) { 11809566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 11819566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 11829566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1183c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1184d8211ee3SMatthew G. Knepley } else if (vy == 0) { 11859566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 11869566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 11879566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1188c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 11893dfda0b1SToby Isaac } 1190d8211ee3SMatthew G. Knepley } else { 11914c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 11929566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 11939566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1194c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 11953dfda0b1SToby Isaac } 1196d8211ee3SMatthew G. Knepley } 1197d8211ee3SMatthew G. Knepley } else { 11983dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 11993dfda0b1SToby Isaac if (vy == numYVertices - 1) { 12009566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1201c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1202c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1203c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 12049566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1205c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1206c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 12073dfda0b1SToby Isaac } 12083dfda0b1SToby Isaac } 12093dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 12103dfda0b1SToby Isaac if (vz == numZVertices - 1) { 12119566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1212c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1213c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1214c2df9bbfSMatthew G. Knepley } else if (vz == 0) { 12159566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1216c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1217c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 12183dfda0b1SToby Isaac } 12193dfda0b1SToby Isaac } 12203dfda0b1SToby Isaac } 12213dfda0b1SToby Isaac } 12223dfda0b1SToby Isaac } 12233dfda0b1SToby Isaac } 12249566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 12259566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 12263dfda0b1SToby Isaac /* Build coordinates */ 12279566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 12289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 12299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 12309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 12313dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex + numVertices; ++v) { 12329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 12339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 12343dfda0b1SToby Isaac } 12359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 12369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 12379566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 12389566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 12399566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 12409566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 12419566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 12429566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12433dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 12443dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 12453dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 12463dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 12473dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1248ad540459SPierre Jolivet if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; 12493dfda0b1SToby Isaac } 12503dfda0b1SToby Isaac } 12513dfda0b1SToby Isaac } 12529566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12539566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 12549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 12553dfda0b1SToby Isaac } 12563dfda0b1SToby Isaac PetscFunctionReturn(0); 12573dfda0b1SToby Isaac } 12583dfda0b1SToby Isaac 1259d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1260d71ae5a4SJacob Faibussowitsch { 12619318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 12629318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1263552f7358SJed Brown 1264552f7358SJed Brown PetscFunctionBegin; 12659318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 12669318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 12679566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 12689371c9d4SSatish Balay for (d = 0; d < dim; ++d) { 12699371c9d4SSatish Balay fac[d] = faces[d]; 12709371c9d4SSatish Balay bdt[d] = periodicity[d]; 12719371c9d4SSatish Balay } 12729566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 12739371c9d4SSatish 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))) { 12746858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 12756858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1276552f7358SJed Brown 12779318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 12786858538eSMatthew G. Knepley if (periodicity[d] != DM_BOUNDARY_NONE) { 12799318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 12809318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1281768d5fceSMatthew G. Knepley } 12826858538eSMatthew G. Knepley } 12834fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1284768d5fceSMatthew G. Knepley } 12859566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 12869318fe57SMatthew G. Knepley PetscFunctionReturn(0); 12879318fe57SMatthew G. Knepley } 12889318fe57SMatthew G. Knepley 1289d71ae5a4SJacob 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) 1290d71ae5a4SJacob Faibussowitsch { 12919318fe57SMatthew G. Knepley PetscFunctionBegin; 12929566063dSJacob Faibussowitsch if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 12939566063dSJacob Faibussowitsch else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 12949566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 12959318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1296768d5fceSMatthew G. Knepley DM udm; 1297768d5fceSMatthew G. Knepley 12989566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 12999566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, udm)); 130069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 1301768d5fceSMatthew G. Knepley } 1302768d5fceSMatthew G. Knepley PetscFunctionReturn(0); 1303c8c68bd8SToby Isaac } 1304c8c68bd8SToby Isaac 1305768d5fceSMatthew G. Knepley /*@C 1306768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1307768d5fceSMatthew G. Knepley 1308d083f849SBarry Smith Collective 1309768d5fceSMatthew G. Knepley 1310768d5fceSMatthew G. Knepley Input Parameters: 1311a1cb98faSBarry Smith + comm - The communicator for the `DM` object 1312768d5fceSMatthew G. Knepley . dim - The spatial dimension 1313a1cb98faSBarry Smith . simplex - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells 1314fdbf62faSLisandro Dalcin . faces - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 1315768d5fceSMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 1316768d5fceSMatthew G. Knepley . upper - The upper right corner, or NULL for (1, 1, 1) 1317a1cb98faSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or NULL for `DM_BOUNDARY_NONE` 1318768d5fceSMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 1319768d5fceSMatthew G. Knepley 1320768d5fceSMatthew G. Knepley Output Parameter: 1321a1cb98faSBarry Smith . dm - The `DM` object 1322768d5fceSMatthew G. Knepley 1323768d5fceSMatthew G. Knepley Level: beginner 1324768d5fceSMatthew G. Knepley 1325a1cb98faSBarry Smith Note: 1326a1cb98faSBarry Smith To customize this mesh using options, use 1327a1cb98faSBarry Smith .vb 1328a1cb98faSBarry Smith DMCreate(comm, &dm); 1329a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 1330a1cb98faSBarry Smith DMSetFromOptions(dm); 1331a1cb98faSBarry Smith .ve 1332a1cb98faSBarry Smith and use the options in `DMSetFromOptions()`. 1333a1cb98faSBarry Smith 1334a1cb98faSBarry Smith Here is the numbering returned for 2 faces in each direction for tensor cells: 1335a1cb98faSBarry Smith .vb 1336a1cb98faSBarry Smith 10---17---11---18----12 1337a1cb98faSBarry Smith | | | 1338a1cb98faSBarry Smith | | | 1339a1cb98faSBarry Smith 20 2 22 3 24 1340a1cb98faSBarry Smith | | | 1341a1cb98faSBarry Smith | | | 1342a1cb98faSBarry Smith 7---15----8---16----9 1343a1cb98faSBarry Smith | | | 1344a1cb98faSBarry Smith | | | 1345a1cb98faSBarry Smith 19 0 21 1 23 1346a1cb98faSBarry Smith | | | 1347a1cb98faSBarry Smith | | | 1348a1cb98faSBarry Smith 4---13----5---14----6 1349a1cb98faSBarry Smith .ve 1350a1cb98faSBarry Smith and for simplicial cells 1351a1cb98faSBarry Smith .vb 1352a1cb98faSBarry Smith 14----8---15----9----16 1353a1cb98faSBarry Smith |\ 5 |\ 7 | 1354a1cb98faSBarry Smith | \ | \ | 1355a1cb98faSBarry Smith 13 2 14 3 15 1356a1cb98faSBarry Smith | 4 \ | 6 \ | 1357a1cb98faSBarry Smith | \ | \ | 1358a1cb98faSBarry Smith 11----6---12----7----13 1359a1cb98faSBarry Smith |\ |\ | 1360a1cb98faSBarry Smith | \ 1 | \ 3 | 1361a1cb98faSBarry Smith 10 0 11 1 12 1362a1cb98faSBarry Smith | 0 \ | 2 \ | 1363a1cb98faSBarry Smith | \ | \ | 1364a1cb98faSBarry Smith 8----4----9----5----10 1365a1cb98faSBarry Smith .ve 1366a1cb98faSBarry Smith 1367a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 1368768d5fceSMatthew G. Knepley @*/ 1369d71ae5a4SJacob 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) 1370d71ae5a4SJacob Faibussowitsch { 13719318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 1372fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 1373fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 1374fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1375552f7358SJed Brown 1376768d5fceSMatthew G. Knepley PetscFunctionBegin; 13779566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 13789566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 13799566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 13807ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 13819318fe57SMatthew G. Knepley PetscFunctionReturn(0); 13829318fe57SMatthew G. Knepley } 1383fdbf62faSLisandro Dalcin 1384d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1385d71ae5a4SJacob Faibussowitsch { 13869318fe57SMatthew G. Knepley DM bdm, vol; 13879318fe57SMatthew G. Knepley PetscInt i; 13889318fe57SMatthew G. Knepley 13899318fe57SMatthew G. Knepley PetscFunctionBegin; 139008401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 13919566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 13929566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 13939566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 13949566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 13959566063dSJacob Faibussowitsch PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol)); 13969566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 139769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 13989318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 13999318fe57SMatthew G. Knepley Vec v; 14009318fe57SMatthew G. Knepley PetscScalar *x; 14019318fe57SMatthew G. Knepley PetscInt cDim, n; 14029318fe57SMatthew G. Knepley 14039566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 14049566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 14059566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 14069566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 14079318fe57SMatthew G. Knepley x += cDim; 14089318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 14099566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 14109566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 14119318fe57SMatthew G. Knepley } 1412552f7358SJed Brown PetscFunctionReturn(0); 1413552f7358SJed Brown } 1414552f7358SJed Brown 141500dabe28SStefano Zampini /*@ 141600dabe28SStefano Zampini DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells. 141700dabe28SStefano Zampini 1418d083f849SBarry Smith Collective 141900dabe28SStefano Zampini 142000dabe28SStefano Zampini Input Parameters: 1421a1cb98faSBarry Smith + comm - The communicator for the `DM` object 142200dabe28SStefano Zampini . faces - Number of faces per dimension, or NULL for (1, 1, 1) 142300dabe28SStefano Zampini . lower - The lower left corner, or NULL for (0, 0, 0) 142400dabe28SStefano Zampini . upper - The upper right corner, or NULL for (1, 1, 1) 1425a1cb98faSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or NULL for `DM_BOUNDARY_NONE` 1426a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 142700dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 142800dabe28SStefano Zampini 142900dabe28SStefano Zampini Output Parameter: 1430a1cb98faSBarry Smith . dm - The `DM` object 143100dabe28SStefano Zampini 143200dabe28SStefano Zampini Level: beginner 143300dabe28SStefano Zampini 1434a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 143500dabe28SStefano Zampini @*/ 1436d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 1437d71ae5a4SJacob Faibussowitsch { 14389318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 143900dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 144000dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 144100dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 144200dabe28SStefano Zampini 144300dabe28SStefano Zampini PetscFunctionBegin; 14449566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 14459566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 14469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 1447d410b0cfSMatthew G. Knepley if (!interpolate) { 1448d410b0cfSMatthew G. Knepley DM udm; 144900dabe28SStefano Zampini 14509566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 145169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 145200dabe28SStefano Zampini } 14537ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 145400dabe28SStefano Zampini PetscFunctionReturn(0); 145500dabe28SStefano Zampini } 145600dabe28SStefano Zampini 1457a9074c1eSMatthew G. Knepley /*@C 1458a1cb98faSBarry Smith DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database. 1459a9074c1eSMatthew G. Knepley 1460d083f849SBarry Smith Logically Collective on dm 1461a9074c1eSMatthew G. Knepley 1462a9074c1eSMatthew G. Knepley Input Parameters: 1463a9074c1eSMatthew G. Knepley + dm - the DM context 1464a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 1465a9074c1eSMatthew G. Knepley 1466a1cb98faSBarry Smith Level: advanced 1467a1cb98faSBarry Smith 1468a1cb98faSBarry Smith Note: 1469a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 1470a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 1471a9074c1eSMatthew G. Knepley 1472a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()` 1473a9074c1eSMatthew G. Knepley @*/ 1474d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 1475d71ae5a4SJacob Faibussowitsch { 1476a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1477a9074c1eSMatthew G. Knepley 1478a9074c1eSMatthew G. Knepley PetscFunctionBegin; 1479a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14809566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 14819566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 1482a9074c1eSMatthew G. Knepley PetscFunctionReturn(0); 1483a9074c1eSMatthew G. Knepley } 1484a9074c1eSMatthew G. Knepley 14859318fe57SMatthew G. Knepley /* Remap geometry to cylinder 148661a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 148761a622f3SMatthew G. Knepley 14889318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 14899318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 14909318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 14910510c589SMatthew G. Knepley 14929318fe57SMatthew G. Knepley phi = arctan(y/x) 14939318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 14949318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 14950510c589SMatthew G. Knepley 14969318fe57SMatthew G. Knepley so we remap them using 14970510c589SMatthew G. Knepley 14989318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 14999318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 15000510c589SMatthew G. Knepley 15019318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 15029318fe57SMatthew G. Knepley */ 1503d71ae5a4SJacob 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[]) 1504d71ae5a4SJacob Faibussowitsch { 15059318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 15069318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 150722cc497dSMatthew G. Knepley 15089318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 15099318fe57SMatthew G. Knepley f0[0] = u[0]; 15109318fe57SMatthew G. Knepley f0[1] = u[1]; 15119318fe57SMatthew G. Knepley } else { 15129318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 15130510c589SMatthew G. Knepley 15149318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 15159318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 15169318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 15179318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 15189318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 15199318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 15209318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 15219318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 15229318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 15239318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 15249318fe57SMatthew G. Knepley } else { 15259318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 15269318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 15279318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 15289318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 15299318fe57SMatthew G. Knepley } 15309318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 15319318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 15329318fe57SMatthew G. Knepley } 15339318fe57SMatthew G. Knepley f0[2] = u[2]; 15349318fe57SMatthew G. Knepley } 15350510c589SMatthew G. Knepley 1536d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ) 1537d71ae5a4SJacob Faibussowitsch { 15380510c589SMatthew G. Knepley const PetscInt dim = 3; 15399318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 1540d8c47e87SMatthew G. Knepley PetscMPIInt rank; 15410510c589SMatthew G. Knepley 15420510c589SMatthew G. Knepley PetscFunctionBegin; 15439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15449566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 15450510c589SMatthew G. Knepley /* Create topology */ 15460510c589SMatthew G. Knepley { 15470510c589SMatthew G. Knepley PetscInt cone[8], c; 15480510c589SMatthew G. Knepley 1549dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 1550dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 1551006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 1552ae8bcbbbSMatthew G. Knepley numCells *= 3; 1553dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 1554006a8963SMatthew G. Knepley } 15559566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 15569566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 15579566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 1558dd400576SPatrick Sanan if (rank == 0) { 1559006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 15609371c9d4SSatish Balay cone[0] = 15; 15619371c9d4SSatish Balay cone[1] = 18; 15629371c9d4SSatish Balay cone[2] = 17; 15639371c9d4SSatish Balay cone[3] = 16; 15649371c9d4SSatish Balay cone[4] = 31; 15659371c9d4SSatish Balay cone[5] = 32; 15669371c9d4SSatish Balay cone[6] = 33; 15679371c9d4SSatish Balay cone[7] = 34; 15689566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 15699371c9d4SSatish Balay cone[0] = 16; 15709371c9d4SSatish Balay cone[1] = 17; 15719371c9d4SSatish Balay cone[2] = 24; 15729371c9d4SSatish Balay cone[3] = 23; 15739371c9d4SSatish Balay cone[4] = 32; 15749371c9d4SSatish Balay cone[5] = 36; 15759371c9d4SSatish Balay cone[6] = 37; 15769371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 15779566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 15789371c9d4SSatish Balay cone[0] = 18; 15799371c9d4SSatish Balay cone[1] = 27; 15809371c9d4SSatish Balay cone[2] = 24; 15819371c9d4SSatish Balay cone[3] = 17; 15829371c9d4SSatish Balay cone[4] = 34; 15839371c9d4SSatish Balay cone[5] = 33; 15849371c9d4SSatish Balay cone[6] = 37; 15859371c9d4SSatish Balay cone[7] = 38; 15869566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 15879371c9d4SSatish Balay cone[0] = 29; 15889371c9d4SSatish Balay cone[1] = 27; 15899371c9d4SSatish Balay cone[2] = 18; 15909371c9d4SSatish Balay cone[3] = 15; 15919371c9d4SSatish Balay cone[4] = 35; 15929371c9d4SSatish Balay cone[5] = 31; 15939371c9d4SSatish Balay cone[6] = 34; 15949371c9d4SSatish Balay cone[7] = 38; 15959566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 15969371c9d4SSatish Balay cone[0] = 29; 15979371c9d4SSatish Balay cone[1] = 15; 15989371c9d4SSatish Balay cone[2] = 16; 15999371c9d4SSatish Balay cone[3] = 23; 16009371c9d4SSatish Balay cone[4] = 35; 16019371c9d4SSatish Balay cone[5] = 36; 16029371c9d4SSatish Balay cone[6] = 32; 16039371c9d4SSatish Balay cone[7] = 31; 16049566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1605006a8963SMatthew G. Knepley 16069371c9d4SSatish Balay cone[0] = 31; 16079371c9d4SSatish Balay cone[1] = 34; 16089371c9d4SSatish Balay cone[2] = 33; 16099371c9d4SSatish Balay cone[3] = 32; 16109371c9d4SSatish Balay cone[4] = 19; 16119371c9d4SSatish Balay cone[5] = 22; 16129371c9d4SSatish Balay cone[6] = 21; 16139371c9d4SSatish Balay cone[7] = 20; 16149566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 16159371c9d4SSatish Balay cone[0] = 32; 16169371c9d4SSatish Balay cone[1] = 33; 16179371c9d4SSatish Balay cone[2] = 37; 16189371c9d4SSatish Balay cone[3] = 36; 16199371c9d4SSatish Balay cone[4] = 22; 16209371c9d4SSatish Balay cone[5] = 25; 16219371c9d4SSatish Balay cone[6] = 26; 16229371c9d4SSatish Balay cone[7] = 21; 16239566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 16249371c9d4SSatish Balay cone[0] = 34; 16259371c9d4SSatish Balay cone[1] = 38; 16269371c9d4SSatish Balay cone[2] = 37; 16279371c9d4SSatish Balay cone[3] = 33; 16289371c9d4SSatish Balay cone[4] = 20; 16299371c9d4SSatish Balay cone[5] = 21; 16309371c9d4SSatish Balay cone[6] = 26; 16319371c9d4SSatish Balay cone[7] = 28; 16329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 16339371c9d4SSatish Balay cone[0] = 35; 16349371c9d4SSatish Balay cone[1] = 38; 16359371c9d4SSatish Balay cone[2] = 34; 16369371c9d4SSatish Balay cone[3] = 31; 16379371c9d4SSatish Balay cone[4] = 30; 16389371c9d4SSatish Balay cone[5] = 19; 16399371c9d4SSatish Balay cone[6] = 20; 16409371c9d4SSatish Balay cone[7] = 28; 16419566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 16429371c9d4SSatish Balay cone[0] = 35; 16439371c9d4SSatish Balay cone[1] = 31; 16449371c9d4SSatish Balay cone[2] = 32; 16459371c9d4SSatish Balay cone[3] = 36; 16469371c9d4SSatish Balay cone[4] = 30; 16479371c9d4SSatish Balay cone[5] = 25; 16489371c9d4SSatish Balay cone[6] = 22; 16499371c9d4SSatish Balay cone[7] = 19; 16509566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 1651ae8bcbbbSMatthew G. Knepley 16529371c9d4SSatish Balay cone[0] = 19; 16539371c9d4SSatish Balay cone[1] = 20; 16549371c9d4SSatish Balay cone[2] = 21; 16559371c9d4SSatish Balay cone[3] = 22; 16569371c9d4SSatish Balay cone[4] = 15; 16579371c9d4SSatish Balay cone[5] = 16; 16589371c9d4SSatish Balay cone[6] = 17; 16599371c9d4SSatish Balay cone[7] = 18; 16609566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 16619371c9d4SSatish Balay cone[0] = 22; 16629371c9d4SSatish Balay cone[1] = 21; 16639371c9d4SSatish Balay cone[2] = 26; 16649371c9d4SSatish Balay cone[3] = 25; 16659371c9d4SSatish Balay cone[4] = 16; 16669371c9d4SSatish Balay cone[5] = 23; 16679371c9d4SSatish Balay cone[6] = 24; 16689371c9d4SSatish Balay cone[7] = 17; 16699566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 16709371c9d4SSatish Balay cone[0] = 20; 16719371c9d4SSatish Balay cone[1] = 28; 16729371c9d4SSatish Balay cone[2] = 26; 16739371c9d4SSatish Balay cone[3] = 21; 16749371c9d4SSatish Balay cone[4] = 18; 16759371c9d4SSatish Balay cone[5] = 17; 16769371c9d4SSatish Balay cone[6] = 24; 16779371c9d4SSatish Balay cone[7] = 27; 16789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 16799371c9d4SSatish Balay cone[0] = 30; 16809371c9d4SSatish Balay cone[1] = 28; 16819371c9d4SSatish Balay cone[2] = 20; 16829371c9d4SSatish Balay cone[3] = 19; 16839371c9d4SSatish Balay cone[4] = 29; 16849371c9d4SSatish Balay cone[5] = 15; 16859371c9d4SSatish Balay cone[6] = 18; 16869371c9d4SSatish Balay cone[7] = 27; 16879566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 16889371c9d4SSatish Balay cone[0] = 30; 16899371c9d4SSatish Balay cone[1] = 19; 16909371c9d4SSatish Balay cone[2] = 22; 16919371c9d4SSatish Balay cone[3] = 25; 16929371c9d4SSatish Balay cone[4] = 29; 16939371c9d4SSatish Balay cone[5] = 23; 16949371c9d4SSatish Balay cone[6] = 16; 16959371c9d4SSatish Balay cone[7] = 15; 16969566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 1697006a8963SMatthew G. Knepley } else { 16989371c9d4SSatish Balay cone[0] = 5; 16999371c9d4SSatish Balay cone[1] = 8; 17009371c9d4SSatish Balay cone[2] = 7; 17019371c9d4SSatish Balay cone[3] = 6; 17029371c9d4SSatish Balay cone[4] = 9; 17039371c9d4SSatish Balay cone[5] = 12; 17049371c9d4SSatish Balay cone[6] = 11; 17059371c9d4SSatish Balay cone[7] = 10; 17069566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 17079371c9d4SSatish Balay cone[0] = 6; 17089371c9d4SSatish Balay cone[1] = 7; 17099371c9d4SSatish Balay cone[2] = 14; 17109371c9d4SSatish Balay cone[3] = 13; 17119371c9d4SSatish Balay cone[4] = 12; 17129371c9d4SSatish Balay cone[5] = 15; 17139371c9d4SSatish Balay cone[6] = 16; 17149371c9d4SSatish Balay cone[7] = 11; 17159566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 17169371c9d4SSatish Balay cone[0] = 8; 17179371c9d4SSatish Balay cone[1] = 17; 17189371c9d4SSatish Balay cone[2] = 14; 17199371c9d4SSatish Balay cone[3] = 7; 17209371c9d4SSatish Balay cone[4] = 10; 17219371c9d4SSatish Balay cone[5] = 11; 17229371c9d4SSatish Balay cone[6] = 16; 17239371c9d4SSatish Balay cone[7] = 18; 17249566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 17259371c9d4SSatish Balay cone[0] = 19; 17269371c9d4SSatish Balay cone[1] = 17; 17279371c9d4SSatish Balay cone[2] = 8; 17289371c9d4SSatish Balay cone[3] = 5; 17299371c9d4SSatish Balay cone[4] = 20; 17309371c9d4SSatish Balay cone[5] = 9; 17319371c9d4SSatish Balay cone[6] = 10; 17329371c9d4SSatish Balay cone[7] = 18; 17339566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 17349371c9d4SSatish Balay cone[0] = 19; 17359371c9d4SSatish Balay cone[1] = 5; 17369371c9d4SSatish Balay cone[2] = 6; 17379371c9d4SSatish Balay cone[3] = 13; 17389371c9d4SSatish Balay cone[4] = 20; 17399371c9d4SSatish Balay cone[5] = 15; 17409371c9d4SSatish Balay cone[6] = 12; 17419371c9d4SSatish Balay cone[7] = 9; 17429566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1743006a8963SMatthew G. Knepley } 1744d8c47e87SMatthew G. Knepley } 17459566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 17469566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 17470510c589SMatthew G. Knepley } 1748dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 17490510c589SMatthew G. Knepley { 17500510c589SMatthew G. Knepley Vec coordinates; 17510510c589SMatthew G. Knepley PetscSection coordSection; 17520510c589SMatthew G. Knepley PetscScalar *coords; 17530510c589SMatthew G. Knepley PetscInt coordSize, v; 17540510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 17550510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 17560510c589SMatthew G. Knepley 17570510c589SMatthew G. Knepley /* Build coordinates */ 17589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 17599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 17609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 17619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 17620510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 17639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 17649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 17650510c589SMatthew G. Knepley } 17669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 17679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 17689566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 17699566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 17709566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 17719566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 17729566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 17739566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 1774dd400576SPatrick Sanan if (rank == 0) { 17759371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 17769371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 17779371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 17789371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 17799371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 17809371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 17819371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 17829371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 17839371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 17849371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 17859371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 17869371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 17879371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 17889371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 17899371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 17909371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 17919371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 17929371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 17939371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 17949371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 17959371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 17969371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 17979371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 17989371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 17999371c9d4SSatish Balay coords[8 * dim + 0] = dis; 18009371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 18019371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 18029371c9d4SSatish Balay coords[9 * dim + 0] = dis; 18039371c9d4SSatish Balay coords[9 * dim + 1] = dis; 18049371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 18059371c9d4SSatish Balay coords[10 * dim + 0] = dis; 18069371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 18079371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 18089371c9d4SSatish Balay coords[11 * dim + 0] = dis; 18099371c9d4SSatish Balay coords[11 * dim + 1] = dis; 18109371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 18119371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 18129371c9d4SSatish Balay coords[12 * dim + 1] = dis; 18139371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 18149371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 18159371c9d4SSatish Balay coords[13 * dim + 1] = dis; 18169371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 18179371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 18189371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 18199371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 18209371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 18219371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 18229371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 1823ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 18249371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 18259371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 18269371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 18279371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 18289371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 18299371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 18309371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 18319371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 18329371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 18339371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 18349371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 18359371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 18369371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 18379371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 18389371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 18399371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 18409371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 18419371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 18429371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 18439371c9d4SSatish Balay coords[22 * dim + 1] = dis; 18449371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 18459371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 18469371c9d4SSatish Balay coords[23 * dim + 1] = dis; 18479371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 1848ae8bcbbbSMatthew G. Knepley } 1849d8c47e87SMatthew G. Knepley } 18509566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 18519566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 18529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 18530510c589SMatthew G. Knepley } 1854006a8963SMatthew G. Knepley /* Create periodicity */ 1855006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 18566858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 18576858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1858006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 1859ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 18606858538eSMatthew G. Knepley PetscInt numZCells = 3; 1861006a8963SMatthew G. Knepley 18626858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 18636858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 18644fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1865006a8963SMatthew G. Knepley } 1866dbc1dc17SMatthew G. Knepley { 18679318fe57SMatthew G. Knepley DM cdm; 18689318fe57SMatthew G. Knepley PetscDS cds; 18699318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 1870dbc1dc17SMatthew G. Knepley 18719566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder)); 18729566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18739566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 18749566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 1875dbc1dc17SMatthew G. Knepley } 18769318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 18779566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 18780510c589SMatthew G. Knepley PetscFunctionReturn(0); 18790510c589SMatthew G. Knepley } 18800510c589SMatthew G. Knepley 188124119c2aSMatthew G. Knepley /*@ 18829318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 188324119c2aSMatthew G. Knepley 1884d083f849SBarry Smith Collective 188524119c2aSMatthew G. Knepley 188624119c2aSMatthew G. Knepley Input Parameters: 1887a1cb98faSBarry Smith + comm - The communicator for the `DM` object 18889318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction 188924119c2aSMatthew G. Knepley 189024119c2aSMatthew G. Knepley Output Parameter: 189124119c2aSMatthew G. Knepley . dm - The DM object 189224119c2aSMatthew G. Knepley 189324119c2aSMatthew G. Knepley Level: beginner 189424119c2aSMatthew G. Knepley 1895a1cb98faSBarry Smith Note: 1896a1cb98faSBarry Smith Here is the output numbering looking from the bottom of the cylinder: 1897a1cb98faSBarry Smith .vb 1898a1cb98faSBarry Smith 17-----14 1899a1cb98faSBarry Smith | | 1900a1cb98faSBarry Smith | 2 | 1901a1cb98faSBarry Smith | | 1902a1cb98faSBarry Smith 17-----8-----7-----14 1903a1cb98faSBarry Smith | | | | 1904a1cb98faSBarry Smith | 3 | 0 | 1 | 1905a1cb98faSBarry Smith | | | | 1906a1cb98faSBarry Smith 19-----5-----6-----13 1907a1cb98faSBarry Smith | | 1908a1cb98faSBarry Smith | 4 | 1909a1cb98faSBarry Smith | | 1910a1cb98faSBarry Smith 19-----13 1911a1cb98faSBarry Smith 1912a1cb98faSBarry Smith and up through the top 1913a1cb98faSBarry Smith 1914a1cb98faSBarry Smith 18-----16 1915a1cb98faSBarry Smith | | 1916a1cb98faSBarry Smith | 2 | 1917a1cb98faSBarry Smith | | 1918a1cb98faSBarry Smith 18----10----11-----16 1919a1cb98faSBarry Smith | | | | 1920a1cb98faSBarry Smith | 3 | 0 | 1 | 1921a1cb98faSBarry Smith | | | | 1922a1cb98faSBarry Smith 20-----9----12-----15 1923a1cb98faSBarry Smith | | 1924a1cb98faSBarry Smith | 4 | 1925a1cb98faSBarry Smith | | 1926a1cb98faSBarry Smith 20-----15 1927a1cb98faSBarry Smith .ve 1928a1cb98faSBarry Smith 1929a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 193024119c2aSMatthew G. Knepley @*/ 1931d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm) 1932d71ae5a4SJacob Faibussowitsch { 19339318fe57SMatthew G. Knepley PetscFunctionBegin; 19349318fe57SMatthew G. Knepley PetscValidPointer(dm, 3); 19359566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 19369566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 19379566063dSJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ)); 19389318fe57SMatthew G. Knepley PetscFunctionReturn(0); 19399318fe57SMatthew G. Knepley } 19409318fe57SMatthew G. Knepley 1941d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 1942d71ae5a4SJacob Faibussowitsch { 194324119c2aSMatthew G. Knepley const PetscInt dim = 3; 1944412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 19459fe9f049SMatthew G. Knepley PetscMPIInt rank; 194624119c2aSMatthew G. Knepley 194724119c2aSMatthew G. Knepley PetscFunctionBegin; 194863a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 19499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 19509566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 1951412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 19529566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 195324119c2aSMatthew G. Knepley /* Create topology */ 195424119c2aSMatthew G. Knepley { 195524119c2aSMatthew G. Knepley PetscInt cone[6], c; 195624119c2aSMatthew G. Knepley 1957dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 1958dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 19599566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 19609566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 19619566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 196224119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 19639371c9d4SSatish Balay cone[0] = c + n * 1; 19649371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 19659371c9d4SSatish Balay cone[2] = 0 + 3 * n; 19669371c9d4SSatish Balay cone[3] = c + n * 2; 19679371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 19689371c9d4SSatish Balay cone[5] = 1 + 3 * n; 19699566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 19709566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 197124119c2aSMatthew G. Knepley } 19729566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 19739566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 197424119c2aSMatthew G. Knepley } 197548a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 197624119c2aSMatthew G. Knepley /* Create cylinder geometry */ 197724119c2aSMatthew G. Knepley { 197824119c2aSMatthew G. Knepley Vec coordinates; 197924119c2aSMatthew G. Knepley PetscSection coordSection; 198024119c2aSMatthew G. Knepley PetscScalar *coords; 1981412e9a14SMatthew G. Knepley PetscInt coordSize, c; 198224119c2aSMatthew G. Knepley 198324119c2aSMatthew G. Knepley /* Build coordinates */ 19849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 19859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 19869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 19879566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 198824119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 19899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 19909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 199124119c2aSMatthew G. Knepley } 19929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 19939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 19949566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 19959566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 19969566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 19979566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 19989566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 19999566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 200024119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 20019371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 20029371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 20039371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 20049371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 20059371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 20069371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 200724119c2aSMatthew G. Knepley } 2008dd400576SPatrick Sanan if (rank == 0) { 20099371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 20109371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 20119371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 20129371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 20139371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 20149371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 20159fe9f049SMatthew G. Knepley } 20169566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 20179566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 20189566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 201924119c2aSMatthew G. Knepley } 20209318fe57SMatthew G. Knepley /* Interpolate */ 20219566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 20229318fe57SMatthew G. Knepley PetscFunctionReturn(0); 20239318fe57SMatthew G. Knepley } 20249318fe57SMatthew G. Knepley 20259318fe57SMatthew G. Knepley /*@ 20269318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 20279318fe57SMatthew G. Knepley 20289318fe57SMatthew G. Knepley Collective 20299318fe57SMatthew G. Knepley 20309318fe57SMatthew G. Knepley Input Parameters: 2031a1cb98faSBarry Smith + comm - The communicator for the `DM` object 20329318fe57SMatthew G. Knepley . n - The number of wedges around the origin 20339318fe57SMatthew G. Knepley - interpolate - Create edges and faces 20349318fe57SMatthew G. Knepley 20359318fe57SMatthew G. Knepley Output Parameter: 2036a1cb98faSBarry Smith . dm - The `DM` object 20379318fe57SMatthew G. Knepley 20389318fe57SMatthew G. Knepley Level: beginner 20399318fe57SMatthew G. Knepley 2040a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 20419318fe57SMatthew G. Knepley @*/ 2042d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 2043d71ae5a4SJacob Faibussowitsch { 20449318fe57SMatthew G. Knepley PetscFunctionBegin; 20459318fe57SMatthew G. Knepley PetscValidPointer(dm, 4); 20469566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 20479566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 20489566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 204924119c2aSMatthew G. Knepley PetscFunctionReturn(0); 205024119c2aSMatthew G. Knepley } 205124119c2aSMatthew G. Knepley 2052d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2053d71ae5a4SJacob Faibussowitsch { 205465a81367SMatthew G. Knepley PetscReal prod = 0.0; 205565a81367SMatthew G. Knepley PetscInt i; 205665a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 205765a81367SMatthew G. Knepley return PetscSqrtReal(prod); 205865a81367SMatthew G. Knepley } 2059d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2060d71ae5a4SJacob Faibussowitsch { 206165a81367SMatthew G. Knepley PetscReal prod = 0.0; 206265a81367SMatthew G. Knepley PetscInt i; 206365a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i] * y[i]; 206465a81367SMatthew G. Knepley return prod; 206565a81367SMatthew G. Knepley } 206665a81367SMatthew G. Knepley 206751a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 2068d71ae5a4SJacob 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[]) 2069d71ae5a4SJacob Faibussowitsch { 207051a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 207151a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 207251a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 207351a74b61SMatthew G. Knepley 207451a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 207551a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 207651a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 207751a74b61SMatthew G. Knepley } 207851a74b61SMatthew G. Knepley 2079d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 2080d71ae5a4SJacob Faibussowitsch { 208165a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 208265a81367SMatthew G. Knepley PetscSection coordSection; 208365a81367SMatthew G. Knepley Vec coordinates; 208465a81367SMatthew G. Knepley PetscScalar *coords; 208565a81367SMatthew G. Knepley PetscReal *coordsIn; 2086064cae4fSPierre Jolivet PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, c, e; 208765a81367SMatthew G. Knepley PetscMPIInt rank; 208865a81367SMatthew G. Knepley 208965a81367SMatthew G. Knepley PetscFunctionBegin; 20909318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 20919566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 20929566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 20939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 209465a81367SMatthew G. Knepley switch (dim) { 209565a81367SMatthew G. Knepley case 2: 209665a81367SMatthew G. Knepley if (simplex) { 209751a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 209851a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 209965a81367SMatthew G. Knepley const PetscInt degree = 5; 210051a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 210165a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 210265a81367SMatthew G. Knepley PetscInt cone[3]; 210365a81367SMatthew G. Knepley PetscInt *graph, p, i, j, k; 210465a81367SMatthew G. Knepley 21059371c9d4SSatish Balay vertex[0] *= R / radius; 21069371c9d4SSatish Balay vertex[1] *= R / radius; 21079371c9d4SSatish Balay vertex[2] *= R / radius; 2108dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 2109dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 211065a81367SMatthew G. Knepley firstVertex = numCells; 211151a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 211265a81367SMatthew G. Knepley 211365a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 211465a81367SMatthew G. Knepley 211565a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 211651a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 211765a81367SMatthew G. Knepley */ 211865a81367SMatthew G. Knepley /* Construct vertices */ 21199566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2120dd400576SPatrick Sanan if (rank == 0) { 212165a81367SMatthew G. Knepley for (p = 0, i = 0; p < embedDim; ++p) { 212265a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 212365a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 212465a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 212565a81367SMatthew G. Knepley ++i; 212665a81367SMatthew G. Knepley } 212765a81367SMatthew G. Knepley } 212865a81367SMatthew G. Knepley } 212945da822fSValeria Barra } 213065a81367SMatthew G. Knepley /* Construct graph */ 21319566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 213265a81367SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 213365a81367SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 21349371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 21359371c9d4SSatish Balay graph[i * numVerts + j] = 1; 21369371c9d4SSatish Balay ++k; 21379371c9d4SSatish Balay } 213865a81367SMatthew G. Knepley } 213963a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 214065a81367SMatthew G. Knepley } 214165a81367SMatthew G. Knepley /* Build Topology */ 21429566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 214348a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 21449566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 214565a81367SMatthew G. Knepley /* Cells */ 214665a81367SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 214765a81367SMatthew G. Knepley for (j = 0; j < i; ++j) { 214865a81367SMatthew G. Knepley for (k = 0; k < j; ++k) { 214965a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 21509371c9d4SSatish Balay cone[0] = firstVertex + i; 21519371c9d4SSatish Balay cone[1] = firstVertex + j; 21529371c9d4SSatish Balay cone[2] = firstVertex + k; 215365a81367SMatthew G. Knepley /* Check orientation */ 215465a81367SMatthew G. Knepley { 21559371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 21569371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 21579371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 21589371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 21599371c9d4SSatish Balay }; 216065a81367SMatthew G. Knepley PetscReal normal[3]; 216165a81367SMatthew G. Knepley PetscInt e, f; 216265a81367SMatthew G. Knepley 216365a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 216465a81367SMatthew G. Knepley normal[d] = 0.0; 216565a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2166ad540459SPierre 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]); 216765a81367SMatthew G. Knepley } 216865a81367SMatthew G. Knepley } 21699371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 21709371c9d4SSatish Balay PetscInt tmp = cone[1]; 21719371c9d4SSatish Balay cone[1] = cone[2]; 21729371c9d4SSatish Balay cone[2] = tmp; 217365a81367SMatthew G. Knepley } 217465a81367SMatthew G. Knepley } 21759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 217665a81367SMatthew G. Knepley } 217765a81367SMatthew G. Knepley } 217865a81367SMatthew G. Knepley } 217965a81367SMatthew G. Knepley } 21809566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 21819566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 21829566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 218365a81367SMatthew G. Knepley } else { 21842829fed8SMatthew G. Knepley /* 21852829fed8SMatthew G. Knepley 12-21--13 21862829fed8SMatthew G. Knepley | | 21872829fed8SMatthew G. Knepley 25 4 24 21882829fed8SMatthew G. Knepley | | 21892829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 21902829fed8SMatthew G. Knepley | | | | 21912829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 21922829fed8SMatthew G. Knepley | | | | 21932829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 21942829fed8SMatthew G. Knepley | | 21952829fed8SMatthew G. Knepley 20 1 19 21962829fed8SMatthew G. Knepley | | 21972829fed8SMatthew G. Knepley 10-18--11 21982829fed8SMatthew G. Knepley | | 21992829fed8SMatthew G. Knepley 23 2 22 22002829fed8SMatthew G. Knepley | | 22012829fed8SMatthew G. Knepley 12-21--13 22022829fed8SMatthew G. Knepley */ 22032829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 22042829fed8SMatthew G. Knepley 2205dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 2206dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 2207dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 220865a81367SMatthew G. Knepley firstVertex = numCells; 220965a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 22102829fed8SMatthew G. Knepley /* Build Topology */ 22119566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 221248a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 221348a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 22149566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2215dd400576SPatrick Sanan if (rank == 0) { 22162829fed8SMatthew G. Knepley /* Cell 0 */ 22179371c9d4SSatish Balay cone[0] = 14; 22189371c9d4SSatish Balay cone[1] = 15; 22199371c9d4SSatish Balay cone[2] = 16; 22209371c9d4SSatish Balay cone[3] = 17; 22219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 22229371c9d4SSatish Balay ornt[0] = 0; 22239371c9d4SSatish Balay ornt[1] = 0; 22249371c9d4SSatish Balay ornt[2] = 0; 22259371c9d4SSatish Balay ornt[3] = 0; 22269566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 22272829fed8SMatthew G. Knepley /* Cell 1 */ 22289371c9d4SSatish Balay cone[0] = 18; 22299371c9d4SSatish Balay cone[1] = 19; 22309371c9d4SSatish Balay cone[2] = 14; 22319371c9d4SSatish Balay cone[3] = 20; 22329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 22339371c9d4SSatish Balay ornt[0] = 0; 22349371c9d4SSatish Balay ornt[1] = 0; 22359371c9d4SSatish Balay ornt[2] = -1; 22369371c9d4SSatish Balay ornt[3] = 0; 22379566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 22382829fed8SMatthew G. Knepley /* Cell 2 */ 22399371c9d4SSatish Balay cone[0] = 21; 22409371c9d4SSatish Balay cone[1] = 22; 22419371c9d4SSatish Balay cone[2] = 18; 22429371c9d4SSatish Balay cone[3] = 23; 22439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 22449371c9d4SSatish Balay ornt[0] = 0; 22459371c9d4SSatish Balay ornt[1] = 0; 22469371c9d4SSatish Balay ornt[2] = -1; 22479371c9d4SSatish Balay ornt[3] = 0; 22489566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 22492829fed8SMatthew G. Knepley /* Cell 3 */ 22509371c9d4SSatish Balay cone[0] = 19; 22519371c9d4SSatish Balay cone[1] = 22; 22529371c9d4SSatish Balay cone[2] = 24; 22539371c9d4SSatish Balay cone[3] = 15; 22549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 22559371c9d4SSatish Balay ornt[0] = -1; 22569371c9d4SSatish Balay ornt[1] = -1; 22579371c9d4SSatish Balay ornt[2] = 0; 22589371c9d4SSatish Balay ornt[3] = -1; 22599566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 22602829fed8SMatthew G. Knepley /* Cell 4 */ 22619371c9d4SSatish Balay cone[0] = 16; 22629371c9d4SSatish Balay cone[1] = 24; 22639371c9d4SSatish Balay cone[2] = 21; 22649371c9d4SSatish Balay cone[3] = 25; 22659566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 22669371c9d4SSatish Balay ornt[0] = -1; 22679371c9d4SSatish Balay ornt[1] = -1; 22689371c9d4SSatish Balay ornt[2] = -1; 22699371c9d4SSatish Balay ornt[3] = 0; 22709566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 22712829fed8SMatthew G. Knepley /* Cell 5 */ 22729371c9d4SSatish Balay cone[0] = 20; 22739371c9d4SSatish Balay cone[1] = 17; 22749371c9d4SSatish Balay cone[2] = 25; 22759371c9d4SSatish Balay cone[3] = 23; 22769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 22779371c9d4SSatish Balay ornt[0] = -1; 22789371c9d4SSatish Balay ornt[1] = -1; 22799371c9d4SSatish Balay ornt[2] = -1; 22809371c9d4SSatish Balay ornt[3] = -1; 22819566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 22822829fed8SMatthew G. Knepley /* Edges */ 22839371c9d4SSatish Balay cone[0] = 6; 22849371c9d4SSatish Balay cone[1] = 7; 22859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 22869371c9d4SSatish Balay cone[0] = 7; 22879371c9d4SSatish Balay cone[1] = 8; 22889566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 22899371c9d4SSatish Balay cone[0] = 8; 22909371c9d4SSatish Balay cone[1] = 9; 22919566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 22929371c9d4SSatish Balay cone[0] = 9; 22939371c9d4SSatish Balay cone[1] = 6; 22949566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 22959371c9d4SSatish Balay cone[0] = 10; 22969371c9d4SSatish Balay cone[1] = 11; 22979566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 22989371c9d4SSatish Balay cone[0] = 11; 22999371c9d4SSatish Balay cone[1] = 7; 23009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 23019371c9d4SSatish Balay cone[0] = 6; 23029371c9d4SSatish Balay cone[1] = 10; 23039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 23049371c9d4SSatish Balay cone[0] = 12; 23059371c9d4SSatish Balay cone[1] = 13; 23069566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 23079371c9d4SSatish Balay cone[0] = 13; 23089371c9d4SSatish Balay cone[1] = 11; 23099566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 23109371c9d4SSatish Balay cone[0] = 10; 23119371c9d4SSatish Balay cone[1] = 12; 23129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 23139371c9d4SSatish Balay cone[0] = 13; 23149371c9d4SSatish Balay cone[1] = 8; 23159566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 23169371c9d4SSatish Balay cone[0] = 12; 23179371c9d4SSatish Balay cone[1] = 9; 23189566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 231945da822fSValeria Barra } 23209566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 23219566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 23222829fed8SMatthew G. Knepley /* Build coordinates */ 23239566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2324dd400576SPatrick Sanan if (rank == 0) { 23259371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 23269371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 23279371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 23289371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 23299371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 23309371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 23319371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 23329371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 23339371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 23349371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 23359371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 23369371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 23379371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 23389371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 23399371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 23409371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 23419371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 23429371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 23439371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 23449371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 23459371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 23469371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 23479371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 23489371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 234965a81367SMatthew G. Knepley } 235045da822fSValeria Barra } 235165a81367SMatthew G. Knepley break; 235265a81367SMatthew G. Knepley case 3: 2353116ded15SMatthew G. Knepley if (simplex) { 2354116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 235551a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 235651a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 235751a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 2358116ded15SMatthew G. Knepley const PetscInt degree = 12; 2359116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 23609371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 23619371c9d4SSatish Balay {0, 1, 2, 3}, 23629371c9d4SSatish Balay {0, 2, 3, 1}, 23639371c9d4SSatish Balay {0, 3, 1, 2}, 23649371c9d4SSatish Balay {1, 0, 3, 2}, 23659371c9d4SSatish Balay {1, 2, 0, 3}, 23669371c9d4SSatish Balay {1, 3, 2, 0}, 23679371c9d4SSatish Balay {2, 0, 1, 3}, 23689371c9d4SSatish Balay {2, 1, 3, 0}, 23699371c9d4SSatish Balay {2, 3, 0, 1}, 23709371c9d4SSatish Balay {3, 0, 2, 1}, 23719371c9d4SSatish Balay {3, 1, 0, 2}, 23729371c9d4SSatish Balay {3, 2, 1, 0} 23739371c9d4SSatish Balay }; 2374116ded15SMatthew G. Knepley PetscInt cone[4]; 2375116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 2376116ded15SMatthew G. Knepley 23779371c9d4SSatish Balay vertexA[0] *= R; 23789371c9d4SSatish Balay vertexA[1] *= R; 23799371c9d4SSatish Balay vertexA[2] *= R; 23809371c9d4SSatish Balay vertexA[3] *= R; 23819371c9d4SSatish Balay vertexB[0] *= R; 23829371c9d4SSatish Balay vertexB[1] *= R; 23839371c9d4SSatish Balay vertexB[2] *= R; 23849371c9d4SSatish Balay vertexB[3] *= R; 23859371c9d4SSatish Balay vertexC[0] *= R; 23869371c9d4SSatish Balay vertexC[1] *= R; 23879371c9d4SSatish Balay vertexC[2] *= R; 23889371c9d4SSatish Balay vertexC[3] *= R; 2389dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 2390dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 2391116ded15SMatthew G. Knepley firstVertex = numCells; 2392116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 2393116ded15SMatthew G. Knepley 2394116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 2395116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 2396116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 2397116ded15SMatthew G. Knepley 2398116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 23996333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 2400116ded15SMatthew G. Knepley 2401116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 2402116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 2403116ded15SMatthew G. Knepley */ 2404116ded15SMatthew G. Knepley /* Construct vertices */ 24059566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2406116ded15SMatthew G. Knepley i = 0; 2407dd400576SPatrick Sanan if (rank == 0) { 2408116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2409116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2410116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2411116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 2412116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 2413116ded15SMatthew G. Knepley ++i; 2414116ded15SMatthew G. Knepley } 2415116ded15SMatthew G. Knepley } 2416116ded15SMatthew G. Knepley } 2417116ded15SMatthew G. Knepley } 2418116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 2419116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 2420116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2421116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 2422116ded15SMatthew G. Knepley ++i; 2423116ded15SMatthew G. Knepley } 2424116ded15SMatthew G. Knepley } 2425116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 2426116ded15SMatthew G. Knepley s[3] = 1; 2427116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2428116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2429116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2430116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 2431116ded15SMatthew G. Knepley ++i; 2432116ded15SMatthew G. Knepley } 2433116ded15SMatthew G. Knepley } 2434116ded15SMatthew G. Knepley } 2435116ded15SMatthew G. Knepley } 243645da822fSValeria Barra } 243763a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 2438116ded15SMatthew G. Knepley /* Construct graph */ 24399566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 2440116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 2441116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 24429371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 24439371c9d4SSatish Balay graph[i * numVerts + j] = 1; 24449371c9d4SSatish Balay ++k; 24459371c9d4SSatish Balay } 2446116ded15SMatthew G. Knepley } 244763a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 2448116ded15SMatthew G. Knepley } 2449116ded15SMatthew G. Knepley /* Build Topology */ 24509566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 245148a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 24529566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2453116ded15SMatthew G. Knepley /* Cells */ 2454dd400576SPatrick Sanan if (rank == 0) { 2455116ded15SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 2456116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 2457116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 2458116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 24599371c9d4SSatish 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]) { 24609371c9d4SSatish Balay cone[0] = firstVertex + i; 24619371c9d4SSatish Balay cone[1] = firstVertex + j; 24629371c9d4SSatish Balay cone[2] = firstVertex + k; 24639371c9d4SSatish Balay cone[3] = firstVertex + l; 2464116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 2465116ded15SMatthew G. Knepley { 24669371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 24679371c9d4SSatish 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}}}, 2468116ded15SMatthew G. Knepley 24699371c9d4SSatish 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}}}, 2470116ded15SMatthew G. Knepley 24719371c9d4SSatish 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}}}, 2472116ded15SMatthew G. Knepley 24739371c9d4SSatish 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}} } 24749371c9d4SSatish Balay }; 2475116ded15SMatthew G. Knepley PetscReal normal[4]; 2476116ded15SMatthew G. Knepley PetscInt e, f, g; 2477116ded15SMatthew G. Knepley 2478116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 2479116ded15SMatthew G. Knepley normal[d] = 0.0; 2480116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2481116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 2482116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 2483116ded15SMatthew 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]); 2484116ded15SMatthew G. Knepley } 2485116ded15SMatthew G. Knepley } 2486116ded15SMatthew G. Knepley } 2487116ded15SMatthew G. Knepley } 24889371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 24899371c9d4SSatish Balay PetscInt tmp = cone[1]; 24909371c9d4SSatish Balay cone[1] = cone[2]; 24919371c9d4SSatish Balay cone[2] = tmp; 24929371c9d4SSatish Balay } 2493116ded15SMatthew G. Knepley } 24949566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 2495116ded15SMatthew G. Knepley } 2496116ded15SMatthew G. Knepley } 2497116ded15SMatthew G. Knepley } 2498116ded15SMatthew G. Knepley } 2499116ded15SMatthew G. Knepley } 250045da822fSValeria Barra } 25019566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 25029566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 25039566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 2504116ded15SMatthew G. Knepley } 2505f4d061e9SPierre Jolivet break; 2506d71ae5a4SJacob Faibussowitsch default: 2507d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 250865a81367SMatthew G. Knepley } 250965a81367SMatthew G. Knepley /* Create coordinates */ 25109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 25119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 25129566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 25139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 25142829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 25159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 25169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 25172829fed8SMatthew G. Knepley } 25189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 25199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 25209566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 25219566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 25229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 25239566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 25249566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 25259566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 25269371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 2527ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 25289566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 25299566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 25309566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 25319566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 253251a74b61SMatthew G. Knepley { 253351a74b61SMatthew G. Knepley DM cdm; 253451a74b61SMatthew G. Knepley PetscDS cds; 25359318fe57SMatthew G. Knepley PetscScalar c = R; 253651a74b61SMatthew G. Knepley 25379566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere)); 25389566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 25399566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 25409566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 254151a74b61SMatthew G. Knepley } 25429318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 25439566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 25449318fe57SMatthew G. Knepley PetscFunctionReturn(0); 25459318fe57SMatthew G. Knepley } 25469318fe57SMatthew G. Knepley 2547b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 2548b7f5c055SJed Brown 2549b7f5c055SJed Brown /* 2550b7f5c055SJed Brown The Schwarz P implicit surface is 2551b7f5c055SJed Brown 2552b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 2553b7f5c055SJed Brown */ 2554d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2555d71ae5a4SJacob Faibussowitsch { 2556b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 2557b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 2558b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 2559b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2560b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 2561ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 2562b7f5c055SJed Brown } 2563b7f5c055SJed Brown } 2564b7f5c055SJed Brown 25654663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 2566d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 2567d71ae5a4SJacob Faibussowitsch { 2568ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 25694663dae6SJed Brown return 0; 25704663dae6SJed Brown } 25714663dae6SJed Brown 2572b7f5c055SJed Brown /* 2573b7f5c055SJed Brown The Gyroid implicit surface is 2574b7f5c055SJed Brown 2575b7f5c055SJed 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) 2576b7f5c055SJed Brown 2577b7f5c055SJed Brown */ 2578d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2579d71ae5a4SJacob Faibussowitsch { 2580b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 2581b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 2582b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 2583b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 2584b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 2585b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 2586b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 2587b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2588b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2589b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 2590b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2591b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2592b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 2593b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2594b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2595b7f5c055SJed Brown } 2596b7f5c055SJed Brown 25974663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 2598d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 2599d71ae5a4SJacob Faibussowitsch { 26004663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 26014663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 26024663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 26034663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 26044663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 26054663dae6SJed Brown return 0; 26064663dae6SJed Brown } 26074663dae6SJed Brown 2608b7f5c055SJed Brown /* 2609b7f5c055SJed Brown We wish to solve 2610b7f5c055SJed Brown 2611b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 2612b7f5c055SJed Brown 2613b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 2614b7f5c055SJed 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 2615b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 2616b7f5c055SJed Brown 2617b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 2618b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 2619b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 2620b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 2621b7f5c055SJed Brown Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries. 2622b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 2623b7f5c055SJed Brown 2624b7f5c055SJed Brown f(y) = 0 1 equation 2625b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 2626b7f5c055SJed Brown 2627b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 2628b7f5c055SJed Brown */ 2629d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 2630d71ae5a4SJacob Faibussowitsch { 2631b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 2632b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 26332f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 26349371c9d4SSatish Balay PetscReal n_y[3][3] = { 26359371c9d4SSatish Balay {0, 0, 0}, 26369371c9d4SSatish Balay {0, 0, 0}, 26379371c9d4SSatish Balay {0, 0, 0} 26389371c9d4SSatish Balay }; 2639b7f5c055SJed Brown 2640b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 2641b7f5c055SJed Brown 2642b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 2643b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2644ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 2645b7f5c055SJed Brown 2646b7f5c055SJed Brown // Define the Householder reflector 2647b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 2648b7f5c055SJed Brown n[0] += norm * sign; 2649b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 2650b7f5c055SJed Brown 2651b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2652b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 2653b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 2654b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 2655b7f5c055SJed Brown 2656b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2657b7f5c055SJed Brown n[i] /= norm; 2658b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2659b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 2660b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 2661b7f5c055SJed Brown } 2662b7f5c055SJed Brown } 2663b7f5c055SJed Brown 2664b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 2665b7f5c055SJed 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]; 2666b7f5c055SJed Brown 2667b7f5c055SJed Brown res[0] = f; 2668b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 2669b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 2670b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 2671b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2672b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 2673b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 2674b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 2675b7f5c055SJed Brown } 2676b7f5c055SJed Brown } 2677b7f5c055SJed Brown 2678b7f5c055SJed Brown /* 2679b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 2680b7f5c055SJed Brown */ 2681d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 2682d71ae5a4SJacob Faibussowitsch { 2683b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 2684b7f5c055SJed Brown 2685b7f5c055SJed Brown PetscFunctionBegin; 2686b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 2687b7f5c055SJed Brown PetscScalar res[3], J[9]; 2688b7f5c055SJed Brown PetscReal resnorm; 2689b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 2690b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 2691b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 269263a3b9bcSJacob 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]))); 2693b7f5c055SJed Brown } 2694b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 2695b7f5c055SJed Brown 2696b7f5c055SJed Brown // Take the Newton step 26979566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 2698b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 2699b7f5c055SJed Brown } 2700b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 2701b7f5c055SJed Brown PetscFunctionReturn(0); 2702b7f5c055SJed Brown } 2703b7f5c055SJed Brown 2704b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 2705b7f5c055SJed Brown 2706d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 2707d71ae5a4SJacob Faibussowitsch { 2708b7f5c055SJed Brown PetscMPIInt rank; 2709b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 2710b7f5c055SJed Brown PetscInt(*edges)[2] = NULL, *edgeSets = NULL; 2711b7f5c055SJed Brown PetscInt *cells_flat = NULL; 2712b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 2713b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 27144663dae6SJed Brown PetscSimplePointFunc normalFunc = NULL; 2715b7f5c055SJed Brown DMLabel label; 2716b7f5c055SJed Brown 2717b7f5c055SJed Brown PetscFunctionBegin; 27189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 271963a3b9bcSJacob 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); 2720b7f5c055SJed Brown switch (tpstype) { 2721b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 2722b7f5c055SJed 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"); 2723c5853193SPierre Jolivet if (rank == 0) { 2724b7f5c055SJed Brown PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 2725b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 2726b7f5c055SJed Brown PetscReal L = 1; 2727b7f5c055SJed Brown 2728b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 2729b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 2730b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 2731b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 2732b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 2733b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 27349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 27359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 27369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 27379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 2738b7f5c055SJed Brown // x-normal pipes 2739b7f5c055SJed Brown vcount = 0; 2740b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 2741b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2742b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2743b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2744b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 2745b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2746b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2747b7f5c055SJed Brown } 2748b7f5c055SJed Brown } 2749b7f5c055SJed Brown } 2750b7f5c055SJed Brown } 2751b7f5c055SJed Brown // y-normal pipes 2752b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2753b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 2754b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2755b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2756b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2757b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 2758b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2759b7f5c055SJed Brown } 2760b7f5c055SJed Brown } 2761b7f5c055SJed Brown } 2762b7f5c055SJed Brown } 2763b7f5c055SJed Brown // z-normal pipes 2764b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2765b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2766b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 2767b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2768b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2769b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2770b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 2771b7f5c055SJed Brown } 2772b7f5c055SJed Brown } 2773b7f5c055SJed Brown } 2774b7f5c055SJed Brown } 2775b7f5c055SJed Brown // junctions 2776b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2777b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2778b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2779b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 2780b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 2781b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 2782b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 2783b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 2784b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 2785b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 2786b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 2787b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 2788b7f5c055SJed Brown } 2789b7f5c055SJed Brown } 2790b7f5c055SJed Brown } 2791b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 2792b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 2793b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 2794b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 2795b7f5c055SJed Brown }; 2796b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 27979371c9d4SSatish 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}; 2798b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 27999371c9d4SSatish 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}; 2800b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 2801b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 2802b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 2803b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 2804b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 2805b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 2806b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 2807b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 2808b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 2809b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 2810b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 2811b7f5c055SJed Brown if (ijk[dir] == 0) { 2812b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 2813b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 2814b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 2815b7f5c055SJed Brown numEdges++; 2816b7f5c055SJed Brown } 2817b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 2818b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 2819b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 2820b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 2821b7f5c055SJed Brown numEdges++; 2822b7f5c055SJed Brown } 2823b7f5c055SJed Brown } 2824b7f5c055SJed Brown } 2825b7f5c055SJed Brown } 2826b7f5c055SJed Brown } 2827b7f5c055SJed Brown } 282863a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 2829b7f5c055SJed Brown numFaces = 24 * Njunctions; 2830b7f5c055SJed Brown cells_flat = cells[0][0][0]; 2831b7f5c055SJed Brown } 2832b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 28334663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 2834b7f5c055SJed Brown break; 2835b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 2836c5853193SPierre Jolivet if (rank == 0) { 2837b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 2838b7f5c055SJed Brown // 2839b7f5c055SJed 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) 2840b7f5c055SJed Brown // 2841b7f5c055SJed Brown // on the cell [0,2]^3. 2842b7f5c055SJed Brown // 2843b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 2844b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 2845b7f5c055SJed Brown // like a boomerang: 2846b7f5c055SJed Brown // 2847b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 2848b7f5c055SJed Brown // ----- ------- ------- ------- // 2849b7f5c055SJed Brown // // 2850b7f5c055SJed Brown // + + + + + + + \ + // 2851b7f5c055SJed Brown // \ / \ // 2852b7f5c055SJed Brown // \ `-_ _-' / } // 2853b7f5c055SJed Brown // *-_ `-' _-' / // 2854b7f5c055SJed Brown // + `-+ + + +-' + + / + // 2855b7f5c055SJed Brown // // 2856b7f5c055SJed Brown // // 2857b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 2858b7f5c055SJed Brown // ----- ------- ------- ------- // 2859b7f5c055SJed Brown // // 2860b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 2861b7f5c055SJed Brown // `-_ _-_ _-` / // 2862b7f5c055SJed Brown // \ _-' `-_ / { // 2863b7f5c055SJed Brown // \ / \ // 2864b7f5c055SJed Brown // + + + + + + + \ + // 2865b7f5c055SJed Brown // 2866b7f5c055SJed Brown // 2867b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 2868b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 2869b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 2870b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 2871b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 2872b7f5c055SJed Brown // 2873b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 2874b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 2875b7f5c055SJed Brown // 2876b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 2877b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 2878b7f5c055SJed Brown 2879b7f5c055SJed Brown PetscInt facesPerBlock = 64; 2880b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 2881b7f5c055SJed Brown PetscInt extentPlus[3]; 2882b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 28839371c9d4SSatish 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; 28849371c9d4SSatish Balay const PetscInt pattern[64][4] = { 28859371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 2886b7f5c055SJed Brown /* layer 0 */ 28879371c9d4SSatish Balay {A, C, K, G }, 28889371c9d4SSatish Balay {C, B, II, K }, 28899371c9d4SSatish Balay {D, A, H, L }, 28909371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 28919371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 28929371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 28939371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 28949371c9d4SSatish Balay {B, F, M, II }, 2895b7f5c055SJed Brown /* layer 1 */ 28969371c9d4SSatish Balay {G, K, Q, O }, 28979371c9d4SSatish Balay {K, II, P, Q }, 28989371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 28999371c9d4SSatish Balay {J, L, R, P }, 29009371c9d4SSatish Balay {N, J, P, S }, 29019371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 29029371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 29039371c9d4SSatish Balay {II, M, T, P }, 2904b7f5c055SJed Brown /* layer 2 */ 29059371c9d4SSatish Balay {O, Q, Y, U }, 29069371c9d4SSatish Balay {Q, P, W, Y }, 29079371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 29089371c9d4SSatish Balay {P, R, Ap, W }, 29099371c9d4SSatish Balay {S, P, X, Bp }, 29109371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 29119371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 29129371c9d4SSatish Balay {P, T, Z, X }, 2913b7f5c055SJed Brown /* layer 3 */ 29149371c9d4SSatish Balay {U, Y, Ep, Dp }, 29159371c9d4SSatish Balay {Y, W, Cp, Ep }, 29169371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 29179371c9d4SSatish Balay {W, Ap, Gp, Cp }, 29189371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 29199371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 29209371c9d4SSatish Balay {Z, V, Dp, Hp }, 29219371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 2922b7f5c055SJed Brown /* layer 4 */ 29239371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 29249371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 29259371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 29269371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 29279371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 29289371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 29299371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 29309371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 2931b7f5c055SJed Brown /* layer 5 */ 29329371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 29339371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 29349371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 29359371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 29369371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 29379371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 29389371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 29399371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 2940b7f5c055SJed Brown /* layer 6 */ 29419371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 29429371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 29439371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 29449371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 29459371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 29469371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 29479371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 29489371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 2949b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 29509371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 29519371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 29529371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 29539371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 29549371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 29559371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 29569371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 29579371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 2958b7f5c055SJed Brown }; 2959b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 29609371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 2961bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 2962bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 2963bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 2964bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 2965bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 2966bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 2967b7f5c055SJed Brown 2968bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 2969bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 2970bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 2971bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 2972bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 2973bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 2974bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 2975bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 2976b7f5c055SJed Brown 2977bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 2978bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 2979bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 2980bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 2981bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 2982bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 2983b7f5c055SJed Brown 2984bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 2985bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 2986bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 2987bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 2988bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 2989bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 2990bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 2991bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 2992b7f5c055SJed Brown 2993bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 2994bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 2995bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 2996bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 2997bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 2998bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 2999b7f5c055SJed Brown 3000bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 3001bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 3002bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 3003bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 3004bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 3005bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 3006bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 3007bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 3008b7f5c055SJed Brown 3009bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 3010bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 3011bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 3012bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 3013bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 3014bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 3015b7f5c055SJed Brown 3016bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 3017bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 3018bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 3019bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 3020bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 3021bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 3022bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 3023bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 3024b7f5c055SJed Brown }; 3025b7f5c055SJed Brown PetscInt(*cells)[64][4] = NULL; 3026b7f5c055SJed Brown PetscBool *seen; 3027b7f5c055SJed Brown PetscInt *vertToTrueVert; 3028b7f5c055SJed Brown PetscInt count; 3029b7f5c055SJed Brown 3030b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 3031b7f5c055SJed Brown numBlocks = 1; 3032b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 3033b7f5c055SJed Brown numBlocksPlus = 1; 3034b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 3035b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 30369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 30379566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 3038b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3039b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3040b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3041b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3042b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 3043b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 3044b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 3045b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 3046b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 3047b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 3048b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 3049b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 3050b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 3051b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 3052b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 3053b7f5c055SJed Brown 3054b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 3055b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 3056b7f5c055SJed Brown } 3057b7f5c055SJed Brown } 3058b7f5c055SJed Brown } 3059b7f5c055SJed Brown } 3060b7f5c055SJed Brown } 30619371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 30629371c9d4SSatish Balay if (seen[i]) numVertices++; 3063b7f5c055SJed Brown count = 0; 30649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 30659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 3066b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 3067b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 3068b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 3069b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 3070b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 3071b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 3072b7f5c055SJed Brown 3073b7f5c055SJed Brown if (seen[vIdx]) { 3074b7f5c055SJed Brown PetscInt thisVert; 3075b7f5c055SJed Brown 3076b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 3077b7f5c055SJed Brown 3078b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 3079b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 3080b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 3081b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 3082b7f5c055SJed Brown } 3083b7f5c055SJed Brown } 3084b7f5c055SJed Brown } 3085b7f5c055SJed Brown } 3086b7f5c055SJed Brown } 3087b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 3088b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3089ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 3090b7f5c055SJed Brown } 3091b7f5c055SJed Brown } 30929566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 30939566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 3094b7f5c055SJed Brown cells_flat = cells[0][0]; 3095b7f5c055SJed Brown numEdges = 0; 3096b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 3097b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3098b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3099b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3100b7f5c055SJed Brown 3101b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3102b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 3103b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 3104b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 3105b7f5c055SJed Brown } 3106b7f5c055SJed Brown } 3107b7f5c055SJed Brown } 3108b7f5c055SJed Brown } 31099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 31109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 3111b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 3112b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3113b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3114b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3115b7f5c055SJed Brown 3116b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3117b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 3118b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 3119b7f5c055SJed Brown edges[edge][0] = ev[0]; 3120b7f5c055SJed Brown edges[edge][1] = ev[1]; 3121b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 3122b7f5c055SJed Brown } 3123b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 3124b7f5c055SJed Brown edges[edge][0] = ev[0]; 3125b7f5c055SJed Brown edges[edge][1] = ev[1]; 3126b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 3127b7f5c055SJed Brown } 3128b7f5c055SJed Brown } 3129b7f5c055SJed Brown } 3130b7f5c055SJed Brown } 3131b7f5c055SJed Brown } 3132b7f5c055SJed Brown } 3133b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 31344663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 3135b7f5c055SJed Brown break; 3136b7f5c055SJed Brown } 3137b7f5c055SJed Brown 31389566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 3139c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 31409566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 31419566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 3142b7f5c055SJed Brown { 3143b7f5c055SJed Brown DM idm; 31449566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 314569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3146b7f5c055SJed Brown } 3147c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 31489566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 31499566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 3150b7f5c055SJed Brown 31519566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 31529566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 3153b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 3154b7f5c055SJed Brown PetscInt njoin; 3155b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 31569566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 315763a3b9bcSJacob 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]); 31589566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 31599566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 3160b7f5c055SJed Brown } 31619566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 31629566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 31631436d7faSJed Brown if (tps_distribute) { 31641436d7faSJed Brown DM pdm = NULL; 31651436d7faSJed Brown PetscPartitioner part; 31661436d7faSJed Brown 31679566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 31689566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 31699566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 317048a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 31711436d7faSJed Brown // Do not auto-distribute again 31729566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 31731436d7faSJed Brown } 3174b7f5c055SJed Brown 31759566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 3176b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 3177b7f5c055SJed Brown PetscInt m; 3178b7f5c055SJed Brown DM dmf; 3179b7f5c055SJed Brown Vec X; 3180b7f5c055SJed Brown PetscScalar *x; 31819566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 318269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 3183b7f5c055SJed Brown 31849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 31859566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 31869566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 318748a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 31889566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 3189b7f5c055SJed Brown } 3190b7f5c055SJed Brown 3191b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 31929566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 31939566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 3194b7f5c055SJed Brown 3195b7f5c055SJed Brown if (thickness > 0) { 31964663dae6SJed Brown DM edm, cdm, ecdm; 31974663dae6SJed Brown DMPlexTransform tr; 31984663dae6SJed Brown const char *prefix; 31994663dae6SJed Brown PetscOptions options; 32004663dae6SJed Brown // Code from DMPlexExtrude 32014663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 32024663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 32034663dae6SJed Brown PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE)); 32044663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 32054663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 32064663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 32074663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 32084663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 32094663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 32104663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 32114663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 32124663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 32134663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 32144663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 32154663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 32164663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 32174663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 32184663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 32194663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 32204663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 32214663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 32224663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 32234663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 32244663dae6SJed Brown if (edm) { 32254663dae6SJed Brown ((DM_Plex *)edm->data)->printFEM = ((DM_Plex *)dm->data)->printFEM; 32264663dae6SJed Brown ((DM_Plex *)edm->data)->printL2 = ((DM_Plex *)dm->data)->printL2; 3227f5867de0SMatthew G. Knepley ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate; 32284663dae6SJed Brown } 322969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 3230b7f5c055SJed Brown } 3231b7f5c055SJed Brown PetscFunctionReturn(0); 3232b7f5c055SJed Brown } 3233b7f5c055SJed Brown 3234b7f5c055SJed Brown /*@ 3235b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 3236b7f5c055SJed Brown 3237b7f5c055SJed Brown Collective 3238b7f5c055SJed Brown 3239b7f5c055SJed Brown Input Parameters: 3240a1cb98faSBarry Smith + comm - The communicator for the `DM` object 3241b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 3242b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 3243b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic 32441436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 3245817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 32461436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 3247817da375SSatish Balay - thickness - Thickness in normal direction 3248b7f5c055SJed Brown 3249b7f5c055SJed Brown Output Parameter: 3250a1cb98faSBarry Smith . dm - The `DM` object 3251a1cb98faSBarry Smith 3252a1cb98faSBarry Smith Level: beginner 3253b7f5c055SJed Brown 3254b7f5c055SJed Brown Notes: 3255b7f5c055SJed 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. 3256b7f5c055SJed Brown https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries. 3257b7f5c055SJed 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. 3258b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 3259b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 3260b7f5c055SJed Brown This projection could readily be extended to related surfaces. 3261b7f5c055SJed Brown 3262b7f5c055SJed Brown The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z). 3263b7f5c055SJed Brown When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). Use DMPlexLabelComplete() to propagate to coarse-level vertices. 3264b7f5c055SJed Brown 3265a1cb98faSBarry Smith Developer Note: 3266b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 3267b7f5c055SJed Brown 3268a1cb98faSBarry Smith References: 3269a1cb98faSBarry Smith . * - Maskery et al, Insights into the mechanical properties of several triply periodic minimal surface lattice structures made by polymer additive manufacturing, 2017. 3270a1cb98faSBarry Smith https://doi.org/10.1016/j.polymer.2017.11.049 3271b7f5c055SJed Brown 3272a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 3273b7f5c055SJed Brown @*/ 3274d71ae5a4SJacob 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) 3275d71ae5a4SJacob Faibussowitsch { 3276b7f5c055SJed Brown PetscFunctionBegin; 32779566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 32789566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 32799566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 3280b7f5c055SJed Brown PetscFunctionReturn(0); 3281b7f5c055SJed Brown } 3282b7f5c055SJed Brown 32839318fe57SMatthew G. Knepley /*@ 32849318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 32859318fe57SMatthew G. Knepley 32869318fe57SMatthew G. Knepley Collective 32879318fe57SMatthew G. Knepley 32889318fe57SMatthew G. Knepley Input Parameters: 3289a1cb98faSBarry Smith + comm - The communicator for the `DM` object 32909318fe57SMatthew G. Knepley . dim - The dimension 32919318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 32929318fe57SMatthew G. Knepley - R - The radius 32939318fe57SMatthew G. Knepley 32949318fe57SMatthew G. Knepley Output Parameter: 3295a1cb98faSBarry Smith . dm - The `DM` object 32969318fe57SMatthew G. Knepley 32979318fe57SMatthew G. Knepley Level: beginner 32989318fe57SMatthew G. Knepley 3299a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 33009318fe57SMatthew G. Knepley @*/ 3301d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 3302d71ae5a4SJacob Faibussowitsch { 33039318fe57SMatthew G. Knepley PetscFunctionBegin; 33049318fe57SMatthew G. Knepley PetscValidPointer(dm, 5); 33059566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 33069566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 33079566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 33089318fe57SMatthew G. Knepley PetscFunctionReturn(0); 33099318fe57SMatthew G. Knepley } 33109318fe57SMatthew G. Knepley 3311d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 3312d71ae5a4SJacob Faibussowitsch { 33139318fe57SMatthew G. Knepley DM sdm, vol; 33149318fe57SMatthew G. Knepley DMLabel bdlabel; 33159318fe57SMatthew G. Knepley 33169318fe57SMatthew G. Knepley PetscFunctionBegin; 33179566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 33189566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 33199566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_")); 33209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 33219566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 33229566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 33239566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 33249566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 332569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 33269566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 33279566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 33289566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 33299566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 333051a74b61SMatthew G. Knepley PetscFunctionReturn(0); 333151a74b61SMatthew G. Knepley } 333251a74b61SMatthew G. Knepley 333351a74b61SMatthew G. Knepley /*@ 333451a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 333551a74b61SMatthew G. Knepley 333651a74b61SMatthew G. Knepley Collective 333751a74b61SMatthew G. Knepley 333851a74b61SMatthew G. Knepley Input Parameters: 3339a1cb98faSBarry Smith + comm - The communicator for the `DM` object 334051a74b61SMatthew G. Knepley . dim - The dimension 334151a74b61SMatthew G. Knepley - R - The radius 334251a74b61SMatthew G. Knepley 334351a74b61SMatthew G. Knepley Output Parameter: 3344a1cb98faSBarry Smith . dm - The `DM` object 334551a74b61SMatthew G. Knepley 3346a1cb98faSBarry Smith Options Database Key: 334751a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 334851a74b61SMatthew G. Knepley 334951a74b61SMatthew G. Knepley Level: beginner 335051a74b61SMatthew G. Knepley 3351a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 335251a74b61SMatthew G. Knepley @*/ 3353d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 3354d71ae5a4SJacob Faibussowitsch { 335551a74b61SMatthew G. Knepley PetscFunctionBegin; 33569566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 33579566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 33589566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 33592829fed8SMatthew G. Knepley PetscFunctionReturn(0); 33602829fed8SMatthew G. Knepley } 33612829fed8SMatthew G. Knepley 3362d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 3363d71ae5a4SJacob Faibussowitsch { 33640a6ba040SMatthew G. Knepley PetscFunctionBegin; 33659318fe57SMatthew G. Knepley switch (ct) { 33669371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 33679318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 33689318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 33699318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 33709318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 33719318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 33729318fe57SMatthew G. Knepley 33739566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 33749566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33759371c9d4SSatish Balay } break; 33769371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 33779318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 33789318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 33799318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 33809318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 33819318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 33829318fe57SMatthew G. Knepley 33839566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 33849566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33859371c9d4SSatish Balay } break; 33869371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 3387b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 3388b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 3389b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 3390b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 3391b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 3392b5a892a1SMatthew G. Knepley 33939566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 33949566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33959371c9d4SSatish Balay } break; 33969371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 33979318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 33989318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 33999318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 34009318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 34019318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 34029318fe57SMatthew G. Knepley 34039566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 34049566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34059371c9d4SSatish Balay } break; 34069371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 34079318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 34089318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 34099318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 34109318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 34119318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 34129318fe57SMatthew G. Knepley 34139566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 34149566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34159371c9d4SSatish Balay } break; 34169371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 34179318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 34189318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 34199318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 34209318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 34219318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 34229318fe57SMatthew G. Knepley 34239566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 34249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34259371c9d4SSatish Balay } break; 34269371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 34279318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 34289318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 3429f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 34309318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 3431f0edb160SMatthew 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}; 34329318fe57SMatthew G. Knepley 34339566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34359371c9d4SSatish Balay } break; 34369371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 34379318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 34389318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 3439f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 34409318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34419371c9d4SSatish 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}; 34429318fe57SMatthew G. Knepley 34439566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34449566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34459371c9d4SSatish Balay } break; 34469371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 34479318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 34489318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 3449f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 34509318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 34519371c9d4SSatish 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}; 34529318fe57SMatthew G. Knepley 34539566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34549566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34559371c9d4SSatish Balay } break; 34569371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 34579318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 34589318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 34599318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 34609318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 34619371c9d4SSatish 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}; 34629318fe57SMatthew G. Knepley 34639566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34649566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34659371c9d4SSatish Balay } break; 34669371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 34679318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 34689318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 34699318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 34709318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34719371c9d4SSatish 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}; 34729318fe57SMatthew G. Knepley 34739566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34749566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34759371c9d4SSatish Balay } break; 34769371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 34779318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 34789318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 3479f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 34809318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34819371c9d4SSatish 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}; 34829318fe57SMatthew G. Knepley 34839566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34849566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34859371c9d4SSatish Balay } break; 3486d71ae5a4SJacob Faibussowitsch default: 3487d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 34889318fe57SMatthew G. Knepley } 34899318fe57SMatthew G. Knepley { 34909318fe57SMatthew G. Knepley PetscInt Nv, v; 34919318fe57SMatthew G. Knepley 34929318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 34939566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 34949566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 34959566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 34969566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 34979318fe57SMatthew G. Knepley } 34989566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 34999566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 35000a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 35010a6ba040SMatthew G. Knepley } 35020a6ba040SMatthew G. Knepley 35039318fe57SMatthew G. Knepley /*@ 3504a1cb98faSBarry Smith DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell 35059318fe57SMatthew G. Knepley 35069318fe57SMatthew G. Knepley Collective 35079318fe57SMatthew G. Knepley 35089318fe57SMatthew G. Knepley Input Parameters: 35099318fe57SMatthew G. Knepley + comm - The communicator 35109318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 35119318fe57SMatthew G. Knepley 35129318fe57SMatthew G. Knepley Output Parameter: 35139318fe57SMatthew G. Knepley . refdm - The reference cell 35149318fe57SMatthew G. Knepley 35159318fe57SMatthew G. Knepley Level: intermediate 35169318fe57SMatthew G. Knepley 3517a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()` 35189318fe57SMatthew G. Knepley @*/ 3519d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 3520d71ae5a4SJacob Faibussowitsch { 35210a6ba040SMatthew G. Knepley PetscFunctionBegin; 35229566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 35239566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 35249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 35259318fe57SMatthew G. Knepley PetscFunctionReturn(0); 35269318fe57SMatthew G. Knepley } 352779a015ccSMatthew G. Knepley 3528d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 3529d71ae5a4SJacob Faibussowitsch { 35309318fe57SMatthew G. Knepley DM plex; 35319318fe57SMatthew G. Knepley DMLabel label; 35329318fe57SMatthew G. Knepley PetscBool hasLabel; 35330a6ba040SMatthew G. Knepley 3534c22d3578SMatthew G. Knepley PetscFunctionBegin; 35359566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 35369318fe57SMatthew G. Knepley if (hasLabel) PetscFunctionReturn(0); 35379566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 35389566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 35399566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 35409566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 35411c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 35429566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 35439318fe57SMatthew G. Knepley PetscFunctionReturn(0); 35449318fe57SMatthew G. Knepley } 3545acdc6f61SToby Isaac 3546669647acSMatthew G. Knepley /* 3547669647acSMatthew 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. 3548669647acSMatthew G. Knepley 3549669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 3550669647acSMatthew G. Knepley */ 3551d71ae5a4SJacob 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[]) 3552d71ae5a4SJacob Faibussowitsch { 3553669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 3554669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 3555669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 3556669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 3557669647acSMatthew G. Knepley 3558669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 3559669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 3560669647acSMatthew G. Knepley } 3561669647acSMatthew G. Knepley 3562669647acSMatthew G. Knepley const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 35639318fe57SMatthew G. Knepley 3564d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 3565d71ae5a4SJacob Faibussowitsch { 35669318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 35679318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 35689318fe57SMatthew G. Knepley PetscInt dim = 2; 35699318fe57SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 3570cd7e8a5eSksagiyam PetscBool flg, flg2, fflg, bdfflg, nameflg; 35719318fe57SMatthew G. Knepley MPI_Comm comm; 3572ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3573ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3574ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 35759318fe57SMatthew G. Knepley 35769318fe57SMatthew G. Knepley PetscFunctionBegin; 35779566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 35789318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 35799566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 35809566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 35819566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 35829566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 35839566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 35849566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 35859566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 358663a3b9bcSJacob Faibussowitsch PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim); 35879566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 35889566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 35899566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 35909566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 35919566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 35929318fe57SMatthew G. Knepley 359361a622f3SMatthew G. Knepley switch (cell) { 359461a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 359561a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 359661a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 359761a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 359861a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 359961a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 3600d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 3601d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 3602d71ae5a4SJacob Faibussowitsch break; 3603d71ae5a4SJacob Faibussowitsch default: 3604d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 3605d71ae5a4SJacob Faibussowitsch break; 360661a622f3SMatthew G. Knepley } 360761a622f3SMatthew G. Knepley 36089318fe57SMatthew G. Knepley if (fflg) { 36099318fe57SMatthew G. Knepley DM dmnew; 36109318fe57SMatthew G. Knepley 36119566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew)); 36125de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 361369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 36149318fe57SMatthew G. Knepley } else if (refDomain) { 36159566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 36169318fe57SMatthew G. Knepley } else if (bdfflg) { 36179318fe57SMatthew G. Knepley DM bdm, dmnew; 36189318fe57SMatthew G. Knepley 36199566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm)); 36209566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 36219566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 36229566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 36239566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 36245de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 362569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 36269318fe57SMatthew G. Knepley } else { 36279566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 36289318fe57SMatthew G. Knepley switch (shape) { 3629669647acSMatthew G. Knepley case DM_SHAPE_BOX: 3630669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 36319318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 36329318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 36339318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 36349318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3635669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 36369318fe57SMatthew G. Knepley PetscInt i, n; 36379318fe57SMatthew G. Knepley 36389318fe57SMatthew G. Knepley n = dim; 36399318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 36409566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 36419318fe57SMatthew G. Knepley n = 3; 36429566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 364363a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 36449318fe57SMatthew G. Knepley n = 3; 36459566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 364663a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 36479318fe57SMatthew G. Knepley n = 3; 36489566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 364963a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 3650669647acSMatthew G. Knepley 3651669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 3652669647acSMatthew G. Knepley if (isAnnular) 3653669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 3654669647acSMatthew G. Knepley 36559318fe57SMatthew G. Knepley switch (cell) { 365661a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 36579566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 3658d410b0cfSMatthew G. Knepley if (!interpolate) { 3659d410b0cfSMatthew G. Knepley DM udm; 3660d410b0cfSMatthew G. Knepley 36619566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 366269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3663d410b0cfSMatthew G. Knepley } 36649318fe57SMatthew G. Knepley break; 3665d71ae5a4SJacob Faibussowitsch default: 3666d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate)); 3667d71ae5a4SJacob Faibussowitsch break; 36689318fe57SMatthew G. Knepley } 3669669647acSMatthew G. Knepley if (isAnnular) { 3670669647acSMatthew G. Knepley DM cdm; 3671669647acSMatthew G. Knepley PetscDS cds; 3672669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 3673669647acSMatthew G. Knepley 3674669647acSMatthew G. Knepley // Fix coordinates for annular region 3675669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 3676669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 3677669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 3678669647acSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, NULL)); 3679669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 3680669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 3681669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 3682669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 3683669647acSMatthew G. Knepley } 36849371c9d4SSatish Balay } break; 36859371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 36869318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 36879318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 36889318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 36899318fe57SMatthew G. Knepley PetscInt i, n; 36909318fe57SMatthew G. Knepley 36919318fe57SMatthew G. Knepley n = dim + 1; 36929318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 36939566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 36949318fe57SMatthew G. Knepley n = 3; 36959566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 369663a3b9bcSJacob 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); 36979318fe57SMatthew G. Knepley n = 3; 36989566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 369963a3b9bcSJacob 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); 37009566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 37019371c9d4SSatish Balay } break; 37029371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 37039318fe57SMatthew G. Knepley PetscReal R = 1.0; 37049318fe57SMatthew G. Knepley 37059566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 37069566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 37079371c9d4SSatish Balay } break; 37089371c9d4SSatish Balay case DM_SHAPE_BALL: { 37099318fe57SMatthew G. Knepley PetscReal R = 1.0; 37109318fe57SMatthew G. Knepley 37119566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 37129566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 37139371c9d4SSatish Balay } break; 37149371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 37159318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 37169318fe57SMatthew G. Knepley PetscInt Nw = 6; 37179318fe57SMatthew G. Knepley 37189566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 37199566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 37209318fe57SMatthew G. Knepley switch (cell) { 3721d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 3722d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 3723d71ae5a4SJacob Faibussowitsch break; 3724d71ae5a4SJacob Faibussowitsch default: 3725d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt)); 3726d71ae5a4SJacob Faibussowitsch break; 37279318fe57SMatthew G. Knepley } 37289371c9d4SSatish Balay } break; 3729b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 37309371c9d4SSatish Balay case DM_SHAPE_GYROID: { 3731b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 3732b7f5c055SJed Brown PetscReal thickness = 0.; 3733b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3734b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 37351436d7faSJed Brown PetscBool tps_distribute; 37369566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 37379566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 37389566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 37399566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 37409566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 37419566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 37429566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 37439566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 37449371c9d4SSatish Balay } break; 37459371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 374605bd46c0SStefano Zampini DM dmnew; 374705bd46c0SStefano Zampini PetscReal rl = 0.0; 374805bd46c0SStefano Zampini 374905bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 375005bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 37515de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 375269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 37539371c9d4SSatish Balay } break; 3754d71ae5a4SJacob Faibussowitsch default: 3755d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 37569318fe57SMatthew G. Knepley } 37579318fe57SMatthew G. Knepley } 37589566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 375948a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 37600a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 37610a6ba040SMatthew G. Knepley } 37620a6ba040SMatthew G. Knepley 3763d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 3764d71ae5a4SJacob Faibussowitsch { 37650a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 37667f9d8d6cSVaclav Hapla PetscBool flg, flg2; 37679318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 37680a6ba040SMatthew G. Knepley 37690a6ba040SMatthew G. Knepley PetscFunctionBegin; 37700a6ba040SMatthew G. Knepley /* Handle viewing */ 37719566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 37729566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 37739566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 37749566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 3775f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 37769566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 37779566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 37789318fe57SMatthew G. Knepley /* Labeling */ 37799566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 37809566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 3781953fc75cSMatthew G. Knepley /* Point Location */ 37829566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 37830848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 37849566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 37852e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 37869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 3787b29cfa1cSToby Isaac /* Projection behavior */ 3788d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 37899566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 3790f12cf164SMatthew G. Knepley /* Checking structure */ 3791f12cf164SMatthew G. Knepley { 37927f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 3793f12cf164SMatthew G. Knepley 37947f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 37957f9d8d6cSVaclav Hapla if (all) { 37967f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 37977f9d8d6cSVaclav Hapla } else { 37989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 37997f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 38009566063dSJacob 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)); 38017f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 38029566063dSJacob 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)); 38037f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 38049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 38057f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 38069566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 3807d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 38089566063dSJacob 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)); 38097f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 38107f9d8d6cSVaclav Hapla } 38119566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 38129566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 3813f12cf164SMatthew G. Knepley } 38149318fe57SMatthew G. Knepley { 38159318fe57SMatthew G. Knepley PetscReal scale = 1.0; 38164f3833eaSMatthew G. Knepley 38179566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 38189318fe57SMatthew G. Knepley if (flg) { 38199318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 38209318fe57SMatthew G. Knepley 38219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 38229566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 38239566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 38249566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 38259318fe57SMatthew G. Knepley } 38269318fe57SMatthew G. Knepley } 38279566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 382868d4fef7SMatthew G. Knepley PetscFunctionReturn(0); 382968d4fef7SMatthew G. Knepley } 383068d4fef7SMatthew G. Knepley 3831d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap) 3832d71ae5a4SJacob Faibussowitsch { 3833c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 3834c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 3835c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 3836c506a872SMatthew G. Knepley PetscBool flg; 3837c506a872SMatthew G. Knepley 3838c506a872SMatthew G. Knepley PetscFunctionBegin; 3839c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 3840c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 3841c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 3842c506a872SMatthew G. Knepley if (numOvLabels) { 3843c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 3844c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 3845c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 3846c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 3847c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 3848c506a872SMatthew G. Knepley } 3849c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 3850c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 3851c506a872SMatthew 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); 3852c506a872SMatthew G. Knepley 3853c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 3854c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 3855c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 3856c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 3857c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 3858c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 3859c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 3860c506a872SMatthew G. Knepley } 3861c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 3862c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 3863c506a872SMatthew 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); 3864c506a872SMatthew G. Knepley } 3865c506a872SMatthew G. Knepley PetscFunctionReturn(0); 3866c506a872SMatthew G. Knepley } 3867c506a872SMatthew G. Knepley 3868d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 3869d71ae5a4SJacob Faibussowitsch { 3870bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 3871bdf63967SMatthew G. Knepley char oname[256]; 3872d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 38739318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 3874e600fa54SMatthew 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; 38756bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 387668d4fef7SMatthew G. Knepley 387768d4fef7SMatthew G. Knepley PetscFunctionBegin; 3878d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 3879dd4c3f67SMatthew G. Knepley if (dm->cloneOpts) goto non_refine; 38809318fe57SMatthew G. Knepley /* Handle automatic creation */ 38819566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 38826bc1bd01Sksagiyam if (dim < 0) { 38836bc1bd01Sksagiyam PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 38846bc1bd01Sksagiyam created = PETSC_TRUE; 38856bc1bd01Sksagiyam } 38866bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 3887d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 38889566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 3889d89e6e46SMatthew G. Knepley if (flg) { 3890d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 3891d89e6e46SMatthew G. Knepley 38929566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 3893d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 3894d89e6e46SMatthew G. Knepley DM udm; 3895d89e6e46SMatthew G. Knepley 38969566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 389769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3898d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 3899d89e6e46SMatthew G. Knepley DM idm; 3900d89e6e46SMatthew G. Knepley 39019566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 390269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3903d89e6e46SMatthew G. Knepley } 3904d89e6e46SMatthew G. Knepley } 39059b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 39069566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg)); 3907ad540459SPierre Jolivet if (flg) ((DM_Plex *)dm->data)->ignoreModel = ignoreModel; 39089566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 39099566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 39109566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 39119566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 39129566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 39139566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 39149318fe57SMatthew G. Knepley if (flg) { 39159566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 39169566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 39179318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 39189318fe57SMatthew G. Knepley } 39199b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 39209b44eab4SMatthew G. Knepley DM rdm; 39219b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 39229b44eab4SMatthew G. Knepley 3923dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 39249566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 392569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 3926dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 392761a622f3SMatthew G. Knepley if (coordFunc && remap) { 39289566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 39299b44eab4SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 39309b44eab4SMatthew G. Knepley } 39319b44eab4SMatthew G. Knepley } 39329566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 39339318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 39349566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 39359318fe57SMatthew G. Knepley if (extLayers) { 39369318fe57SMatthew G. Knepley DM edm; 39379318fe57SMatthew G. Knepley 39389566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 393969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 394048d16a33SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = NULL; 3941dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3942d410b0cfSMatthew G. Knepley extLayers = 0; 39435e17fc22SAidan Hamilton PetscCall(DMGetDimension(dm, &dim)); 39449318fe57SMatthew G. Knepley } 3945bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 39466bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 39479566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 39486bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 39499566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 39506bc1bd01Sksagiyam if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) { 3951bdf63967SMatthew G. Knepley DM pdm; 3952bdf63967SMatthew G. Knepley IS perm; 3953bdf63967SMatthew G. Knepley 39549566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 39559566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 39569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 395769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 3958dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3959bdf63967SMatthew G. Knepley } 39609b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 39619566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 3962c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 3963dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 39649b44eab4SMatthew G. Knepley if (distribute) { 39659b44eab4SMatthew G. Knepley DM pdm = NULL; 39669b44eab4SMatthew G. Knepley PetscPartitioner part; 39679b44eab4SMatthew G. Knepley 39689566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 39699566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 39709566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm)); 397148a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 39729b44eab4SMatthew G. Knepley } 39739318fe57SMatthew G. Knepley /* Create coordinate space */ 39749318fe57SMatthew G. Knepley if (created) { 397561a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 39769318fe57SMatthew G. Knepley PetscInt degree = 1; 3977*5515ebd3SMatthew G. Knepley PetscInt height = 0; 3978*5515ebd3SMatthew G. Knepley DM cdm; 39796858538eSMatthew G. Knepley PetscBool flg; 39809318fe57SMatthew G. Knepley 39819566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg)); 39829566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 39839566063dSJacob Faibussowitsch if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc)); 3984*5515ebd3SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 398561a622f3SMatthew G. Knepley if (flg && !coordSpace) { 398661a622f3SMatthew G. Knepley PetscDS cds; 398761a622f3SMatthew G. Knepley PetscObject obj; 398861a622f3SMatthew G. Knepley PetscClassId id; 398961a622f3SMatthew G. Knepley 39909566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 39919566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 39929566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 399361a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 399461a622f3SMatthew G. Knepley PetscContainer dummy; 399561a622f3SMatthew G. Knepley 39969566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 39979566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 39989566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 39999566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 40009566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 400161a622f3SMatthew G. Knepley } 400261a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 400361a622f3SMatthew G. Knepley } 40046858538eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg)); 4005*5515ebd3SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg)); 4006*5515ebd3SMatthew G. Knepley if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height)); 40079566063dSJacob Faibussowitsch PetscCall(DMLocalizeCoordinates(dm)); 40089318fe57SMatthew G. Knepley } 400968d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 401061a622f3SMatthew G. Knepley remap = PETSC_TRUE; 40119566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 40129566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 40139566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 40149566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 401568d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 4016acdc6f61SToby Isaac DM *dms, coarseDM; 401768d4fef7SMatthew G. Knepley 40189566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 40199566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 40209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 40219566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 402268d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 40239566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 402468d4fef7SMatthew G. Knepley if (refine == 1) { 40259566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 40269566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 402768d4fef7SMatthew G. Knepley } else { 40289566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 40299566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 40309566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 40319566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 403268d4fef7SMatthew G. Knepley } 40339566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 40349566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 403568d4fef7SMatthew G. Knepley /* Free DMs */ 403668d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 4037dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 40389566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 403968d4fef7SMatthew G. Knepley } 40409566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 404168d4fef7SMatthew G. Knepley } else { 404268d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 40439318fe57SMatthew G. Knepley DM rdm; 404451a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 404568d4fef7SMatthew G. Knepley 4046dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40479566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 404868d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 404969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 4050dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 405161a622f3SMatthew G. Knepley if (coordFunc && remap) { 40529566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 405351a74b61SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 405451a74b61SMatthew G. Knepley } 405568d4fef7SMatthew G. Knepley } 405668d4fef7SMatthew G. Knepley } 40573cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 40589566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 40599566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 4060b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 4061b653a561SMatthew G. Knepley DM *dms; 4062b653a561SMatthew G. Knepley 40639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 40649566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 4065b653a561SMatthew G. Knepley /* Free DMs */ 4066b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 4067dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 40689566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 4069b653a561SMatthew G. Knepley } 40709566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 4071b653a561SMatthew G. Knepley } else { 4072b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 40739318fe57SMatthew G. Knepley DM cdm; 40749318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 40753cf6fe12SMatthew G. Knepley 4076dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40779566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 40783cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 407969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 4080dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40819318fe57SMatthew G. Knepley if (coordFunc) { 40829566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 40839318fe57SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 40849318fe57SMatthew G. Knepley } 40853cf6fe12SMatthew G. Knepley } 4086b653a561SMatthew G. Knepley } 4087909dfd52SMatthew G. Knepley /* Handle ghost cells */ 40889566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 4089909dfd52SMatthew G. Knepley if (ghostCells) { 4090909dfd52SMatthew G. Knepley DM gdm; 4091909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 4092909dfd52SMatthew G. Knepley 4093909dfd52SMatthew G. Knepley lname[0] = '\0'; 40949566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 40959566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 409669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 4097909dfd52SMatthew G. Knepley } 40986913077dSMatthew G. Knepley /* Handle 1D order */ 40996bc1bd01Sksagiyam if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) { 41006913077dSMatthew G. Knepley DM cdm, rdm; 41016913077dSMatthew G. Knepley PetscDS cds; 41026913077dSMatthew G. Knepley PetscObject obj; 41036913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 41046913077dSMatthew G. Knepley IS perm; 41056bc1bd01Sksagiyam PetscInt Nf; 41066913077dSMatthew G. Knepley PetscBool distributed; 41076913077dSMatthew G. Knepley 41089566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 41099566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 41109566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 41119566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 41126913077dSMatthew G. Knepley if (Nf) { 41139566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 41149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 41156913077dSMatthew G. Knepley } 41166bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 41179566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 41189566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 411969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 41209566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 41216913077dSMatthew G. Knepley } 41226913077dSMatthew G. Knepley } 41233cf6fe12SMatthew G. Knepley /* Handle */ 4124dd4c3f67SMatthew G. Knepley non_refine: 4125dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 4126d0609cedSBarry Smith PetscOptionsHeadEnd(); 41270a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 41280a6ba040SMatthew G. Knepley } 41290a6ba040SMatthew G. Knepley 4130d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 4131d71ae5a4SJacob Faibussowitsch { 4132552f7358SJed Brown PetscFunctionBegin; 41339566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 41349566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 41359566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 41369566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 41379566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 41389566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 4139552f7358SJed Brown PetscFunctionReturn(0); 4140552f7358SJed Brown } 4141552f7358SJed Brown 4142d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 4143d71ae5a4SJacob Faibussowitsch { 4144552f7358SJed Brown PetscFunctionBegin; 41459566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 41469566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 41479566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 4148552f7358SJed Brown PetscFunctionReturn(0); 4149552f7358SJed Brown } 4150552f7358SJed Brown 4151d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4152d71ae5a4SJacob Faibussowitsch { 4153793f3fe5SMatthew G. Knepley PetscInt depth, d; 4154793f3fe5SMatthew G. Knepley 4155793f3fe5SMatthew G. Knepley PetscFunctionBegin; 41569566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4157793f3fe5SMatthew G. Knepley if (depth == 1) { 41589566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 41599566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 41609566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 41619371c9d4SSatish Balay else { 41629371c9d4SSatish Balay *pStart = 0; 41639371c9d4SSatish Balay *pEnd = 0; 41649371c9d4SSatish Balay } 4165793f3fe5SMatthew G. Knepley } else { 41669566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 4167793f3fe5SMatthew G. Knepley } 4168793f3fe5SMatthew G. Knepley PetscFunctionReturn(0); 4169793f3fe5SMatthew G. Knepley } 4170793f3fe5SMatthew G. Knepley 4171d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 4172d71ae5a4SJacob Faibussowitsch { 4173502a2867SDave May PetscSF sf; 41740a19bb7dSprj- PetscInt niranks, njranks, n; 41750a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 41760a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 4177502a2867SDave May 41782f356facSMatthew G. Knepley PetscFunctionBegin; 41799566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 41800a19bb7dSprj- if (!data->neighbors) { 41819566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 41829566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 41839566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 41849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 41859566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 41869566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 41870a19bb7dSprj- n = njranks + niranks; 41889566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 41890a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 41909566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 41910a19bb7dSprj- } 41920a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 41930a19bb7dSprj- if (ranks) { 41940a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 41950a19bb7dSprj- else *ranks = NULL; 41960a19bb7dSprj- } 4197502a2867SDave May PetscFunctionReturn(0); 4198502a2867SDave May } 4199502a2867SDave May 42001eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 42011eb70e55SToby Isaac 4202d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 4203d71ae5a4SJacob Faibussowitsch { 4204552f7358SJed Brown PetscFunctionBegin; 4205552f7358SJed Brown dm->ops->view = DMView_Plex; 42062c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 4207552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 420838221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 4209552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 42101bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 421166ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 4212552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 4213552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 4214184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 42150298fd71SBarry Smith dm->ops->createfieldis = NULL; 4216552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 4217f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 42180a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 4219552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 4220bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 4221bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 4222b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 42235a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 4224552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 42250a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 42260a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 4227b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 4228d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 42290298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 42300298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 42310298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 42320298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 4233552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 4234552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 42352adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 4236793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 4237552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 42380709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 42390709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 4240bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 42418c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 4242ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 42430709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 4244b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 42452a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 424628d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 42479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 42489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 42499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 42509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 42519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 42529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 42539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 42546bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 42556bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 42569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 4257c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 4258c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 4259552f7358SJed Brown PetscFunctionReturn(0); 4260552f7358SJed Brown } 4261552f7358SJed Brown 4262d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 4263d71ae5a4SJacob Faibussowitsch { 426463a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 426563a16f15SMatthew G. Knepley 426663a16f15SMatthew G. Knepley PetscFunctionBegin; 426763a16f15SMatthew G. Knepley mesh->refct++; 426863a16f15SMatthew G. Knepley (*newdm)->data = mesh; 42699566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 42709566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 427163a16f15SMatthew G. Knepley PetscFunctionReturn(0); 427263a16f15SMatthew G. Knepley } 427363a16f15SMatthew G. Knepley 42748818961aSMatthew G Knepley /*MC 4275a1cb98faSBarry Smith DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 42768818961aSMatthew G Knepley In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is 42778818961aSMatthew G Knepley specified by a PetscSection object. Ownership in the global representation is determined by 4278a1cb98faSBarry Smith ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object. 42798818961aSMatthew G Knepley 4280e5893cccSMatthew G. Knepley Options Database Keys: 4281250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 4282250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 4283250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 4284250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 4285250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 4286250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 4287250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 4288ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 4289f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 4290f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 4291d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 4292f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 4293250712c9SMatthew G. Knepley . -dm_plex_check_all - Perform all shecks below 4294f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 4295f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 4296f12cf164SMatthew 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 4297f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 4298f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 4299e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 4300e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 4301e5893cccSMatthew G. Knepley 43028818961aSMatthew G Knepley Level: intermediate 43038818961aSMatthew G Knepley 4304a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection` 43058818961aSMatthew G Knepley M*/ 43068818961aSMatthew G Knepley 4307d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 4308d71ae5a4SJacob Faibussowitsch { 4309552f7358SJed Brown DM_Plex *mesh; 4310412e9a14SMatthew G. Knepley PetscInt unit; 4311552f7358SJed Brown 4312552f7358SJed Brown PetscFunctionBegin; 4313552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43144dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 4315552f7358SJed Brown dm->data = mesh; 4316552f7358SJed Brown 4317552f7358SJed Brown mesh->refct = 1; 43189566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 43199566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 4320552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 4321552f7358SJed Brown mesh->refinementLimit = -1.0; 4322e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 43236bc1bd01Sksagiyam mesh->reorderDefault = DMPLEX_REORDER_DEFAULT_NOTSET; 43241d1f2f2aSksagiyam mesh->distributionName = NULL; 43257d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 43267d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 4327552f7358SJed Brown 43289566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 43292e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 4330d9deefdfSMatthew G. Knepley 43318865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 4332552f7358SJed Brown 4333df0420ecSMatthew G. Knepley mesh->depthState = -1; 4334ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 43356113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 4336552f7358SJed Brown 43379566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 4338552f7358SJed Brown PetscFunctionReturn(0); 4339552f7358SJed Brown } 4340552f7358SJed Brown 4341552f7358SJed Brown /*@ 4342a1cb98faSBarry Smith DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 4343552f7358SJed Brown 4344d083f849SBarry Smith Collective 4345552f7358SJed Brown 4346552f7358SJed Brown Input Parameter: 4347a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object 4348552f7358SJed Brown 4349552f7358SJed Brown Output Parameter: 4350a1cb98faSBarry Smith . mesh - The `DMPLEX` object 4351552f7358SJed Brown 4352552f7358SJed Brown Level: beginner 4353552f7358SJed Brown 4354a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()` 4355552f7358SJed Brown @*/ 4356d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 4357d71ae5a4SJacob Faibussowitsch { 4358552f7358SJed Brown PetscFunctionBegin; 4359552f7358SJed Brown PetscValidPointer(mesh, 2); 43609566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 43619566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 4362552f7358SJed Brown PetscFunctionReturn(0); 4363552f7358SJed Brown } 4364552f7358SJed Brown 4365b09969d6SVaclav Hapla /*@C 4366a1cb98faSBarry Smith DMPlexBuildFromCellListParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 4367a1cb98faSBarry Smith 4368a1cb98faSBarry Smith Collective on dm 4369b09969d6SVaclav Hapla 4370b09969d6SVaclav Hapla Input Parameters: 4371a1cb98faSBarry Smith + dm - The `DM` 4372b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4373a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 4374a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DETERMINE` 4375b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 43765e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4377b09969d6SVaclav Hapla 4378be8c289dSNicolas Barral Output Parameters: 4379a1cb98faSBarry Smith + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 4380be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4381b09969d6SVaclav Hapla 4382b09969d6SVaclav Hapla Level: advanced 4383b09969d6SVaclav Hapla 4384a1cb98faSBarry Smith Notes: 4385a1cb98faSBarry Smith Two triangles sharing a face 4386a1cb98faSBarry Smith .vb 4387a1cb98faSBarry Smith 4388a1cb98faSBarry Smith 2 4389a1cb98faSBarry Smith / | \ 4390a1cb98faSBarry Smith / | \ 4391a1cb98faSBarry Smith / | \ 4392a1cb98faSBarry Smith 0 0 | 1 3 4393a1cb98faSBarry Smith \ | / 4394a1cb98faSBarry Smith \ | / 4395a1cb98faSBarry Smith \ | / 4396a1cb98faSBarry Smith 1 4397a1cb98faSBarry Smith .ve 4398a1cb98faSBarry Smith would have input 4399a1cb98faSBarry Smith .vb 4400a1cb98faSBarry Smith numCells = 2, numVertices = 4 4401a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 4402a1cb98faSBarry Smith .ve 4403a1cb98faSBarry Smith which would result in the `DMPLEX` 4404a1cb98faSBarry Smith .vb 4405a1cb98faSBarry Smith 4406a1cb98faSBarry Smith 4 4407a1cb98faSBarry Smith / | \ 4408a1cb98faSBarry Smith / | \ 4409a1cb98faSBarry Smith / | \ 4410a1cb98faSBarry Smith 2 0 | 1 5 4411a1cb98faSBarry Smith \ | / 4412a1cb98faSBarry Smith \ | / 4413a1cb98faSBarry Smith \ | / 4414a1cb98faSBarry Smith 3 4415a1cb98faSBarry Smith .ve 4416a1cb98faSBarry Smith 4417a1cb98faSBarry Smith Vertices are implicitly numbered consecutively 0,...,NVertices. 4418a1cb98faSBarry Smith Each rank owns a chunk of numVertices consecutive vertices. 4419a1cb98faSBarry Smith If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 4420a1cb98faSBarry Smith If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 4421a1cb98faSBarry Smith If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 4422a1cb98faSBarry Smith 4423a1cb98faSBarry Smith The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 4424a1cb98faSBarry Smith 4425a1cb98faSBarry Smith Fortran Note: 4426a1cb98faSBarry Smith Not currently supported in Fortran. 4427a1cb98faSBarry Smith 4428a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 4429a1cb98faSBarry Smith `PetscSF` 4430b09969d6SVaclav Hapla @*/ 4431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved) 4432d71ae5a4SJacob Faibussowitsch { 44332464107aSksagiyam PetscSF sfPoint; 44342464107aSksagiyam PetscLayout layout; 443582fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 4436a47d0d45SMatthew G. Knepley 4437a47d0d45SMatthew G. Knepley PetscFunctionBegin; 443825b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 44399566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 444025b6865aSVaclav Hapla /* Get/check global number of vertices */ 444125b6865aSVaclav Hapla { 444225b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 444325b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 444425b6865aSVaclav Hapla 444525b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 444625b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 44479371c9d4SSatish Balay for (i = 0; i < len; i++) 44489371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 444925b6865aSVaclav Hapla ++NVerticesInCells; 44509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 445125b6865aSVaclav Hapla 445225b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 44539371c9d4SSatish Balay else 44549371c9d4SSatish 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); 445525b6865aSVaclav Hapla } 44569079aca8SVaclav Hapla /* Count locally unique vertices */ 44579079aca8SVaclav Hapla { 44589079aca8SVaclav Hapla PetscHSetI vhash; 44599079aca8SVaclav Hapla PetscInt off = 0; 44609079aca8SVaclav Hapla 44619566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 4462a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 446348a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 4464a47d0d45SMatthew G. Knepley } 44659566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 44669566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 4467ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 44689566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 44699566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 447063a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 4471a47d0d45SMatthew G. Knepley } 44729566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 4473a47d0d45SMatthew G. Knepley /* Create cones */ 44749566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 44759566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 44769566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 44779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4478a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 4479a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 4480a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 4481a47d0d45SMatthew G. Knepley PetscInt lv; 4482a47d0d45SMatthew G. Knepley 44839079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 44849079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 44859566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 448663a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 4487961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 4488a47d0d45SMatthew G. Knepley } 4489a47d0d45SMatthew G. Knepley } 44902464107aSksagiyam /* Build point sf */ 44919566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 44929566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 44939566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 44949566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 44959566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 44969566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 44979566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 44989566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 44992464107aSksagiyam if (dm->sf) { 45002464107aSksagiyam const char *prefix; 45012464107aSksagiyam 45029566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 45039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 45042464107aSksagiyam } 45059566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 45069566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 45079566063dSJacob Faibussowitsch if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF")); 4508a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 45099566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 45109566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 45119566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4512a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4513a47d0d45SMatthew G. Knepley } 4514a47d0d45SMatthew G. Knepley 4515b09969d6SVaclav Hapla /*@C 4516a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4517a1cb98faSBarry Smith 4518a1cb98faSBarry Smith Collective on dm 4519b09969d6SVaclav Hapla 4520b09969d6SVaclav Hapla Input Parameters: 4521a1cb98faSBarry Smith + dm - The `DM` 4522b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4523a1cb98faSBarry Smith . sfVert - `PetscSF` describing complete vertex ownership 4524b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4525b09969d6SVaclav Hapla 4526b09969d6SVaclav Hapla Level: advanced 4527b09969d6SVaclav Hapla 4528a1cb98faSBarry Smith Fortran Note: 4529b09969d6SVaclav Hapla Not currently supported in Fortran. 4530b09969d6SVaclav Hapla 4531a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 4532b09969d6SVaclav Hapla @*/ 4533d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 4534d71ae5a4SJacob Faibussowitsch { 4535a47d0d45SMatthew G. Knepley PetscSection coordSection; 4536a47d0d45SMatthew G. Knepley Vec coordinates; 4537a47d0d45SMatthew G. Knepley PetscScalar *coords; 45381edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 4539a47d0d45SMatthew G. Knepley 4540a47d0d45SMatthew G. Knepley PetscFunctionBegin; 45419566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 45429566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 45431dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 45449566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 45459566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 45461dca8a05SBarry 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); 45479566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 45489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 45499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 45509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 45511edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 45529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 45539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4554a47d0d45SMatthew G. Knepley } 45559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 45569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 45579566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 45589566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 45599566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 45609566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 45619566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 45629566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 4563a47d0d45SMatthew G. Knepley { 4564a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 4565a47d0d45SMatthew G. Knepley 4566a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 45679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype)); 45689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 456921016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 457021016a8bSBarry Smith { 457121016a8bSBarry Smith PetscScalar *svertexCoords; 457221016a8bSBarry Smith PetscInt i; 45739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 45743612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 45759566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 45769566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 45779566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 457821016a8bSBarry Smith } 457921016a8bSBarry Smith #else 45809566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 45819566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 458221016a8bSBarry Smith #endif 45839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 4584a47d0d45SMatthew G. Knepley } 45859566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 45869566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 45879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 45889566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4589a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4590a47d0d45SMatthew G. Knepley } 4591a47d0d45SMatthew G. Knepley 4592c3edce3dSSatish Balay /*@ 4593a1cb98faSBarry Smith DMPlexCreateFromCellListParallelPetsc - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) 4594a1cb98faSBarry Smith 4595a1cb98faSBarry Smith Collective 4596a47d0d45SMatthew G. Knepley 4597a47d0d45SMatthew G. Knepley Input Parameters: 4598a47d0d45SMatthew G. Knepley + comm - The communicator 4599a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 4600a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 4601a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 4602a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DECIDE` 4603a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 4604a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 4605a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4606a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 4607a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4608a47d0d45SMatthew G. Knepley 4609d8d19677SJose E. Roman Output Parameters: 4610a1cb98faSBarry Smith + dm - The `DM` 4611a1cb98faSBarry Smith . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 4612be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4613a47d0d45SMatthew G. Knepley 4614b09969d6SVaclav Hapla Level: intermediate 4615a47d0d45SMatthew G. Knepley 4616a1cb98faSBarry Smith Notes: 4617a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 4618a1cb98faSBarry Smith `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 4619a1cb98faSBarry Smith 4620a1cb98faSBarry Smith See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters. 4621a1cb98faSBarry Smith 4622a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 4623a1cb98faSBarry Smith 4624a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 4625a47d0d45SMatthew G. Knepley @*/ 4626d71ae5a4SJacob 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) 4627d71ae5a4SJacob Faibussowitsch { 4628a47d0d45SMatthew G. Knepley PetscSF sfVert; 4629a47d0d45SMatthew G. Knepley 4630a47d0d45SMatthew G. Knepley PetscFunctionBegin; 46319566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 46329566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 4633a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 4634064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 46359566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 46369566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 4637a47d0d45SMatthew G. Knepley if (interpolate) { 46385fd9971aSMatthew G. Knepley DM idm; 4639a47d0d45SMatthew G. Knepley 46409566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 46419566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 4642a47d0d45SMatthew G. Knepley *dm = idm; 4643a47d0d45SMatthew G. Knepley } 46449566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 464518d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 46469566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 4647a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4648a47d0d45SMatthew G. Knepley } 4649a47d0d45SMatthew G. Knepley 4650b09969d6SVaclav Hapla /*@C 4651a1cb98faSBarry Smith DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 4652a1cb98faSBarry Smith 4653a1cb98faSBarry Smith Collective on dm 46549298eaa6SMatthew G Knepley 46559298eaa6SMatthew G Knepley Input Parameters: 4656a1cb98faSBarry Smith + dm - The `DM` 4657b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4658a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE` 46599298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 46605e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 46619298eaa6SMatthew G Knepley 4662b09969d6SVaclav Hapla Level: advanced 46639298eaa6SMatthew G Knepley 4664b09969d6SVaclav Hapla Notes: 4665b09969d6SVaclav Hapla Two triangles sharing a face 4666a1cb98faSBarry Smith .vb 46679298eaa6SMatthew G Knepley 4668a1cb98faSBarry Smith 2 4669a1cb98faSBarry Smith / | \ 4670a1cb98faSBarry Smith / | \ 4671a1cb98faSBarry Smith / | \ 4672a1cb98faSBarry Smith 0 0 | 1 3 4673a1cb98faSBarry Smith \ | / 4674a1cb98faSBarry Smith \ | / 4675a1cb98faSBarry Smith \ | / 4676a1cb98faSBarry Smith 1 4677a1cb98faSBarry Smith .ve 4678a1cb98faSBarry Smith would have input 4679a1cb98faSBarry Smith .vb 4680a1cb98faSBarry Smith numCells = 2, numVertices = 4 4681a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 4682a1cb98faSBarry Smith .ve 4683a1cb98faSBarry Smith which would result in the `DMPLEX` 4684a1cb98faSBarry Smith .vb 4685a1cb98faSBarry Smith 4686a1cb98faSBarry Smith 4 4687a1cb98faSBarry Smith / | \ 4688a1cb98faSBarry Smith / | \ 4689a1cb98faSBarry Smith / | \ 4690a1cb98faSBarry Smith 2 0 | 1 5 4691a1cb98faSBarry Smith \ | / 4692a1cb98faSBarry Smith \ | / 4693a1cb98faSBarry Smith \ | / 4694a1cb98faSBarry Smith 3 4695a1cb98faSBarry Smith .ve 4696a1cb98faSBarry Smith 4697a1cb98faSBarry Smith If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1. 469825b6865aSVaclav Hapla 4699b09969d6SVaclav Hapla Not currently supported in Fortran. 47009298eaa6SMatthew G Knepley 4701a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 4702b09969d6SVaclav Hapla @*/ 4703d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 4704d71ae5a4SJacob Faibussowitsch { 4705961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 4706b09969d6SVaclav Hapla 4707b09969d6SVaclav Hapla PetscFunctionBegin; 47089566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 47099566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 471025b6865aSVaclav Hapla /* Get/check global number of vertices */ 471125b6865aSVaclav Hapla { 471225b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 471325b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 471425b6865aSVaclav Hapla 471525b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 471625b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 47179371c9d4SSatish Balay for (i = 0; i < len; i++) 47189371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 471925b6865aSVaclav Hapla ++NVerticesInCells; 472025b6865aSVaclav Hapla 472125b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 47229371c9d4SSatish Balay else 47239371c9d4SSatish 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); 472425b6865aSVaclav Hapla } 47259566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 472648a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 47279566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 47289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4729b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 4730ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 4731b09969d6SVaclav Hapla } 47329566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 47339566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 47349566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4735b09969d6SVaclav Hapla PetscFunctionReturn(0); 4736b09969d6SVaclav Hapla } 4737b09969d6SVaclav Hapla 4738b09969d6SVaclav Hapla /*@C 4739a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4740a1cb98faSBarry Smith 4741a1cb98faSBarry Smith Collective on dm 4742b09969d6SVaclav Hapla 4743b09969d6SVaclav Hapla Input Parameters: 4744a1cb98faSBarry Smith + dm - The `DM` 4745b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4746b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4747b09969d6SVaclav Hapla 4748b09969d6SVaclav Hapla Level: advanced 4749b09969d6SVaclav Hapla 4750a1cb98faSBarry Smith Fortran Note: 4751b09969d6SVaclav Hapla Not currently supported in Fortran. 4752b09969d6SVaclav Hapla 4753a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 4754b09969d6SVaclav Hapla @*/ 4755d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 4756d71ae5a4SJacob Faibussowitsch { 4757b09969d6SVaclav Hapla PetscSection coordSection; 4758b09969d6SVaclav Hapla Vec coordinates; 4759b09969d6SVaclav Hapla DM cdm; 4760b09969d6SVaclav Hapla PetscScalar *coords; 47611edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 4762b09969d6SVaclav Hapla 4763b09969d6SVaclav Hapla PetscFunctionBegin; 47649566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 47659566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 47661dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 47679566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 47689566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 47699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 47709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 47719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 47721edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 47739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 47749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4775b09969d6SVaclav Hapla } 47769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4777b09969d6SVaclav Hapla 47789566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 47799566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 47809566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 47819566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 47829566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 47831edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 4784ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 4785b09969d6SVaclav Hapla } 47869566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 47879566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 47889566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 47899566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4790b09969d6SVaclav Hapla PetscFunctionReturn(0); 4791b09969d6SVaclav Hapla } 4792b09969d6SVaclav Hapla 4793b09969d6SVaclav Hapla /*@ 4794a1cb98faSBarry Smith DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 47953df08285SMatthew G. Knepley 4796a1cb98faSBarry Smith Collective 4797b09969d6SVaclav Hapla 4798b09969d6SVaclav Hapla Input Parameters: 4799b09969d6SVaclav Hapla + comm - The communicator 4800b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 48013df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 4802a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0 48033df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 4804b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 48053df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0 4806b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 48073df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0 4808b09969d6SVaclav Hapla 4809b09969d6SVaclav Hapla Output Parameter: 4810a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0 481125b6865aSVaclav Hapla 4812b09969d6SVaclav Hapla Level: intermediate 4813b09969d6SVaclav Hapla 4814a1cb98faSBarry Smith Notes: 4815a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`, 4816a1cb98faSBarry Smith `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()` 4817a1cb98faSBarry Smith 4818a1cb98faSBarry Smith See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters. 4819a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters. 4820a1cb98faSBarry Smith See `DMPlexCreateFromCellListParallelPetsc()` for parallel input 4821a1cb98faSBarry Smith 4822a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 48239298eaa6SMatthew G Knepley @*/ 4824d71ae5a4SJacob 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) 4825d71ae5a4SJacob Faibussowitsch { 48263df08285SMatthew G. Knepley PetscMPIInt rank; 48279298eaa6SMatthew G Knepley 48289298eaa6SMatthew G Knepley PetscFunctionBegin; 482928b400f6SJacob 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."); 48309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 48319566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 48329566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 48339566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 4834c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 48359566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 48369298eaa6SMatthew G Knepley if (interpolate) { 48375fd9971aSMatthew G. Knepley DM idm; 48389298eaa6SMatthew G Knepley 48399566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 48409566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 48419298eaa6SMatthew G Knepley *dm = idm; 48429298eaa6SMatthew G Knepley } 4843c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 48449566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 48459298eaa6SMatthew G Knepley PetscFunctionReturn(0); 48469298eaa6SMatthew G Knepley } 48479298eaa6SMatthew G Knepley 4848939f6067SMatthew G. Knepley /*@ 4849939f6067SMatthew 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 4850939f6067SMatthew G. Knepley 4851939f6067SMatthew G. Knepley Input Parameters: 4852c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension() 4853939f6067SMatthew G. Knepley . depth - The depth of the DAG 4854367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth 4855939f6067SMatthew G. Knepley . coneSize - The cone size of each point 4856939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 4857939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 4858367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim() 4859939f6067SMatthew G. Knepley 4860939f6067SMatthew G. Knepley Output Parameter: 4861939f6067SMatthew G. Knepley . dm - The DM 4862939f6067SMatthew G. Knepley 4863a1cb98faSBarry Smith Note: 4864a1cb98faSBarry Smith Two triangles sharing a face would have input 4865a1cb98faSBarry Smith .vb 4866a1cb98faSBarry Smith depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 4867a1cb98faSBarry Smith cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 4868a1cb98faSBarry Smith vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 4869a1cb98faSBarry Smith .ve 4870939f6067SMatthew G. Knepley which would result in the DMPlex 4871a1cb98faSBarry Smith .vb 4872a1cb98faSBarry Smith 4 4873a1cb98faSBarry Smith / | \ 4874a1cb98faSBarry Smith / | \ 4875a1cb98faSBarry Smith / | \ 4876a1cb98faSBarry Smith 2 0 | 1 5 4877a1cb98faSBarry Smith \ | / 4878a1cb98faSBarry Smith \ | / 4879a1cb98faSBarry Smith \ | / 4880a1cb98faSBarry Smith 3 4881a1cb98faSBarry Smith .ve 4882a1cb98faSBarry Smith Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()` 4883939f6067SMatthew G. Knepley 4884939f6067SMatthew G. Knepley Level: advanced 4885939f6067SMatthew G. Knepley 4886a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 4887939f6067SMatthew G. Knepley @*/ 4888d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 4889d71ae5a4SJacob Faibussowitsch { 48909298eaa6SMatthew G Knepley Vec coordinates; 48919298eaa6SMatthew G Knepley PetscSection coordSection; 48929298eaa6SMatthew G Knepley PetscScalar *coords; 4893811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 48949298eaa6SMatthew G Knepley 48959298eaa6SMatthew G Knepley PetscFunctionBegin; 48969566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 48979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 489863a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 48999298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 49009566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 49019298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 49029566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 4903ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 490497e052ccSToby Isaac } 49051dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 49069566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 49079298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 49089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 49099566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 49109298eaa6SMatthew G Knepley } 49119566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 49129566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 49139298eaa6SMatthew G Knepley /* Build coordinates */ 49149566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 49159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 49169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 49179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 49189298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 49199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 49209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 49219298eaa6SMatthew G Knepley } 49229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 49239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 49249566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 49259566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 49269566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 49279566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dimEmbed)); 49289566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 49299318fe57SMatthew G. Knepley if (vertexCoords) { 49309566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 49319298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 49329298eaa6SMatthew G Knepley PetscInt off; 49339298eaa6SMatthew G Knepley 49349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 4935ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 49369298eaa6SMatthew G Knepley } 49379318fe57SMatthew G. Knepley } 49389566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 49399566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 49409566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 49419298eaa6SMatthew G Knepley PetscFunctionReturn(0); 49429298eaa6SMatthew G Knepley } 49438415267dSToby Isaac 4944ca522641SMatthew G. Knepley /*@C 4945a1cb98faSBarry Smith DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file. 4946a1cb98faSBarry Smith 4947a1cb98faSBarry Smith Collective 49488ca92349SMatthew G. Knepley 49498ca92349SMatthew G. Knepley + comm - The MPI communicator 49508ca92349SMatthew G. Knepley . filename - Name of the .dat file 49518ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 49528ca92349SMatthew G. Knepley 49538ca92349SMatthew G. Knepley Output Parameter: 4954a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 49558ca92349SMatthew G. Knepley 49568ca92349SMatthew G. Knepley Level: beginner 49578ca92349SMatthew G. Knepley 4958a1cb98faSBarry Smith Note: 4959a1cb98faSBarry Smith The format is the simplest possible: 4960a1cb98faSBarry Smith .vb 4961a1cb98faSBarry Smith Ne 4962a1cb98faSBarry Smith v0 v1 ... vk 4963a1cb98faSBarry Smith Nv 4964a1cb98faSBarry Smith x y z marker 4965a1cb98faSBarry Smith .ve 4966a1cb98faSBarry Smith 4967a1cb98faSBarry Smith Developer Note: 4968a1cb98faSBarry Smith Should use a `PetscViewer` not a filename 4969a1cb98faSBarry Smith 4970a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 49718ca92349SMatthew G. Knepley @*/ 4972d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 4973d71ae5a4SJacob Faibussowitsch { 49748ca92349SMatthew G. Knepley DMLabel marker; 49758ca92349SMatthew G. Knepley PetscViewer viewer; 49768ca92349SMatthew G. Knepley Vec coordinates; 49778ca92349SMatthew G. Knepley PetscSection coordSection; 49788ca92349SMatthew G. Knepley PetscScalar *coords; 49798ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 49808ca92349SMatthew G. Knepley PetscInt dim = 3, cdim = 3, coordSize, v, c, d; 49818ca92349SMatthew G. Knepley PetscMPIInt rank; 4982f8d5e320SMatthew G. Knepley int snum, Nv, Nc, Ncn, Nl; 49838ca92349SMatthew G. Knepley 49848ca92349SMatthew G. Knepley PetscFunctionBegin; 49859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 49869566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 49879566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 49889566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 49899566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 4990dd400576SPatrick Sanan if (rank == 0) { 49919566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING)); 4992f8d5e320SMatthew G. Knepley snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl); 499308401ef6SPierre Jolivet PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 499425ce1634SJed Brown } else { 4995f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 49968ca92349SMatthew G. Knepley } 49979566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 49989566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 49999566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 50009566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 50019566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 50028ca92349SMatthew G. Knepley /* Read topology */ 5003dd400576SPatrick Sanan if (rank == 0) { 5004f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 5005f8d5e320SMatthew G. Knepley PetscInt cone[8]; 50068ca92349SMatthew G. Knepley int vbuf[8], v; 50078ca92349SMatthew G. Knepley 50089371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 50099371c9d4SSatish Balay format[c * 3 + 0] = '%'; 50109371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 50119371c9d4SSatish Balay format[c * 3 + 2] = ' '; 50129371c9d4SSatish Balay } 5013f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 50149566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 50159566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 50168ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 50179566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 5018f8d5e320SMatthew G. Knepley switch (Ncn) { 5019d71ae5a4SJacob Faibussowitsch case 2: 5020d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 5021d71ae5a4SJacob Faibussowitsch break; 5022d71ae5a4SJacob Faibussowitsch case 3: 5023d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 5024d71ae5a4SJacob Faibussowitsch break; 5025d71ae5a4SJacob Faibussowitsch case 4: 5026d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 5027d71ae5a4SJacob Faibussowitsch break; 5028d71ae5a4SJacob Faibussowitsch case 6: 5029d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 5030d71ae5a4SJacob Faibussowitsch break; 5031d71ae5a4SJacob Faibussowitsch case 8: 5032d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 5033d71ae5a4SJacob Faibussowitsch break; 5034d71ae5a4SJacob Faibussowitsch default: 5035d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 5036f8d5e320SMatthew G. Knepley } 503708401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 5038f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 50398ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 5040f8d5e320SMatthew G. Knepley if (Ncn == 8) { 50418ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 50428ca92349SMatthew G. Knepley cone[1] = cone[3]; 50438ca92349SMatthew G. Knepley cone[3] = tmp; 50448ca92349SMatthew G. Knepley } 50459566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 50468ca92349SMatthew G. Knepley } 50478ca92349SMatthew G. Knepley } 50489566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 50499566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 50508ca92349SMatthew G. Knepley /* Read coordinates */ 50519566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 50529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 50539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 50549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 50558ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 50569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 50579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 50588ca92349SMatthew G. Knepley } 50599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 50609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 50619566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 50629566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 50639566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 50649566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 50659566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 50669566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5067dd400576SPatrick Sanan if (rank == 0) { 5068f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 50698ca92349SMatthew G. Knepley double x[3]; 5070f8d5e320SMatthew G. Knepley int l, val[3]; 50718ca92349SMatthew G. Knepley 5072f8d5e320SMatthew G. Knepley if (Nl) { 50739371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 50749371c9d4SSatish Balay format[l * 3 + 0] = '%'; 50759371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 50769371c9d4SSatish Balay format[l * 3 + 2] = ' '; 50779371c9d4SSatish Balay } 5078f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 50799566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 50809566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 5081f8d5e320SMatthew G. Knepley } 50828ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 50839566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 5084f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 508508401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 5086f8d5e320SMatthew G. Knepley switch (Nl) { 5087d71ae5a4SJacob Faibussowitsch case 0: 5088d71ae5a4SJacob Faibussowitsch snum = 0; 5089d71ae5a4SJacob Faibussowitsch break; 5090d71ae5a4SJacob Faibussowitsch case 1: 5091d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 5092d71ae5a4SJacob Faibussowitsch break; 5093d71ae5a4SJacob Faibussowitsch case 2: 5094d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 5095d71ae5a4SJacob Faibussowitsch break; 5096d71ae5a4SJacob Faibussowitsch case 3: 5097d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 5098d71ae5a4SJacob Faibussowitsch break; 5099d71ae5a4SJacob Faibussowitsch default: 5100d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 5101f8d5e320SMatthew G. Knepley } 510208401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 51038ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 51049566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 51058ca92349SMatthew G. Knepley } 51068ca92349SMatthew G. Knepley } 51079566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 51089566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 51099566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 51109566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 51118ca92349SMatthew G. Knepley if (interpolate) { 51128ca92349SMatthew G. Knepley DM idm; 51138ca92349SMatthew G. Knepley DMLabel bdlabel; 51148ca92349SMatthew G. Knepley 51159566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 51169566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 51178ca92349SMatthew G. Knepley *dm = idm; 51188ca92349SMatthew G. Knepley 5119f8d5e320SMatthew G. Knepley if (!Nl) { 51209566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 51219566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 51229566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 51239566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 51248ca92349SMatthew G. Knepley } 5125f8d5e320SMatthew G. Knepley } 51268ca92349SMatthew G. Knepley PetscFunctionReturn(0); 51278ca92349SMatthew G. Knepley } 51288ca92349SMatthew G. Knepley 51298ca92349SMatthew G. Knepley /*@C 5130a1cb98faSBarry Smith DMPlexCreateFromFile - This takes a filename and produces a `DM` 5131a1cb98faSBarry Smith 5132a1cb98faSBarry Smith Collective 5133ca522641SMatthew G. Knepley 5134ca522641SMatthew G. Knepley Input Parameters: 5135ca522641SMatthew G. Knepley + comm - The communicator 5136ca522641SMatthew G. Knepley . filename - A file name 5137a1cb98faSBarry Smith . plexname - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats 5138ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 5139ca522641SMatthew G. Knepley 5140ca522641SMatthew G. Knepley Output Parameter: 5141a1cb98faSBarry Smith . dm - The `DM` 5142ca522641SMatthew G. Knepley 5143a1cb98faSBarry Smith Options Database Key: 5144a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5 514502ef0d99SVaclav Hapla 5146bca97951SVaclav Hapla Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g. 5147bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 5148bca97951SVaclav Hapla 5149ca522641SMatthew G. Knepley Level: beginner 5150ca522641SMatthew G. Knepley 5151a1cb98faSBarry Smith Notes: 5152a1cb98faSBarry Smith Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX` 5153a1cb98faSBarry Smith meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()` 5154a1cb98faSBarry Smith before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object. 5155a1cb98faSBarry Smith The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally 5156a1cb98faSBarry Smith calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats. 5157a1cb98faSBarry Smith 5158a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 5159ca522641SMatthew G. Knepley @*/ 5160d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 5161d71ae5a4SJacob Faibussowitsch { 5162ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 5163ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 5164ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 5165ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 5166ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 5167ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 5168ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 5169ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 5170ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 5171ef3a5affSJacob Faibussowitsch const char extMed[] = ".med"; 5172ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 5173ef3a5affSJacob Faibussowitsch const char extEGADSLite[] = ".egadslite"; 5174ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 5175ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 5176ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 5177ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 5178ca522641SMatthew G. Knepley size_t len; 5179c1cad2e7SMatthew G. Knepley PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV; 5180ca522641SMatthew G. Knepley PetscMPIInt rank; 5181ca522641SMatthew G. Knepley 5182ca522641SMatthew G. Knepley PetscFunctionBegin; 51835d80c0bfSVaclav Hapla PetscValidCharPointer(filename, 2); 51840d862eaeSPierre Jolivet if (plexname) PetscValidCharPointer(plexname, 3); 5185cd7e8a5eSksagiyam PetscValidPointer(dm, 5); 51869566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 51879566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 51889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 51899566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 519028b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 5191ef3a5affSJacob Faibussowitsch 51929371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 51939371c9d4SSatish Balay do { \ 5194274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 5195274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 5196274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 5197274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 5198ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 5199ef3a5affSJacob Faibussowitsch } else { \ 5200274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 5201ef3a5affSJacob Faibussowitsch } \ 5202ef3a5affSJacob Faibussowitsch } while (0) 5203ef3a5affSJacob Faibussowitsch 5204ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 5205ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 5206ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 5207ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 5208ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 5209ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 5210ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 5211ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 5212ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 5213ef3a5affSJacob Faibussowitsch CheckExtension(extMed, isMed); 5214ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 5215ef3a5affSJacob Faibussowitsch CheckExtension(extEGADSLite, isEGADSLite); 5216ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 5217ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 5218ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 5219ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 5220ef3a5affSJacob Faibussowitsch 5221ef3a5affSJacob Faibussowitsch #undef CheckExtension 5222ef3a5affSJacob Faibussowitsch 5223de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 52249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 5225ca522641SMatthew G. Knepley } else if (isCGNS) { 52269566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 522790c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 52289566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 52292f0bd6dcSMichael Lange } else if (isFluent) { 52309566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 5231cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 52329c48423bSVaclav Hapla PetscBool load_hdf5_xdmf = PETSC_FALSE; 5233cc2f8f65SMatthew G. Knepley PetscViewer viewer; 5234cc2f8f65SMatthew G. Knepley 523543b242b4SVaclav 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 */ 52369566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf)); 52379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL)); 52389566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 52399566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 52409566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 52419566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 52429566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 52439566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 5244cd7e8a5eSksagiyam 52459566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 52469566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 52479566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 52489566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 52499566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 52509566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer)); 52519566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 52525fd9971aSMatthew G. Knepley 52535fd9971aSMatthew G. Knepley if (interpolate) { 52545fd9971aSMatthew G. Knepley DM idm; 52555fd9971aSMatthew G. Knepley 52569566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 52579566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 52585fd9971aSMatthew G. Knepley *dm = idm; 52595fd9971aSMatthew G. Knepley } 5260707dd687SMichael Lange } else if (isMed) { 52619566063dSJacob Faibussowitsch PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm)); 5262f2801cd6SMatthew G. Knepley } else if (isPLY) { 52639566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 5264c1cad2e7SMatthew G. Knepley } else if (isEGADSLite || isEGADS || isIGES || isSTEP) { 52659566063dSJacob Faibussowitsch if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm)); 52669566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm)); 52677bee2925SMatthew Knepley if (!interpolate) { 52687bee2925SMatthew Knepley DM udm; 52697bee2925SMatthew Knepley 52709566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 52719566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 52727bee2925SMatthew Knepley *dm = udm; 52737bee2925SMatthew Knepley } 52748ca92349SMatthew G. Knepley } else if (isCV) { 52759566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 527698921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 52779566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 52789566063dSJacob Faibussowitsch if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 52799566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 5280ca522641SMatthew G. Knepley PetscFunctionReturn(0); 5281ca522641SMatthew G. Knepley } 52829f6c5813SMatthew G. Knepley /*@C 52839f6c5813SMatthew 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. 52849f6c5813SMatthew G. Knepley 52859f6c5813SMatthew G. Knepley Input Parameter: 52869f6c5813SMatthew G. Knepley . tr - The `DMPlexTransform` 52879f6c5813SMatthew G. Knepley 52889f6c5813SMatthew G. Knepley Output Parameter: 52899f6c5813SMatthew G. Knepley . dm - The `DM` 52909f6c5813SMatthew G. Knepley 52919f6c5813SMatthew G. Knepley Notes: 52929f6c5813SMatthew 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. 52939f6c5813SMatthew G. Knepley 52949f6c5813SMatthew G. Knepley Level: beginner 52959f6c5813SMatthew G. Knepley 52969f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 52979f6c5813SMatthew G. Knepley @*/ 52989f6c5813SMatthew G. Knepley PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, DM *dm) 52999f6c5813SMatthew G. Knepley { 53009f6c5813SMatthew G. Knepley DM bdm; 53019f6c5813SMatthew G. Knepley PetscInt Nl; 53029f6c5813SMatthew G. Knepley 53039f6c5813SMatthew G. Knepley PetscFunctionBegin; 53049f6c5813SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm)); 53059f6c5813SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 53069f6c5813SMatthew G. Knepley PetscCall(DMSetFromOptions(*dm)); 53079f6c5813SMatthew G. Knepley 53089f6c5813SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)tr)); 53099f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr)); 53109f6c5813SMatthew G. Knepley ((DM_Plex *)(*dm)->data)->tr = tr; 53119f6c5813SMatthew G. Knepley 53129f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformGetDM(tr, &bdm)); 53139f6c5813SMatthew G. Knepley PetscCall(DMGetNumLabels(bdm, &Nl)); 53149f6c5813SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 53159f6c5813SMatthew G. Knepley DMLabel label, labelNew; 53169f6c5813SMatthew G. Knepley const char *lname; 53179f6c5813SMatthew G. Knepley PetscBool isDepth, isCellType; 53189f6c5813SMatthew G. Knepley 53199f6c5813SMatthew G. Knepley PetscCall(DMGetLabelName(bdm, l, &lname)); 53209f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 53219f6c5813SMatthew G. Knepley if (isDepth) continue; 53229f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "celltype", &isCellType)); 53239f6c5813SMatthew G. Knepley if (isCellType) continue; 53249f6c5813SMatthew G. Knepley PetscCall(DMCreateLabel(*dm, lname)); 53259f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(bdm, lname, &label)); 53269f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(*dm, lname, &labelNew)); 53279f6c5813SMatthew G. Knepley PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL)); 53289f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetLabel(labelNew, label)); 53299f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetTransform(labelNew, tr)); 53309f6c5813SMatthew G. Knepley PetscCall(DMLabelSetUp(labelNew)); 53319f6c5813SMatthew G. Knepley } 53329f6c5813SMatthew G. Knepley PetscFunctionReturn(0); 53339f6c5813SMatthew G. Knepley } 5334