1552f7358SJed Brown #define PETSCDM_DLL 2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h> /*I "petscdmplex.h" I*/ 40c312b8eSJed Brown #include <petscsf.h> 54663dae6SJed Brown #include <petscdmplextransform.h> 69f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h> 7b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h> 8b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h> 9552f7358SJed Brown 10b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 1158cd63d5SVaclav Hapla 129318fe57SMatthew G. Knepley /* External function declarations here */ 139318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm); 149318fe57SMatthew G. Knepley 15e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */ 16d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout) 17d71ae5a4SJacob Faibussowitsch { 184fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 196858538eSMatthew G. Knepley PetscBool dist; 206bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 21e600fa54SMatthew G. Knepley 22e600fa54SMatthew G. Knepley PetscFunctionBegin; 23e600fa54SMatthew G. Knepley if (copyPeriodicity) { 244fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L)); 254fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L)); 26e600fa54SMatthew G. Knepley } 279566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dmin, &dist)); 289566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dmout, dist)); 296bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dmin, &reorder)); 306bc1bd01Sksagiyam PetscCall(DMPlexReorderSetDefault(dmout, reorder)); 31e600fa54SMatthew G. Knepley ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation; 321baa6e33SBarry Smith if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0)); 33e600fa54SMatthew G. Knepley PetscFunctionReturn(0); 34e600fa54SMatthew G. Knepley } 35e600fa54SMatthew G. Knepley 369318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 379318fe57SMatthew G. Knepley - Share the DM_Plex structure 389318fe57SMatthew G. Knepley - Share the coordinates 399318fe57SMatthew G. Knepley - Share the SF 409318fe57SMatthew G. Knepley */ 41d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm) 42d71ae5a4SJacob Faibussowitsch { 439318fe57SMatthew G. Knepley PetscSF sf; 449318fe57SMatthew G. Knepley DM dmNew = *ndm, coordDM, coarseDM; 459318fe57SMatthew G. Knepley Vec coords; 464fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 479318fe57SMatthew G. Knepley PetscInt dim, cdim; 489318fe57SMatthew G. Knepley 499318fe57SMatthew G. Knepley PetscFunctionBegin; 509318fe57SMatthew G. Knepley if (dm == dmNew) { 519566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 529318fe57SMatthew G. Knepley PetscFunctionReturn(0); 539318fe57SMatthew G. Knepley } 549318fe57SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 559566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmNew, &dim)); 569566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmNew, &cdim)); 589566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 599566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sf)); 609566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sf)); 619566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmNew, &coordDM)); 629566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmNew, &coords)); 639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dm, coordDM)); 649566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 656858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM)); 666858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords)); 676858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dm, coordDM)); 686858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 699318fe57SMatthew G. Knepley /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */ 706858538eSMatthew G. Knepley PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 716858538eSMatthew G. Knepley dm->coordinates[0].field = dmNew->coordinates[0].field; 7261a622f3SMatthew G. Knepley ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc; 734fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 744fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 759566063dSJacob Faibussowitsch PetscCall(DMDestroy_Plex(dm)); 769566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 779318fe57SMatthew G. Knepley dm->data = dmNew->data; 789318fe57SMatthew G. Knepley ((DM_Plex *)dmNew->data)->refct++; 799566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 809566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 819566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmNew, &coarseDM)); 829566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 839566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 849318fe57SMatthew G. Knepley PetscFunctionReturn(0); 859318fe57SMatthew G. Knepley } 869318fe57SMatthew G. Knepley 879318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew 889318fe57SMatthew G. Knepley - Swap the DM_Plex structure 899318fe57SMatthew G. Knepley - Swap the coordinates 909318fe57SMatthew G. Knepley - Swap the point PetscSF 919318fe57SMatthew G. Knepley */ 92d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 93d71ae5a4SJacob Faibussowitsch { 949318fe57SMatthew G. Knepley DM coordDMA, coordDMB; 959318fe57SMatthew G. Knepley Vec coordsA, coordsB; 969318fe57SMatthew G. Knepley PetscSF sfA, sfB; 979318fe57SMatthew G. Knepley DMField fieldTmp; 989318fe57SMatthew G. Knepley void *tmp; 999318fe57SMatthew G. Knepley DMLabelLink listTmp; 1009318fe57SMatthew G. Knepley DMLabel depthTmp; 1019318fe57SMatthew G. Knepley PetscInt tmpI; 1029318fe57SMatthew G. Knepley 1039318fe57SMatthew G. Knepley PetscFunctionBegin; 1049318fe57SMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 1059566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmA, &sfA)); 1069566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmB, &sfB)); 1079566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sfA)); 1089566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmA, sfB)); 1099566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmB, sfA)); 1109566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)sfA)); 1119318fe57SMatthew G. Knepley 1129566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &coordDMA)); 1139566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &coordDMB)); 1149566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordDMA)); 1159566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmA, coordDMB)); 1169566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmB, coordDMA)); 1179566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 1189318fe57SMatthew G. Knepley 1199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordsA)); 1209566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmB, &coordsB)); 1219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordsA)); 1229566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmA, coordsB)); 1239566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordsA)); 1249566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordsA)); 1259318fe57SMatthew G. Knepley 1266858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA)); 1276858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB)); 1286858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordDMA)); 1296858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmA, coordDMB)); 1306858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmB, coordDMA)); 1316858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 1326858538eSMatthew G. Knepley 1336858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA)); 1346858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB)); 1356858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordsA)); 1366858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB)); 1376858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA)); 1386858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordsA)); 1396858538eSMatthew G. Knepley 1406858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[0].field; 1416858538eSMatthew G. Knepley dmA->coordinates[0].field = dmB->coordinates[0].field; 1426858538eSMatthew G. Knepley dmB->coordinates[0].field = fieldTmp; 1436858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[1].field; 1446858538eSMatthew G. Knepley dmA->coordinates[1].field = dmB->coordinates[1].field; 1456858538eSMatthew G. Knepley dmB->coordinates[1].field = fieldTmp; 1469318fe57SMatthew G. Knepley tmp = dmA->data; 1479318fe57SMatthew G. Knepley dmA->data = dmB->data; 1489318fe57SMatthew G. Knepley dmB->data = tmp; 1499318fe57SMatthew G. Knepley listTmp = dmA->labels; 1509318fe57SMatthew G. Knepley dmA->labels = dmB->labels; 1519318fe57SMatthew G. Knepley dmB->labels = listTmp; 1529318fe57SMatthew G. Knepley depthTmp = dmA->depthLabel; 1539318fe57SMatthew G. Knepley dmA->depthLabel = dmB->depthLabel; 1549318fe57SMatthew G. Knepley dmB->depthLabel = depthTmp; 1559318fe57SMatthew G. Knepley depthTmp = dmA->celltypeLabel; 1569318fe57SMatthew G. Knepley dmA->celltypeLabel = dmB->celltypeLabel; 1579318fe57SMatthew G. Knepley dmB->celltypeLabel = depthTmp; 1589318fe57SMatthew G. Knepley tmpI = dmA->levelup; 1599318fe57SMatthew G. Knepley dmA->levelup = dmB->levelup; 1609318fe57SMatthew G. Knepley dmB->levelup = tmpI; 1619318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1629318fe57SMatthew G. Knepley } 1639318fe57SMatthew G. Knepley 164d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) 165d71ae5a4SJacob Faibussowitsch { 1669318fe57SMatthew G. Knepley DM idm; 1679318fe57SMatthew G. Knepley 1689318fe57SMatthew G. Knepley PetscFunctionBegin; 1699566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 1709566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 17169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 1729318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1739318fe57SMatthew G. Knepley } 1749318fe57SMatthew G. Knepley 1759318fe57SMatthew G. Knepley /*@C 1769318fe57SMatthew G. Knepley DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates 1779318fe57SMatthew G. Knepley 1789318fe57SMatthew G. Knepley Collective 1799318fe57SMatthew G. Knepley 1809318fe57SMatthew G. Knepley Input Parameters: 1819318fe57SMatthew G. Knepley + DM - The DM 1824f9ab2b4SJed Brown . degree - The degree of the finite element or PETSC_DECIDE 1839318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface 1849318fe57SMatthew G. Knepley 1859318fe57SMatthew G. Knepley Level: advanced 1869318fe57SMatthew G. Knepley 187db781477SPatrick Sanan .seealso: `PetscFECreateLagrange()`, `DMGetCoordinateDM()` 1889318fe57SMatthew G. Knepley @*/ 189d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc) 190d71ae5a4SJacob Faibussowitsch { 1919318fe57SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1929318fe57SMatthew G. Knepley DM cdm; 1939318fe57SMatthew G. Knepley PetscDS cds; 1949318fe57SMatthew G. Knepley PetscFE fe; 1959318fe57SMatthew G. Knepley PetscClassId id; 1969318fe57SMatthew G. Knepley 1979318fe57SMatthew G. Knepley PetscFunctionBegin; 1989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 1999566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 2009566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, (PetscObject *)&fe)); 2019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 2029318fe57SMatthew G. Knepley if (id != PETSCFE_CLASSID) { 2039318fe57SMatthew G. Knepley 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); 209*dc431b0cSMatthew 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 { 213*dc431b0cSMatthew G. Knepley DMPolytopeType ct; 214*dc431b0cSMatthew G. Knepley PetscInt cStart, cEnd, ctTmp; 215*dc431b0cSMatthew G. Knepley 216*dc431b0cSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 217*dc431b0cSMatthew G. Knepley // Want to match cell types 218*dc431b0cSMatthew G. Knepley if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 219*dc431b0cSMatthew G. Knepley else ct = DM_POLYTOPE_UNKNOWN; 220*dc431b0cSMatthew G. Knepley ctTmp = (PetscInt)ct; 221*dc431b0cSMatthew G. Knepley PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &ctTmp, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm))); 222*dc431b0cSMatthew G. Knepley ct = (DMPolytopeType)ctTmp; 223*dc431b0cSMatthew G. Knepley // Work around current bug 224*dc431b0cSMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) fe = NULL; 225*dc431b0cSMatthew G. Knepley else PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe)); 2264f9ab2b4SJed Brown } 227*dc431b0cSMatthew 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: 2401df5d5c5SMatthew G. Knepley + 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: 2471df5d5c5SMatthew G. Knepley . dm - The DM object 2481df5d5c5SMatthew G. Knepley 2491df5d5c5SMatthew G. Knepley Level: beginner 2501df5d5c5SMatthew G. Knepley 251db781477SPatrick Sanan .seealso: `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: 7299318fe57SMatthew G. Knepley + 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: 7379318fe57SMatthew G. Knepley . dm - The DM object 7389318fe57SMatthew G. Knepley 7399318fe57SMatthew G. Knepley Level: beginner 7409318fe57SMatthew G. Knepley 741db781477SPatrick Sanan .seealso: `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: 1311768d5fceSMatthew G. Knepley + comm - The communicator for the DM object 1312768d5fceSMatthew G. Knepley . dim - The spatial dimension 1313768d5fceSMatthew G. Knepley . 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) 1317fdbf62faSLisandro Dalcin . 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: 1321768d5fceSMatthew G. Knepley . dm - The DM object 1322768d5fceSMatthew G. Knepley 13239318fe57SMatthew G. Knepley Note: If you want to customize this mesh using options, you just need to 13249318fe57SMatthew G. Knepley $ DMCreate(comm, &dm); 13259318fe57SMatthew G. Knepley $ DMSetType(dm, DMPLEX); 13269318fe57SMatthew G. Knepley $ DMSetFromOptions(dm); 13279318fe57SMatthew G. Knepley and use the options on the DMSetFromOptions() page. 13281367e252SJed Brown 13291367e252SJed Brown Here is the numbering returned for 2 faces in each direction for tensor cells: 1330768d5fceSMatthew G. Knepley $ 10---17---11---18----12 1331768d5fceSMatthew G. Knepley $ | | | 1332768d5fceSMatthew G. Knepley $ | | | 1333768d5fceSMatthew G. Knepley $ 20 2 22 3 24 1334768d5fceSMatthew G. Knepley $ | | | 1335768d5fceSMatthew G. Knepley $ | | | 1336768d5fceSMatthew G. Knepley $ 7---15----8---16----9 1337768d5fceSMatthew G. Knepley $ | | | 1338768d5fceSMatthew G. Knepley $ | | | 1339768d5fceSMatthew G. Knepley $ 19 0 21 1 23 1340768d5fceSMatthew G. Knepley $ | | | 1341768d5fceSMatthew G. Knepley $ | | | 1342768d5fceSMatthew G. Knepley $ 4---13----5---14----6 1343768d5fceSMatthew G. Knepley 1344768d5fceSMatthew G. Knepley and for simplicial cells 1345768d5fceSMatthew G. Knepley 1346768d5fceSMatthew G. Knepley $ 14----8---15----9----16 1347768d5fceSMatthew G. Knepley $ |\ 5 |\ 7 | 1348768d5fceSMatthew G. Knepley $ | \ | \ | 1349768d5fceSMatthew G. Knepley $ 13 2 14 3 15 1350768d5fceSMatthew G. Knepley $ | 4 \ | 6 \ | 1351768d5fceSMatthew G. Knepley $ | \ | \ | 1352768d5fceSMatthew G. Knepley $ 11----6---12----7----13 1353768d5fceSMatthew G. Knepley $ |\ |\ | 1354768d5fceSMatthew G. Knepley $ | \ 1 | \ 3 | 1355768d5fceSMatthew G. Knepley $ 10 0 11 1 12 1356768d5fceSMatthew G. Knepley $ | 0 \ | 2 \ | 1357768d5fceSMatthew G. Knepley $ | \ | \ | 1358768d5fceSMatthew G. Knepley $ 8----4----9----5----10 1359768d5fceSMatthew G. Knepley 1360768d5fceSMatthew G. Knepley Level: beginner 1361768d5fceSMatthew G. Knepley 1362db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 1363768d5fceSMatthew G. Knepley @*/ 1364d71ae5a4SJacob 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) 1365d71ae5a4SJacob Faibussowitsch { 13669318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 1367fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 1368fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 1369fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1370552f7358SJed Brown 1371768d5fceSMatthew G. Knepley PetscFunctionBegin; 13729566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 13739566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 13749566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 13757ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 13769318fe57SMatthew G. Knepley PetscFunctionReturn(0); 13779318fe57SMatthew G. Knepley } 1378fdbf62faSLisandro Dalcin 1379d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1380d71ae5a4SJacob Faibussowitsch { 13819318fe57SMatthew G. Knepley DM bdm, vol; 13829318fe57SMatthew G. Knepley PetscInt i; 13839318fe57SMatthew G. Knepley 13849318fe57SMatthew G. Knepley PetscFunctionBegin; 138508401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 13869566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 13879566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 13889566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 13899566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 13909566063dSJacob Faibussowitsch PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol)); 13919566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 139269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 13939318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 13949318fe57SMatthew G. Knepley Vec v; 13959318fe57SMatthew G. Knepley PetscScalar *x; 13969318fe57SMatthew G. Knepley PetscInt cDim, n; 13979318fe57SMatthew G. Knepley 13989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 13999566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 14009566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 14019566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 14029318fe57SMatthew G. Knepley x += cDim; 14039318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 14049566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 14059566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 14069318fe57SMatthew G. Knepley } 1407552f7358SJed Brown PetscFunctionReturn(0); 1408552f7358SJed Brown } 1409552f7358SJed Brown 141000dabe28SStefano Zampini /*@ 141100dabe28SStefano Zampini DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells. 141200dabe28SStefano Zampini 1413d083f849SBarry Smith Collective 141400dabe28SStefano Zampini 141500dabe28SStefano Zampini Input Parameters: 141600dabe28SStefano Zampini + comm - The communicator for the DM object 141700dabe28SStefano Zampini . faces - Number of faces per dimension, or NULL for (1, 1, 1) 141800dabe28SStefano Zampini . lower - The lower left corner, or NULL for (0, 0, 0) 141900dabe28SStefano Zampini . upper - The upper right corner, or NULL for (1, 1, 1) 142000dabe28SStefano Zampini . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE 1421d0fcb9c2SMatthew G. Knepley . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 142200dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 142300dabe28SStefano Zampini 142400dabe28SStefano Zampini Output Parameter: 142500dabe28SStefano Zampini . dm - The DM object 142600dabe28SStefano Zampini 142700dabe28SStefano Zampini Level: beginner 142800dabe28SStefano Zampini 1429db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 143000dabe28SStefano Zampini @*/ 1431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 1432d71ae5a4SJacob Faibussowitsch { 14339318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 143400dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 143500dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 143600dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 143700dabe28SStefano Zampini 143800dabe28SStefano Zampini PetscFunctionBegin; 14399566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 14409566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 14419566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 1442d410b0cfSMatthew G. Knepley if (!interpolate) { 1443d410b0cfSMatthew G. Knepley DM udm; 144400dabe28SStefano Zampini 14459566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 144669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 144700dabe28SStefano Zampini } 14487ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 144900dabe28SStefano Zampini PetscFunctionReturn(0); 145000dabe28SStefano Zampini } 145100dabe28SStefano Zampini 1452a9074c1eSMatthew G. Knepley /*@C 1453a9074c1eSMatthew G. Knepley DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database. 1454a9074c1eSMatthew G. Knepley 1455d083f849SBarry Smith Logically Collective on dm 1456a9074c1eSMatthew G. Knepley 1457a9074c1eSMatthew G. Knepley Input Parameters: 1458a9074c1eSMatthew G. Knepley + dm - the DM context 1459a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 1460a9074c1eSMatthew G. Knepley 1461a9074c1eSMatthew G. Knepley Notes: 1462a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 1463a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 1464a9074c1eSMatthew G. Knepley 1465a9074c1eSMatthew G. Knepley Level: advanced 1466a9074c1eSMatthew G. Knepley 1467db781477SPatrick Sanan .seealso: `SNESSetFromOptions()` 1468a9074c1eSMatthew G. Knepley @*/ 1469d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 1470d71ae5a4SJacob Faibussowitsch { 1471a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1472a9074c1eSMatthew G. Knepley 1473a9074c1eSMatthew G. Knepley PetscFunctionBegin; 1474a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14759566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 14769566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 1477a9074c1eSMatthew G. Knepley PetscFunctionReturn(0); 1478a9074c1eSMatthew G. Knepley } 1479a9074c1eSMatthew G. Knepley 14809318fe57SMatthew G. Knepley /* Remap geometry to cylinder 148161a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 148261a622f3SMatthew G. Knepley 14839318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 14849318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 14859318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 14860510c589SMatthew G. Knepley 14879318fe57SMatthew G. Knepley phi = arctan(y/x) 14889318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 14899318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 14900510c589SMatthew G. Knepley 14919318fe57SMatthew G. Knepley so we remap them using 14920510c589SMatthew G. Knepley 14939318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 14949318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 14950510c589SMatthew G. Knepley 14969318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 14979318fe57SMatthew G. Knepley */ 1498d71ae5a4SJacob 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[]) 1499d71ae5a4SJacob Faibussowitsch { 15009318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 15019318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 150222cc497dSMatthew G. Knepley 15039318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 15049318fe57SMatthew G. Knepley f0[0] = u[0]; 15059318fe57SMatthew G. Knepley f0[1] = u[1]; 15069318fe57SMatthew G. Knepley } else { 15079318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 15080510c589SMatthew G. Knepley 15099318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 15109318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 15119318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 15129318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 15139318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 15149318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 15159318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 15169318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 15179318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 15189318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 15199318fe57SMatthew G. Knepley } else { 15209318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 15219318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 15229318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 15239318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 15249318fe57SMatthew G. Knepley } 15259318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 15269318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 15279318fe57SMatthew G. Knepley } 15289318fe57SMatthew G. Knepley f0[2] = u[2]; 15299318fe57SMatthew G. Knepley } 15300510c589SMatthew G. Knepley 1531d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ) 1532d71ae5a4SJacob Faibussowitsch { 15330510c589SMatthew G. Knepley const PetscInt dim = 3; 15349318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 1535d8c47e87SMatthew G. Knepley PetscMPIInt rank; 15360510c589SMatthew G. Knepley 15370510c589SMatthew G. Knepley PetscFunctionBegin; 15389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15399566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 15400510c589SMatthew G. Knepley /* Create topology */ 15410510c589SMatthew G. Knepley { 15420510c589SMatthew G. Knepley PetscInt cone[8], c; 15430510c589SMatthew G. Knepley 1544dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 1545dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 1546006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 1547ae8bcbbbSMatthew G. Knepley numCells *= 3; 1548dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 1549006a8963SMatthew G. Knepley } 15509566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 15519566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 15529566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 1553dd400576SPatrick Sanan if (rank == 0) { 1554006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 15559371c9d4SSatish Balay cone[0] = 15; 15569371c9d4SSatish Balay cone[1] = 18; 15579371c9d4SSatish Balay cone[2] = 17; 15589371c9d4SSatish Balay cone[3] = 16; 15599371c9d4SSatish Balay cone[4] = 31; 15609371c9d4SSatish Balay cone[5] = 32; 15619371c9d4SSatish Balay cone[6] = 33; 15629371c9d4SSatish Balay cone[7] = 34; 15639566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 15649371c9d4SSatish Balay cone[0] = 16; 15659371c9d4SSatish Balay cone[1] = 17; 15669371c9d4SSatish Balay cone[2] = 24; 15679371c9d4SSatish Balay cone[3] = 23; 15689371c9d4SSatish Balay cone[4] = 32; 15699371c9d4SSatish Balay cone[5] = 36; 15709371c9d4SSatish Balay cone[6] = 37; 15719371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 15729566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 15739371c9d4SSatish Balay cone[0] = 18; 15749371c9d4SSatish Balay cone[1] = 27; 15759371c9d4SSatish Balay cone[2] = 24; 15769371c9d4SSatish Balay cone[3] = 17; 15779371c9d4SSatish Balay cone[4] = 34; 15789371c9d4SSatish Balay cone[5] = 33; 15799371c9d4SSatish Balay cone[6] = 37; 15809371c9d4SSatish Balay cone[7] = 38; 15819566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 15829371c9d4SSatish Balay cone[0] = 29; 15839371c9d4SSatish Balay cone[1] = 27; 15849371c9d4SSatish Balay cone[2] = 18; 15859371c9d4SSatish Balay cone[3] = 15; 15869371c9d4SSatish Balay cone[4] = 35; 15879371c9d4SSatish Balay cone[5] = 31; 15889371c9d4SSatish Balay cone[6] = 34; 15899371c9d4SSatish Balay cone[7] = 38; 15909566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 15919371c9d4SSatish Balay cone[0] = 29; 15929371c9d4SSatish Balay cone[1] = 15; 15939371c9d4SSatish Balay cone[2] = 16; 15949371c9d4SSatish Balay cone[3] = 23; 15959371c9d4SSatish Balay cone[4] = 35; 15969371c9d4SSatish Balay cone[5] = 36; 15979371c9d4SSatish Balay cone[6] = 32; 15989371c9d4SSatish Balay cone[7] = 31; 15999566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1600006a8963SMatthew G. Knepley 16019371c9d4SSatish Balay cone[0] = 31; 16029371c9d4SSatish Balay cone[1] = 34; 16039371c9d4SSatish Balay cone[2] = 33; 16049371c9d4SSatish Balay cone[3] = 32; 16059371c9d4SSatish Balay cone[4] = 19; 16069371c9d4SSatish Balay cone[5] = 22; 16079371c9d4SSatish Balay cone[6] = 21; 16089371c9d4SSatish Balay cone[7] = 20; 16099566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 16109371c9d4SSatish Balay cone[0] = 32; 16119371c9d4SSatish Balay cone[1] = 33; 16129371c9d4SSatish Balay cone[2] = 37; 16139371c9d4SSatish Balay cone[3] = 36; 16149371c9d4SSatish Balay cone[4] = 22; 16159371c9d4SSatish Balay cone[5] = 25; 16169371c9d4SSatish Balay cone[6] = 26; 16179371c9d4SSatish Balay cone[7] = 21; 16189566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 16199371c9d4SSatish Balay cone[0] = 34; 16209371c9d4SSatish Balay cone[1] = 38; 16219371c9d4SSatish Balay cone[2] = 37; 16229371c9d4SSatish Balay cone[3] = 33; 16239371c9d4SSatish Balay cone[4] = 20; 16249371c9d4SSatish Balay cone[5] = 21; 16259371c9d4SSatish Balay cone[6] = 26; 16269371c9d4SSatish Balay cone[7] = 28; 16279566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 16289371c9d4SSatish Balay cone[0] = 35; 16299371c9d4SSatish Balay cone[1] = 38; 16309371c9d4SSatish Balay cone[2] = 34; 16319371c9d4SSatish Balay cone[3] = 31; 16329371c9d4SSatish Balay cone[4] = 30; 16339371c9d4SSatish Balay cone[5] = 19; 16349371c9d4SSatish Balay cone[6] = 20; 16359371c9d4SSatish Balay cone[7] = 28; 16369566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 16379371c9d4SSatish Balay cone[0] = 35; 16389371c9d4SSatish Balay cone[1] = 31; 16399371c9d4SSatish Balay cone[2] = 32; 16409371c9d4SSatish Balay cone[3] = 36; 16419371c9d4SSatish Balay cone[4] = 30; 16429371c9d4SSatish Balay cone[5] = 25; 16439371c9d4SSatish Balay cone[6] = 22; 16449371c9d4SSatish Balay cone[7] = 19; 16459566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 1646ae8bcbbbSMatthew G. Knepley 16479371c9d4SSatish Balay cone[0] = 19; 16489371c9d4SSatish Balay cone[1] = 20; 16499371c9d4SSatish Balay cone[2] = 21; 16509371c9d4SSatish Balay cone[3] = 22; 16519371c9d4SSatish Balay cone[4] = 15; 16529371c9d4SSatish Balay cone[5] = 16; 16539371c9d4SSatish Balay cone[6] = 17; 16549371c9d4SSatish Balay cone[7] = 18; 16559566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 16569371c9d4SSatish Balay cone[0] = 22; 16579371c9d4SSatish Balay cone[1] = 21; 16589371c9d4SSatish Balay cone[2] = 26; 16599371c9d4SSatish Balay cone[3] = 25; 16609371c9d4SSatish Balay cone[4] = 16; 16619371c9d4SSatish Balay cone[5] = 23; 16629371c9d4SSatish Balay cone[6] = 24; 16639371c9d4SSatish Balay cone[7] = 17; 16649566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 16659371c9d4SSatish Balay cone[0] = 20; 16669371c9d4SSatish Balay cone[1] = 28; 16679371c9d4SSatish Balay cone[2] = 26; 16689371c9d4SSatish Balay cone[3] = 21; 16699371c9d4SSatish Balay cone[4] = 18; 16709371c9d4SSatish Balay cone[5] = 17; 16719371c9d4SSatish Balay cone[6] = 24; 16729371c9d4SSatish Balay cone[7] = 27; 16739566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 16749371c9d4SSatish Balay cone[0] = 30; 16759371c9d4SSatish Balay cone[1] = 28; 16769371c9d4SSatish Balay cone[2] = 20; 16779371c9d4SSatish Balay cone[3] = 19; 16789371c9d4SSatish Balay cone[4] = 29; 16799371c9d4SSatish Balay cone[5] = 15; 16809371c9d4SSatish Balay cone[6] = 18; 16819371c9d4SSatish Balay cone[7] = 27; 16829566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 16839371c9d4SSatish Balay cone[0] = 30; 16849371c9d4SSatish Balay cone[1] = 19; 16859371c9d4SSatish Balay cone[2] = 22; 16869371c9d4SSatish Balay cone[3] = 25; 16879371c9d4SSatish Balay cone[4] = 29; 16889371c9d4SSatish Balay cone[5] = 23; 16899371c9d4SSatish Balay cone[6] = 16; 16909371c9d4SSatish Balay cone[7] = 15; 16919566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 1692006a8963SMatthew G. Knepley } else { 16939371c9d4SSatish Balay cone[0] = 5; 16949371c9d4SSatish Balay cone[1] = 8; 16959371c9d4SSatish Balay cone[2] = 7; 16969371c9d4SSatish Balay cone[3] = 6; 16979371c9d4SSatish Balay cone[4] = 9; 16989371c9d4SSatish Balay cone[5] = 12; 16999371c9d4SSatish Balay cone[6] = 11; 17009371c9d4SSatish Balay cone[7] = 10; 17019566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 17029371c9d4SSatish Balay cone[0] = 6; 17039371c9d4SSatish Balay cone[1] = 7; 17049371c9d4SSatish Balay cone[2] = 14; 17059371c9d4SSatish Balay cone[3] = 13; 17069371c9d4SSatish Balay cone[4] = 12; 17079371c9d4SSatish Balay cone[5] = 15; 17089371c9d4SSatish Balay cone[6] = 16; 17099371c9d4SSatish Balay cone[7] = 11; 17109566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 17119371c9d4SSatish Balay cone[0] = 8; 17129371c9d4SSatish Balay cone[1] = 17; 17139371c9d4SSatish Balay cone[2] = 14; 17149371c9d4SSatish Balay cone[3] = 7; 17159371c9d4SSatish Balay cone[4] = 10; 17169371c9d4SSatish Balay cone[5] = 11; 17179371c9d4SSatish Balay cone[6] = 16; 17189371c9d4SSatish Balay cone[7] = 18; 17199566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 17209371c9d4SSatish Balay cone[0] = 19; 17219371c9d4SSatish Balay cone[1] = 17; 17229371c9d4SSatish Balay cone[2] = 8; 17239371c9d4SSatish Balay cone[3] = 5; 17249371c9d4SSatish Balay cone[4] = 20; 17259371c9d4SSatish Balay cone[5] = 9; 17269371c9d4SSatish Balay cone[6] = 10; 17279371c9d4SSatish Balay cone[7] = 18; 17289566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 17299371c9d4SSatish Balay cone[0] = 19; 17309371c9d4SSatish Balay cone[1] = 5; 17319371c9d4SSatish Balay cone[2] = 6; 17329371c9d4SSatish Balay cone[3] = 13; 17339371c9d4SSatish Balay cone[4] = 20; 17349371c9d4SSatish Balay cone[5] = 15; 17359371c9d4SSatish Balay cone[6] = 12; 17369371c9d4SSatish Balay cone[7] = 9; 17379566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 1738006a8963SMatthew G. Knepley } 1739d8c47e87SMatthew G. Knepley } 17409566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 17419566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 17420510c589SMatthew G. Knepley } 1743dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 17440510c589SMatthew G. Knepley { 17450510c589SMatthew G. Knepley Vec coordinates; 17460510c589SMatthew G. Knepley PetscSection coordSection; 17470510c589SMatthew G. Knepley PetscScalar *coords; 17480510c589SMatthew G. Knepley PetscInt coordSize, v; 17490510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 17500510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 17510510c589SMatthew G. Knepley 17520510c589SMatthew G. Knepley /* Build coordinates */ 17539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 17549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 17559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 17569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 17570510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 17589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 17599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 17600510c589SMatthew G. Knepley } 17619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 17629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 17639566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 17649566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 17659566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 17669566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 17679566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 17689566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 1769dd400576SPatrick Sanan if (rank == 0) { 17709371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 17719371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 17729371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 17739371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 17749371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 17759371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 17769371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 17779371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 17789371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 17799371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 17809371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 17819371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 17829371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 17839371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 17849371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 17859371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 17869371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 17879371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 17889371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 17899371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 17909371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 17919371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 17929371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 17939371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 17949371c9d4SSatish Balay coords[8 * dim + 0] = dis; 17959371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 17969371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 17979371c9d4SSatish Balay coords[9 * dim + 0] = dis; 17989371c9d4SSatish Balay coords[9 * dim + 1] = dis; 17999371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 18009371c9d4SSatish Balay coords[10 * dim + 0] = dis; 18019371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 18029371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 18039371c9d4SSatish Balay coords[11 * dim + 0] = dis; 18049371c9d4SSatish Balay coords[11 * dim + 1] = dis; 18059371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 18069371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 18079371c9d4SSatish Balay coords[12 * dim + 1] = dis; 18089371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 18099371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 18109371c9d4SSatish Balay coords[13 * dim + 1] = dis; 18119371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 18129371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 18139371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 18149371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 18159371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 18169371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 18179371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 1818ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 18199371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 18209371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 18219371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 18229371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 18239371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 18249371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 18259371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 18269371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 18279371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 18289371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 18299371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 18309371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 18319371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 18329371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 18339371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 18349371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 18359371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 18369371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 18379371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 18389371c9d4SSatish Balay coords[22 * dim + 1] = dis; 18399371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 18409371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 18419371c9d4SSatish Balay coords[23 * dim + 1] = dis; 18429371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 1843ae8bcbbbSMatthew G. Knepley } 1844d8c47e87SMatthew G. Knepley } 18459566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 18469566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 18479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 18480510c589SMatthew G. Knepley } 1849006a8963SMatthew G. Knepley /* Create periodicity */ 1850006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 18516858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 18526858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1853006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 1854ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 18556858538eSMatthew G. Knepley PetscInt numZCells = 3; 1856006a8963SMatthew G. Knepley 18576858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 18586858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 18594fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1860006a8963SMatthew G. Knepley } 1861dbc1dc17SMatthew G. Knepley { 18629318fe57SMatthew G. Knepley DM cdm; 18639318fe57SMatthew G. Knepley PetscDS cds; 18649318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 1865dbc1dc17SMatthew G. Knepley 18669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder)); 18679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18689566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 18699566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 1870dbc1dc17SMatthew G. Knepley } 18719318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 18729566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 18730510c589SMatthew G. Knepley PetscFunctionReturn(0); 18740510c589SMatthew G. Knepley } 18750510c589SMatthew G. Knepley 187624119c2aSMatthew G. Knepley /*@ 18779318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 187824119c2aSMatthew G. Knepley 1879d083f849SBarry Smith Collective 188024119c2aSMatthew G. Knepley 188124119c2aSMatthew G. Knepley Input Parameters: 188224119c2aSMatthew G. Knepley + comm - The communicator for the DM object 18839318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction 188424119c2aSMatthew G. Knepley 188524119c2aSMatthew G. Knepley Output Parameter: 188624119c2aSMatthew G. Knepley . dm - The DM object 188724119c2aSMatthew G. Knepley 18889318fe57SMatthew G. Knepley Note: 18899318fe57SMatthew G. Knepley Here is the output numbering looking from the bottom of the cylinder: 18909318fe57SMatthew G. Knepley $ 17-----14 18919318fe57SMatthew G. Knepley $ | | 18929318fe57SMatthew G. Knepley $ | 2 | 18939318fe57SMatthew G. Knepley $ | | 18949318fe57SMatthew G. Knepley $ 17-----8-----7-----14 18959318fe57SMatthew G. Knepley $ | | | | 18969318fe57SMatthew G. Knepley $ | 3 | 0 | 1 | 18979318fe57SMatthew G. Knepley $ | | | | 18989318fe57SMatthew G. Knepley $ 19-----5-----6-----13 18999318fe57SMatthew G. Knepley $ | | 19009318fe57SMatthew G. Knepley $ | 4 | 19019318fe57SMatthew G. Knepley $ | | 19029318fe57SMatthew G. Knepley $ 19-----13 19039318fe57SMatthew G. Knepley $ 19049318fe57SMatthew G. Knepley $ and up through the top 19059318fe57SMatthew G. Knepley $ 19069318fe57SMatthew G. Knepley $ 18-----16 19079318fe57SMatthew G. Knepley $ | | 19089318fe57SMatthew G. Knepley $ | 2 | 19099318fe57SMatthew G. Knepley $ | | 19109318fe57SMatthew G. Knepley $ 18----10----11-----16 19119318fe57SMatthew G. Knepley $ | | | | 19129318fe57SMatthew G. Knepley $ | 3 | 0 | 1 | 19139318fe57SMatthew G. Knepley $ | | | | 19149318fe57SMatthew G. Knepley $ 20-----9----12-----15 19159318fe57SMatthew G. Knepley $ | | 19169318fe57SMatthew G. Knepley $ | 4 | 19179318fe57SMatthew G. Knepley $ | | 19189318fe57SMatthew G. Knepley $ 20-----15 19199318fe57SMatthew G. Knepley 192024119c2aSMatthew G. Knepley Level: beginner 192124119c2aSMatthew G. Knepley 1922db781477SPatrick Sanan .seealso: `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 192324119c2aSMatthew G. Knepley @*/ 1924d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm) 1925d71ae5a4SJacob Faibussowitsch { 19269318fe57SMatthew G. Knepley PetscFunctionBegin; 19279318fe57SMatthew G. Knepley PetscValidPointer(dm, 3); 19289566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 19299566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 19309566063dSJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ)); 19319318fe57SMatthew G. Knepley PetscFunctionReturn(0); 19329318fe57SMatthew G. Knepley } 19339318fe57SMatthew G. Knepley 1934d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 1935d71ae5a4SJacob Faibussowitsch { 193624119c2aSMatthew G. Knepley const PetscInt dim = 3; 1937412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 19389fe9f049SMatthew G. Knepley PetscMPIInt rank; 193924119c2aSMatthew G. Knepley 194024119c2aSMatthew G. Knepley PetscFunctionBegin; 194163a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 19429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 19439566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 1944412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 19459566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 194624119c2aSMatthew G. Knepley /* Create topology */ 194724119c2aSMatthew G. Knepley { 194824119c2aSMatthew G. Knepley PetscInt cone[6], c; 194924119c2aSMatthew G. Knepley 1950dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 1951dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 19529566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 19539566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 19549566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 195524119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 19569371c9d4SSatish Balay cone[0] = c + n * 1; 19579371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 19589371c9d4SSatish Balay cone[2] = 0 + 3 * n; 19599371c9d4SSatish Balay cone[3] = c + n * 2; 19609371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 19619371c9d4SSatish Balay cone[5] = 1 + 3 * n; 19629566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 19639566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 196424119c2aSMatthew G. Knepley } 19659566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 19669566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 196724119c2aSMatthew G. Knepley } 196848a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 196924119c2aSMatthew G. Knepley /* Create cylinder geometry */ 197024119c2aSMatthew G. Knepley { 197124119c2aSMatthew G. Knepley Vec coordinates; 197224119c2aSMatthew G. Knepley PetscSection coordSection; 197324119c2aSMatthew G. Knepley PetscScalar *coords; 1974412e9a14SMatthew G. Knepley PetscInt coordSize, c; 197524119c2aSMatthew G. Knepley 197624119c2aSMatthew G. Knepley /* Build coordinates */ 19779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 19789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 19799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 19809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 198124119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 19829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 19839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 198424119c2aSMatthew G. Knepley } 19859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 19869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 19879566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 19889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 19899566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 19909566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 19919566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 19929566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 199324119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 19949371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 19959371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 19969371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 19979371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 19989371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 19999371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 200024119c2aSMatthew G. Knepley } 2001dd400576SPatrick Sanan if (rank == 0) { 20029371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 20039371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 20049371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 20059371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 20069371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 20079371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 20089fe9f049SMatthew G. Knepley } 20099566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 20109566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 20119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 201224119c2aSMatthew G. Knepley } 20139318fe57SMatthew G. Knepley /* Interpolate */ 20149566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 20159318fe57SMatthew G. Knepley PetscFunctionReturn(0); 20169318fe57SMatthew G. Knepley } 20179318fe57SMatthew G. Knepley 20189318fe57SMatthew G. Knepley /*@ 20199318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 20209318fe57SMatthew G. Knepley 20219318fe57SMatthew G. Knepley Collective 20229318fe57SMatthew G. Knepley 20239318fe57SMatthew G. Knepley Input Parameters: 20249318fe57SMatthew G. Knepley + comm - The communicator for the DM object 20259318fe57SMatthew G. Knepley . n - The number of wedges around the origin 20269318fe57SMatthew G. Knepley - interpolate - Create edges and faces 20279318fe57SMatthew G. Knepley 20289318fe57SMatthew G. Knepley Output Parameter: 20299318fe57SMatthew G. Knepley . dm - The DM object 20309318fe57SMatthew G. Knepley 20319318fe57SMatthew G. Knepley Level: beginner 20329318fe57SMatthew G. Knepley 2033db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 20349318fe57SMatthew G. Knepley @*/ 2035d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 2036d71ae5a4SJacob Faibussowitsch { 20379318fe57SMatthew G. Knepley PetscFunctionBegin; 20389318fe57SMatthew G. Knepley PetscValidPointer(dm, 4); 20399566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 20409566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 20419566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 204224119c2aSMatthew G. Knepley PetscFunctionReturn(0); 204324119c2aSMatthew G. Knepley } 204424119c2aSMatthew G. Knepley 2045d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2046d71ae5a4SJacob Faibussowitsch { 204765a81367SMatthew G. Knepley PetscReal prod = 0.0; 204865a81367SMatthew G. Knepley PetscInt i; 204965a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 205065a81367SMatthew G. Knepley return PetscSqrtReal(prod); 205165a81367SMatthew G. Knepley } 2052d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(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 += x[i] * y[i]; 205765a81367SMatthew G. Knepley return prod; 205865a81367SMatthew G. Knepley } 205965a81367SMatthew G. Knepley 206051a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 2061d71ae5a4SJacob 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[]) 2062d71ae5a4SJacob Faibussowitsch { 206351a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 206451a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 206551a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 206651a74b61SMatthew G. Knepley 206751a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 206851a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 206951a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 207051a74b61SMatthew G. Knepley } 207151a74b61SMatthew G. Knepley 2072d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 2073d71ae5a4SJacob Faibussowitsch { 207465a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 207565a81367SMatthew G. Knepley PetscSection coordSection; 207665a81367SMatthew G. Knepley Vec coordinates; 207765a81367SMatthew G. Knepley PetscScalar *coords; 207865a81367SMatthew G. Knepley PetscReal *coordsIn; 2079064cae4fSPierre Jolivet PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, c, e; 208065a81367SMatthew G. Knepley PetscMPIInt rank; 208165a81367SMatthew G. Knepley 208265a81367SMatthew G. Knepley PetscFunctionBegin; 20839318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 20849566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 20859566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 20869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 208765a81367SMatthew G. Knepley switch (dim) { 208865a81367SMatthew G. Knepley case 2: 208965a81367SMatthew G. Knepley if (simplex) { 209051a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 209151a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 209265a81367SMatthew G. Knepley const PetscInt degree = 5; 209351a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 209465a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 209565a81367SMatthew G. Knepley PetscInt cone[3]; 209665a81367SMatthew G. Knepley PetscInt *graph, p, i, j, k; 209765a81367SMatthew G. Knepley 20989371c9d4SSatish Balay vertex[0] *= R / radius; 20999371c9d4SSatish Balay vertex[1] *= R / radius; 21009371c9d4SSatish Balay vertex[2] *= R / radius; 2101dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 2102dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 210365a81367SMatthew G. Knepley firstVertex = numCells; 210451a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 210565a81367SMatthew G. Knepley 210665a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 210765a81367SMatthew G. Knepley 210865a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 210951a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 211065a81367SMatthew G. Knepley */ 211165a81367SMatthew G. Knepley /* Construct vertices */ 21129566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2113dd400576SPatrick Sanan if (rank == 0) { 211465a81367SMatthew G. Knepley for (p = 0, i = 0; p < embedDim; ++p) { 211565a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 211665a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 211765a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 211865a81367SMatthew G. Knepley ++i; 211965a81367SMatthew G. Knepley } 212065a81367SMatthew G. Knepley } 212165a81367SMatthew G. Knepley } 212245da822fSValeria Barra } 212365a81367SMatthew G. Knepley /* Construct graph */ 21249566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 212565a81367SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 212665a81367SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 21279371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 21289371c9d4SSatish Balay graph[i * numVerts + j] = 1; 21299371c9d4SSatish Balay ++k; 21309371c9d4SSatish Balay } 213165a81367SMatthew G. Knepley } 213263a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 213365a81367SMatthew G. Knepley } 213465a81367SMatthew G. Knepley /* Build Topology */ 21359566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 213648a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 21379566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 213865a81367SMatthew G. Knepley /* Cells */ 213965a81367SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 214065a81367SMatthew G. Knepley for (j = 0; j < i; ++j) { 214165a81367SMatthew G. Knepley for (k = 0; k < j; ++k) { 214265a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 21439371c9d4SSatish Balay cone[0] = firstVertex + i; 21449371c9d4SSatish Balay cone[1] = firstVertex + j; 21459371c9d4SSatish Balay cone[2] = firstVertex + k; 214665a81367SMatthew G. Knepley /* Check orientation */ 214765a81367SMatthew G. Knepley { 21489371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 21499371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 21509371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 21519371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 21529371c9d4SSatish Balay }; 215365a81367SMatthew G. Knepley PetscReal normal[3]; 215465a81367SMatthew G. Knepley PetscInt e, f; 215565a81367SMatthew G. Knepley 215665a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 215765a81367SMatthew G. Knepley normal[d] = 0.0; 215865a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2159ad540459SPierre 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]); 216065a81367SMatthew G. Knepley } 216165a81367SMatthew G. Knepley } 21629371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 21639371c9d4SSatish Balay PetscInt tmp = cone[1]; 21649371c9d4SSatish Balay cone[1] = cone[2]; 21659371c9d4SSatish Balay cone[2] = tmp; 216665a81367SMatthew G. Knepley } 216765a81367SMatthew G. Knepley } 21689566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 216965a81367SMatthew G. Knepley } 217065a81367SMatthew G. Knepley } 217165a81367SMatthew G. Knepley } 217265a81367SMatthew G. Knepley } 21739566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 21749566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 21759566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 217665a81367SMatthew G. Knepley } else { 21772829fed8SMatthew G. Knepley /* 21782829fed8SMatthew G. Knepley 12-21--13 21792829fed8SMatthew G. Knepley | | 21802829fed8SMatthew G. Knepley 25 4 24 21812829fed8SMatthew G. Knepley | | 21822829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 21832829fed8SMatthew G. Knepley | | | | 21842829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 21852829fed8SMatthew G. Knepley | | | | 21862829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 21872829fed8SMatthew G. Knepley | | 21882829fed8SMatthew G. Knepley 20 1 19 21892829fed8SMatthew G. Knepley | | 21902829fed8SMatthew G. Knepley 10-18--11 21912829fed8SMatthew G. Knepley | | 21922829fed8SMatthew G. Knepley 23 2 22 21932829fed8SMatthew G. Knepley | | 21942829fed8SMatthew G. Knepley 12-21--13 21952829fed8SMatthew G. Knepley */ 21962829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 21972829fed8SMatthew G. Knepley 2198dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 2199dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 2200dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 220165a81367SMatthew G. Knepley firstVertex = numCells; 220265a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 22032829fed8SMatthew G. Knepley /* Build Topology */ 22049566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 220548a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 220648a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 22079566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2208dd400576SPatrick Sanan if (rank == 0) { 22092829fed8SMatthew G. Knepley /* Cell 0 */ 22109371c9d4SSatish Balay cone[0] = 14; 22119371c9d4SSatish Balay cone[1] = 15; 22129371c9d4SSatish Balay cone[2] = 16; 22139371c9d4SSatish Balay cone[3] = 17; 22149566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 22159371c9d4SSatish Balay ornt[0] = 0; 22169371c9d4SSatish Balay ornt[1] = 0; 22179371c9d4SSatish Balay ornt[2] = 0; 22189371c9d4SSatish Balay ornt[3] = 0; 22199566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 22202829fed8SMatthew G. Knepley /* Cell 1 */ 22219371c9d4SSatish Balay cone[0] = 18; 22229371c9d4SSatish Balay cone[1] = 19; 22239371c9d4SSatish Balay cone[2] = 14; 22249371c9d4SSatish Balay cone[3] = 20; 22259566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 22269371c9d4SSatish Balay ornt[0] = 0; 22279371c9d4SSatish Balay ornt[1] = 0; 22289371c9d4SSatish Balay ornt[2] = -1; 22299371c9d4SSatish Balay ornt[3] = 0; 22309566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 22312829fed8SMatthew G. Knepley /* Cell 2 */ 22329371c9d4SSatish Balay cone[0] = 21; 22339371c9d4SSatish Balay cone[1] = 22; 22349371c9d4SSatish Balay cone[2] = 18; 22359371c9d4SSatish Balay cone[3] = 23; 22369566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 22379371c9d4SSatish Balay ornt[0] = 0; 22389371c9d4SSatish Balay ornt[1] = 0; 22399371c9d4SSatish Balay ornt[2] = -1; 22409371c9d4SSatish Balay ornt[3] = 0; 22419566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 22422829fed8SMatthew G. Knepley /* Cell 3 */ 22439371c9d4SSatish Balay cone[0] = 19; 22449371c9d4SSatish Balay cone[1] = 22; 22459371c9d4SSatish Balay cone[2] = 24; 22469371c9d4SSatish Balay cone[3] = 15; 22479566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 22489371c9d4SSatish Balay ornt[0] = -1; 22499371c9d4SSatish Balay ornt[1] = -1; 22509371c9d4SSatish Balay ornt[2] = 0; 22519371c9d4SSatish Balay ornt[3] = -1; 22529566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 22532829fed8SMatthew G. Knepley /* Cell 4 */ 22549371c9d4SSatish Balay cone[0] = 16; 22559371c9d4SSatish Balay cone[1] = 24; 22569371c9d4SSatish Balay cone[2] = 21; 22579371c9d4SSatish Balay cone[3] = 25; 22589566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 22599371c9d4SSatish Balay ornt[0] = -1; 22609371c9d4SSatish Balay ornt[1] = -1; 22619371c9d4SSatish Balay ornt[2] = -1; 22629371c9d4SSatish Balay ornt[3] = 0; 22639566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 22642829fed8SMatthew G. Knepley /* Cell 5 */ 22659371c9d4SSatish Balay cone[0] = 20; 22669371c9d4SSatish Balay cone[1] = 17; 22679371c9d4SSatish Balay cone[2] = 25; 22689371c9d4SSatish Balay cone[3] = 23; 22699566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 22709371c9d4SSatish Balay ornt[0] = -1; 22719371c9d4SSatish Balay ornt[1] = -1; 22729371c9d4SSatish Balay ornt[2] = -1; 22739371c9d4SSatish Balay ornt[3] = -1; 22749566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 22752829fed8SMatthew G. Knepley /* Edges */ 22769371c9d4SSatish Balay cone[0] = 6; 22779371c9d4SSatish Balay cone[1] = 7; 22789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 22799371c9d4SSatish Balay cone[0] = 7; 22809371c9d4SSatish Balay cone[1] = 8; 22819566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 22829371c9d4SSatish Balay cone[0] = 8; 22839371c9d4SSatish Balay cone[1] = 9; 22849566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 22859371c9d4SSatish Balay cone[0] = 9; 22869371c9d4SSatish Balay cone[1] = 6; 22879566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 22889371c9d4SSatish Balay cone[0] = 10; 22899371c9d4SSatish Balay cone[1] = 11; 22909566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 22919371c9d4SSatish Balay cone[0] = 11; 22929371c9d4SSatish Balay cone[1] = 7; 22939566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 22949371c9d4SSatish Balay cone[0] = 6; 22959371c9d4SSatish Balay cone[1] = 10; 22969566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 22979371c9d4SSatish Balay cone[0] = 12; 22989371c9d4SSatish Balay cone[1] = 13; 22999566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 23009371c9d4SSatish Balay cone[0] = 13; 23019371c9d4SSatish Balay cone[1] = 11; 23029566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 23039371c9d4SSatish Balay cone[0] = 10; 23049371c9d4SSatish Balay cone[1] = 12; 23059566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 23069371c9d4SSatish Balay cone[0] = 13; 23079371c9d4SSatish Balay cone[1] = 8; 23089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 23099371c9d4SSatish Balay cone[0] = 12; 23109371c9d4SSatish Balay cone[1] = 9; 23119566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 231245da822fSValeria Barra } 23139566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 23149566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 23152829fed8SMatthew G. Knepley /* Build coordinates */ 23169566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2317dd400576SPatrick Sanan if (rank == 0) { 23189371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 23199371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 23209371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 23219371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 23229371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 23239371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 23249371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 23259371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 23269371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 23279371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 23289371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 23299371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 23309371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 23319371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 23329371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 23339371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 23349371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 23359371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 23369371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 23379371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 23389371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 23399371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 23409371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 23419371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 234265a81367SMatthew G. Knepley } 234345da822fSValeria Barra } 234465a81367SMatthew G. Knepley break; 234565a81367SMatthew G. Knepley case 3: 2346116ded15SMatthew G. Knepley if (simplex) { 2347116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 234851a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 234951a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 235051a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 2351116ded15SMatthew G. Knepley const PetscInt degree = 12; 2352116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 23539371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 23549371c9d4SSatish Balay {0, 1, 2, 3}, 23559371c9d4SSatish Balay {0, 2, 3, 1}, 23569371c9d4SSatish Balay {0, 3, 1, 2}, 23579371c9d4SSatish Balay {1, 0, 3, 2}, 23589371c9d4SSatish Balay {1, 2, 0, 3}, 23599371c9d4SSatish Balay {1, 3, 2, 0}, 23609371c9d4SSatish Balay {2, 0, 1, 3}, 23619371c9d4SSatish Balay {2, 1, 3, 0}, 23629371c9d4SSatish Balay {2, 3, 0, 1}, 23639371c9d4SSatish Balay {3, 0, 2, 1}, 23649371c9d4SSatish Balay {3, 1, 0, 2}, 23659371c9d4SSatish Balay {3, 2, 1, 0} 23669371c9d4SSatish Balay }; 2367116ded15SMatthew G. Knepley PetscInt cone[4]; 2368116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 2369116ded15SMatthew G. Knepley 23709371c9d4SSatish Balay vertexA[0] *= R; 23719371c9d4SSatish Balay vertexA[1] *= R; 23729371c9d4SSatish Balay vertexA[2] *= R; 23739371c9d4SSatish Balay vertexA[3] *= R; 23749371c9d4SSatish Balay vertexB[0] *= R; 23759371c9d4SSatish Balay vertexB[1] *= R; 23769371c9d4SSatish Balay vertexB[2] *= R; 23779371c9d4SSatish Balay vertexB[3] *= R; 23789371c9d4SSatish Balay vertexC[0] *= R; 23799371c9d4SSatish Balay vertexC[1] *= R; 23809371c9d4SSatish Balay vertexC[2] *= R; 23819371c9d4SSatish Balay vertexC[3] *= R; 2382dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 2383dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 2384116ded15SMatthew G. Knepley firstVertex = numCells; 2385116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 2386116ded15SMatthew G. Knepley 2387116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 2388116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 2389116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 2390116ded15SMatthew G. Knepley 2391116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 23926333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 2393116ded15SMatthew G. Knepley 2394116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 2395116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 2396116ded15SMatthew G. Knepley */ 2397116ded15SMatthew G. Knepley /* Construct vertices */ 23989566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2399116ded15SMatthew G. Knepley i = 0; 2400dd400576SPatrick Sanan if (rank == 0) { 2401116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2402116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2403116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2404116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 2405116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 2406116ded15SMatthew G. Knepley ++i; 2407116ded15SMatthew G. Knepley } 2408116ded15SMatthew G. Knepley } 2409116ded15SMatthew G. Knepley } 2410116ded15SMatthew G. Knepley } 2411116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 2412116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 2413116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2414116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 2415116ded15SMatthew G. Knepley ++i; 2416116ded15SMatthew G. Knepley } 2417116ded15SMatthew G. Knepley } 2418116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 2419116ded15SMatthew G. Knepley s[3] = 1; 2420116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2421116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2422116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2423116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 2424116ded15SMatthew G. Knepley ++i; 2425116ded15SMatthew G. Knepley } 2426116ded15SMatthew G. Knepley } 2427116ded15SMatthew G. Knepley } 2428116ded15SMatthew G. Knepley } 242945da822fSValeria Barra } 243063a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 2431116ded15SMatthew G. Knepley /* Construct graph */ 24329566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 2433116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 2434116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 24359371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 24369371c9d4SSatish Balay graph[i * numVerts + j] = 1; 24379371c9d4SSatish Balay ++k; 24389371c9d4SSatish Balay } 2439116ded15SMatthew G. Knepley } 244063a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 2441116ded15SMatthew G. Knepley } 2442116ded15SMatthew G. Knepley /* Build Topology */ 24439566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 244448a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 24459566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 2446116ded15SMatthew G. Knepley /* Cells */ 2447dd400576SPatrick Sanan if (rank == 0) { 2448116ded15SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 2449116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 2450116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 2451116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 24529371c9d4SSatish 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]) { 24539371c9d4SSatish Balay cone[0] = firstVertex + i; 24549371c9d4SSatish Balay cone[1] = firstVertex + j; 24559371c9d4SSatish Balay cone[2] = firstVertex + k; 24569371c9d4SSatish Balay cone[3] = firstVertex + l; 2457116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 2458116ded15SMatthew G. Knepley { 24599371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 24609371c9d4SSatish 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}}}, 2461116ded15SMatthew G. Knepley 24629371c9d4SSatish 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}}}, 2463116ded15SMatthew G. Knepley 24649371c9d4SSatish 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}}}, 2465116ded15SMatthew G. Knepley 24669371c9d4SSatish 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}} } 24679371c9d4SSatish Balay }; 2468116ded15SMatthew G. Knepley PetscReal normal[4]; 2469116ded15SMatthew G. Knepley PetscInt e, f, g; 2470116ded15SMatthew G. Knepley 2471116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 2472116ded15SMatthew G. Knepley normal[d] = 0.0; 2473116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2474116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 2475116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 2476116ded15SMatthew 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]); 2477116ded15SMatthew G. Knepley } 2478116ded15SMatthew G. Knepley } 2479116ded15SMatthew G. Knepley } 2480116ded15SMatthew G. Knepley } 24819371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 24829371c9d4SSatish Balay PetscInt tmp = cone[1]; 24839371c9d4SSatish Balay cone[1] = cone[2]; 24849371c9d4SSatish Balay cone[2] = tmp; 24859371c9d4SSatish Balay } 2486116ded15SMatthew G. Knepley } 24879566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 2488116ded15SMatthew G. Knepley } 2489116ded15SMatthew G. Knepley } 2490116ded15SMatthew G. Knepley } 2491116ded15SMatthew G. Knepley } 2492116ded15SMatthew G. Knepley } 249345da822fSValeria Barra } 24949566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 24959566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 24969566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 2497116ded15SMatthew G. Knepley } 2498f4d061e9SPierre Jolivet break; 2499d71ae5a4SJacob Faibussowitsch default: 2500d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 250165a81367SMatthew G. Knepley } 250265a81367SMatthew G. Knepley /* Create coordinates */ 25039566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 25049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 25059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 25069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 25072829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 25089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 25099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 25102829fed8SMatthew G. Knepley } 25119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 25129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 25139566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 25149566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 25159566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 25169566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 25179566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 25189566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 25199371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 2520ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 25219566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 25229566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 25239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 25249566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 252551a74b61SMatthew G. Knepley { 252651a74b61SMatthew G. Knepley DM cdm; 252751a74b61SMatthew G. Knepley PetscDS cds; 25289318fe57SMatthew G. Knepley PetscScalar c = R; 252951a74b61SMatthew G. Knepley 25309566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere)); 25319566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 25329566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 25339566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 253451a74b61SMatthew G. Knepley } 25359318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 25369566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 25379318fe57SMatthew G. Knepley PetscFunctionReturn(0); 25389318fe57SMatthew G. Knepley } 25399318fe57SMatthew G. Knepley 2540b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 2541b7f5c055SJed Brown 2542b7f5c055SJed Brown /* 2543b7f5c055SJed Brown The Schwarz P implicit surface is 2544b7f5c055SJed Brown 2545b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 2546b7f5c055SJed Brown */ 2547d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2548d71ae5a4SJacob Faibussowitsch { 2549b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 2550b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 2551b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 2552b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2553b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 2554ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 2555b7f5c055SJed Brown } 2556b7f5c055SJed Brown } 2557b7f5c055SJed Brown 25584663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 2559d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 2560d71ae5a4SJacob Faibussowitsch { 2561ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 25624663dae6SJed Brown return 0; 25634663dae6SJed Brown } 25644663dae6SJed Brown 2565b7f5c055SJed Brown /* 2566b7f5c055SJed Brown The Gyroid implicit surface is 2567b7f5c055SJed Brown 2568b7f5c055SJed 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) 2569b7f5c055SJed Brown 2570b7f5c055SJed Brown */ 2571d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2572d71ae5a4SJacob Faibussowitsch { 2573b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 2574b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 2575b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 2576b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 2577b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 2578b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 2579b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 2580b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2581b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2582b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 2583b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2584b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2585b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 2586b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2587b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2588b7f5c055SJed Brown } 2589b7f5c055SJed Brown 25904663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 2591d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 2592d71ae5a4SJacob Faibussowitsch { 25934663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 25944663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 25954663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 25964663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 25974663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 25984663dae6SJed Brown return 0; 25994663dae6SJed Brown } 26004663dae6SJed Brown 2601b7f5c055SJed Brown /* 2602b7f5c055SJed Brown We wish to solve 2603b7f5c055SJed Brown 2604b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 2605b7f5c055SJed Brown 2606b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 2607b7f5c055SJed 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 2608b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 2609b7f5c055SJed Brown 2610b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 2611b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 2612b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 2613b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 2614b7f5c055SJed Brown Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries. 2615b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 2616b7f5c055SJed Brown 2617b7f5c055SJed Brown f(y) = 0 1 equation 2618b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 2619b7f5c055SJed Brown 2620b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 2621b7f5c055SJed Brown */ 2622d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 2623d71ae5a4SJacob Faibussowitsch { 2624b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 2625b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 26262f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 26279371c9d4SSatish Balay PetscReal n_y[3][3] = { 26289371c9d4SSatish Balay {0, 0, 0}, 26299371c9d4SSatish Balay {0, 0, 0}, 26309371c9d4SSatish Balay {0, 0, 0} 26319371c9d4SSatish Balay }; 2632b7f5c055SJed Brown 2633b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 2634b7f5c055SJed Brown 2635b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 2636b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2637ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 2638b7f5c055SJed Brown 2639b7f5c055SJed Brown // Define the Householder reflector 2640b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 2641b7f5c055SJed Brown n[0] += norm * sign; 2642b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 2643b7f5c055SJed Brown 2644b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2645b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 2646b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 2647b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 2648b7f5c055SJed Brown 2649b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 2650b7f5c055SJed Brown n[i] /= norm; 2651b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2652b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 2653b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 2654b7f5c055SJed Brown } 2655b7f5c055SJed Brown } 2656b7f5c055SJed Brown 2657b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 2658b7f5c055SJed 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]; 2659b7f5c055SJed Brown 2660b7f5c055SJed Brown res[0] = f; 2661b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 2662b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 2663b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 2664b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 2665b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 2666b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 2667b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 2668b7f5c055SJed Brown } 2669b7f5c055SJed Brown } 2670b7f5c055SJed Brown 2671b7f5c055SJed Brown /* 2672b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 2673b7f5c055SJed Brown */ 2674d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 2675d71ae5a4SJacob Faibussowitsch { 2676b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 2677b7f5c055SJed Brown 2678b7f5c055SJed Brown PetscFunctionBegin; 2679b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 2680b7f5c055SJed Brown PetscScalar res[3], J[9]; 2681b7f5c055SJed Brown PetscReal resnorm; 2682b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 2683b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 2684b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 268563a3b9bcSJacob 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]))); 2686b7f5c055SJed Brown } 2687b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 2688b7f5c055SJed Brown 2689b7f5c055SJed Brown // Take the Newton step 26909566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 2691b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 2692b7f5c055SJed Brown } 2693b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 2694b7f5c055SJed Brown PetscFunctionReturn(0); 2695b7f5c055SJed Brown } 2696b7f5c055SJed Brown 2697b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 2698b7f5c055SJed Brown 2699d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 2700d71ae5a4SJacob Faibussowitsch { 2701b7f5c055SJed Brown PetscMPIInt rank; 2702b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 2703b7f5c055SJed Brown PetscInt(*edges)[2] = NULL, *edgeSets = NULL; 2704b7f5c055SJed Brown PetscInt *cells_flat = NULL; 2705b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 2706b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 27074663dae6SJed Brown PetscSimplePointFunc normalFunc = NULL; 2708b7f5c055SJed Brown DMLabel label; 2709b7f5c055SJed Brown 2710b7f5c055SJed Brown PetscFunctionBegin; 27119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 271263a3b9bcSJacob 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); 2713b7f5c055SJed Brown switch (tpstype) { 2714b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 2715b7f5c055SJed 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"); 2716c5853193SPierre Jolivet if (rank == 0) { 2717b7f5c055SJed Brown PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 2718b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 2719b7f5c055SJed Brown PetscReal L = 1; 2720b7f5c055SJed Brown 2721b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 2722b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 2723b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 2724b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 2725b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 2726b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 27279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 27289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 27299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 27309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 2731b7f5c055SJed Brown // x-normal pipes 2732b7f5c055SJed Brown vcount = 0; 2733b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 2734b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2735b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2736b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2737b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 2738b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2739b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2740b7f5c055SJed Brown } 2741b7f5c055SJed Brown } 2742b7f5c055SJed Brown } 2743b7f5c055SJed Brown } 2744b7f5c055SJed Brown // y-normal pipes 2745b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2746b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 2747b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2748b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2749b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2750b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 2751b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2752b7f5c055SJed Brown } 2753b7f5c055SJed Brown } 2754b7f5c055SJed Brown } 2755b7f5c055SJed Brown } 2756b7f5c055SJed Brown // z-normal pipes 2757b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2758b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2759b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 2760b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 2761b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2762b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 2763b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 2764b7f5c055SJed Brown } 2765b7f5c055SJed Brown } 2766b7f5c055SJed Brown } 2767b7f5c055SJed Brown } 2768b7f5c055SJed Brown // junctions 2769b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2770b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2771b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2772b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 2773b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 2774b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 2775b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 2776b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 2777b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 2778b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 2779b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 2780b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 2781b7f5c055SJed Brown } 2782b7f5c055SJed Brown } 2783b7f5c055SJed Brown } 2784b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 2785b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 2786b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 2787b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 2788b7f5c055SJed Brown }; 2789b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 27909371c9d4SSatish 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}; 2791b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 27929371c9d4SSatish 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}; 2793b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 2794b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 2795b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 2796b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 2797b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 2798b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 2799b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 2800b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 2801b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 2802b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 2803b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 2804b7f5c055SJed Brown if (ijk[dir] == 0) { 2805b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 2806b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 2807b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 2808b7f5c055SJed Brown numEdges++; 2809b7f5c055SJed Brown } 2810b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 2811b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 2812b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 2813b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 2814b7f5c055SJed Brown numEdges++; 2815b7f5c055SJed Brown } 2816b7f5c055SJed Brown } 2817b7f5c055SJed Brown } 2818b7f5c055SJed Brown } 2819b7f5c055SJed Brown } 2820b7f5c055SJed Brown } 282163a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 2822b7f5c055SJed Brown numFaces = 24 * Njunctions; 2823b7f5c055SJed Brown cells_flat = cells[0][0][0]; 2824b7f5c055SJed Brown } 2825b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 28264663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 2827b7f5c055SJed Brown break; 2828b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 2829c5853193SPierre Jolivet if (rank == 0) { 2830b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 2831b7f5c055SJed Brown // 2832b7f5c055SJed 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) 2833b7f5c055SJed Brown // 2834b7f5c055SJed Brown // on the cell [0,2]^3. 2835b7f5c055SJed Brown // 2836b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 2837b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 2838b7f5c055SJed Brown // like a boomerang: 2839b7f5c055SJed Brown // 2840b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 2841b7f5c055SJed Brown // ----- ------- ------- ------- // 2842b7f5c055SJed Brown // // 2843b7f5c055SJed Brown // + + + + + + + \ + // 2844b7f5c055SJed Brown // \ / \ // 2845b7f5c055SJed Brown // \ `-_ _-' / } // 2846b7f5c055SJed Brown // *-_ `-' _-' / // 2847b7f5c055SJed Brown // + `-+ + + +-' + + / + // 2848b7f5c055SJed Brown // // 2849b7f5c055SJed Brown // // 2850b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 2851b7f5c055SJed Brown // ----- ------- ------- ------- // 2852b7f5c055SJed Brown // // 2853b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 2854b7f5c055SJed Brown // `-_ _-_ _-` / // 2855b7f5c055SJed Brown // \ _-' `-_ / { // 2856b7f5c055SJed Brown // \ / \ // 2857b7f5c055SJed Brown // + + + + + + + \ + // 2858b7f5c055SJed Brown // 2859b7f5c055SJed Brown // 2860b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 2861b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 2862b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 2863b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 2864b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 2865b7f5c055SJed Brown // 2866b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 2867b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 2868b7f5c055SJed Brown // 2869b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 2870b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 2871b7f5c055SJed Brown 2872b7f5c055SJed Brown PetscInt facesPerBlock = 64; 2873b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 2874b7f5c055SJed Brown PetscInt extentPlus[3]; 2875b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 28769371c9d4SSatish 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; 28779371c9d4SSatish Balay const PetscInt pattern[64][4] = { 28789371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 2879b7f5c055SJed Brown /* layer 0 */ 28809371c9d4SSatish Balay {A, C, K, G }, 28819371c9d4SSatish Balay {C, B, II, K }, 28829371c9d4SSatish Balay {D, A, H, L }, 28839371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 28849371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 28859371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 28869371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 28879371c9d4SSatish Balay {B, F, M, II }, 2888b7f5c055SJed Brown /* layer 1 */ 28899371c9d4SSatish Balay {G, K, Q, O }, 28909371c9d4SSatish Balay {K, II, P, Q }, 28919371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 28929371c9d4SSatish Balay {J, L, R, P }, 28939371c9d4SSatish Balay {N, J, P, S }, 28949371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 28959371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 28969371c9d4SSatish Balay {II, M, T, P }, 2897b7f5c055SJed Brown /* layer 2 */ 28989371c9d4SSatish Balay {O, Q, Y, U }, 28999371c9d4SSatish Balay {Q, P, W, Y }, 29009371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 29019371c9d4SSatish Balay {P, R, Ap, W }, 29029371c9d4SSatish Balay {S, P, X, Bp }, 29039371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 29049371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 29059371c9d4SSatish Balay {P, T, Z, X }, 2906b7f5c055SJed Brown /* layer 3 */ 29079371c9d4SSatish Balay {U, Y, Ep, Dp }, 29089371c9d4SSatish Balay {Y, W, Cp, Ep }, 29099371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 29109371c9d4SSatish Balay {W, Ap, Gp, Cp }, 29119371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 29129371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 29139371c9d4SSatish Balay {Z, V, Dp, Hp }, 29149371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 2915b7f5c055SJed Brown /* layer 4 */ 29169371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 29179371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 29189371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 29199371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 29209371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 29219371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 29229371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 29239371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 2924b7f5c055SJed Brown /* layer 5 */ 29259371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 29269371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 29279371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 29289371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 29299371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 29309371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 29319371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 29329371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 2933b7f5c055SJed Brown /* layer 6 */ 29349371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 29359371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 29369371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 29379371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 29389371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 29399371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 29409371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 29419371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 2942b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 29439371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 29449371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 29459371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 29469371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 29479371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 29489371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 29499371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 29509371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 2951b7f5c055SJed Brown }; 2952b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 29539371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 2954bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 2955bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 2956bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 2957bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 2958bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 2959bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 2960b7f5c055SJed Brown 2961bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 2962bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 2963bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 2964bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 2965bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 2966bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 2967bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 2968bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 2969b7f5c055SJed Brown 2970bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 2971bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 2972bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 2973bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 2974bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 2975bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 2976b7f5c055SJed Brown 2977bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 2978bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 2979bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 2980bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 2981bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 2982bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 2983bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 2984bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 2985b7f5c055SJed Brown 2986bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 2987bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 2988bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 2989bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 2990bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 2991bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 2992b7f5c055SJed Brown 2993bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 2994bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 2995bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 2996bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 2997bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 2998bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 2999bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 3000bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 3001b7f5c055SJed Brown 3002bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 3003bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 3004bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 3005bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 3006bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 3007bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 3008b7f5c055SJed Brown 3009bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 3010bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 3011bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 3012bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 3013bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 3014bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 3015bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 3016bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 3017b7f5c055SJed Brown }; 3018b7f5c055SJed Brown PetscInt(*cells)[64][4] = NULL; 3019b7f5c055SJed Brown PetscBool *seen; 3020b7f5c055SJed Brown PetscInt *vertToTrueVert; 3021b7f5c055SJed Brown PetscInt count; 3022b7f5c055SJed Brown 3023b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 3024b7f5c055SJed Brown numBlocks = 1; 3025b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 3026b7f5c055SJed Brown numBlocksPlus = 1; 3027b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 3028b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 30299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 30309566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 3031b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3032b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3033b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3034b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3035b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 3036b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 3037b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 3038b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 3039b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 3040b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 3041b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 3042b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 3043b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 3044b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 3045b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 3046b7f5c055SJed Brown 3047b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 3048b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 3049b7f5c055SJed Brown } 3050b7f5c055SJed Brown } 3051b7f5c055SJed Brown } 3052b7f5c055SJed Brown } 3053b7f5c055SJed Brown } 30549371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 30559371c9d4SSatish Balay if (seen[i]) numVertices++; 3056b7f5c055SJed Brown count = 0; 30579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 30589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 3059b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 3060b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 3061b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 3062b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 3063b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 3064b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 3065b7f5c055SJed Brown 3066b7f5c055SJed Brown if (seen[vIdx]) { 3067b7f5c055SJed Brown PetscInt thisVert; 3068b7f5c055SJed Brown 3069b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 3070b7f5c055SJed Brown 3071b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 3072b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 3073b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 3074b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 3075b7f5c055SJed Brown } 3076b7f5c055SJed Brown } 3077b7f5c055SJed Brown } 3078b7f5c055SJed Brown } 3079b7f5c055SJed Brown } 3080b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 3081b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3082ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 3083b7f5c055SJed Brown } 3084b7f5c055SJed Brown } 30859566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 30869566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 3087b7f5c055SJed Brown cells_flat = cells[0][0]; 3088b7f5c055SJed Brown numEdges = 0; 3089b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 3090b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3091b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3092b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3093b7f5c055SJed Brown 3094b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3095b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 3096b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 3097b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 3098b7f5c055SJed Brown } 3099b7f5c055SJed Brown } 3100b7f5c055SJed Brown } 3101b7f5c055SJed Brown } 31029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 31039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 3104b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 3105b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3106b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3107b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3108b7f5c055SJed Brown 3109b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3110b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 3111b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 3112b7f5c055SJed Brown edges[edge][0] = ev[0]; 3113b7f5c055SJed Brown edges[edge][1] = ev[1]; 3114b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 3115b7f5c055SJed Brown } 3116b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 3117b7f5c055SJed Brown edges[edge][0] = ev[0]; 3118b7f5c055SJed Brown edges[edge][1] = ev[1]; 3119b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 3120b7f5c055SJed Brown } 3121b7f5c055SJed Brown } 3122b7f5c055SJed Brown } 3123b7f5c055SJed Brown } 3124b7f5c055SJed Brown } 3125b7f5c055SJed Brown } 3126b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 31274663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 3128b7f5c055SJed Brown break; 3129b7f5c055SJed Brown } 3130b7f5c055SJed Brown 31319566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 3132c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 31339566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 31349566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 3135b7f5c055SJed Brown { 3136b7f5c055SJed Brown DM idm; 31379566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 313869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3139b7f5c055SJed Brown } 3140c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 31419566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 31429566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 3143b7f5c055SJed Brown 31449566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 31459566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 3146b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 3147b7f5c055SJed Brown PetscInt njoin; 3148b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 31499566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 315063a3b9bcSJacob 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]); 31519566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 31529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 3153b7f5c055SJed Brown } 31549566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 31559566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 31561436d7faSJed Brown if (tps_distribute) { 31571436d7faSJed Brown DM pdm = NULL; 31581436d7faSJed Brown PetscPartitioner part; 31591436d7faSJed Brown 31609566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 31619566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 31629566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 316348a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 31641436d7faSJed Brown // Do not auto-distribute again 31659566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 31661436d7faSJed Brown } 3167b7f5c055SJed Brown 31689566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 3169b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 3170b7f5c055SJed Brown PetscInt m; 3171b7f5c055SJed Brown DM dmf; 3172b7f5c055SJed Brown Vec X; 3173b7f5c055SJed Brown PetscScalar *x; 31749566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 317569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 3176b7f5c055SJed Brown 31779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 31789566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 31799566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 318048a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 31819566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 3182b7f5c055SJed Brown } 3183b7f5c055SJed Brown 3184b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 31859566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 31869566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 3187b7f5c055SJed Brown 3188b7f5c055SJed Brown if (thickness > 0) { 31894663dae6SJed Brown DM edm, cdm, ecdm; 31904663dae6SJed Brown DMPlexTransform tr; 31914663dae6SJed Brown const char *prefix; 31924663dae6SJed Brown PetscOptions options; 31934663dae6SJed Brown // Code from DMPlexExtrude 31944663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 31954663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 31964663dae6SJed Brown PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE)); 31974663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 31984663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 31994663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 32004663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 32014663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 32024663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 32034663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 32044663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 32054663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 32064663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 32074663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 32084663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 32094663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 32104663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 32114663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 32124663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 32134663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 32144663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 32154663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 32164663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 32174663dae6SJed Brown if (edm) { 32184663dae6SJed Brown ((DM_Plex *)edm->data)->printFEM = ((DM_Plex *)dm->data)->printFEM; 32194663dae6SJed Brown ((DM_Plex *)edm->data)->printL2 = ((DM_Plex *)dm->data)->printL2; 3220f5867de0SMatthew G. Knepley ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate; 32214663dae6SJed Brown } 322269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 3223b7f5c055SJed Brown } 3224b7f5c055SJed Brown PetscFunctionReturn(0); 3225b7f5c055SJed Brown } 3226b7f5c055SJed Brown 3227b7f5c055SJed Brown /*@ 3228b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 3229b7f5c055SJed Brown 3230b7f5c055SJed Brown Collective 3231b7f5c055SJed Brown 3232b7f5c055SJed Brown Input Parameters: 3233b7f5c055SJed Brown + comm - The communicator for the DM object 3234b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 3235b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 3236b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic 32371436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 3238817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 32391436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 3240817da375SSatish Balay - thickness - Thickness in normal direction 3241b7f5c055SJed Brown 3242b7f5c055SJed Brown Output Parameter: 3243b7f5c055SJed Brown . dm - The DM object 3244b7f5c055SJed Brown 3245b7f5c055SJed Brown Notes: 3246b7f5c055SJed 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. 3247b7f5c055SJed Brown https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries. 3248b7f5c055SJed 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. 3249b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 3250b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 3251b7f5c055SJed Brown This projection could readily be extended to related surfaces. 3252b7f5c055SJed Brown 3253b7f5c055SJed Brown The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z). 3254b7f5c055SJed Brown When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). Use DMPlexLabelComplete() to propagate to coarse-level vertices. 3255b7f5c055SJed Brown 3256b7f5c055SJed Brown References: 3257606c0280SSatish Balay . * - Maskery et al, Insights into the mechanical properties of several triply periodic minimal surface lattice structures made by polymer additive manufacturing, 2017. https://doi.org/10.1016/j.polymer.2017.11.049 3258b7f5c055SJed Brown 3259b7f5c055SJed Brown Developer Notes: 3260b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 3261b7f5c055SJed Brown 3262b7f5c055SJed Brown Level: beginner 3263b7f5c055SJed Brown 3264db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 3265b7f5c055SJed Brown @*/ 3266d71ae5a4SJacob 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) 3267d71ae5a4SJacob Faibussowitsch { 3268b7f5c055SJed Brown PetscFunctionBegin; 32699566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 32709566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 32719566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 3272b7f5c055SJed Brown PetscFunctionReturn(0); 3273b7f5c055SJed Brown } 3274b7f5c055SJed Brown 32759318fe57SMatthew G. Knepley /*@ 32769318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 32779318fe57SMatthew G. Knepley 32789318fe57SMatthew G. Knepley Collective 32799318fe57SMatthew G. Knepley 32809318fe57SMatthew G. Knepley Input Parameters: 32819318fe57SMatthew G. Knepley + comm - The communicator for the DM object 32829318fe57SMatthew G. Knepley . dim - The dimension 32839318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 32849318fe57SMatthew G. Knepley - R - The radius 32859318fe57SMatthew G. Knepley 32869318fe57SMatthew G. Knepley Output Parameter: 32879318fe57SMatthew G. Knepley . dm - The DM object 32889318fe57SMatthew G. Knepley 32899318fe57SMatthew G. Knepley Level: beginner 32909318fe57SMatthew G. Knepley 3291db781477SPatrick Sanan .seealso: `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 32929318fe57SMatthew G. Knepley @*/ 3293d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 3294d71ae5a4SJacob Faibussowitsch { 32959318fe57SMatthew G. Knepley PetscFunctionBegin; 32969318fe57SMatthew G. Knepley PetscValidPointer(dm, 5); 32979566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 32989566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 32999566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 33009318fe57SMatthew G. Knepley PetscFunctionReturn(0); 33019318fe57SMatthew G. Knepley } 33029318fe57SMatthew G. Knepley 3303d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 3304d71ae5a4SJacob Faibussowitsch { 33059318fe57SMatthew G. Knepley DM sdm, vol; 33069318fe57SMatthew G. Knepley DMLabel bdlabel; 33079318fe57SMatthew G. Knepley 33089318fe57SMatthew G. Knepley PetscFunctionBegin; 33099566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 33109566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 33119566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_")); 33129566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 33139566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 33149566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 33159566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 33169566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 331769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 33189566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 33199566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 33209566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 33219566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 332251a74b61SMatthew G. Knepley PetscFunctionReturn(0); 332351a74b61SMatthew G. Knepley } 332451a74b61SMatthew G. Knepley 332551a74b61SMatthew G. Knepley /*@ 332651a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 332751a74b61SMatthew G. Knepley 332851a74b61SMatthew G. Knepley Collective 332951a74b61SMatthew G. Knepley 333051a74b61SMatthew G. Knepley Input Parameters: 333151a74b61SMatthew G. Knepley + comm - The communicator for the DM object 333251a74b61SMatthew G. Knepley . dim - The dimension 333351a74b61SMatthew G. Knepley - R - The radius 333451a74b61SMatthew G. Knepley 333551a74b61SMatthew G. Knepley Output Parameter: 333651a74b61SMatthew G. Knepley . dm - The DM object 333751a74b61SMatthew G. Knepley 333851a74b61SMatthew G. Knepley Options Database Keys: 333951a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 334051a74b61SMatthew G. Knepley 334151a74b61SMatthew G. Knepley Level: beginner 334251a74b61SMatthew G. Knepley 3343db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 334451a74b61SMatthew G. Knepley @*/ 3345d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 3346d71ae5a4SJacob Faibussowitsch { 334751a74b61SMatthew G. Knepley PetscFunctionBegin; 33489566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 33499566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 33509566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 33512829fed8SMatthew G. Knepley PetscFunctionReturn(0); 33522829fed8SMatthew G. Knepley } 33532829fed8SMatthew G. Knepley 3354d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 3355d71ae5a4SJacob Faibussowitsch { 33560a6ba040SMatthew G. Knepley PetscFunctionBegin; 33579318fe57SMatthew G. Knepley switch (ct) { 33589371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 33599318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 33609318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 33619318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 33629318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 33639318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 33649318fe57SMatthew G. Knepley 33659566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 33669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33679371c9d4SSatish Balay } break; 33689371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 33699318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 33709318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 33719318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 33729318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 33739318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 33749318fe57SMatthew G. Knepley 33759566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 33769566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33779371c9d4SSatish Balay } break; 33789371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 3379b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 3380b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 3381b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 3382b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 3383b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 3384b5a892a1SMatthew G. Knepley 33859566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 33869566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33879371c9d4SSatish Balay } break; 33889371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 33899318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 33909318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 33919318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 33929318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 33939318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 33949318fe57SMatthew G. Knepley 33959566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 33969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 33979371c9d4SSatish Balay } break; 33989371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 33999318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 34009318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 34019318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 34029318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 34039318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 34049318fe57SMatthew G. Knepley 34059566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 34069566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34079371c9d4SSatish Balay } break; 34089371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 34099318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 34109318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 34119318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 34129318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 34139318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 34149318fe57SMatthew G. Knepley 34159566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 34169566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34179371c9d4SSatish Balay } break; 34189371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 34199318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 34209318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 3421f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 34229318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 3423f0edb160SMatthew 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}; 34249318fe57SMatthew G. Knepley 34259566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34269566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34279371c9d4SSatish Balay } break; 34289371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 34299318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 34309318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 3431f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 34329318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34339371c9d4SSatish 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}; 34349318fe57SMatthew G. Knepley 34359566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34379371c9d4SSatish Balay } break; 34389371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 34399318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 34409318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 3441f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 34429318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 34439371c9d4SSatish Balay PetscScalar vertexCoords[18] = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0}; 34449318fe57SMatthew G. Knepley 34459566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34479371c9d4SSatish Balay } break; 34489371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 34499318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 34509318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 34519318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 34529318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 34539371c9d4SSatish 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}; 34549318fe57SMatthew G. Knepley 34559566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34569566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34579371c9d4SSatish Balay } break; 34589371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 34599318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 34609318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 34619318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 34629318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34639371c9d4SSatish Balay PetscScalar vertexCoords[24] = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; 34649318fe57SMatthew G. Knepley 34659566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34679371c9d4SSatish Balay } break; 34689371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 34699318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 34709318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 3471f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 34729318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 34739371c9d4SSatish 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}; 34749318fe57SMatthew G. Knepley 34759566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 34769566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 34779371c9d4SSatish Balay } break; 3478d71ae5a4SJacob Faibussowitsch default: 3479d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 34809318fe57SMatthew G. Knepley } 34819318fe57SMatthew G. Knepley { 34829318fe57SMatthew G. Knepley PetscInt Nv, v; 34839318fe57SMatthew G. Knepley 34849318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 34859566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 34869566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 34879566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 34889566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 34899318fe57SMatthew G. Knepley } 34909566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 34919566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 34920a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 34930a6ba040SMatthew G. Knepley } 34940a6ba040SMatthew G. Knepley 34959318fe57SMatthew G. Knepley /*@ 34969318fe57SMatthew G. Knepley DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell 34979318fe57SMatthew G. Knepley 34989318fe57SMatthew G. Knepley Collective 34999318fe57SMatthew G. Knepley 35009318fe57SMatthew G. Knepley Input Parameters: 35019318fe57SMatthew G. Knepley + comm - The communicator 35029318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 35039318fe57SMatthew G. Knepley 35049318fe57SMatthew G. Knepley Output Parameter: 35059318fe57SMatthew G. Knepley . refdm - The reference cell 35069318fe57SMatthew G. Knepley 35079318fe57SMatthew G. Knepley Level: intermediate 35089318fe57SMatthew G. Knepley 3509db781477SPatrick Sanan .seealso: `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()` 35109318fe57SMatthew G. Knepley @*/ 3511d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 3512d71ae5a4SJacob Faibussowitsch { 35130a6ba040SMatthew G. Knepley PetscFunctionBegin; 35149566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 35159566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 35169566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 35179318fe57SMatthew G. Knepley PetscFunctionReturn(0); 35189318fe57SMatthew G. Knepley } 351979a015ccSMatthew G. Knepley 3520d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 3521d71ae5a4SJacob Faibussowitsch { 35229318fe57SMatthew G. Knepley DM plex; 35239318fe57SMatthew G. Knepley DMLabel label; 35249318fe57SMatthew G. Knepley PetscBool hasLabel; 35250a6ba040SMatthew G. Knepley 3526c22d3578SMatthew G. Knepley PetscFunctionBegin; 35279566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 35289318fe57SMatthew G. Knepley if (hasLabel) PetscFunctionReturn(0); 35299566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 35309566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 35319566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 35329566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 35331c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 35349566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 35359318fe57SMatthew G. Knepley PetscFunctionReturn(0); 35369318fe57SMatthew G. Knepley } 3537acdc6f61SToby Isaac 3538669647acSMatthew G. Knepley /* 3539669647acSMatthew 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. 3540669647acSMatthew G. Knepley 3541669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 3542669647acSMatthew G. Knepley */ 3543d71ae5a4SJacob 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[]) 3544d71ae5a4SJacob Faibussowitsch { 3545669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 3546669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 3547669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 3548669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 3549669647acSMatthew G. Knepley 3550669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 3551669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 3552669647acSMatthew G. Knepley } 3553669647acSMatthew G. Knepley 3554669647acSMatthew G. Knepley const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 35559318fe57SMatthew G. Knepley 3556d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 3557d71ae5a4SJacob Faibussowitsch { 35589318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 35599318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 35609318fe57SMatthew G. Knepley PetscInt dim = 2; 35619318fe57SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 3562cd7e8a5eSksagiyam PetscBool flg, flg2, fflg, bdfflg, nameflg; 35639318fe57SMatthew G. Knepley MPI_Comm comm; 3564ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3565ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3566ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 35679318fe57SMatthew G. Knepley 35689318fe57SMatthew G. Knepley PetscFunctionBegin; 35699566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 35709318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 35719566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 35729566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 35739566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 35749566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 35759566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 35769566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 35779566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 357863a3b9bcSJacob Faibussowitsch PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim); 35799566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 35809566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 35819566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 35829566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 35839566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 35849318fe57SMatthew G. Knepley 358561a622f3SMatthew G. Knepley switch (cell) { 358661a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 358761a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 358861a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 358961a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 359061a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 359161a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 3592d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 3593d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 3594d71ae5a4SJacob Faibussowitsch break; 3595d71ae5a4SJacob Faibussowitsch default: 3596d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 3597d71ae5a4SJacob Faibussowitsch break; 359861a622f3SMatthew G. Knepley } 359961a622f3SMatthew G. Knepley 36009318fe57SMatthew G. Knepley if (fflg) { 36019318fe57SMatthew G. Knepley DM dmnew; 36029318fe57SMatthew G. Knepley 36039566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew)); 36045de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 360569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 36069318fe57SMatthew G. Knepley } else if (refDomain) { 36079566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 36089318fe57SMatthew G. Knepley } else if (bdfflg) { 36099318fe57SMatthew G. Knepley DM bdm, dmnew; 36109318fe57SMatthew G. Knepley 36119566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm)); 36129566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 36139566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 36149566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 36159566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 36165de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 361769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 36189318fe57SMatthew G. Knepley } else { 36199566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 36209318fe57SMatthew G. Knepley switch (shape) { 3621669647acSMatthew G. Knepley case DM_SHAPE_BOX: 3622669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 36239318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 36249318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 36259318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 36269318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3627669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 36289318fe57SMatthew G. Knepley PetscInt i, n; 36299318fe57SMatthew G. Knepley 36309318fe57SMatthew G. Knepley n = dim; 36319318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 36329566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 36339318fe57SMatthew G. Knepley n = 3; 36349566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 363563a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 36369318fe57SMatthew G. Knepley n = 3; 36379566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 363863a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 36399318fe57SMatthew G. Knepley n = 3; 36409566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 364163a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 3642669647acSMatthew G. Knepley 3643669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 3644669647acSMatthew G. Knepley if (isAnnular) 3645669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 3646669647acSMatthew G. Knepley 36479318fe57SMatthew G. Knepley switch (cell) { 364861a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 36499566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 3650d410b0cfSMatthew G. Knepley if (!interpolate) { 3651d410b0cfSMatthew G. Knepley DM udm; 3652d410b0cfSMatthew G. Knepley 36539566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 365469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3655d410b0cfSMatthew G. Knepley } 36569318fe57SMatthew G. Knepley break; 3657d71ae5a4SJacob Faibussowitsch default: 3658d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate)); 3659d71ae5a4SJacob Faibussowitsch break; 36609318fe57SMatthew G. Knepley } 3661669647acSMatthew G. Knepley if (isAnnular) { 3662669647acSMatthew G. Knepley DM cdm; 3663669647acSMatthew G. Knepley PetscDS cds; 3664669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 3665669647acSMatthew G. Knepley 3666669647acSMatthew G. Knepley // Fix coordinates for annular region 3667669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 3668669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 3669669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 3670669647acSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, NULL)); 3671669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 3672669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 3673669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 3674669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 3675669647acSMatthew G. Knepley } 36769371c9d4SSatish Balay } break; 36779371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 36789318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 36799318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 36809318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 36819318fe57SMatthew G. Knepley PetscInt i, n; 36829318fe57SMatthew G. Knepley 36839318fe57SMatthew G. Knepley n = dim + 1; 36849318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 36859566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 36869318fe57SMatthew G. Knepley n = 3; 36879566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 368863a3b9bcSJacob 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); 36899318fe57SMatthew G. Knepley n = 3; 36909566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 369163a3b9bcSJacob 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); 36929566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 36939371c9d4SSatish Balay } break; 36949371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 36959318fe57SMatthew G. Knepley PetscReal R = 1.0; 36969318fe57SMatthew G. Knepley 36979566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 36989566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 36999371c9d4SSatish Balay } break; 37009371c9d4SSatish Balay case DM_SHAPE_BALL: { 37019318fe57SMatthew G. Knepley PetscReal R = 1.0; 37029318fe57SMatthew G. Knepley 37039566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 37049566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 37059371c9d4SSatish Balay } break; 37069371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 37079318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 37089318fe57SMatthew G. Knepley PetscInt Nw = 6; 37099318fe57SMatthew G. Knepley 37109566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 37119566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 37129318fe57SMatthew G. Knepley switch (cell) { 3713d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 3714d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 3715d71ae5a4SJacob Faibussowitsch break; 3716d71ae5a4SJacob Faibussowitsch default: 3717d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt)); 3718d71ae5a4SJacob Faibussowitsch break; 37199318fe57SMatthew G. Knepley } 37209371c9d4SSatish Balay } break; 3721b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 37229371c9d4SSatish Balay case DM_SHAPE_GYROID: { 3723b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 3724b7f5c055SJed Brown PetscReal thickness = 0.; 3725b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3726b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 37271436d7faSJed Brown PetscBool tps_distribute; 37289566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 37299566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 37309566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 37319566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 37329566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 37339566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 37349566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 37359566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 37369371c9d4SSatish Balay } break; 37379371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 373805bd46c0SStefano Zampini DM dmnew; 373905bd46c0SStefano Zampini PetscReal rl = 0.0; 374005bd46c0SStefano Zampini 374105bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 374205bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 37435de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 374469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 37459371c9d4SSatish Balay } break; 3746d71ae5a4SJacob Faibussowitsch default: 3747d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 37489318fe57SMatthew G. Knepley } 37499318fe57SMatthew G. Knepley } 37509566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 375148a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 37520a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 37530a6ba040SMatthew G. Knepley } 37540a6ba040SMatthew G. Knepley 3755d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 3756d71ae5a4SJacob Faibussowitsch { 37570a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 37587f9d8d6cSVaclav Hapla PetscBool flg, flg2; 37599318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 37600a6ba040SMatthew G. Knepley 37610a6ba040SMatthew G. Knepley PetscFunctionBegin; 37620a6ba040SMatthew G. Knepley /* Handle viewing */ 37639566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 37649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 37659566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 37669566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 3767f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 37689566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 37699566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 37709318fe57SMatthew G. Knepley /* Labeling */ 37719566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 37729566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 3773953fc75cSMatthew G. Knepley /* Point Location */ 37749566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 37750848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 37769566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 37772e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 37789566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 3779b29cfa1cSToby Isaac /* Projection behavior */ 3780d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 37819566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 3782f12cf164SMatthew G. Knepley /* Checking structure */ 3783f12cf164SMatthew G. Knepley { 37847f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 3785f12cf164SMatthew G. Knepley 37867f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 37877f9d8d6cSVaclav Hapla if (all) { 37887f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 37897f9d8d6cSVaclav Hapla } else { 37909566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 37917f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 37929566063dSJacob 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)); 37937f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 37949566063dSJacob 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)); 37957f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 37969566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 37977f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 37989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 3799d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 38009566063dSJacob 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)); 38017f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 38027f9d8d6cSVaclav Hapla } 38039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 38049566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 3805f12cf164SMatthew G. Knepley } 38069318fe57SMatthew G. Knepley { 38079318fe57SMatthew G. Knepley PetscReal scale = 1.0; 38084f3833eaSMatthew G. Knepley 38099566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 38109318fe57SMatthew G. Knepley if (flg) { 38119318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 38129318fe57SMatthew G. Knepley 38139566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 38149566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 38159566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 38169566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 38179318fe57SMatthew G. Knepley } 38189318fe57SMatthew G. Knepley } 38199566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 382068d4fef7SMatthew G. Knepley PetscFunctionReturn(0); 382168d4fef7SMatthew G. Knepley } 382268d4fef7SMatthew G. Knepley 3823d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap) 3824d71ae5a4SJacob Faibussowitsch { 3825c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 3826c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 3827c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 3828c506a872SMatthew G. Knepley PetscBool flg; 3829c506a872SMatthew G. Knepley 3830c506a872SMatthew G. Knepley PetscFunctionBegin; 3831c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 3832c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 3833c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 3834c506a872SMatthew G. Knepley if (numOvLabels) { 3835c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 3836c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 3837c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 3838c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 3839c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 3840c506a872SMatthew G. Knepley } 3841c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 3842c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 3843c506a872SMatthew 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); 3844c506a872SMatthew G. Knepley 3845c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 3846c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 3847c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 3848c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 3849c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 3850c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 3851c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 3852c506a872SMatthew G. Knepley } 3853c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 3854c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 3855c506a872SMatthew 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); 3856c506a872SMatthew G. Knepley } 3857c506a872SMatthew G. Knepley PetscFunctionReturn(0); 3858c506a872SMatthew G. Knepley } 3859c506a872SMatthew G. Knepley 3860d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 3861d71ae5a4SJacob Faibussowitsch { 3862bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 3863bdf63967SMatthew G. Knepley char oname[256]; 3864d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 38659318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 3866e600fa54SMatthew 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; 38676bc1bd01Sksagiyam DMPlexReorderDefaultFlag reorder; 386868d4fef7SMatthew G. Knepley 386968d4fef7SMatthew G. Knepley PetscFunctionBegin; 3870d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 3871dd4c3f67SMatthew G. Knepley if (dm->cloneOpts) goto non_refine; 38729318fe57SMatthew G. Knepley /* Handle automatic creation */ 38739566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 38746bc1bd01Sksagiyam if (dim < 0) { 38756bc1bd01Sksagiyam PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 38766bc1bd01Sksagiyam created = PETSC_TRUE; 38776bc1bd01Sksagiyam } 38786bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 3879d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 38809566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 3881d89e6e46SMatthew G. Knepley if (flg) { 3882d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 3883d89e6e46SMatthew G. Knepley 38849566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 3885d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 3886d89e6e46SMatthew G. Knepley DM udm; 3887d89e6e46SMatthew G. Knepley 38889566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 388969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 3890d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 3891d89e6e46SMatthew G. Knepley DM idm; 3892d89e6e46SMatthew G. Knepley 38939566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 389469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3895d89e6e46SMatthew G. Knepley } 3896d89e6e46SMatthew G. Knepley } 38979b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 38989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg)); 3899ad540459SPierre Jolivet if (flg) ((DM_Plex *)dm->data)->ignoreModel = ignoreModel; 39009566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 39019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 39029566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 39039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 39049566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 39059566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 39069318fe57SMatthew G. Knepley if (flg) { 39079566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 39089566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 39099318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 39109318fe57SMatthew G. Knepley } 39119b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 39129b44eab4SMatthew G. Knepley DM rdm; 39139b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 39149b44eab4SMatthew G. Knepley 3915dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 39169566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 391769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 3918dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 391961a622f3SMatthew G. Knepley if (coordFunc && remap) { 39209566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 39219b44eab4SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 39229b44eab4SMatthew G. Knepley } 39239b44eab4SMatthew G. Knepley } 39249566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 39259318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 39269566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 39279318fe57SMatthew G. Knepley if (extLayers) { 39289318fe57SMatthew G. Knepley DM edm; 39299318fe57SMatthew G. Knepley 39309566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 393169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 393248d16a33SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = NULL; 3933dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3934d410b0cfSMatthew G. Knepley extLayers = 0; 39355e17fc22SAidan Hamilton PetscCall(DMGetDimension(dm, &dim)); 39369318fe57SMatthew G. Knepley } 3937bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 39386bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 39399566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 39406bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 39419566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 39426bc1bd01Sksagiyam if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) { 3943bdf63967SMatthew G. Knepley DM pdm; 3944bdf63967SMatthew G. Knepley IS perm; 3945bdf63967SMatthew G. Knepley 39469566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 39479566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 39489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 394969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 3950dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 3951bdf63967SMatthew G. Knepley } 39529b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 39539566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 3954c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 3955dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 39569b44eab4SMatthew G. Knepley if (distribute) { 39579b44eab4SMatthew G. Knepley DM pdm = NULL; 39589b44eab4SMatthew G. Knepley PetscPartitioner part; 39599b44eab4SMatthew G. Knepley 39609566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 39619566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 39629566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm)); 396348a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 39649b44eab4SMatthew G. Knepley } 39659318fe57SMatthew G. Knepley /* Create coordinate space */ 39669318fe57SMatthew G. Knepley if (created) { 396761a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 39689318fe57SMatthew G. Knepley PetscInt degree = 1; 39696858538eSMatthew G. Knepley PetscBool flg; 39709318fe57SMatthew G. Knepley 39719566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg)); 39729566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 39739566063dSJacob Faibussowitsch if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc)); 397461a622f3SMatthew G. Knepley if (flg && !coordSpace) { 397561a622f3SMatthew G. Knepley DM cdm; 397661a622f3SMatthew G. Knepley PetscDS cds; 397761a622f3SMatthew G. Knepley PetscObject obj; 397861a622f3SMatthew G. Knepley PetscClassId id; 397961a622f3SMatthew G. Knepley 39809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 39819566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 39829566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 39839566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 398461a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 398561a622f3SMatthew G. Knepley PetscContainer dummy; 398661a622f3SMatthew G. Knepley 39879566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 39889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 39899566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 39909566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 39919566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 399261a622f3SMatthew G. Knepley } 399361a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 399461a622f3SMatthew G. Knepley } 39956858538eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg)); 39969566063dSJacob Faibussowitsch PetscCall(DMLocalizeCoordinates(dm)); 39979318fe57SMatthew G. Knepley } 399868d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 399961a622f3SMatthew G. Knepley remap = PETSC_TRUE; 40009566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 40019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 40029566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 40039566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 400468d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 4005acdc6f61SToby Isaac DM *dms, coarseDM; 400668d4fef7SMatthew G. Knepley 40079566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 40089566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 40099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 40109566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 401168d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 40129566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 401368d4fef7SMatthew G. Knepley if (refine == 1) { 40149566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 40159566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 401668d4fef7SMatthew G. Knepley } else { 40179566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 40189566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 40199566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 40209566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 402168d4fef7SMatthew G. Knepley } 40229566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 40239566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 402468d4fef7SMatthew G. Knepley /* Free DMs */ 402568d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 4026dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 40279566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 402868d4fef7SMatthew G. Knepley } 40299566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 403068d4fef7SMatthew G. Knepley } else { 403168d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 40329318fe57SMatthew G. Knepley DM rdm; 403351a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 403468d4fef7SMatthew G. Knepley 4035dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40369566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 403768d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 403869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 4039dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 404061a622f3SMatthew G. Knepley if (coordFunc && remap) { 40419566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 404251a74b61SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 404351a74b61SMatthew G. Knepley } 404468d4fef7SMatthew G. Knepley } 404568d4fef7SMatthew G. Knepley } 40463cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 40479566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 40489566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 4049b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 4050b653a561SMatthew G. Knepley DM *dms; 4051b653a561SMatthew G. Knepley 40529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 40539566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 4054b653a561SMatthew G. Knepley /* Free DMs */ 4055b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 4056dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 40579566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 4058b653a561SMatthew G. Knepley } 40599566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 4060b653a561SMatthew G. Knepley } else { 4061b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 40629318fe57SMatthew G. Knepley DM cdm; 40639318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 40643cf6fe12SMatthew G. Knepley 4065dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40669566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 40673cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 406869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 4069dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 40709318fe57SMatthew G. Knepley if (coordFunc) { 40719566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 40729318fe57SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 40739318fe57SMatthew G. Knepley } 40743cf6fe12SMatthew G. Knepley } 4075b653a561SMatthew G. Knepley } 4076909dfd52SMatthew G. Knepley /* Handle ghost cells */ 40779566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 4078909dfd52SMatthew G. Knepley if (ghostCells) { 4079909dfd52SMatthew G. Knepley DM gdm; 4080909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 4081909dfd52SMatthew G. Knepley 4082909dfd52SMatthew G. Knepley lname[0] = '\0'; 40839566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 40849566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 408569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 4086909dfd52SMatthew G. Knepley } 40876913077dSMatthew G. Knepley /* Handle 1D order */ 40886bc1bd01Sksagiyam if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) { 40896913077dSMatthew G. Knepley DM cdm, rdm; 40906913077dSMatthew G. Knepley PetscDS cds; 40916913077dSMatthew G. Knepley PetscObject obj; 40926913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 40936913077dSMatthew G. Knepley IS perm; 40946bc1bd01Sksagiyam PetscInt Nf; 40956913077dSMatthew G. Knepley PetscBool distributed; 40966913077dSMatthew G. Knepley 40979566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 40989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 40999566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 41009566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 41016913077dSMatthew G. Knepley if (Nf) { 41029566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 41039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 41046913077dSMatthew G. Knepley } 41056bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 41069566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 41079566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 410869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 41099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 41106913077dSMatthew G. Knepley } 41116913077dSMatthew G. Knepley } 41123cf6fe12SMatthew G. Knepley /* Handle */ 4113dd4c3f67SMatthew G. Knepley non_refine: 4114dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 4115d0609cedSBarry Smith PetscOptionsHeadEnd(); 41160a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 41170a6ba040SMatthew G. Knepley } 41180a6ba040SMatthew G. Knepley 4119d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 4120d71ae5a4SJacob Faibussowitsch { 4121552f7358SJed Brown PetscFunctionBegin; 41229566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 41239566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 41249566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 41259566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 41269566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 41279566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 4128552f7358SJed Brown PetscFunctionReturn(0); 4129552f7358SJed Brown } 4130552f7358SJed Brown 4131d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 4132d71ae5a4SJacob Faibussowitsch { 4133552f7358SJed Brown PetscFunctionBegin; 41349566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 41359566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 41369566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 4137552f7358SJed Brown PetscFunctionReturn(0); 4138552f7358SJed Brown } 4139552f7358SJed Brown 4140d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4141d71ae5a4SJacob Faibussowitsch { 4142793f3fe5SMatthew G. Knepley PetscInt depth, d; 4143793f3fe5SMatthew G. Knepley 4144793f3fe5SMatthew G. Knepley PetscFunctionBegin; 41459566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4146793f3fe5SMatthew G. Knepley if (depth == 1) { 41479566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 41489566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 41499566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 41509371c9d4SSatish Balay else { 41519371c9d4SSatish Balay *pStart = 0; 41529371c9d4SSatish Balay *pEnd = 0; 41539371c9d4SSatish Balay } 4154793f3fe5SMatthew G. Knepley } else { 41559566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 4156793f3fe5SMatthew G. Knepley } 4157793f3fe5SMatthew G. Knepley PetscFunctionReturn(0); 4158793f3fe5SMatthew G. Knepley } 4159793f3fe5SMatthew G. Knepley 4160d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 4161d71ae5a4SJacob Faibussowitsch { 4162502a2867SDave May PetscSF sf; 41630a19bb7dSprj- PetscInt niranks, njranks, n; 41640a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 41650a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 4166502a2867SDave May 41672f356facSMatthew G. Knepley PetscFunctionBegin; 41689566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 41690a19bb7dSprj- if (!data->neighbors) { 41709566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 41719566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 41729566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 41739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 41749566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 41759566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 41760a19bb7dSprj- n = njranks + niranks; 41779566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 41780a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 41799566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 41800a19bb7dSprj- } 41810a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 41820a19bb7dSprj- if (ranks) { 41830a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 41840a19bb7dSprj- else *ranks = NULL; 41850a19bb7dSprj- } 4186502a2867SDave May PetscFunctionReturn(0); 4187502a2867SDave May } 4188502a2867SDave May 41891eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 41901eb70e55SToby Isaac 4191d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 4192d71ae5a4SJacob Faibussowitsch { 4193552f7358SJed Brown PetscFunctionBegin; 4194552f7358SJed Brown dm->ops->view = DMView_Plex; 41952c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 4196552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 419738221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 4198552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 41991bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 420066ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 4201552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 4202552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 4203184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 42040298fd71SBarry Smith dm->ops->createfieldis = NULL; 4205552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 4206f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 42070a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 4208552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 4209bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 4210bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 4211b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 42125a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 4213552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 42140a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 42150a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 4216b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 4217d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 42180298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 42190298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 42200298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 42210298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 4222552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 4223552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 42242adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 4225793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 4226552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 42270709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 42280709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 4229bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 42308c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 4231ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 42320709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 4233b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 42342a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 423528d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 42369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 42379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 42389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 42399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 42409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 42419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 42429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 42436bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 42446bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 42459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 4246c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 4247c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 4248552f7358SJed Brown PetscFunctionReturn(0); 4249552f7358SJed Brown } 4250552f7358SJed Brown 4251d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 4252d71ae5a4SJacob Faibussowitsch { 425363a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 425463a16f15SMatthew G. Knepley 425563a16f15SMatthew G. Knepley PetscFunctionBegin; 425663a16f15SMatthew G. Knepley mesh->refct++; 425763a16f15SMatthew G. Knepley (*newdm)->data = mesh; 42589566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 42599566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 426063a16f15SMatthew G. Knepley PetscFunctionReturn(0); 426163a16f15SMatthew G. Knepley } 426263a16f15SMatthew G. Knepley 42638818961aSMatthew G Knepley /*MC 42648818961aSMatthew G Knepley DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 42658818961aSMatthew G Knepley In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is 42668818961aSMatthew G Knepley specified by a PetscSection object. Ownership in the global representation is determined by 42678818961aSMatthew G Knepley ownership of the underlying DMPlex points. This is specified by another PetscSection object. 42688818961aSMatthew G Knepley 4269e5893cccSMatthew G. Knepley Options Database Keys: 4270250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 4271250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 4272250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 4273250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 4274250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 4275250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 4276250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 4277ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 4278f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 4279f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 4280d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 4281f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 4282250712c9SMatthew G. Knepley . -dm_plex_check_all - Perform all shecks below 4283f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 4284f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 4285f12cf164SMatthew 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 4286f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 4287f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 4288e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 4289e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 4290e5893cccSMatthew G. Knepley 42918818961aSMatthew G Knepley Level: intermediate 42928818961aSMatthew G Knepley 4293db781477SPatrick Sanan .seealso: `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()` 42948818961aSMatthew G Knepley M*/ 42958818961aSMatthew G Knepley 4296d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 4297d71ae5a4SJacob Faibussowitsch { 4298552f7358SJed Brown DM_Plex *mesh; 4299412e9a14SMatthew G. Knepley PetscInt unit; 4300552f7358SJed Brown 4301552f7358SJed Brown PetscFunctionBegin; 4302552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43034dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 4304552f7358SJed Brown dm->data = mesh; 4305552f7358SJed Brown 4306552f7358SJed Brown mesh->refct = 1; 43079566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 43089566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 4309552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 4310552f7358SJed Brown mesh->refinementLimit = -1.0; 4311e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 43126bc1bd01Sksagiyam mesh->reorderDefault = DMPLEX_REORDER_DEFAULT_NOTSET; 43131d1f2f2aSksagiyam mesh->distributionName = NULL; 43147d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 43157d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 4316552f7358SJed Brown 43179566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 43182e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 4319d9deefdfSMatthew G. Knepley 43208865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 4321552f7358SJed Brown 4322df0420ecSMatthew G. Knepley mesh->depthState = -1; 4323ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 43246113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 4325552f7358SJed Brown 43269566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 4327552f7358SJed Brown PetscFunctionReturn(0); 4328552f7358SJed Brown } 4329552f7358SJed Brown 4330552f7358SJed Brown /*@ 4331552f7358SJed Brown DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 4332552f7358SJed Brown 4333d083f849SBarry Smith Collective 4334552f7358SJed Brown 4335552f7358SJed Brown Input Parameter: 4336552f7358SJed Brown . comm - The communicator for the DMPlex object 4337552f7358SJed Brown 4338552f7358SJed Brown Output Parameter: 4339552f7358SJed Brown . mesh - The DMPlex object 4340552f7358SJed Brown 4341552f7358SJed Brown Level: beginner 4342552f7358SJed Brown 4343552f7358SJed Brown @*/ 4344d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 4345d71ae5a4SJacob Faibussowitsch { 4346552f7358SJed Brown PetscFunctionBegin; 4347552f7358SJed Brown PetscValidPointer(mesh, 2); 43489566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 43499566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 4350552f7358SJed Brown PetscFunctionReturn(0); 4351552f7358SJed Brown } 4352552f7358SJed Brown 4353b09969d6SVaclav Hapla /*@C 4354b09969d6SVaclav Hapla DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output) 4355b09969d6SVaclav Hapla 4356b09969d6SVaclav Hapla Input Parameters: 4357b09969d6SVaclav Hapla + dm - The DM 4358b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4359325d53feSBarry Smith . numVertices - The number of vertices to be owned by this process, or PETSC_DECIDE 4360325d53feSBarry Smith . NVertices - The global number of vertices, or PETSC_DETERMINE 4361b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 43625e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4363b09969d6SVaclav Hapla 4364be8c289dSNicolas Barral Output Parameters: 4365be8c289dSNicolas Barral + vertexSF - (Optional) SF describing complete vertex ownership 4366be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4367b09969d6SVaclav Hapla 4368b09969d6SVaclav Hapla Notes: 4369b09969d6SVaclav Hapla Two triangles sharing a face 4370b09969d6SVaclav Hapla $ 4371b09969d6SVaclav Hapla $ 2 4372b09969d6SVaclav Hapla $ / | \ 4373b09969d6SVaclav Hapla $ / | \ 4374b09969d6SVaclav Hapla $ / | \ 4375b09969d6SVaclav Hapla $ 0 0 | 1 3 4376b09969d6SVaclav Hapla $ \ | / 4377b09969d6SVaclav Hapla $ \ | / 4378b09969d6SVaclav Hapla $ \ | / 4379b09969d6SVaclav Hapla $ 1 4380b09969d6SVaclav Hapla would have input 4381b09969d6SVaclav Hapla $ numCells = 2, numVertices = 4 4382b09969d6SVaclav Hapla $ cells = [0 1 2 1 3 2] 4383b09969d6SVaclav Hapla $ 4384b09969d6SVaclav Hapla which would result in the DMPlex 4385b09969d6SVaclav Hapla $ 4386b09969d6SVaclav Hapla $ 4 4387b09969d6SVaclav Hapla $ / | \ 4388b09969d6SVaclav Hapla $ / | \ 4389b09969d6SVaclav Hapla $ / | \ 4390b09969d6SVaclav Hapla $ 2 0 | 1 5 4391b09969d6SVaclav Hapla $ \ | / 4392b09969d6SVaclav Hapla $ \ | / 4393b09969d6SVaclav Hapla $ \ | / 4394b09969d6SVaclav Hapla $ 3 4395b09969d6SVaclav Hapla 439625b6865aSVaclav Hapla Vertices are implicitly numbered consecutively 0,...,NVertices. 439725b6865aSVaclav Hapla Each rank owns a chunk of numVertices consecutive vertices. 439825b6865aSVaclav Hapla If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout. 4399325d53feSBarry Smith If NVertices is PETSC_DETERMINE and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 4400325d53feSBarry Smith If only NVertices is PETSC_DETERMINE, it is computed as the sum of numVertices over all ranks. 440125b6865aSVaclav Hapla 4402b09969d6SVaclav Hapla The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 4403b09969d6SVaclav Hapla 4404b09969d6SVaclav Hapla Not currently supported in Fortran. 4405b09969d6SVaclav Hapla 4406b09969d6SVaclav Hapla Level: advanced 4407b09969d6SVaclav Hapla 4408db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()` 4409b09969d6SVaclav Hapla @*/ 4410d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved) 4411d71ae5a4SJacob Faibussowitsch { 44122464107aSksagiyam PetscSF sfPoint; 44132464107aSksagiyam PetscLayout layout; 441482fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 4415a47d0d45SMatthew G. Knepley 4416a47d0d45SMatthew G. Knepley PetscFunctionBegin; 441725b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 44189566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 441925b6865aSVaclav Hapla /* Get/check global number of vertices */ 442025b6865aSVaclav Hapla { 442125b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 442225b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 442325b6865aSVaclav Hapla 442425b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 442525b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 44269371c9d4SSatish Balay for (i = 0; i < len; i++) 44279371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 442825b6865aSVaclav Hapla ++NVerticesInCells; 44299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 443025b6865aSVaclav Hapla 443125b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 44329371c9d4SSatish Balay else 44339371c9d4SSatish 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); 443425b6865aSVaclav Hapla } 44359079aca8SVaclav Hapla /* Count locally unique vertices */ 44369079aca8SVaclav Hapla { 44379079aca8SVaclav Hapla PetscHSetI vhash; 44389079aca8SVaclav Hapla PetscInt off = 0; 44399079aca8SVaclav Hapla 44409566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 4441a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 444248a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 4443a47d0d45SMatthew G. Knepley } 44449566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 44459566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 4446ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 44479566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 44489566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 444963a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 4450a47d0d45SMatthew G. Knepley } 44519566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 4452a47d0d45SMatthew G. Knepley /* Create cones */ 44539566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 44549566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 44559566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 44569566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4457a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 4458a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 4459a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 4460a47d0d45SMatthew G. Knepley PetscInt lv; 4461a47d0d45SMatthew G. Knepley 44629079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 44639079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 44649566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 446563a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 4466961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 4467a47d0d45SMatthew G. Knepley } 4468a47d0d45SMatthew G. Knepley } 44692464107aSksagiyam /* Build point sf */ 44709566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 44719566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 44729566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 44739566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 44749566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 44759566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 44769566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 44779566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 44782464107aSksagiyam if (dm->sf) { 44792464107aSksagiyam const char *prefix; 44802464107aSksagiyam 44819566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 44829566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 44832464107aSksagiyam } 44849566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 44859566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 44869566063dSJacob Faibussowitsch if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF")); 4487a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 44889566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 44899566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 44909566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4491a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4492a47d0d45SMatthew G. Knepley } 4493a47d0d45SMatthew G. Knepley 4494b09969d6SVaclav Hapla /*@C 4495b09969d6SVaclav Hapla DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4496b09969d6SVaclav Hapla 4497b09969d6SVaclav Hapla Input Parameters: 4498b09969d6SVaclav Hapla + dm - The DM 4499b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4500b09969d6SVaclav Hapla . sfVert - SF describing complete vertex ownership 4501b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4502b09969d6SVaclav Hapla 4503b09969d6SVaclav Hapla Level: advanced 4504b09969d6SVaclav Hapla 4505b09969d6SVaclav Hapla Notes: 4506b09969d6SVaclav Hapla Not currently supported in Fortran. 4507b09969d6SVaclav Hapla 4508db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 4509b09969d6SVaclav Hapla @*/ 4510d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 4511d71ae5a4SJacob Faibussowitsch { 4512a47d0d45SMatthew G. Knepley PetscSection coordSection; 4513a47d0d45SMatthew G. Knepley Vec coordinates; 4514a47d0d45SMatthew G. Knepley PetscScalar *coords; 45151edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 4516a47d0d45SMatthew G. Knepley 4517a47d0d45SMatthew G. Knepley PetscFunctionBegin; 45189566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 45199566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 45201dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 45219566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 45229566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 45231dca8a05SBarry 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); 45249566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 45259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 45269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 45279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 45281edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 45299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 45309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4531a47d0d45SMatthew G. Knepley } 45329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 45339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 45349566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 45359566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 45369566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 45379566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 45389566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 45399566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 4540a47d0d45SMatthew G. Knepley { 4541a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 4542a47d0d45SMatthew G. Knepley 4543a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 45449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype)); 45459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 454621016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 454721016a8bSBarry Smith { 454821016a8bSBarry Smith PetscScalar *svertexCoords; 454921016a8bSBarry Smith PetscInt i; 45509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 45513612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 45529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 45539566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 45549566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 455521016a8bSBarry Smith } 455621016a8bSBarry Smith #else 45579566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 45589566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 455921016a8bSBarry Smith #endif 45609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 4561a47d0d45SMatthew G. Knepley } 45629566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 45639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 45649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 45659566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4566a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4567a47d0d45SMatthew G. Knepley } 4568a47d0d45SMatthew G. Knepley 4569c3edce3dSSatish Balay /*@ 4570b09969d6SVaclav Hapla DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output) 4571a47d0d45SMatthew G. Knepley 4572a47d0d45SMatthew G. Knepley Input Parameters: 4573a47d0d45SMatthew G. Knepley + comm - The communicator 4574a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 4575a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 457625b6865aSVaclav Hapla . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 457725b6865aSVaclav Hapla . NVertices - The global number of vertices, or PETSC_DECIDE 4578a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 4579a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 4580a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4581a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 4582a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4583a47d0d45SMatthew G. Knepley 4584d8d19677SJose E. Roman Output Parameters: 458518d54ad4SMichael Lange + dm - The DM 4586be8c289dSNicolas Barral . vertexSF - (Optional) SF describing complete vertex ownership 4587be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4588a47d0d45SMatthew G. Knepley 4589b09969d6SVaclav Hapla Notes: 4590b09969d6SVaclav Hapla This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), 4591b09969d6SVaclav Hapla DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel() 4592a47d0d45SMatthew G. Knepley 459325b6865aSVaclav Hapla See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters. 459425b6865aSVaclav Hapla See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters. 459525b6865aSVaclav Hapla 4596b09969d6SVaclav Hapla Level: intermediate 4597a47d0d45SMatthew G. Knepley 4598db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 4599a47d0d45SMatthew G. Knepley @*/ 4600d71ae5a4SJacob 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) 4601d71ae5a4SJacob Faibussowitsch { 4602a47d0d45SMatthew G. Knepley PetscSF sfVert; 4603a47d0d45SMatthew G. Knepley 4604a47d0d45SMatthew G. Knepley PetscFunctionBegin; 46059566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 46069566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 4607a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 4608064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 46099566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 46109566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 4611a47d0d45SMatthew G. Knepley if (interpolate) { 46125fd9971aSMatthew G. Knepley DM idm; 4613a47d0d45SMatthew G. Knepley 46149566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 46159566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 4616a47d0d45SMatthew G. Knepley *dm = idm; 4617a47d0d45SMatthew G. Knepley } 46189566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 461918d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 46209566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 4621a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4622a47d0d45SMatthew G. Knepley } 4623a47d0d45SMatthew G. Knepley 4624b09969d6SVaclav Hapla /*@C 4625b09969d6SVaclav Hapla DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output) 46269298eaa6SMatthew G Knepley 46279298eaa6SMatthew G Knepley Input Parameters: 4628b09969d6SVaclav Hapla + dm - The DM 4629b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4630325d53feSBarry Smith . numVertices - The number of vertices owned by this process, or PETSC_DETERMINE 46319298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 46325e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 46339298eaa6SMatthew G Knepley 4634b09969d6SVaclav Hapla Level: advanced 46359298eaa6SMatthew G Knepley 4636b09969d6SVaclav Hapla Notes: 4637b09969d6SVaclav Hapla Two triangles sharing a face 46389298eaa6SMatthew G Knepley $ 46399298eaa6SMatthew G Knepley $ 2 46409298eaa6SMatthew G Knepley $ / | \ 46419298eaa6SMatthew G Knepley $ / | \ 46429298eaa6SMatthew G Knepley $ / | \ 46439298eaa6SMatthew G Knepley $ 0 0 | 1 3 46449298eaa6SMatthew G Knepley $ \ | / 46459298eaa6SMatthew G Knepley $ \ | / 46469298eaa6SMatthew G Knepley $ \ | / 46479298eaa6SMatthew G Knepley $ 1 46489298eaa6SMatthew G Knepley would have input 46499298eaa6SMatthew G Knepley $ numCells = 2, numVertices = 4 46509298eaa6SMatthew G Knepley $ cells = [0 1 2 1 3 2] 46519298eaa6SMatthew G Knepley $ 46529298eaa6SMatthew G Knepley which would result in the DMPlex 46539298eaa6SMatthew G Knepley $ 46549298eaa6SMatthew G Knepley $ 4 46559298eaa6SMatthew G Knepley $ / | \ 46569298eaa6SMatthew G Knepley $ / | \ 46579298eaa6SMatthew G Knepley $ / | \ 46589298eaa6SMatthew G Knepley $ 2 0 | 1 5 46599298eaa6SMatthew G Knepley $ \ | / 46609298eaa6SMatthew G Knepley $ \ | / 46619298eaa6SMatthew G Knepley $ \ | / 46629298eaa6SMatthew G Knepley $ 3 46639298eaa6SMatthew G Knepley 4664325d53feSBarry Smith If numVertices is PETSC_DETERMINE, it is computed by PETSc as the maximum vertex index in cells + 1. 466525b6865aSVaclav Hapla 4666b09969d6SVaclav Hapla Not currently supported in Fortran. 46679298eaa6SMatthew G Knepley 4668db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 4669b09969d6SVaclav Hapla @*/ 4670d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 4671d71ae5a4SJacob Faibussowitsch { 4672961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 4673b09969d6SVaclav Hapla 4674b09969d6SVaclav Hapla PetscFunctionBegin; 46759566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 46769566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 467725b6865aSVaclav Hapla /* Get/check global number of vertices */ 467825b6865aSVaclav Hapla { 467925b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 468025b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 468125b6865aSVaclav Hapla 468225b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 468325b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 46849371c9d4SSatish Balay for (i = 0; i < len; i++) 46859371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 468625b6865aSVaclav Hapla ++NVerticesInCells; 468725b6865aSVaclav Hapla 468825b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 46899371c9d4SSatish Balay else 46909371c9d4SSatish 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); 469125b6865aSVaclav Hapla } 46929566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 469348a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 46949566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 46959566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 4696b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 4697ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 4698b09969d6SVaclav Hapla } 46999566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 47009566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 47019566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 4702b09969d6SVaclav Hapla PetscFunctionReturn(0); 4703b09969d6SVaclav Hapla } 4704b09969d6SVaclav Hapla 4705b09969d6SVaclav Hapla /*@C 4706b09969d6SVaclav Hapla DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4707b09969d6SVaclav Hapla 4708b09969d6SVaclav Hapla Input Parameters: 4709b09969d6SVaclav Hapla + dm - The DM 4710b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4711b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4712b09969d6SVaclav Hapla 4713b09969d6SVaclav Hapla Level: advanced 4714b09969d6SVaclav Hapla 4715b09969d6SVaclav Hapla Notes: 4716b09969d6SVaclav Hapla Not currently supported in Fortran. 4717b09969d6SVaclav Hapla 4718db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 4719b09969d6SVaclav Hapla @*/ 4720d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 4721d71ae5a4SJacob Faibussowitsch { 4722b09969d6SVaclav Hapla PetscSection coordSection; 4723b09969d6SVaclav Hapla Vec coordinates; 4724b09969d6SVaclav Hapla DM cdm; 4725b09969d6SVaclav Hapla PetscScalar *coords; 47261edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 4727b09969d6SVaclav Hapla 4728b09969d6SVaclav Hapla PetscFunctionBegin; 47299566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 47309566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 47311dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 47329566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 47339566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 47349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 47359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 47369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 47371edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 47389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 47399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4740b09969d6SVaclav Hapla } 47419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4742b09969d6SVaclav Hapla 47439566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 47449566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 47459566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 47469566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 47479566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 47481edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 4749ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 4750b09969d6SVaclav Hapla } 47519566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 47529566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 47539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 47549566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 4755b09969d6SVaclav Hapla PetscFunctionReturn(0); 4756b09969d6SVaclav Hapla } 4757b09969d6SVaclav Hapla 4758b09969d6SVaclav Hapla /*@ 47593df08285SMatthew G. Knepley DMPlexCreateFromCellListPetsc - Create DMPLEX from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 47603df08285SMatthew G. Knepley 47613df08285SMatthew G. Knepley Collective on comm 4762b09969d6SVaclav Hapla 4763b09969d6SVaclav Hapla Input Parameters: 4764b09969d6SVaclav Hapla + comm - The communicator 4765b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 47663df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 47673df08285SMatthew G. Knepley . numVertices - The number of vertices owned by this process, or PETSC_DECIDE, only on process 0 47683df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 4769b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 47703df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0 4771b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 47723df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0 4773b09969d6SVaclav Hapla 4774b09969d6SVaclav Hapla Output Parameter: 47753df08285SMatthew G. Knepley . dm - The DM, which only has points on process 0 4776b09969d6SVaclav Hapla 4777b09969d6SVaclav Hapla Notes: 4778b09969d6SVaclav Hapla This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(), 4779b09969d6SVaclav Hapla DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList() 4780b09969d6SVaclav Hapla 478125b6865aSVaclav Hapla See DMPlexBuildFromCellList() for an example and details about the topology-related parameters. 478225b6865aSVaclav Hapla See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters. 47833df08285SMatthew G. Knepley See DMPlexCreateFromCellListParallelPetsc() for parallel input 478425b6865aSVaclav Hapla 4785b09969d6SVaclav Hapla Level: intermediate 4786b09969d6SVaclav Hapla 4787db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 47889298eaa6SMatthew G Knepley @*/ 4789d71ae5a4SJacob 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) 4790d71ae5a4SJacob Faibussowitsch { 47913df08285SMatthew G. Knepley PetscMPIInt rank; 47929298eaa6SMatthew G Knepley 47939298eaa6SMatthew G Knepley PetscFunctionBegin; 479428b400f6SJacob 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."); 47959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 47969566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 47979566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 47989566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 4799c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 48009566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 48019298eaa6SMatthew G Knepley if (interpolate) { 48025fd9971aSMatthew G. Knepley DM idm; 48039298eaa6SMatthew G Knepley 48049566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 48059566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 48069298eaa6SMatthew G Knepley *dm = idm; 48079298eaa6SMatthew G Knepley } 4808c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 48099566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 48109298eaa6SMatthew G Knepley PetscFunctionReturn(0); 48119298eaa6SMatthew G Knepley } 48129298eaa6SMatthew G Knepley 4813939f6067SMatthew G. Knepley /*@ 4814939f6067SMatthew 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 4815939f6067SMatthew G. Knepley 4816939f6067SMatthew G. Knepley Input Parameters: 4817c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension() 4818939f6067SMatthew G. Knepley . depth - The depth of the DAG 4819367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth 4820939f6067SMatthew G. Knepley . coneSize - The cone size of each point 4821939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 4822939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 4823367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim() 4824939f6067SMatthew G. Knepley 4825939f6067SMatthew G. Knepley Output Parameter: 4826939f6067SMatthew G. Knepley . dm - The DM 4827939f6067SMatthew G. Knepley 4828939f6067SMatthew G. Knepley Note: Two triangles sharing a face would have input 4829939f6067SMatthew G. Knepley $ depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 4830939f6067SMatthew G. Knepley $ cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 4831939f6067SMatthew G. Knepley $ vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 4832939f6067SMatthew G. Knepley $ 4833939f6067SMatthew G. Knepley which would result in the DMPlex 4834939f6067SMatthew G. Knepley $ 4835939f6067SMatthew G. Knepley $ 4 4836939f6067SMatthew G. Knepley $ / | \ 4837939f6067SMatthew G. Knepley $ / | \ 4838939f6067SMatthew G. Knepley $ / | \ 4839939f6067SMatthew G. Knepley $ 2 0 | 1 5 4840939f6067SMatthew G. Knepley $ \ | / 4841939f6067SMatthew G. Knepley $ \ | / 4842939f6067SMatthew G. Knepley $ \ | / 4843939f6067SMatthew G. Knepley $ 3 4844939f6067SMatthew G. Knepley $ 4845a4a685f2SJacob Faibussowitsch $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc() 4846939f6067SMatthew G. Knepley 4847939f6067SMatthew G. Knepley Level: advanced 4848939f6067SMatthew G. Knepley 4849db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 4850939f6067SMatthew G. Knepley @*/ 4851d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 4852d71ae5a4SJacob Faibussowitsch { 48539298eaa6SMatthew G Knepley Vec coordinates; 48549298eaa6SMatthew G Knepley PetscSection coordSection; 48559298eaa6SMatthew G Knepley PetscScalar *coords; 4856811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 48579298eaa6SMatthew G Knepley 48589298eaa6SMatthew G Knepley PetscFunctionBegin; 48599566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 48609566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 486163a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 48629298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 48639566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 48649298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 48659566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 4866ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 486797e052ccSToby Isaac } 48681dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 48699566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 48709298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 48719566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 48729566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 48739298eaa6SMatthew G Knepley } 48749566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 48759566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 48769298eaa6SMatthew G Knepley /* Build coordinates */ 48779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 48789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 48799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 48809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 48819298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 48829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 48839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 48849298eaa6SMatthew G Knepley } 48859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 48869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 48879566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 48889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 48899566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 48909566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dimEmbed)); 48919566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 48929318fe57SMatthew G. Knepley if (vertexCoords) { 48939566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 48949298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 48959298eaa6SMatthew G Knepley PetscInt off; 48969298eaa6SMatthew G Knepley 48979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 4898ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 48999298eaa6SMatthew G Knepley } 49009318fe57SMatthew G. Knepley } 49019566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 49029566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 49039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 49049298eaa6SMatthew G Knepley PetscFunctionReturn(0); 49059298eaa6SMatthew G Knepley } 49068415267dSToby Isaac 4907ca522641SMatthew G. Knepley /*@C 49088ca92349SMatthew G. Knepley DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file. 49098ca92349SMatthew G. Knepley 49108ca92349SMatthew G. Knepley + comm - The MPI communicator 49118ca92349SMatthew G. Knepley . filename - Name of the .dat file 49128ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 49138ca92349SMatthew G. Knepley 49148ca92349SMatthew G. Knepley Output Parameter: 49158ca92349SMatthew G. Knepley . dm - The DM object representing the mesh 49168ca92349SMatthew G. Knepley 49178ca92349SMatthew G. Knepley Note: The format is the simplest possible: 49188ca92349SMatthew G. Knepley $ Ne 49198ca92349SMatthew G. Knepley $ v0 v1 ... vk 49208ca92349SMatthew G. Knepley $ Nv 49218ca92349SMatthew G. Knepley $ x y z marker 49228ca92349SMatthew G. Knepley 49238ca92349SMatthew G. Knepley Level: beginner 49248ca92349SMatthew G. Knepley 4925db781477SPatrick Sanan .seealso: `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 49268ca92349SMatthew G. Knepley @*/ 4927d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 4928d71ae5a4SJacob Faibussowitsch { 49298ca92349SMatthew G. Knepley DMLabel marker; 49308ca92349SMatthew G. Knepley PetscViewer viewer; 49318ca92349SMatthew G. Knepley Vec coordinates; 49328ca92349SMatthew G. Knepley PetscSection coordSection; 49338ca92349SMatthew G. Knepley PetscScalar *coords; 49348ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 49358ca92349SMatthew G. Knepley PetscInt dim = 3, cdim = 3, coordSize, v, c, d; 49368ca92349SMatthew G. Knepley PetscMPIInt rank; 4937f8d5e320SMatthew G. Knepley int snum, Nv, Nc, Ncn, Nl; 49388ca92349SMatthew G. Knepley 49398ca92349SMatthew G. Knepley PetscFunctionBegin; 49409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 49419566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 49429566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 49439566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 49449566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 4945dd400576SPatrick Sanan if (rank == 0) { 49469566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING)); 4947f8d5e320SMatthew G. Knepley snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl); 494808401ef6SPierre Jolivet PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 494925ce1634SJed Brown } else { 4950f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 49518ca92349SMatthew G. Knepley } 49529566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 49539566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 49549566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 49559566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 49569566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 49578ca92349SMatthew G. Knepley /* Read topology */ 4958dd400576SPatrick Sanan if (rank == 0) { 4959f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 4960f8d5e320SMatthew G. Knepley PetscInt cone[8]; 49618ca92349SMatthew G. Knepley int vbuf[8], v; 49628ca92349SMatthew G. Knepley 49639371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 49649371c9d4SSatish Balay format[c * 3 + 0] = '%'; 49659371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 49669371c9d4SSatish Balay format[c * 3 + 2] = ' '; 49679371c9d4SSatish Balay } 4968f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 49699566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 49709566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 49718ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 49729566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 4973f8d5e320SMatthew G. Knepley switch (Ncn) { 4974d71ae5a4SJacob Faibussowitsch case 2: 4975d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 4976d71ae5a4SJacob Faibussowitsch break; 4977d71ae5a4SJacob Faibussowitsch case 3: 4978d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 4979d71ae5a4SJacob Faibussowitsch break; 4980d71ae5a4SJacob Faibussowitsch case 4: 4981d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 4982d71ae5a4SJacob Faibussowitsch break; 4983d71ae5a4SJacob Faibussowitsch case 6: 4984d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 4985d71ae5a4SJacob Faibussowitsch break; 4986d71ae5a4SJacob Faibussowitsch case 8: 4987d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 4988d71ae5a4SJacob Faibussowitsch break; 4989d71ae5a4SJacob Faibussowitsch default: 4990d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 4991f8d5e320SMatthew G. Knepley } 499208401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 4993f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 49948ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 4995f8d5e320SMatthew G. Knepley if (Ncn == 8) { 49968ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 49978ca92349SMatthew G. Knepley cone[1] = cone[3]; 49988ca92349SMatthew G. Knepley cone[3] = tmp; 49998ca92349SMatthew G. Knepley } 50009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 50018ca92349SMatthew G. Knepley } 50028ca92349SMatthew G. Knepley } 50039566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 50049566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 50058ca92349SMatthew G. Knepley /* Read coordinates */ 50069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 50079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 50089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 50099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 50108ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 50119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 50129566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 50138ca92349SMatthew G. Knepley } 50149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 50159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 50169566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 50179566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 50189566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 50199566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 50209566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 50219566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5022dd400576SPatrick Sanan if (rank == 0) { 5023f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 50248ca92349SMatthew G. Knepley double x[3]; 5025f8d5e320SMatthew G. Knepley int l, val[3]; 50268ca92349SMatthew G. Knepley 5027f8d5e320SMatthew G. Knepley if (Nl) { 50289371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 50299371c9d4SSatish Balay format[l * 3 + 0] = '%'; 50309371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 50319371c9d4SSatish Balay format[l * 3 + 2] = ' '; 50329371c9d4SSatish Balay } 5033f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 50349566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 50359566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 5036f8d5e320SMatthew G. Knepley } 50378ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 50389566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 5039f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 504008401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 5041f8d5e320SMatthew G. Knepley switch (Nl) { 5042d71ae5a4SJacob Faibussowitsch case 0: 5043d71ae5a4SJacob Faibussowitsch snum = 0; 5044d71ae5a4SJacob Faibussowitsch break; 5045d71ae5a4SJacob Faibussowitsch case 1: 5046d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 5047d71ae5a4SJacob Faibussowitsch break; 5048d71ae5a4SJacob Faibussowitsch case 2: 5049d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 5050d71ae5a4SJacob Faibussowitsch break; 5051d71ae5a4SJacob Faibussowitsch case 3: 5052d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 5053d71ae5a4SJacob Faibussowitsch break; 5054d71ae5a4SJacob Faibussowitsch default: 5055d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 5056f8d5e320SMatthew G. Knepley } 505708401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 50588ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 50599566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 50608ca92349SMatthew G. Knepley } 50618ca92349SMatthew G. Knepley } 50629566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 50639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 50649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 50659566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 50668ca92349SMatthew G. Knepley if (interpolate) { 50678ca92349SMatthew G. Knepley DM idm; 50688ca92349SMatthew G. Knepley DMLabel bdlabel; 50698ca92349SMatthew G. Knepley 50709566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 50719566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 50728ca92349SMatthew G. Knepley *dm = idm; 50738ca92349SMatthew G. Knepley 5074f8d5e320SMatthew G. Knepley if (!Nl) { 50759566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 50769566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 50779566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 50789566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 50798ca92349SMatthew G. Knepley } 5080f8d5e320SMatthew G. Knepley } 50818ca92349SMatthew G. Knepley PetscFunctionReturn(0); 50828ca92349SMatthew G. Knepley } 50838ca92349SMatthew G. Knepley 50848ca92349SMatthew G. Knepley /*@C 5085ca522641SMatthew G. Knepley DMPlexCreateFromFile - This takes a filename and produces a DM 5086ca522641SMatthew G. Knepley 5087ca522641SMatthew G. Knepley Input Parameters: 5088ca522641SMatthew G. Knepley + comm - The communicator 5089ca522641SMatthew G. Knepley . filename - A file name 5090cd7e8a5eSksagiyam . plexname - The object name of the resulting DM, also used for intra-datafile lookup by some formats 5091ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 5092ca522641SMatthew G. Knepley 5093ca522641SMatthew G. Knepley Output Parameter: 5094ca522641SMatthew G. Knepley . dm - The DM 5095ca522641SMatthew G. Knepley 509602ef0d99SVaclav Hapla Options Database Keys: 509702ef0d99SVaclav Hapla . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5 509802ef0d99SVaclav Hapla 5099bca97951SVaclav Hapla Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g. 5100bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 5101bca97951SVaclav Hapla 5102cd7e8a5eSksagiyam Notes: 5103cd7e8a5eSksagiyam Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex 5104cd7e8a5eSksagiyam meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName() 5105cd7e8a5eSksagiyam before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object. 5106cd7e8a5eSksagiyam The input parameter name is thus used to name the DMPlex object when DMPlexCreateFromFile() internally 5107cd7e8a5eSksagiyam calls DMLoad(). Currently, name is ignored for other viewer types and/or formats. 5108cd7e8a5eSksagiyam 5109ca522641SMatthew G. Knepley Level: beginner 5110ca522641SMatthew G. Knepley 5111db781477SPatrick Sanan .seealso: `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 5112ca522641SMatthew G. Knepley @*/ 5113d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 5114d71ae5a4SJacob Faibussowitsch { 5115ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 5116ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 5117ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 5118ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 5119ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 5120ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 5121ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 5122ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 5123ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 5124ef3a5affSJacob Faibussowitsch const char extMed[] = ".med"; 5125ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 5126ef3a5affSJacob Faibussowitsch const char extEGADSLite[] = ".egadslite"; 5127ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 5128ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 5129ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 5130ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 5131ca522641SMatthew G. Knepley size_t len; 5132c1cad2e7SMatthew G. Knepley PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV; 5133ca522641SMatthew G. Knepley PetscMPIInt rank; 5134ca522641SMatthew G. Knepley 5135ca522641SMatthew G. Knepley PetscFunctionBegin; 51365d80c0bfSVaclav Hapla PetscValidCharPointer(filename, 2); 51370d862eaeSPierre Jolivet if (plexname) PetscValidCharPointer(plexname, 3); 5138cd7e8a5eSksagiyam PetscValidPointer(dm, 5); 51399566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 51409566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 51419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 51429566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 514328b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 5144ef3a5affSJacob Faibussowitsch 51459371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 51469371c9d4SSatish Balay do { \ 5147274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 5148274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 5149274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 5150274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 5151ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 5152ef3a5affSJacob Faibussowitsch } else { \ 5153274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 5154ef3a5affSJacob Faibussowitsch } \ 5155ef3a5affSJacob Faibussowitsch } while (0) 5156ef3a5affSJacob Faibussowitsch 5157ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 5158ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 5159ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 5160ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 5161ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 5162ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 5163ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 5164ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 5165ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 5166ef3a5affSJacob Faibussowitsch CheckExtension(extMed, isMed); 5167ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 5168ef3a5affSJacob Faibussowitsch CheckExtension(extEGADSLite, isEGADSLite); 5169ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 5170ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 5171ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 5172ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 5173ef3a5affSJacob Faibussowitsch 5174ef3a5affSJacob Faibussowitsch #undef CheckExtension 5175ef3a5affSJacob Faibussowitsch 5176de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 51779566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 5178ca522641SMatthew G. Knepley } else if (isCGNS) { 51799566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 518090c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 51819566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 51822f0bd6dcSMichael Lange } else if (isFluent) { 51839566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 5184cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 51859c48423bSVaclav Hapla PetscBool load_hdf5_xdmf = PETSC_FALSE; 5186cc2f8f65SMatthew G. Knepley PetscViewer viewer; 5187cc2f8f65SMatthew G. Knepley 518843b242b4SVaclav 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 */ 51899566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf)); 51909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL)); 51919566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 51929566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 51939566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 51949566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 51959566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 51969566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 5197cd7e8a5eSksagiyam 51989566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 51999566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 52009566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 52019566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 52029566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 52039566063dSJacob Faibussowitsch if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer)); 52049566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 52055fd9971aSMatthew G. Knepley 52065fd9971aSMatthew G. Knepley if (interpolate) { 52075fd9971aSMatthew G. Knepley DM idm; 52085fd9971aSMatthew G. Knepley 52099566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 52109566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 52115fd9971aSMatthew G. Knepley *dm = idm; 52125fd9971aSMatthew G. Knepley } 5213707dd687SMichael Lange } else if (isMed) { 52149566063dSJacob Faibussowitsch PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm)); 5215f2801cd6SMatthew G. Knepley } else if (isPLY) { 52169566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 5217c1cad2e7SMatthew G. Knepley } else if (isEGADSLite || isEGADS || isIGES || isSTEP) { 52189566063dSJacob Faibussowitsch if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm)); 52199566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm)); 52207bee2925SMatthew Knepley if (!interpolate) { 52217bee2925SMatthew Knepley DM udm; 52227bee2925SMatthew Knepley 52239566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 52249566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 52257bee2925SMatthew Knepley *dm = udm; 52267bee2925SMatthew Knepley } 52278ca92349SMatthew G. Knepley } else if (isCV) { 52289566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 522998921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 52309566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 52319566063dSJacob Faibussowitsch if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname)); 52329566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 5233ca522641SMatthew G. Knepley PetscFunctionReturn(0); 5234ca522641SMatthew G. Knepley } 52359f6c5813SMatthew G. Knepley /*@C 52369f6c5813SMatthew 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. 52379f6c5813SMatthew G. Knepley 52389f6c5813SMatthew G. Knepley Input Parameter: 52399f6c5813SMatthew G. Knepley . tr - The `DMPlexTransform` 52409f6c5813SMatthew G. Knepley 52419f6c5813SMatthew G. Knepley Output Parameter: 52429f6c5813SMatthew G. Knepley . dm - The `DM` 52439f6c5813SMatthew G. Knepley 52449f6c5813SMatthew G. Knepley Notes: 52459f6c5813SMatthew 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. 52469f6c5813SMatthew G. Knepley 52479f6c5813SMatthew G. Knepley Level: beginner 52489f6c5813SMatthew G. Knepley 52499f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 52509f6c5813SMatthew G. Knepley @*/ 52519f6c5813SMatthew G. Knepley PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, DM *dm) 52529f6c5813SMatthew G. Knepley { 52539f6c5813SMatthew G. Knepley DM bdm; 52549f6c5813SMatthew G. Knepley PetscInt Nl; 52559f6c5813SMatthew G. Knepley 52569f6c5813SMatthew G. Knepley PetscFunctionBegin; 52579f6c5813SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm)); 52589f6c5813SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 52599f6c5813SMatthew G. Knepley PetscCall(DMSetFromOptions(*dm)); 52609f6c5813SMatthew G. Knepley 52619f6c5813SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)tr)); 52629f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr)); 52639f6c5813SMatthew G. Knepley ((DM_Plex *)(*dm)->data)->tr = tr; 52649f6c5813SMatthew G. Knepley 52659f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformGetDM(tr, &bdm)); 52669f6c5813SMatthew G. Knepley PetscCall(DMGetNumLabels(bdm, &Nl)); 52679f6c5813SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 52689f6c5813SMatthew G. Knepley DMLabel label, labelNew; 52699f6c5813SMatthew G. Knepley const char *lname; 52709f6c5813SMatthew G. Knepley PetscBool isDepth, isCellType; 52719f6c5813SMatthew G. Knepley 52729f6c5813SMatthew G. Knepley PetscCall(DMGetLabelName(bdm, l, &lname)); 52739f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 52749f6c5813SMatthew G. Knepley if (isDepth) continue; 52759f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "celltype", &isCellType)); 52769f6c5813SMatthew G. Knepley if (isCellType) continue; 52779f6c5813SMatthew G. Knepley PetscCall(DMCreateLabel(*dm, lname)); 52789f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(bdm, lname, &label)); 52799f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(*dm, lname, &labelNew)); 52809f6c5813SMatthew G. Knepley PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL)); 52819f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetLabel(labelNew, label)); 52829f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetTransform(labelNew, tr)); 52839f6c5813SMatthew G. Knepley PetscCall(DMLabelSetUp(labelNew)); 52849f6c5813SMatthew G. Knepley } 52859f6c5813SMatthew G. Knepley PetscFunctionReturn(0); 52869f6c5813SMatthew G. Knepley } 5287