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> 5b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h> 6b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h> 7552f7358SJed Brown 8b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 958cd63d5SVaclav Hapla 109318fe57SMatthew G. Knepley /* External function declarations here */ 119318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm); 129318fe57SMatthew G. Knepley 13e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */ 14e600fa54SMatthew G. Knepley PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, DM dmout) 15e600fa54SMatthew G. Knepley { 16e600fa54SMatthew G. Knepley const DMBoundaryType *bd; 17e600fa54SMatthew G. Knepley const PetscReal *maxCell, *L; 18e600fa54SMatthew G. Knepley PetscBool isper, dist; 19e600fa54SMatthew G. Knepley 20e600fa54SMatthew G. Knepley PetscFunctionBegin; 21e600fa54SMatthew G. Knepley if (copyPeriodicity) { 225f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPeriodicity(dmin, &isper, &maxCell, &L, &bd)); 235f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPeriodicity(dmout, isper, maxCell, L, bd)); 24e600fa54SMatthew G. Knepley } 255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeGetDefault(dmin, &dist)); 265f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeSetDefault(dmout, dist)); 27e600fa54SMatthew G. Knepley ((DM_Plex *) dmout->data)->useHashLocation = ((DM_Plex *) dmin->data)->useHashLocation; 28e600fa54SMatthew G. Knepley PetscFunctionReturn(0); 29e600fa54SMatthew G. Knepley } 30e600fa54SMatthew G. Knepley 319318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 329318fe57SMatthew G. Knepley - Share the DM_Plex structure 339318fe57SMatthew G. Knepley - Share the coordinates 349318fe57SMatthew G. Knepley - Share the SF 359318fe57SMatthew G. Knepley */ 369318fe57SMatthew G. Knepley static PetscErrorCode DMPlexReplace_Static(DM dm, DM *ndm) 379318fe57SMatthew G. Knepley { 389318fe57SMatthew G. Knepley PetscSF sf; 399318fe57SMatthew G. Knepley DM dmNew = *ndm, coordDM, coarseDM; 409318fe57SMatthew G. Knepley Vec coords; 419318fe57SMatthew G. Knepley PetscBool isper; 429318fe57SMatthew G. Knepley const PetscReal *maxCell, *L; 439318fe57SMatthew G. Knepley const DMBoundaryType *bd; 449318fe57SMatthew G. Knepley PetscInt dim, cdim; 459318fe57SMatthew G. Knepley 469318fe57SMatthew G. Knepley PetscFunctionBegin; 479318fe57SMatthew G. Knepley if (dm == dmNew) { 485f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(ndm)); 499318fe57SMatthew G. Knepley PetscFunctionReturn(0); 509318fe57SMatthew G. Knepley } 519318fe57SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 525f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dmNew, &dim)); 535f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, dim)); 545f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dmNew, &cdim)); 555f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, cdim)); 565f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dmNew, &sf)); 575f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(dm, sf)); 585f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dmNew, &coordDM)); 595f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dmNew, &coords)); 605f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDM(dm, coordDM)); 615f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coords)); 629318fe57SMatthew G. Knepley /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */ 635f80ce2aSJacob Faibussowitsch CHKERRQ(DMFieldDestroy(&dm->coordinateField)); 649318fe57SMatthew G. Knepley dm->coordinateField = dmNew->coordinateField; 6561a622f3SMatthew G. Knepley ((DM_Plex *) dmNew->data)->coordFunc = ((DM_Plex *) dm->data)->coordFunc; 665f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPeriodicity(dmNew, &isper, &maxCell, &L, &bd)); 675f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPeriodicity(dm, isper, maxCell, L, bd)); 685f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy_Plex(dm)); 695f80ce2aSJacob Faibussowitsch CHKERRQ(DMInitialize_Plex(dm)); 709318fe57SMatthew G. Knepley dm->data = dmNew->data; 719318fe57SMatthew G. Knepley ((DM_Plex *) dmNew->data)->refct++; 725f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroyLabelLinkList_Internal(dm)); 735f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 745f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoarseDM(dmNew,&coarseDM)); 755f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoarseDM(dm,coarseDM)); 765f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(ndm)); 779318fe57SMatthew G. Knepley PetscFunctionReturn(0); 789318fe57SMatthew G. Knepley } 799318fe57SMatthew G. Knepley 809318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew 819318fe57SMatthew G. Knepley - Swap the DM_Plex structure 829318fe57SMatthew G. Knepley - Swap the coordinates 839318fe57SMatthew G. Knepley - Swap the point PetscSF 849318fe57SMatthew G. Knepley */ 859318fe57SMatthew G. Knepley static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 869318fe57SMatthew G. Knepley { 879318fe57SMatthew G. Knepley DM coordDMA, coordDMB; 889318fe57SMatthew G. Knepley Vec coordsA, coordsB; 899318fe57SMatthew G. Knepley PetscSF sfA, sfB; 909318fe57SMatthew G. Knepley DMField fieldTmp; 919318fe57SMatthew G. Knepley void *tmp; 929318fe57SMatthew G. Knepley DMLabelLink listTmp; 939318fe57SMatthew G. Knepley DMLabel depthTmp; 949318fe57SMatthew G. Knepley PetscInt tmpI; 959318fe57SMatthew G. Knepley 969318fe57SMatthew G. Knepley PetscFunctionBegin; 979318fe57SMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 985f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dmA, &sfA)); 995f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dmB, &sfB)); 1005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) sfA)); 1015f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(dmA, sfB)); 1025f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(dmB, sfA)); 1035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectDereference((PetscObject) sfA)); 1049318fe57SMatthew G. Knepley 1055f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dmA, &coordDMA)); 1065f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dmB, &coordDMB)); 1075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) coordDMA)); 1085f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDM(dmA, coordDMB)); 1095f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDM(dmB, coordDMA)); 1105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectDereference((PetscObject) coordDMA)); 1119318fe57SMatthew G. Knepley 1125f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dmA, &coordsA)); 1135f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dmB, &coordsB)); 1145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) coordsA)); 1155f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dmA, coordsB)); 1165f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dmB, coordsA)); 1175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectDereference((PetscObject) coordsA)); 1189318fe57SMatthew G. Knepley 1199318fe57SMatthew G. Knepley fieldTmp = dmA->coordinateField; 1209318fe57SMatthew G. Knepley dmA->coordinateField = dmB->coordinateField; 1219318fe57SMatthew G. Knepley dmB->coordinateField = fieldTmp; 1229318fe57SMatthew G. Knepley tmp = dmA->data; 1239318fe57SMatthew G. Knepley dmA->data = dmB->data; 1249318fe57SMatthew G. Knepley dmB->data = tmp; 1259318fe57SMatthew G. Knepley listTmp = dmA->labels; 1269318fe57SMatthew G. Knepley dmA->labels = dmB->labels; 1279318fe57SMatthew G. Knepley dmB->labels = listTmp; 1289318fe57SMatthew G. Knepley depthTmp = dmA->depthLabel; 1299318fe57SMatthew G. Knepley dmA->depthLabel = dmB->depthLabel; 1309318fe57SMatthew G. Knepley dmB->depthLabel = depthTmp; 1319318fe57SMatthew G. Knepley depthTmp = dmA->celltypeLabel; 1329318fe57SMatthew G. Knepley dmA->celltypeLabel = dmB->celltypeLabel; 1339318fe57SMatthew G. Knepley dmB->celltypeLabel = depthTmp; 1349318fe57SMatthew G. Knepley tmpI = dmA->levelup; 1359318fe57SMatthew G. Knepley dmA->levelup = dmB->levelup; 1369318fe57SMatthew G. Knepley dmB->levelup = tmpI; 1379318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1389318fe57SMatthew G. Knepley } 1399318fe57SMatthew G. Knepley 1409318fe57SMatthew G. Knepley static PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) 1419318fe57SMatthew G. Knepley { 1429318fe57SMatthew G. Knepley DM idm; 1439318fe57SMatthew G. Knepley 1449318fe57SMatthew G. Knepley PetscFunctionBegin; 1455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(dm, &idm)); 1465f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopyCoordinates(dm, idm)); 1475f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &idm)); 1489318fe57SMatthew G. Knepley PetscFunctionReturn(0); 1499318fe57SMatthew G. Knepley } 1509318fe57SMatthew G. Knepley 1519318fe57SMatthew G. Knepley /*@C 1529318fe57SMatthew G. Knepley DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates 1539318fe57SMatthew G. Knepley 1549318fe57SMatthew G. Knepley Collective 1559318fe57SMatthew G. Knepley 1569318fe57SMatthew G. Knepley Input Parameters: 1579318fe57SMatthew G. Knepley + DM - The DM 1584f9ab2b4SJed Brown . degree - The degree of the finite element or PETSC_DECIDE 1599318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface 1609318fe57SMatthew G. Knepley 1619318fe57SMatthew G. Knepley Level: advanced 1629318fe57SMatthew G. Knepley 1639318fe57SMatthew G. Knepley .seealso: PetscFECreateLagrange(), DMGetCoordinateDM() 1649318fe57SMatthew G. Knepley @*/ 1659318fe57SMatthew G. Knepley PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc) 1669318fe57SMatthew G. Knepley { 1679318fe57SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 1689318fe57SMatthew G. Knepley DM cdm; 1699318fe57SMatthew G. Knepley PetscDS cds; 1709318fe57SMatthew G. Knepley PetscFE fe; 1719318fe57SMatthew G. Knepley PetscClassId id; 1729318fe57SMatthew G. Knepley 1739318fe57SMatthew G. Knepley PetscFunctionBegin; 1745f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 1755f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(cdm, &cds)); 1765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetDiscretization(cds, 0, (PetscObject *) &fe)); 1775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId((PetscObject) fe, &id)); 1789318fe57SMatthew G. Knepley if (id != PETSCFE_CLASSID) { 1799318fe57SMatthew G. Knepley PetscBool simplex; 1809318fe57SMatthew G. Knepley PetscInt dim, dE, qorder; 1815f80ce2aSJacob Faibussowitsch PetscErrorCode ierr; 1829318fe57SMatthew G. Knepley 1835f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 1845f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm, &dE)); 1855f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsSimplex(dm, &simplex)); 1869318fe57SMatthew G. Knepley qorder = degree; 1879318fe57SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) cdm);CHKERRQ(ierr); 1885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-coord_dm_default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0)); 1899318fe57SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 1904f9ab2b4SJed Brown if (degree == PETSC_DECIDE) fe = NULL; 1914f9ab2b4SJed Brown else { 1925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, degree, qorder, &fe)); 1935f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(cdm, 0, NULL, (PetscObject) fe)); 1945f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateDS(cdm)); 1954f9ab2b4SJed Brown } 1965f80ce2aSJacob Faibussowitsch CHKERRQ(DMProjectCoordinates(dm, fe)); 1975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEDestroy(&fe)); 1989318fe57SMatthew G. Knepley } 1999318fe57SMatthew G. Knepley mesh->coordFunc = coordFunc; 2009318fe57SMatthew G. Knepley PetscFunctionReturn(0); 2019318fe57SMatthew G. Knepley } 2029318fe57SMatthew G. Knepley 2031df5d5c5SMatthew G. Knepley /*@ 2041df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 2051df5d5c5SMatthew G. Knepley 206d083f849SBarry Smith Collective 2071df5d5c5SMatthew G. Knepley 2081df5d5c5SMatthew G. Knepley Input Parameters: 2091df5d5c5SMatthew G. Knepley + comm - The communicator for the DM object 2101df5d5c5SMatthew G. Knepley . dim - The spatial dimension 2111df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 2121df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 2131df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 2141df5d5c5SMatthew G. Knepley 2151df5d5c5SMatthew G. Knepley Output Parameter: 2161df5d5c5SMatthew G. Knepley . dm - The DM object 2171df5d5c5SMatthew G. Knepley 2181df5d5c5SMatthew G. Knepley Level: beginner 2191df5d5c5SMatthew G. Knepley 2201df5d5c5SMatthew G. Knepley .seealso: DMSetType(), DMCreate() 2211df5d5c5SMatthew G. Knepley @*/ 2220fdc7489SMatthew Knepley PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) 2231df5d5c5SMatthew G. Knepley { 2241df5d5c5SMatthew G. Knepley DM dm; 2251df5d5c5SMatthew G. Knepley PetscMPIInt rank; 2261df5d5c5SMatthew G. Knepley 2271df5d5c5SMatthew G. Knepley PetscFunctionBegin; 2285f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, &dm)); 2295f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(dm, DMPLEX)); 2305f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, dim)); 2315f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 232ce78fa2fSMatthew G. Knepley switch (dim) { 233ce78fa2fSMatthew G. Knepley case 2: 2345f80ce2aSJacob Faibussowitsch if (simplex) CHKERRQ(PetscObjectSetName((PetscObject) dm, "triangular")); 2355f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscObjectSetName((PetscObject) dm, "quadrilateral")); 236ce78fa2fSMatthew G. Knepley break; 237ce78fa2fSMatthew G. Knepley case 3: 2385f80ce2aSJacob Faibussowitsch if (simplex) CHKERRQ(PetscObjectSetName((PetscObject) dm, "tetrahedral")); 2395f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscObjectSetName((PetscObject) dm, "hexahedral")); 240ce78fa2fSMatthew G. Knepley break; 241ce78fa2fSMatthew G. Knepley default: 24298921bdaSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %D", dim); 243ce78fa2fSMatthew G. Knepley } 2441df5d5c5SMatthew G. Knepley if (rank) { 2451df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 2465f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 2471df5d5c5SMatthew G. Knepley } else { 2481df5d5c5SMatthew G. Knepley switch (dim) { 2491df5d5c5SMatthew G. Knepley case 2: 2501df5d5c5SMatthew G. Knepley if (simplex) { 2511df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 2521df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 2531df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 2541df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 2551df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 2561df5d5c5SMatthew G. Knepley 2575f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2581df5d5c5SMatthew G. Knepley } else { 2591df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 2601df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 2611df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 2621df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2631df5d5c5SMatthew 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}; 2641df5d5c5SMatthew G. Knepley 2655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2661df5d5c5SMatthew G. Knepley } 2671df5d5c5SMatthew G. Knepley break; 2681df5d5c5SMatthew G. Knepley case 3: 2691df5d5c5SMatthew G. Knepley if (simplex) { 2701df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 2711df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 2721df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 2731df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2741df5d5c5SMatthew 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}; 2751df5d5c5SMatthew G. Knepley 2765f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2771df5d5c5SMatthew G. Knepley } else { 2781df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 2791df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 2801df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 2811df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 2821df5d5c5SMatthew G. Knepley 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, 2831df5d5c5SMatthew G. Knepley -1.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5, 2841df5d5c5SMatthew G. Knepley 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, 0.5, 0.5}; 2851df5d5c5SMatthew G. Knepley 2865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2871df5d5c5SMatthew G. Knepley } 2881df5d5c5SMatthew G. Knepley break; 2891df5d5c5SMatthew G. Knepley default: 29098921bdaSJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %D", dim); 2911df5d5c5SMatthew G. Knepley } 2921df5d5c5SMatthew G. Knepley } 2931df5d5c5SMatthew G. Knepley *newdm = dm; 2941df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 2951df5d5c5SMatthew G. Knepley DM rdm; 2961df5d5c5SMatthew G. Knepley const char *name; 2971df5d5c5SMatthew G. Knepley 2985f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 2995f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 3005f80ce2aSJacob Faibussowitsch CHKERRQ(DMRefine(*newdm, comm, &rdm)); 3015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) *newdm, &name)); 3025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) rdm, name)); 3035f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(newdm)); 3041df5d5c5SMatthew G. Knepley *newdm = rdm; 3051df5d5c5SMatthew G. Knepley } 3061df5d5c5SMatthew G. Knepley if (interpolate) { 3075fd9971aSMatthew G. Knepley DM idm; 3081df5d5c5SMatthew G. Knepley 3095f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(*newdm, &idm)); 3105f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(newdm)); 3111df5d5c5SMatthew G. Knepley *newdm = idm; 3121df5d5c5SMatthew G. Knepley } 3131df5d5c5SMatthew G. Knepley PetscFunctionReturn(0); 3141df5d5c5SMatthew G. Knepley } 3151df5d5c5SMatthew G. Knepley 3169318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 3179318fe57SMatthew G. Knepley { 3189318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 3199318fe57SMatthew G. Knepley PetscInt markerRight = 1; 3209318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 3219318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 3229318fe57SMatthew G. Knepley Vec coordinates; 3239318fe57SMatthew G. Knepley PetscSection coordSection; 3249318fe57SMatthew G. Knepley PetscScalar *coords; 3259318fe57SMatthew G. Knepley PetscInt coordSize; 3269318fe57SMatthew G. Knepley PetscMPIInt rank; 3279318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 328552f7358SJed Brown 3299318fe57SMatthew G. Knepley PetscFunctionBegin; 3305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 3319318fe57SMatthew G. Knepley if (markerSeparate) { 3329318fe57SMatthew G. Knepley markerRight = 2; 3339318fe57SMatthew G. Knepley markerLeft = 1; 3349318fe57SMatthew G. Knepley } 3355f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 3369318fe57SMatthew G. Knepley if (!rank) { 3375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numVertices)); 3385f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */ 3395f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", 0, markerLeft)); 3405f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", 1, markerRight)); 3419318fe57SMatthew G. Knepley } 3425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 3435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 3449318fe57SMatthew G. Knepley /* Build coordinates */ 3455f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, cdim)); 3465f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 3475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 3485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, 0, numVertices)); 3495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 3509318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 3515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, cdim)); 3525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 3539318fe57SMatthew G. Knepley } 3545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 3555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 3565f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 3575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 3585f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 3595f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, cdim)); 3605f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 3615f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 3629318fe57SMatthew G. Knepley coords[0] = lower[0]; 3639318fe57SMatthew G. Knepley coords[1] = upper[0]; 3645f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 3655f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 3665f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 3679318fe57SMatthew G. Knepley PetscFunctionReturn(0); 3689318fe57SMatthew G. Knepley } 36926492d91SMatthew G. Knepley 3709318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 371552f7358SJed Brown { 3721df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0]+1)*(edges[1]+1); 3731df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1]; 374552f7358SJed Brown PetscInt markerTop = 1; 375552f7358SJed Brown PetscInt markerBottom = 1; 376552f7358SJed Brown PetscInt markerRight = 1; 377552f7358SJed Brown PetscInt markerLeft = 1; 378552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 379552f7358SJed Brown Vec coordinates; 380552f7358SJed Brown PetscSection coordSection; 381552f7358SJed Brown PetscScalar *coords; 382552f7358SJed Brown PetscInt coordSize; 383552f7358SJed Brown PetscMPIInt rank; 384552f7358SJed Brown PetscInt v, vx, vy; 385552f7358SJed Brown 386552f7358SJed Brown PetscFunctionBegin; 3875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 388552f7358SJed Brown if (markerSeparate) { 3891df21d24SMatthew G. Knepley markerTop = 3; 3901df21d24SMatthew G. Knepley markerBottom = 1; 3911df21d24SMatthew G. Knepley markerRight = 2; 3921df21d24SMatthew G. Knepley markerLeft = 4; 393552f7358SJed Brown } 3945f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 395dd400576SPatrick Sanan if (rank == 0) { 396552f7358SJed Brown PetscInt e, ex, ey; 397552f7358SJed Brown 3985f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numEdges+numVertices)); 399552f7358SJed Brown for (e = 0; e < numEdges; ++e) { 4005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, e, 2)); 401552f7358SJed Brown } 4025f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */ 403552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 404552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 405552f7358SJed Brown PetscInt edge = vx*edges[1] + ey + edges[0]*(edges[1]+1); 406552f7358SJed Brown PetscInt vertex = ey*(edges[0]+1) + vx + numEdges; 407da80777bSKarl Rupp PetscInt cone[2]; 408552f7358SJed Brown 409da80777bSKarl Rupp cone[0] = vertex; cone[1] = vertex+edges[0]+1; 4105f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, edge, cone)); 411552f7358SJed Brown if (vx == edges[0]) { 4125f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerRight)); 4135f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 414552f7358SJed Brown if (ey == edges[1]-1) { 4155f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 4165f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 417552f7358SJed Brown } 418552f7358SJed Brown } else if (vx == 0) { 4195f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerLeft)); 4205f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 421552f7358SJed Brown if (ey == edges[1]-1) { 4225f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 4235f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 424552f7358SJed Brown } 425552f7358SJed Brown } 426552f7358SJed Brown } 427552f7358SJed Brown } 428552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 429552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 430552f7358SJed Brown PetscInt edge = vy*edges[0] + ex; 431552f7358SJed Brown PetscInt vertex = vy*(edges[0]+1) + ex + numEdges; 432da80777bSKarl Rupp PetscInt cone[2]; 433552f7358SJed Brown 434da80777bSKarl Rupp cone[0] = vertex; cone[1] = vertex+1; 4355f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, edge, cone)); 436552f7358SJed Brown if (vy == edges[1]) { 4375f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerTop)); 4385f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 439552f7358SJed Brown if (ex == edges[0]-1) { 4405f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 4415f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 442552f7358SJed Brown } 443552f7358SJed Brown } else if (vy == 0) { 4445f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBottom)); 4455f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 446552f7358SJed Brown if (ex == edges[0]-1) { 4475f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 4485f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 449552f7358SJed Brown } 450552f7358SJed Brown } 451552f7358SJed Brown } 452552f7358SJed Brown } 453552f7358SJed Brown } 4545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 4555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 456552f7358SJed Brown /* Build coordinates */ 4575f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, 2)); 4585f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 4595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 4605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 4615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, 2)); 462552f7358SJed Brown for (v = numEdges; v < numEdges+numVertices; ++v) { 4635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, 2)); 4645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 465552f7358SJed Brown } 4665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 4675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 4685f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 4695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 4705f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 4715f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, 2)); 4725f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 4735f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 474552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 475552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 476552f7358SJed Brown coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx; 477552f7358SJed Brown coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy; 478552f7358SJed Brown } 479552f7358SJed Brown } 4805f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 4815f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 4825f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 483552f7358SJed Brown PetscFunctionReturn(0); 484552f7358SJed Brown } 485552f7358SJed Brown 4869318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 487552f7358SJed Brown { 4889e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 4897b59f5a9SMichael Lange PetscInt numFaces = 2*faces[0]*faces[1] + 2*faces[1]*faces[2] + 2*faces[0]*faces[2]; 490552f7358SJed Brown Vec coordinates; 491552f7358SJed Brown PetscSection coordSection; 492552f7358SJed Brown PetscScalar *coords; 493552f7358SJed Brown PetscInt coordSize; 494552f7358SJed Brown PetscMPIInt rank; 495552f7358SJed Brown PetscInt v, vx, vy, vz; 4967b59f5a9SMichael Lange PetscInt voffset, iface=0, cone[4]; 497552f7358SJed Brown 498552f7358SJed Brown PetscFunctionBegin; 4992c71b3e2SJacob Faibussowitsch PetscCheckFalse((faces[0] < 1) || (faces[1] < 1) || (faces[2] < 1),PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Must have at least 1 face per side"); 5005f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 5019e8abbc3SMichael Lange vertices[0] = faces[0]+1; vertices[1] = faces[1]+1; vertices[2] = faces[2]+1; 5029e8abbc3SMichael Lange numVertices = vertices[0]*vertices[1]*vertices[2]; 503dd400576SPatrick Sanan if (rank == 0) { 504552f7358SJed Brown PetscInt f; 505552f7358SJed Brown 5065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numFaces+numVertices)); 507552f7358SJed Brown for (f = 0; f < numFaces; ++f) { 5085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, f, 4)); 509552f7358SJed Brown } 5105f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */ 5117b59f5a9SMichael Lange 5127b59f5a9SMichael Lange /* Side 0 (Top) */ 5137b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5147b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5157b59f5a9SMichael Lange voffset = numFaces + vertices[0]*vertices[1]*(vertices[2]-1) + vy*vertices[0] + vx; 5167b59f5a9SMichael Lange cone[0] = voffset; cone[1] = voffset+1; cone[2] = voffset+vertices[0]+1; cone[3] = voffset+vertices[0]; 5175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, iface, cone)); 5185f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1)); 5195f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1)); 5205f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+1, 1)); 5215f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1)); 5225f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+1, 1)); 5237b59f5a9SMichael Lange iface++; 524552f7358SJed Brown } 525552f7358SJed Brown } 5267b59f5a9SMichael Lange 5277b59f5a9SMichael Lange /* Side 1 (Bottom) */ 5287b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5297b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5307b59f5a9SMichael Lange voffset = numFaces + vy*(faces[0]+1) + vx; 5317b59f5a9SMichael Lange cone[0] = voffset+1; cone[1] = voffset; cone[2] = voffset+vertices[0]; cone[3] = voffset+vertices[0]+1; 5325f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, iface, cone)); 5335f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1)); 5345f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1)); 5355f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+1, 1)); 5365f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1)); 5375f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+1, 1)); 5387b59f5a9SMichael Lange iface++; 539552f7358SJed Brown } 540552f7358SJed Brown } 5417b59f5a9SMichael Lange 5427b59f5a9SMichael Lange /* Side 2 (Front) */ 5437b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 5447b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5457b59f5a9SMichael Lange voffset = numFaces + vz*vertices[0]*vertices[1] + vx; 5467b59f5a9SMichael Lange cone[0] = voffset; cone[1] = voffset+1; cone[2] = voffset+vertices[0]*vertices[1]+1; cone[3] = voffset+vertices[0]*vertices[1]; 5475f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, iface, cone)); 5485f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1)); 5495f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1)); 5505f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+1, 1)); 5515f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+0, 1)); 5525f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+1, 1)); 5537b59f5a9SMichael Lange iface++; 554552f7358SJed Brown } 5557b59f5a9SMichael Lange } 5567b59f5a9SMichael Lange 5577b59f5a9SMichael Lange /* Side 3 (Back) */ 5587b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 5597b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 5607b59f5a9SMichael Lange voffset = numFaces + vz*vertices[0]*vertices[1] + vertices[0]*(vertices[1]-1) + vx; 5617b59f5a9SMichael Lange cone[0] = voffset+vertices[0]*vertices[1]; cone[1] = voffset+vertices[0]*vertices[1]+1; 5627b59f5a9SMichael Lange cone[2] = voffset+1; cone[3] = voffset; 5635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, iface, cone)); 5645f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1)); 5655f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1)); 5665f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+1, 1)); 5675f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+0, 1)); 5685f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+1, 1)); 5697b59f5a9SMichael Lange iface++; 5707b59f5a9SMichael Lange } 5717b59f5a9SMichael Lange } 5727b59f5a9SMichael Lange 5737b59f5a9SMichael Lange /* Side 4 (Left) */ 5747b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 5757b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 5767b59f5a9SMichael Lange voffset = numFaces + vz*vertices[0]*vertices[1] + vy*vertices[0]; 5777b59f5a9SMichael Lange cone[0] = voffset; cone[1] = voffset+vertices[0]*vertices[1]; 5787b59f5a9SMichael Lange cone[2] = voffset+vertices[0]*vertices[1]+vertices[0]; cone[3] = voffset+vertices[0]; 5795f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, iface, cone)); 5805f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1)); 5815f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1)); 5825f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1)); 5835f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[1]+0, 1)); 5845f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+vertices[0], 1)); 5857b59f5a9SMichael Lange iface++; 5867b59f5a9SMichael Lange } 5877b59f5a9SMichael Lange } 5887b59f5a9SMichael Lange 5897b59f5a9SMichael Lange /* Side 5 (Right) */ 5907b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 5917b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 592aab5bcd8SJed Brown voffset = numFaces + vz*vertices[0]*vertices[1] + vy*vertices[0] + faces[0]; 5937b59f5a9SMichael Lange cone[0] = voffset+vertices[0]*vertices[1]; cone[1] = voffset; 5947b59f5a9SMichael Lange cone[2] = voffset+vertices[0]; cone[3] = voffset+vertices[0]*vertices[1]+vertices[0]; 5955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, iface, cone)); 5965f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1)); 5975f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1)); 5985f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1)); 5995f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+0, 1)); 6005f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+vertices[0], 1)); 6017b59f5a9SMichael Lange iface++; 6027b59f5a9SMichael Lange } 603552f7358SJed Brown } 604552f7358SJed Brown } 6055f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 6065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 607552f7358SJed Brown /* Build coordinates */ 6085f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, 3)); 6095f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 6105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 6115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 6125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, 3)); 613552f7358SJed Brown for (v = numFaces; v < numFaces+numVertices; ++v) { 6145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, 3)); 6155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 616552f7358SJed Brown } 6175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 6185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 6195f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 6205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 6215f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6225f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, 3)); 6235f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 6245f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 625552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 626552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 627552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 628552f7358SJed Brown coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx; 629552f7358SJed Brown coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy; 630552f7358SJed Brown coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz; 631552f7358SJed Brown } 632552f7358SJed Brown } 633552f7358SJed Brown } 6345f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 6355f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 6365f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 637552f7358SJed Brown PetscFunctionReturn(0); 638552f7358SJed Brown } 639552f7358SJed Brown 6409318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) 6419318fe57SMatthew G. Knepley { 6429318fe57SMatthew G. Knepley PetscFunctionBegin; 6439318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 6445f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, dim-1)); 6455f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, dim)); 6469318fe57SMatthew G. Knepley switch (dim) { 6475f80ce2aSJacob Faibussowitsch case 1: CHKERRQ(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces));break; 6485f80ce2aSJacob Faibussowitsch case 2: CHKERRQ(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces));break; 6495f80ce2aSJacob Faibussowitsch case 3: CHKERRQ(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces));break; 65098921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Dimension not supported: %D", dim); 6519318fe57SMatthew G. Knepley } 6525f80ce2aSJacob Faibussowitsch if (interpolate) CHKERRQ(DMPlexInterpolateInPlace_Internal(dm)); 6539318fe57SMatthew G. Knepley PetscFunctionReturn(0); 6549318fe57SMatthew G. Knepley } 6559318fe57SMatthew G. Knepley 6569318fe57SMatthew G. Knepley /*@C 6579318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 6589318fe57SMatthew G. Knepley 6599318fe57SMatthew G. Knepley Collective 6609318fe57SMatthew G. Knepley 6619318fe57SMatthew G. Knepley Input Parameters: 6629318fe57SMatthew G. Knepley + comm - The communicator for the DM object 6639318fe57SMatthew G. Knepley . dim - The spatial dimension of the box, so the resulting mesh is has dimension dim-1 6649318fe57SMatthew 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 6659318fe57SMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 6669318fe57SMatthew G. Knepley . upper - The upper right corner, or NULL for (1, 1, 1) 6679318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 6689318fe57SMatthew G. Knepley 6699318fe57SMatthew G. Knepley Output Parameter: 6709318fe57SMatthew G. Knepley . dm - The DM object 6719318fe57SMatthew G. Knepley 6729318fe57SMatthew G. Knepley Level: beginner 6739318fe57SMatthew G. Knepley 6749318fe57SMatthew G. Knepley .seealso: DMSetFromOptions(), DMPlexCreateBoxMesh(), DMPlexCreateFromFile(), DMSetType(), DMCreate() 6759318fe57SMatthew G. Knepley @*/ 6769318fe57SMatthew G. Knepley PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 6779318fe57SMatthew G. Knepley { 6789318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 6799318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 6809318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 6819318fe57SMatthew G. Knepley 6829318fe57SMatthew G. Knepley PetscFunctionBegin; 6835f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm,dm)); 6845f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm,DMPLEX)); 6855f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 6869318fe57SMatthew G. Knepley PetscFunctionReturn(0); 6879318fe57SMatthew G. Knepley } 6889318fe57SMatthew G. Knepley 6899318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm,PetscInt segments,PetscReal lower,PetscReal upper,DMBoundaryType bd) 690fdbf62faSLisandro Dalcin { 691fdbf62faSLisandro Dalcin PetscInt i,fStart,fEnd,numCells = 0,numVerts = 0; 692fdbf62faSLisandro Dalcin PetscInt numPoints[2],*coneSize,*cones,*coneOrientations; 693fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 694fdbf62faSLisandro Dalcin PetscReal L,maxCell; 695fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 696fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 697fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 698fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 699fdbf62faSLisandro Dalcin PetscMPIInt rank; 700fdbf62faSLisandro Dalcin 701fdbf62faSLisandro Dalcin PetscFunctionBegin; 7029318fe57SMatthew G. Knepley PetscValidPointer(dm,1); 703fdbf62faSLisandro Dalcin 7045f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm,1)); 7055f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm,"marker")); 7065f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm,"Face Sets")); 707fdbf62faSLisandro Dalcin 7085f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm),&rank)); 709dd400576SPatrick Sanan if (rank == 0) numCells = segments; 710dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 711fdbf62faSLisandro Dalcin 712fdbf62faSLisandro Dalcin numPoints[0] = numVerts ; numPoints[1] = numCells; 7135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc4(numCells+numVerts,&coneSize,numCells*2,&cones,numCells+numVerts,&coneOrientations,numVerts,&vertexCoords)); 7145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(coneOrientations,numCells+numVerts)); 715fdbf62faSLisandro Dalcin for (i = 0; i < numCells; ++i) { coneSize[i] = 2; } 716fdbf62faSLisandro Dalcin for (i = 0; i < numVerts; ++i) { coneSize[numCells+i] = 0; } 717fdbf62faSLisandro Dalcin for (i = 0; i < numCells; ++i) { cones[2*i] = numCells + i%numVerts; cones[2*i+1] = numCells + (i+1)%numVerts; } 718fdbf62faSLisandro Dalcin for (i = 0; i < numVerts; ++i) { vertexCoords[i] = lower + (upper-lower)*((PetscReal)i/(PetscReal)numCells); } 7195f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(dm,1,numPoints,coneSize,cones,coneOrientations,vertexCoords)); 7205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree4(coneSize,cones,coneOrientations,vertexCoords)); 721fdbf62faSLisandro Dalcin 7225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(((PetscObject)dm)->options,((PetscObject)dm)->prefix,"-dm_plex_separate_marker",&markerSeparate,NULL)); 723fdbf62faSLisandro Dalcin if (markerSeparate) { markerLeft = faceMarkerLeft; markerRight = faceMarkerRight;} 724dd400576SPatrick Sanan if (!wrap && rank == 0) { 7255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm,1,&fStart,&fEnd)); 7265f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm,"marker",fStart,markerLeft)); 7275f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm,"marker",fEnd-1,markerRight)); 7285f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm,"Face Sets",fStart,faceMarkerLeft)); 7295f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm,"Face Sets",fEnd-1,faceMarkerRight)); 730fdbf62faSLisandro Dalcin } 731fdbf62faSLisandro Dalcin if (wrap) { 732fdbf62faSLisandro Dalcin L = upper - lower; 733fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1*(L/(PetscReal)PetscMax(1,segments)); 7345f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPeriodicity(dm,PETSC_TRUE,&maxCell,&L,&bd)); 735fdbf62faSLisandro Dalcin } 7365f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 737fdbf62faSLisandro Dalcin PetscFunctionReturn(0); 738fdbf62faSLisandro Dalcin } 739fdbf62faSLisandro Dalcin 7409318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 741d6218766SMatthew G. Knepley { 7429318fe57SMatthew G. Knepley DM boundary, vol; 743768d5fceSMatthew G. Knepley PetscInt i; 744d6218766SMatthew G. Knepley 745d6218766SMatthew G. Knepley PetscFunctionBegin; 7469318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 7472c71b3e2SJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCheckFalse(periodicity[i] != DM_BOUNDARY_NONE,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Periodicity is not supported for simplex meshes"); 7485f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), &boundary)); 7495f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(boundary, DMPLEX)); 7505f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 7515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 7525f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopy_Internal(dm, PETSC_TRUE, vol)); 7535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &vol)); 7545f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&boundary)); 755d6218766SMatthew G. Knepley PetscFunctionReturn(0); 756d6218766SMatthew G. Knepley } 757d6218766SMatthew G. Knepley 7583dfda0b1SToby Isaac static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 7593dfda0b1SToby Isaac { 760ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 761f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 762f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 763f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 764f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 765f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 766f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 7673dfda0b1SToby Isaac PetscInt dim; 768d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 7693dfda0b1SToby Isaac PetscMPIInt rank; 7703dfda0b1SToby Isaac 7713dfda0b1SToby Isaac PetscFunctionBegin; 7725f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm,&dim)); 7735f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 7745f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm,"marker")); 7755f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm,"Face Sets")); 7765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 777d8211ee3SMatthew G. Knepley if (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST || 778d8211ee3SMatthew G. Knepley bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST || 779d8211ee3SMatthew G. Knepley bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST) { 7804c67ea77SStefano Zampini 7815f80ce2aSJacob Faibussowitsch if (cutMarker) {CHKERRQ(DMCreateLabel(dm, "periodic_cut")); CHKERRQ(DMGetLabel(dm, "periodic_cut", &cutLabel));} 782d8211ee3SMatthew G. Knepley } 7833dfda0b1SToby Isaac switch (dim) { 7843dfda0b1SToby Isaac case 2: 785f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 786f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 787f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 788f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 7893dfda0b1SToby Isaac break; 7903dfda0b1SToby Isaac case 3: 791f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 792f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 793f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 794f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 795f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 796f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 7973dfda0b1SToby Isaac break; 7983dfda0b1SToby Isaac default: 79998921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Dimension %D not supported",dim); 8003dfda0b1SToby Isaac } 8015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 802f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 803f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 804f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 805f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 806f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 807f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 808f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 8093dfda0b1SToby Isaac } 8103dfda0b1SToby Isaac { 811dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 812dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 813dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 814dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0]+1) : 0; 815dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1]+1) : 0; 816dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2]+1) : 0; 8173dfda0b1SToby Isaac const PetscInt numCells = numXEdges*numYEdges*numZEdges; 8183dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges*numZEdges; 8193dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges*numZEdges; 8203dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges*numYEdges; 8213dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices*numXFaces; 8223dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices*numYFaces; 8233dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices*numZFaces; 8243dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 8253dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges*numYVertices*numZVertices; 8263dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges*numXVertices*numZVertices; 8273dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges*numXVertices*numYVertices; 8283dfda0b1SToby Isaac const PetscInt numVertices = numXVertices*numYVertices*numZVertices; 8293dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 8303dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 8313dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 8323dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 8333dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 8343dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 8353dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 8363dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 8373dfda0b1SToby Isaac Vec coordinates; 8383dfda0b1SToby Isaac PetscSection coordSection; 8393dfda0b1SToby Isaac PetscScalar *coords; 8403dfda0b1SToby Isaac PetscInt coordSize; 8413dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 8423dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 8433dfda0b1SToby Isaac 8445f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numFaces+numEdges+numVertices)); 8453dfda0b1SToby Isaac for (c = 0; c < numCells; c++) { 8465f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, c, 6)); 8473dfda0b1SToby Isaac } 8483dfda0b1SToby Isaac for (f = firstXFace; f < firstXFace+numFaces; ++f) { 8495f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, f, 4)); 8503dfda0b1SToby Isaac } 8513dfda0b1SToby Isaac for (e = firstXEdge; e < firstXEdge+numEdges; ++e) { 8525f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, e, 2)); 8533dfda0b1SToby Isaac } 8545f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */ 8553dfda0b1SToby Isaac /* Build cells */ 8563dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 8573dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 8583dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 8593dfda0b1SToby Isaac PetscInt cell = (fz*numYEdges + fy)*numXEdges + fx; 8603dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy*numXEdges+fx)*numZVertices + fz; 8613dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy*numXEdges+fx)*numZVertices + ((fz+1)%numZVertices); 8623dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz*numXEdges+fx)*numYVertices + fy; 8633dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz*numXEdges+fx)*numYVertices + ((fy+1)%numYVertices); 8643dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz*numYEdges+fy)*numXVertices + fx; 8653dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz*numYEdges+fy)*numXVertices + ((fx+1)%numXVertices); 8663dfda0b1SToby Isaac /* B, T, F, K, R, L */ 867b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 86842206facSLisandro Dalcin PetscInt cone[6]; 8693dfda0b1SToby Isaac 8703dfda0b1SToby Isaac /* no boundary twisting in 3D */ 8713dfda0b1SToby Isaac cone[0] = faceB; cone[1] = faceT; cone[2] = faceF; cone[3] = faceK; cone[4] = faceR; cone[5] = faceL; 8725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, cell, cone)); 8735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, cell, ornt)); 8745f80ce2aSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, cell, 2)); 8755f80ce2aSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, cell, 2)); 8765f80ce2aSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, cell, 2)); 8773dfda0b1SToby Isaac } 8783dfda0b1SToby Isaac } 8793dfda0b1SToby Isaac } 8803dfda0b1SToby Isaac /* Build x faces */ 8813dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 8823dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 8833dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 8843dfda0b1SToby Isaac PetscInt face = firstXFace + (fz*numYEdges+fy) *numXVertices+fx; 8853dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy *numXVertices+fx)*numZEdges + fz; 8863dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy+1)%numYVertices)*numXVertices+fx)*numZEdges + fz; 8873dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz *numXVertices+fx)*numYEdges + fy; 8883dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz+1)%numZVertices)*numXVertices+fx)*numYEdges + fy; 889b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 8903dfda0b1SToby Isaac PetscInt cone[4]; 8913dfda0b1SToby Isaac 8923dfda0b1SToby Isaac if (dim == 3) { 8933dfda0b1SToby Isaac /* markers */ 8943dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 8953dfda0b1SToby Isaac if (fx == numXVertices-1) { 8965f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 8975f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", face, markerRight)); 8983dfda0b1SToby Isaac } 8993dfda0b1SToby Isaac else if (fx == 0) { 9005f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 9015f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", face, markerLeft)); 9023dfda0b1SToby Isaac } 9033dfda0b1SToby Isaac } 9043dfda0b1SToby Isaac } 9053dfda0b1SToby Isaac cone[0] = edgeB; cone[1] = edgeR; cone[2] = edgeT; cone[3] = edgeL; 9065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, face, cone)); 9075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, face, ornt)); 9083dfda0b1SToby Isaac } 9093dfda0b1SToby Isaac } 9103dfda0b1SToby Isaac } 9113dfda0b1SToby Isaac /* Build y faces */ 9123dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 91342206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 9143dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 9153dfda0b1SToby Isaac PetscInt face = firstYFace + (fz*numXEdges+fx)*numYVertices + fy; 9163dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy*numXVertices+ fx)*numZEdges + fz; 9173dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy*numXVertices+((fx+1)%numXVertices))*numZEdges + fz; 9183dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz *numYVertices+fy)*numXEdges + fx; 9193dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz+1)%numZVertices)*numYVertices+fy)*numXEdges + fx; 920b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 9213dfda0b1SToby Isaac PetscInt cone[4]; 9223dfda0b1SToby Isaac 9233dfda0b1SToby Isaac if (dim == 3) { 9243dfda0b1SToby Isaac /* markers */ 9253dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 9263dfda0b1SToby Isaac if (fy == numYVertices-1) { 9275f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 9285f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", face, markerBack)); 9293dfda0b1SToby Isaac } 9303dfda0b1SToby Isaac else if (fy == 0) { 9315f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 9325f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", face, markerFront)); 9333dfda0b1SToby Isaac } 9343dfda0b1SToby Isaac } 9353dfda0b1SToby Isaac } 9363dfda0b1SToby Isaac cone[0] = edgeB; cone[1] = edgeR; cone[2] = edgeT; cone[3] = edgeL; 9375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, face, cone)); 9385f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, face, ornt)); 9393dfda0b1SToby Isaac } 9403dfda0b1SToby Isaac } 9413dfda0b1SToby Isaac } 9423dfda0b1SToby Isaac /* Build z faces */ 9433dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 9443dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 9453dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 9463dfda0b1SToby Isaac PetscInt face = firstZFace + (fy*numXEdges+fx)*numZVertices + fz; 9473dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz*numXVertices+ fx)*numYEdges + fy; 9483dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz*numXVertices+((fx+1)%numXVertices))*numYEdges + fy; 9493dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz*numYVertices+ fy)*numXEdges + fx; 9503dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz*numYVertices+((fy+1)%numYVertices))*numXEdges + fx; 951b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 9523dfda0b1SToby Isaac PetscInt cone[4]; 9533dfda0b1SToby Isaac 9543dfda0b1SToby Isaac if (dim == 2) { 955b5a892a1SMatthew G. Knepley if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges-1) {edgeR += numYEdges-1-2*fy; ornt[1] = -1;} 9563dfda0b1SToby Isaac if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges-1) {edgeT += numXEdges-1-2*fx; ornt[2] = 0;} 9575f80ce2aSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, face, 2)); 9585f80ce2aSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, face, 2)); 959d1c88043SMatthew G. Knepley } else { 9603dfda0b1SToby Isaac /* markers */ 9613dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 9623dfda0b1SToby Isaac if (fz == numZVertices-1) { 9635f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 9645f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", face, markerTop)); 9653dfda0b1SToby Isaac } 9663dfda0b1SToby Isaac else if (fz == 0) { 9675f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 9685f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", face, markerBottom)); 9693dfda0b1SToby Isaac } 9703dfda0b1SToby Isaac } 9713dfda0b1SToby Isaac } 9723dfda0b1SToby Isaac cone[0] = edgeB; cone[1] = edgeR; cone[2] = edgeT; cone[3] = edgeL; 9735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, face, cone)); 9745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, face, ornt)); 9753dfda0b1SToby Isaac } 9763dfda0b1SToby Isaac } 9773dfda0b1SToby Isaac } 9783dfda0b1SToby Isaac /* Build Z edges*/ 9793dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 9803dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 9813dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 9823dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy*numXVertices+vx)*numZEdges + ez; 9833dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez *numYVertices+vy)*numXVertices + vx; 9843dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez+1)%numZVertices)*numYVertices+vy)*numXVertices + vx; 9853dfda0b1SToby Isaac PetscInt cone[2]; 9863dfda0b1SToby Isaac 9873dfda0b1SToby Isaac if (dim == 3) { 9883dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 9893dfda0b1SToby Isaac if (vx == numXVertices-1) { 9905f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerRight)); 9913dfda0b1SToby Isaac } 9923dfda0b1SToby Isaac else if (vx == 0) { 9935f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerLeft)); 9943dfda0b1SToby Isaac } 9953dfda0b1SToby Isaac } 9963dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 9973dfda0b1SToby Isaac if (vy == numYVertices-1) { 9985f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBack)); 9993dfda0b1SToby Isaac } 10003dfda0b1SToby Isaac else if (vy == 0) { 10015f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerFront)); 10023dfda0b1SToby Isaac } 10033dfda0b1SToby Isaac } 10043dfda0b1SToby Isaac } 10053dfda0b1SToby Isaac cone[0] = vertexB; cone[1] = vertexT; 10065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, edge, cone)); 10073dfda0b1SToby Isaac } 10083dfda0b1SToby Isaac } 10093dfda0b1SToby Isaac } 10103dfda0b1SToby Isaac /* Build Y edges*/ 10113dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 10123dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 10133dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 10143dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges-1) ? (numXVertices-vx-1) : (vz*numYVertices+((ey+1)%numYVertices))*numXVertices + vx; 10153dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz*numXVertices+vx)*numYEdges + ey; 10163dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz*numYVertices+ey)*numXVertices + vx; 10173dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 10183dfda0b1SToby Isaac PetscInt cone[2]; 10193dfda0b1SToby Isaac 10203dfda0b1SToby Isaac cone[0] = vertexF; cone[1] = vertexK; 10215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, edge, cone)); 10223dfda0b1SToby Isaac if (dim == 2) { 10233dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 10243dfda0b1SToby Isaac if (vx == numXVertices-1) { 10255f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 10265f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerRight)); 10275f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 10283dfda0b1SToby Isaac if (ey == numYEdges-1) { 10295f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 10303dfda0b1SToby Isaac } 1031d8211ee3SMatthew G. Knepley } else if (vx == 0) { 10325f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 10335f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerLeft)); 10345f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 10353dfda0b1SToby Isaac if (ey == numYEdges-1) { 10365f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 10373dfda0b1SToby Isaac } 10383dfda0b1SToby Isaac } 1039d8211ee3SMatthew G. Knepley } else { 10404c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 10415f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(cutLabel, edge, 1)); 10425f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(cutLabel, cone[0], 1)); 1043d8211ee3SMatthew G. Knepley if (ey == numYEdges-1) { 10445f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(cutLabel, cone[1], 1)); 10453dfda0b1SToby Isaac } 10463dfda0b1SToby Isaac } 1047d8211ee3SMatthew G. Knepley } 1048d8211ee3SMatthew G. Knepley } else { 10493dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 10503dfda0b1SToby Isaac if (vx == numXVertices-1) { 10515f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerRight)); 1052d8211ee3SMatthew G. Knepley } else if (vx == 0) { 10535f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerLeft)); 10543dfda0b1SToby Isaac } 10553dfda0b1SToby Isaac } 10563dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 10573dfda0b1SToby Isaac if (vz == numZVertices-1) { 10585f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerTop)); 1059d8211ee3SMatthew G. Knepley } else if (vz == 0) { 10605f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBottom)); 10613dfda0b1SToby Isaac } 10623dfda0b1SToby Isaac } 10633dfda0b1SToby Isaac } 10643dfda0b1SToby Isaac } 10653dfda0b1SToby Isaac } 10663dfda0b1SToby Isaac } 10673dfda0b1SToby Isaac /* Build X edges*/ 10683dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 10693dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 10703dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 10713dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges-1) ? (numYVertices-vy-1)*numXVertices : (vz*numYVertices+vy)*numXVertices + (ex+1)%numXVertices; 10723dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz*numYVertices+vy)*numXEdges + ex; 10733dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz*numYVertices+vy)*numXVertices + ex; 10743dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 10753dfda0b1SToby Isaac PetscInt cone[2]; 10763dfda0b1SToby Isaac 10773dfda0b1SToby Isaac cone[0] = vertexL; cone[1] = vertexR; 10785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, edge, cone)); 10793dfda0b1SToby Isaac if (dim == 2) { 10803dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 10813dfda0b1SToby Isaac if (vy == numYVertices-1) { 10825f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 10835f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerTop)); 10845f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 10853dfda0b1SToby Isaac if (ex == numXEdges-1) { 10865f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 10873dfda0b1SToby Isaac } 1088d8211ee3SMatthew G. Knepley } else if (vy == 0) { 10895f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 10905f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBottom)); 10915f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 10923dfda0b1SToby Isaac if (ex == numXEdges-1) { 10935f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 10943dfda0b1SToby Isaac } 10953dfda0b1SToby Isaac } 1096d8211ee3SMatthew G. Knepley } else { 10974c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 10985f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(cutLabel, edge, 1)); 10995f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(cutLabel, cone[0], 1)); 1100d8211ee3SMatthew G. Knepley if (ex == numXEdges-1) { 11015f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(cutLabel, cone[1], 1)); 11023dfda0b1SToby Isaac } 11033dfda0b1SToby Isaac } 1104d8211ee3SMatthew G. Knepley } 1105d8211ee3SMatthew G. Knepley } else { 11063dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 11073dfda0b1SToby Isaac if (vy == numYVertices-1) { 11085f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBack)); 11093dfda0b1SToby Isaac } 11103dfda0b1SToby Isaac else if (vy == 0) { 11115f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerFront)); 11123dfda0b1SToby Isaac } 11133dfda0b1SToby Isaac } 11143dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 11153dfda0b1SToby Isaac if (vz == numZVertices-1) { 11165f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerTop)); 11173dfda0b1SToby Isaac } 11183dfda0b1SToby Isaac else if (vz == 0) { 11195f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBottom)); 11203dfda0b1SToby Isaac } 11213dfda0b1SToby Isaac } 11223dfda0b1SToby Isaac } 11233dfda0b1SToby Isaac } 11243dfda0b1SToby Isaac } 11253dfda0b1SToby Isaac } 11265f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 11275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 11283dfda0b1SToby Isaac /* Build coordinates */ 11295f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 11305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 11315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dim)); 11325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVertices)); 11333dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex+numVertices; ++v) { 11345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, dim)); 11355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 11363dfda0b1SToby Isaac } 11375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 11385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 11395f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 11405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 11415f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 11425f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, dim)); 11435f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 11445f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 11453dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 11463dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 11473dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 11483dfda0b1SToby Isaac coords[((vz*numYVertices+vy)*numXVertices+vx)*dim+0] = lower[0] + ((upper[0] - lower[0])/numXEdges)*vx; 11493dfda0b1SToby Isaac coords[((vz*numYVertices+vy)*numXVertices+vx)*dim+1] = lower[1] + ((upper[1] - lower[1])/numYEdges)*vy; 11503dfda0b1SToby Isaac if (dim == 3) { 11513dfda0b1SToby Isaac coords[((vz*numYVertices+vy)*numXVertices+vx)*dim+2] = lower[2] + ((upper[2] - lower[2])/numZEdges)*vz; 11523dfda0b1SToby Isaac } 11533dfda0b1SToby Isaac } 11543dfda0b1SToby Isaac } 11553dfda0b1SToby Isaac } 11565f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 11575f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 11585f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 11593dfda0b1SToby Isaac } 11603dfda0b1SToby Isaac PetscFunctionReturn(0); 11613dfda0b1SToby Isaac } 11623dfda0b1SToby Isaac 11639318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1164a6dfd86eSKarl Rupp { 11659318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 11669318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1167552f7358SJed Brown 1168552f7358SJed Brown PetscFunctionBegin; 11699318fe57SMatthew G. Knepley PetscValidPointer(dm, 1); 11709318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 11715f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, dim)); 11729318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) {fac[d] = faces[d]; bdt[d] = periodicity[d];} 11735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 1174768d5fceSMatthew G. Knepley if (periodicity[0] == DM_BOUNDARY_PERIODIC || periodicity[0] == DM_BOUNDARY_TWIST || 1175768d5fceSMatthew G. Knepley periodicity[1] == DM_BOUNDARY_PERIODIC || periodicity[1] == DM_BOUNDARY_TWIST || 1176768d5fceSMatthew G. Knepley (dim > 2 && (periodicity[2] == DM_BOUNDARY_PERIODIC || periodicity[2] == DM_BOUNDARY_TWIST))) { 1177768d5fceSMatthew G. Knepley PetscReal L[3]; 1178768d5fceSMatthew G. Knepley PetscReal maxCell[3]; 1179552f7358SJed Brown 11809318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 11819318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 11829318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1183768d5fceSMatthew G. Knepley } 11845f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPeriodicity(dm, PETSC_TRUE, maxCell, L, periodicity)); 1185768d5fceSMatthew G. Knepley } 11865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 11879318fe57SMatthew G. Knepley PetscFunctionReturn(0); 11889318fe57SMatthew G. Knepley } 11899318fe57SMatthew G. Knepley 11909318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 11919318fe57SMatthew G. Knepley { 11929318fe57SMatthew G. Knepley PetscFunctionBegin; 11935f80ce2aSJacob Faibussowitsch if (dim == 1) CHKERRQ(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 11945f80ce2aSJacob Faibussowitsch else if (simplex) CHKERRQ(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 11955f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 11969318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1197768d5fceSMatthew G. Knepley DM udm; 1198768d5fceSMatthew G. Knepley 11995f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexUninterpolate(dm, &udm)); 12005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopyCoordinates(dm, udm)); 12015f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &udm)); 1202768d5fceSMatthew G. Knepley } 1203768d5fceSMatthew G. Knepley PetscFunctionReturn(0); 1204c8c68bd8SToby Isaac } 1205c8c68bd8SToby Isaac 1206768d5fceSMatthew G. Knepley /*@C 1207768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1208768d5fceSMatthew G. Knepley 1209d083f849SBarry Smith Collective 1210768d5fceSMatthew G. Knepley 1211768d5fceSMatthew G. Knepley Input Parameters: 1212768d5fceSMatthew G. Knepley + comm - The communicator for the DM object 1213768d5fceSMatthew G. Knepley . dim - The spatial dimension 1214768d5fceSMatthew G. Knepley . simplex - PETSC_TRUE for simplices, PETSC_FALSE for tensor cells 1215fdbf62faSLisandro Dalcin . faces - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 1216768d5fceSMatthew G. Knepley . lower - The lower left corner, or NULL for (0, 0, 0) 1217768d5fceSMatthew G. Knepley . upper - The upper right corner, or NULL for (1, 1, 1) 1218fdbf62faSLisandro Dalcin . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE 1219768d5fceSMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 1220768d5fceSMatthew G. Knepley 1221768d5fceSMatthew G. Knepley Output Parameter: 1222768d5fceSMatthew G. Knepley . dm - The DM object 1223768d5fceSMatthew G. Knepley 12249318fe57SMatthew G. Knepley Note: If you want to customize this mesh using options, you just need to 12259318fe57SMatthew G. Knepley $ DMCreate(comm, &dm); 12269318fe57SMatthew G. Knepley $ DMSetType(dm, DMPLEX); 12279318fe57SMatthew G. Knepley $ DMSetFromOptions(dm); 12289318fe57SMatthew G. Knepley and use the options on the DMSetFromOptions() page. 12291367e252SJed Brown 12301367e252SJed Brown Here is the numbering returned for 2 faces in each direction for tensor cells: 1231768d5fceSMatthew G. Knepley $ 10---17---11---18----12 1232768d5fceSMatthew G. Knepley $ | | | 1233768d5fceSMatthew G. Knepley $ | | | 1234768d5fceSMatthew G. Knepley $ 20 2 22 3 24 1235768d5fceSMatthew G. Knepley $ | | | 1236768d5fceSMatthew G. Knepley $ | | | 1237768d5fceSMatthew G. Knepley $ 7---15----8---16----9 1238768d5fceSMatthew G. Knepley $ | | | 1239768d5fceSMatthew G. Knepley $ | | | 1240768d5fceSMatthew G. Knepley $ 19 0 21 1 23 1241768d5fceSMatthew G. Knepley $ | | | 1242768d5fceSMatthew G. Knepley $ | | | 1243768d5fceSMatthew G. Knepley $ 4---13----5---14----6 1244768d5fceSMatthew G. Knepley 1245768d5fceSMatthew G. Knepley and for simplicial cells 1246768d5fceSMatthew G. Knepley 1247768d5fceSMatthew G. Knepley $ 14----8---15----9----16 1248768d5fceSMatthew G. Knepley $ |\ 5 |\ 7 | 1249768d5fceSMatthew G. Knepley $ | \ | \ | 1250768d5fceSMatthew G. Knepley $ 13 2 14 3 15 1251768d5fceSMatthew G. Knepley $ | 4 \ | 6 \ | 1252768d5fceSMatthew G. Knepley $ | \ | \ | 1253768d5fceSMatthew G. Knepley $ 11----6---12----7----13 1254768d5fceSMatthew G. Knepley $ |\ |\ | 1255768d5fceSMatthew G. Knepley $ | \ 1 | \ 3 | 1256768d5fceSMatthew G. Knepley $ 10 0 11 1 12 1257768d5fceSMatthew G. Knepley $ | 0 \ | 2 \ | 1258768d5fceSMatthew G. Knepley $ | \ | \ | 1259768d5fceSMatthew G. Knepley $ 8----4----9----5----10 1260768d5fceSMatthew G. Knepley 1261768d5fceSMatthew G. Knepley Level: beginner 1262768d5fceSMatthew G. Knepley 12639318fe57SMatthew G. Knepley .seealso: DMSetFromOptions(), DMPlexCreateFromFile(), DMPlexCreateHexCylinderMesh(), DMSetType(), DMCreate() 1264768d5fceSMatthew G. Knepley @*/ 1265768d5fceSMatthew G. Knepley 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) 1266552f7358SJed Brown { 12679318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 1268fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 1269fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 1270fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1271552f7358SJed Brown 1272768d5fceSMatthew G. Knepley PetscFunctionBegin; 12735f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm,dm)); 12745f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm,DMPLEX)); 12755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 12769318fe57SMatthew G. Knepley PetscFunctionReturn(0); 12779318fe57SMatthew G. Knepley } 1278fdbf62faSLisandro Dalcin 1279d410b0cfSMatthew G. Knepley static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 12809318fe57SMatthew G. Knepley { 12819318fe57SMatthew G. Knepley DM bdm, vol; 12829318fe57SMatthew G. Knepley PetscInt i; 12839318fe57SMatthew G. Knepley 12849318fe57SMatthew G. Knepley PetscFunctionBegin; 12852c71b3e2SJacob Faibussowitsch for (i = 0; i < 3; ++i) PetscCheckFalse(periodicity[i] != DM_BOUNDARY_NONE,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 12865f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), &bdm)); 12875f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(bdm, DMPLEX)); 12885f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(bdm, 2)); 12895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 12905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol)); 12915f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&bdm)); 12925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &vol)); 12939318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 12949318fe57SMatthew G. Knepley Vec v; 12959318fe57SMatthew G. Knepley PetscScalar *x; 12969318fe57SMatthew G. Knepley PetscInt cDim, n; 12979318fe57SMatthew G. Knepley 12985f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &v)); 12995f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetBlockSize(v, &cDim)); 13005f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(v, &n)); 13015f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(v, &x)); 13029318fe57SMatthew G. Knepley x += cDim; 13039318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 13045f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(v,&x)); 13055f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, v)); 13069318fe57SMatthew G. Knepley } 1307552f7358SJed Brown PetscFunctionReturn(0); 1308552f7358SJed Brown } 1309552f7358SJed Brown 131000dabe28SStefano Zampini /*@ 131100dabe28SStefano Zampini DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells. 131200dabe28SStefano Zampini 1313d083f849SBarry Smith Collective 131400dabe28SStefano Zampini 131500dabe28SStefano Zampini Input Parameters: 131600dabe28SStefano Zampini + comm - The communicator for the DM object 131700dabe28SStefano Zampini . faces - Number of faces per dimension, or NULL for (1, 1, 1) 131800dabe28SStefano Zampini . lower - The lower left corner, or NULL for (0, 0, 0) 131900dabe28SStefano Zampini . upper - The upper right corner, or NULL for (1, 1, 1) 132000dabe28SStefano Zampini . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE 1321d0fcb9c2SMatthew G. Knepley . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 132200dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 132300dabe28SStefano Zampini 132400dabe28SStefano Zampini Output Parameter: 132500dabe28SStefano Zampini . dm - The DM object 132600dabe28SStefano Zampini 132700dabe28SStefano Zampini Level: beginner 132800dabe28SStefano Zampini 1329d410b0cfSMatthew G. Knepley .seealso: DMPlexCreateHexCylinderMesh(), DMPlexCreateWedgeCylinderMesh(), DMExtrude(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 133000dabe28SStefano Zampini @*/ 1331d0fcb9c2SMatthew G. Knepley PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 133200dabe28SStefano Zampini { 13339318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 133400dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 133500dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 133600dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 133700dabe28SStefano Zampini 133800dabe28SStefano Zampini PetscFunctionBegin; 13395f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm,dm)); 13405f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm,DMPLEX)); 13415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 1342d410b0cfSMatthew G. Knepley if (!interpolate) { 1343d410b0cfSMatthew G. Knepley DM udm; 134400dabe28SStefano Zampini 13455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexUninterpolate(*dm, &udm)); 13465f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(*dm, &udm)); 134700dabe28SStefano Zampini } 134800dabe28SStefano Zampini PetscFunctionReturn(0); 134900dabe28SStefano Zampini } 135000dabe28SStefano Zampini 1351a9074c1eSMatthew G. Knepley /*@C 1352a9074c1eSMatthew G. Knepley DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database. 1353a9074c1eSMatthew G. Knepley 1354d083f849SBarry Smith Logically Collective on dm 1355a9074c1eSMatthew G. Knepley 1356a9074c1eSMatthew G. Knepley Input Parameters: 1357a9074c1eSMatthew G. Knepley + dm - the DM context 1358a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 1359a9074c1eSMatthew G. Knepley 1360a9074c1eSMatthew G. Knepley Notes: 1361a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 1362a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 1363a9074c1eSMatthew G. Knepley 1364a9074c1eSMatthew G. Knepley Level: advanced 1365a9074c1eSMatthew G. Knepley 1366a9074c1eSMatthew G. Knepley .seealso: SNESSetFromOptions() 1367a9074c1eSMatthew G. Knepley @*/ 1368a9074c1eSMatthew G. Knepley PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 1369a9074c1eSMatthew G. Knepley { 1370a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 1371a9074c1eSMatthew G. Knepley 1372a9074c1eSMatthew G. Knepley PetscFunctionBegin; 1373a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) dm, prefix)); 13755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) mesh->partitioner, prefix)); 1376a9074c1eSMatthew G. Knepley PetscFunctionReturn(0); 1377a9074c1eSMatthew G. Knepley } 1378a9074c1eSMatthew G. Knepley 13799318fe57SMatthew G. Knepley /* Remap geometry to cylinder 138061a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 138161a622f3SMatthew G. Knepley 13829318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 13839318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 13849318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 13850510c589SMatthew G. Knepley 13869318fe57SMatthew G. Knepley phi = arctan(y/x) 13879318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 13889318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 13890510c589SMatthew G. Knepley 13909318fe57SMatthew G. Knepley so we remap them using 13910510c589SMatthew G. Knepley 13929318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 13939318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 13940510c589SMatthew G. Knepley 13959318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 13969318fe57SMatthew G. Knepley */ 13979318fe57SMatthew G. Knepley static void snapToCylinder(PetscInt dim, PetscInt Nf, PetscInt NfAux, 13989318fe57SMatthew G. Knepley const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 13999318fe57SMatthew G. Knepley const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 14009318fe57SMatthew G. Knepley PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 14019318fe57SMatthew G. Knepley { 14029318fe57SMatthew G. Knepley const PetscReal dis = 1.0/PetscSqrtReal(2.0); 14039318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5*dis; 140422cc497dSMatthew G. Knepley 14059318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 14069318fe57SMatthew G. Knepley f0[0] = u[0]; 14079318fe57SMatthew G. Knepley f0[1] = u[1]; 14089318fe57SMatthew G. Knepley } else { 14099318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 14100510c589SMatthew G. Knepley 14119318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 14129318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 14139318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 14149318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 14159318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 14169318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI/4.0) && (PetscAbsReal(phi) < 3.0*PETSC_PI/4.0)) { 14179318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2/sinp); 14189318fe57SMatthew G. Knepley df = PetscAbsReal(dis/sinp); 14199318fe57SMatthew G. Knepley xc = ds2*x/PetscAbsReal(y); 14209318fe57SMatthew G. Knepley yc = ds2*PetscSignReal(y); 14219318fe57SMatthew G. Knepley } else { 14229318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2/cosp); 14239318fe57SMatthew G. Knepley df = PetscAbsReal(dis/cosp); 14249318fe57SMatthew G. Knepley xc = ds2*PetscSignReal(x); 14259318fe57SMatthew G. Knepley yc = ds2*y/PetscAbsReal(x); 14269318fe57SMatthew G. Knepley } 14279318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc)*(1.0 - dc)/(df - dc); 14289318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc)*(1.0 - dc)/(df - dc); 14299318fe57SMatthew G. Knepley } 14309318fe57SMatthew G. Knepley f0[2] = u[2]; 14319318fe57SMatthew G. Knepley } 14320510c589SMatthew G. Knepley 14339318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ) 14340510c589SMatthew G. Knepley { 14350510c589SMatthew G. Knepley const PetscInt dim = 3; 14369318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 1437d8c47e87SMatthew G. Knepley PetscMPIInt rank; 14380510c589SMatthew G. Knepley 14390510c589SMatthew G. Knepley PetscFunctionBegin; 14405f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 14415f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, dim)); 14420510c589SMatthew G. Knepley /* Create topology */ 14430510c589SMatthew G. Knepley { 14440510c589SMatthew G. Knepley PetscInt cone[8], c; 14450510c589SMatthew G. Knepley 1446dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 1447dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 1448006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 1449ae8bcbbbSMatthew G. Knepley numCells *= 3; 1450dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 1451006a8963SMatthew G. Knepley } 14525f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVertices)); 14535f80ce2aSJacob Faibussowitsch for (c = 0; c < numCells; c++) CHKERRQ(DMPlexSetConeSize(dm, c, 8)); 14545f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); 1455dd400576SPatrick Sanan if (rank == 0) { 1456006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 1457ae8bcbbbSMatthew G. Knepley cone[0] = 15; cone[1] = 18; cone[2] = 17; cone[3] = 16; 1458ae8bcbbbSMatthew G. Knepley cone[4] = 31; cone[5] = 32; cone[6] = 33; cone[7] = 34; 14595f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 0, cone)); 1460ae8bcbbbSMatthew G. Knepley cone[0] = 16; cone[1] = 17; cone[2] = 24; cone[3] = 23; 1461ae8bcbbbSMatthew G. Knepley cone[4] = 32; cone[5] = 36; cone[6] = 37; cone[7] = 33; /* 22 25 26 21 */ 14625f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 1, cone)); 1463ae8bcbbbSMatthew G. Knepley cone[0] = 18; cone[1] = 27; cone[2] = 24; cone[3] = 17; 1464ae8bcbbbSMatthew G. Knepley cone[4] = 34; cone[5] = 33; cone[6] = 37; cone[7] = 38; 14655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 2, cone)); 1466ae8bcbbbSMatthew G. Knepley cone[0] = 29; cone[1] = 27; cone[2] = 18; cone[3] = 15; 1467ae8bcbbbSMatthew G. Knepley cone[4] = 35; cone[5] = 31; cone[6] = 34; cone[7] = 38; 14685f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 3, cone)); 1469ae8bcbbbSMatthew G. Knepley cone[0] = 29; cone[1] = 15; cone[2] = 16; cone[3] = 23; 1470ae8bcbbbSMatthew G. Knepley cone[4] = 35; cone[5] = 36; cone[6] = 32; cone[7] = 31; 14715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 4, cone)); 1472006a8963SMatthew G. Knepley 1473ae8bcbbbSMatthew G. Knepley cone[0] = 31; cone[1] = 34; cone[2] = 33; cone[3] = 32; 1474ae8bcbbbSMatthew G. Knepley cone[4] = 19; cone[5] = 22; cone[6] = 21; cone[7] = 20; 14755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 5, cone)); 1476ae8bcbbbSMatthew G. Knepley cone[0] = 32; cone[1] = 33; cone[2] = 37; cone[3] = 36; 1477ae8bcbbbSMatthew G. Knepley cone[4] = 22; cone[5] = 25; cone[6] = 26; cone[7] = 21; 14785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 6, cone)); 1479ae8bcbbbSMatthew G. Knepley cone[0] = 34; cone[1] = 38; cone[2] = 37; cone[3] = 33; 1480ae8bcbbbSMatthew G. Knepley cone[4] = 20; cone[5] = 21; cone[6] = 26; cone[7] = 28; 14815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 7, cone)); 1482ae8bcbbbSMatthew G. Knepley cone[0] = 35; cone[1] = 38; cone[2] = 34; cone[3] = 31; 1483ae8bcbbbSMatthew G. Knepley cone[4] = 30; cone[5] = 19; cone[6] = 20; cone[7] = 28; 14845f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 8, cone)); 1485ae8bcbbbSMatthew G. Knepley cone[0] = 35; cone[1] = 31; cone[2] = 32; cone[3] = 36; 1486ae8bcbbbSMatthew G. Knepley cone[4] = 30; cone[5] = 25; cone[6] = 22; cone[7] = 19; 14875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 9, cone)); 1488ae8bcbbbSMatthew G. Knepley 1489ae8bcbbbSMatthew G. Knepley cone[0] = 19; cone[1] = 20; cone[2] = 21; cone[3] = 22; 1490ae8bcbbbSMatthew G. Knepley cone[4] = 15; cone[5] = 16; cone[6] = 17; cone[7] = 18; 14915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 10, cone)); 1492ae8bcbbbSMatthew G. Knepley cone[0] = 22; cone[1] = 21; cone[2] = 26; cone[3] = 25; 1493ae8bcbbbSMatthew G. Knepley cone[4] = 16; cone[5] = 23; cone[6] = 24; cone[7] = 17; 14945f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 11, cone)); 1495ae8bcbbbSMatthew G. Knepley cone[0] = 20; cone[1] = 28; cone[2] = 26; cone[3] = 21; 1496ae8bcbbbSMatthew G. Knepley cone[4] = 18; cone[5] = 17; cone[6] = 24; cone[7] = 27; 14975f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 12, cone)); 1498ae8bcbbbSMatthew G. Knepley cone[0] = 30; cone[1] = 28; cone[2] = 20; cone[3] = 19; 1499ae8bcbbbSMatthew G. Knepley cone[4] = 29; cone[5] = 15; cone[6] = 18; cone[7] = 27; 15005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 13, cone)); 1501ae8bcbbbSMatthew G. Knepley cone[0] = 30; cone[1] = 19; cone[2] = 22; cone[3] = 25; 1502ae8bcbbbSMatthew G. Knepley cone[4] = 29; cone[5] = 23; cone[6] = 16; cone[7] = 15; 15035f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 14, cone)); 1504006a8963SMatthew G. Knepley } else { 150510c6f908SMatthew G. Knepley cone[0] = 5; cone[1] = 8; cone[2] = 7; cone[3] = 6; 150610c6f908SMatthew G. Knepley cone[4] = 9; cone[5] = 12; cone[6] = 11; cone[7] = 10; 15075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 0, cone)); 150810c6f908SMatthew G. Knepley cone[0] = 6; cone[1] = 7; cone[2] = 14; cone[3] = 13; 150910c6f908SMatthew G. Knepley cone[4] = 12; cone[5] = 15; cone[6] = 16; cone[7] = 11; 15105f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 1, cone)); 151110c6f908SMatthew G. Knepley cone[0] = 8; cone[1] = 17; cone[2] = 14; cone[3] = 7; 151210c6f908SMatthew G. Knepley cone[4] = 10; cone[5] = 11; cone[6] = 16; cone[7] = 18; 15135f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 2, cone)); 151410c6f908SMatthew G. Knepley cone[0] = 19; cone[1] = 17; cone[2] = 8; cone[3] = 5; 151510c6f908SMatthew G. Knepley cone[4] = 20; cone[5] = 9; cone[6] = 10; cone[7] = 18; 15165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 3, cone)); 151710c6f908SMatthew G. Knepley cone[0] = 19; cone[1] = 5; cone[2] = 6; cone[3] = 13; 151810c6f908SMatthew G. Knepley cone[4] = 20; cone[5] = 15; cone[6] = 12; cone[7] = 9; 15195f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 4, cone)); 1520006a8963SMatthew G. Knepley } 1521d8c47e87SMatthew G. Knepley } 15225f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 15235f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 15240510c589SMatthew G. Knepley } 1525dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 15260510c589SMatthew G. Knepley { 15270510c589SMatthew G. Knepley Vec coordinates; 15280510c589SMatthew G. Knepley PetscSection coordSection; 15290510c589SMatthew G. Knepley PetscScalar *coords; 15300510c589SMatthew G. Knepley PetscInt coordSize, v; 15310510c589SMatthew G. Knepley const PetscReal dis = 1.0/PetscSqrtReal(2.0); 15320510c589SMatthew G. Knepley const PetscReal ds2 = dis/2.0; 15330510c589SMatthew G. Knepley 15340510c589SMatthew G. Knepley /* Build coordinates */ 15355f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 15365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 15375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dim)); 15385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, numCells, numCells+numVertices)); 15390510c589SMatthew G. Knepley for (v = numCells; v < numCells+numVertices; ++v) { 15405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, dim)); 15415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 15420510c589SMatthew G. Knepley } 15435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 15445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 15455f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 15465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 15475f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 15485f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, dim)); 15495f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 15505f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 1551dd400576SPatrick Sanan if (rank == 0) { 15520510c589SMatthew G. Knepley coords[0*dim+0] = -ds2; coords[0*dim+1] = -ds2; coords[0*dim+2] = 0.0; 15530510c589SMatthew G. Knepley coords[1*dim+0] = ds2; coords[1*dim+1] = -ds2; coords[1*dim+2] = 0.0; 15540510c589SMatthew G. Knepley coords[2*dim+0] = ds2; coords[2*dim+1] = ds2; coords[2*dim+2] = 0.0; 15550510c589SMatthew G. Knepley coords[3*dim+0] = -ds2; coords[3*dim+1] = ds2; coords[3*dim+2] = 0.0; 15560510c589SMatthew G. Knepley coords[4*dim+0] = -ds2; coords[4*dim+1] = -ds2; coords[4*dim+2] = 1.0; 15570510c589SMatthew G. Knepley coords[5*dim+0] = -ds2; coords[5*dim+1] = ds2; coords[5*dim+2] = 1.0; 15580510c589SMatthew G. Knepley coords[6*dim+0] = ds2; coords[6*dim+1] = ds2; coords[6*dim+2] = 1.0; 15590510c589SMatthew G. Knepley coords[7*dim+0] = ds2; coords[7*dim+1] = -ds2; coords[7*dim+2] = 1.0; 15600510c589SMatthew G. Knepley coords[ 8*dim+0] = dis; coords[ 8*dim+1] = -dis; coords[ 8*dim+2] = 0.0; 15610510c589SMatthew G. Knepley coords[ 9*dim+0] = dis; coords[ 9*dim+1] = dis; coords[ 9*dim+2] = 0.0; 15620510c589SMatthew G. Knepley coords[10*dim+0] = dis; coords[10*dim+1] = -dis; coords[10*dim+2] = 1.0; 15630510c589SMatthew G. Knepley coords[11*dim+0] = dis; coords[11*dim+1] = dis; coords[11*dim+2] = 1.0; 15640510c589SMatthew G. Knepley coords[12*dim+0] = -dis; coords[12*dim+1] = dis; coords[12*dim+2] = 0.0; 15650510c589SMatthew G. Knepley coords[13*dim+0] = -dis; coords[13*dim+1] = dis; coords[13*dim+2] = 1.0; 15660510c589SMatthew G. Knepley coords[14*dim+0] = -dis; coords[14*dim+1] = -dis; coords[14*dim+2] = 0.0; 15670510c589SMatthew G. Knepley coords[15*dim+0] = -dis; coords[15*dim+1] = -dis; coords[15*dim+2] = 1.0; 1568ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 1569ae8bcbbbSMatthew G. Knepley /* 15 31 19 */ coords[16*dim+0] = -ds2; coords[16*dim+1] = -ds2; coords[16*dim+2] = 0.5; 1570ae8bcbbbSMatthew G. Knepley /* 16 32 22 */ coords[17*dim+0] = ds2; coords[17*dim+1] = -ds2; coords[17*dim+2] = 0.5; 1571ae8bcbbbSMatthew G. Knepley /* 17 33 21 */ coords[18*dim+0] = ds2; coords[18*dim+1] = ds2; coords[18*dim+2] = 0.5; 1572ae8bcbbbSMatthew G. Knepley /* 18 34 20 */ coords[19*dim+0] = -ds2; coords[19*dim+1] = ds2; coords[19*dim+2] = 0.5; 1573ae8bcbbbSMatthew G. Knepley /* 29 35 30 */ coords[20*dim+0] = -dis; coords[20*dim+1] = -dis; coords[20*dim+2] = 0.5; 1574ae8bcbbbSMatthew G. Knepley /* 23 36 25 */ coords[21*dim+0] = dis; coords[21*dim+1] = -dis; coords[21*dim+2] = 0.5; 1575ae8bcbbbSMatthew G. Knepley /* 24 37 26 */ coords[22*dim+0] = dis; coords[22*dim+1] = dis; coords[22*dim+2] = 0.5; 1576ae8bcbbbSMatthew G. Knepley /* 27 38 28 */ coords[23*dim+0] = -dis; coords[23*dim+1] = dis; coords[23*dim+2] = 0.5; 1577ae8bcbbbSMatthew G. Knepley } 1578d8c47e87SMatthew G. Knepley } 15795f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 15805f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 15815f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 15820510c589SMatthew G. Knepley } 1583006a8963SMatthew G. Knepley /* Create periodicity */ 1584006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 1585006a8963SMatthew G. Knepley PetscReal L[3]; 1586006a8963SMatthew G. Knepley PetscReal maxCell[3]; 1587006a8963SMatthew G. Knepley DMBoundaryType bdType[3]; 1588006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 1589ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 1590ae8bcbbbSMatthew G. Knepley PetscInt i, numZCells = 3; 1591006a8963SMatthew G. Knepley 1592006a8963SMatthew G. Knepley bdType[0] = DM_BOUNDARY_NONE; 1593006a8963SMatthew G. Knepley bdType[1] = DM_BOUNDARY_NONE; 1594006a8963SMatthew G. Knepley bdType[2] = periodicZ; 1595006a8963SMatthew G. Knepley for (i = 0; i < dim; i++) { 1596006a8963SMatthew G. Knepley L[i] = upper[i] - lower[i]; 1597006a8963SMatthew G. Knepley maxCell[i] = 1.1 * (L[i] / numZCells); 1598006a8963SMatthew G. Knepley } 15995f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPeriodicity(dm, PETSC_TRUE, maxCell, L, bdType)); 1600006a8963SMatthew G. Knepley } 1601dbc1dc17SMatthew G. Knepley { 16029318fe57SMatthew G. Knepley DM cdm; 16039318fe57SMatthew G. Knepley PetscDS cds; 16049318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 1605dbc1dc17SMatthew G. Knepley 16065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder)); 16075f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 16085f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(cdm, &cds)); 16095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetConstants(cds, 2, c)); 1610dbc1dc17SMatthew G. Knepley } 16119318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 16125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolateInPlace_Internal(dm)); 16130510c589SMatthew G. Knepley PetscFunctionReturn(0); 16140510c589SMatthew G. Knepley } 16150510c589SMatthew G. Knepley 161624119c2aSMatthew G. Knepley /*@ 16179318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 161824119c2aSMatthew G. Knepley 1619d083f849SBarry Smith Collective 162024119c2aSMatthew G. Knepley 162124119c2aSMatthew G. Knepley Input Parameters: 162224119c2aSMatthew G. Knepley + comm - The communicator for the DM object 16239318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction 162424119c2aSMatthew G. Knepley 162524119c2aSMatthew G. Knepley Output Parameter: 162624119c2aSMatthew G. Knepley . dm - The DM object 162724119c2aSMatthew G. Knepley 16289318fe57SMatthew G. Knepley Note: 16299318fe57SMatthew G. Knepley Here is the output numbering looking from the bottom of the cylinder: 16309318fe57SMatthew G. Knepley $ 17-----14 16319318fe57SMatthew G. Knepley $ | | 16329318fe57SMatthew G. Knepley $ | 2 | 16339318fe57SMatthew G. Knepley $ | | 16349318fe57SMatthew G. Knepley $ 17-----8-----7-----14 16359318fe57SMatthew G. Knepley $ | | | | 16369318fe57SMatthew G. Knepley $ | 3 | 0 | 1 | 16379318fe57SMatthew G. Knepley $ | | | | 16389318fe57SMatthew G. Knepley $ 19-----5-----6-----13 16399318fe57SMatthew G. Knepley $ | | 16409318fe57SMatthew G. Knepley $ | 4 | 16419318fe57SMatthew G. Knepley $ | | 16429318fe57SMatthew G. Knepley $ 19-----13 16439318fe57SMatthew G. Knepley $ 16449318fe57SMatthew G. Knepley $ and up through the top 16459318fe57SMatthew G. Knepley $ 16469318fe57SMatthew G. Knepley $ 18-----16 16479318fe57SMatthew G. Knepley $ | | 16489318fe57SMatthew G. Knepley $ | 2 | 16499318fe57SMatthew G. Knepley $ | | 16509318fe57SMatthew G. Knepley $ 18----10----11-----16 16519318fe57SMatthew G. Knepley $ | | | | 16529318fe57SMatthew G. Knepley $ | 3 | 0 | 1 | 16539318fe57SMatthew G. Knepley $ | | | | 16549318fe57SMatthew G. Knepley $ 20-----9----12-----15 16559318fe57SMatthew G. Knepley $ | | 16569318fe57SMatthew G. Knepley $ | 4 | 16579318fe57SMatthew G. Knepley $ | | 16589318fe57SMatthew G. Knepley $ 20-----15 16599318fe57SMatthew G. Knepley 166024119c2aSMatthew G. Knepley Level: beginner 166124119c2aSMatthew G. Knepley 16629318fe57SMatthew G. Knepley .seealso: DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 166324119c2aSMatthew G. Knepley @*/ 16649318fe57SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm) 16659318fe57SMatthew G. Knepley { 16669318fe57SMatthew G. Knepley PetscFunctionBegin; 16679318fe57SMatthew G. Knepley PetscValidPointer(dm, 3); 16685f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 16695f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 16705f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ)); 16719318fe57SMatthew G. Knepley PetscFunctionReturn(0); 16729318fe57SMatthew G. Knepley } 16739318fe57SMatthew G. Knepley 16749318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 167524119c2aSMatthew G. Knepley { 167624119c2aSMatthew G. Knepley const PetscInt dim = 3; 1677412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 16789fe9f049SMatthew G. Knepley PetscMPIInt rank; 167924119c2aSMatthew G. Knepley 168024119c2aSMatthew G. Knepley PetscFunctionBegin; 16812c71b3e2SJacob Faibussowitsch PetscCheckFalse(n < 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %D cannot be negative", n); 16825f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 16835f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, dim)); 1684412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 16855f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm, "celltype")); 168624119c2aSMatthew G. Knepley /* Create topology */ 168724119c2aSMatthew G. Knepley { 168824119c2aSMatthew G. Knepley PetscInt cone[6], c; 168924119c2aSMatthew G. Knepley 1690dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 1691dd400576SPatrick Sanan numVertices = rank == 0 ? 2*(n+1) : 0; 16925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVertices)); 16935f80ce2aSJacob Faibussowitsch for (c = 0; c < numCells; c++) CHKERRQ(DMPlexSetConeSize(dm, c, 6)); 16945f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); 169524119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 169624119c2aSMatthew G. Knepley cone[0] = c+n*1; cone[1] = (c+1)%n+n*1; cone[2] = 0+3*n; 169724119c2aSMatthew G. Knepley cone[3] = c+n*2; cone[4] = (c+1)%n+n*2; cone[5] = 1+3*n; 16985f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, c, cone)); 16995f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 170024119c2aSMatthew G. Knepley } 17015f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 17025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 170324119c2aSMatthew G. Knepley } 1704412e9a14SMatthew G. Knepley for (v = numCells; v < numCells+numVertices; ++v) { 17055f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 170624119c2aSMatthew G. Knepley } 170724119c2aSMatthew G. Knepley /* Create cylinder geometry */ 170824119c2aSMatthew G. Knepley { 170924119c2aSMatthew G. Knepley Vec coordinates; 171024119c2aSMatthew G. Knepley PetscSection coordSection; 171124119c2aSMatthew G. Knepley PetscScalar *coords; 1712412e9a14SMatthew G. Knepley PetscInt coordSize, c; 171324119c2aSMatthew G. Knepley 171424119c2aSMatthew G. Knepley /* Build coordinates */ 17155f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 17165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 17175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dim)); 17185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, numCells, numCells+numVertices)); 171924119c2aSMatthew G. Knepley for (v = numCells; v < numCells+numVertices; ++v) { 17205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, dim)); 17215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 172224119c2aSMatthew G. Knepley } 17235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 17245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 17255f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 17265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 17275f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 17285f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, dim)); 17295f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 17305f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 173124119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 173224119c2aSMatthew G. Knepley coords[(c+0*n)*dim+0] = PetscCosReal(2.0*c*PETSC_PI/n); coords[(c+0*n)*dim+1] = PetscSinReal(2.0*c*PETSC_PI/n); coords[(c+0*n)*dim+2] = 1.0; 173324119c2aSMatthew G. Knepley coords[(c+1*n)*dim+0] = PetscCosReal(2.0*c*PETSC_PI/n); coords[(c+1*n)*dim+1] = PetscSinReal(2.0*c*PETSC_PI/n); coords[(c+1*n)*dim+2] = 0.0; 173424119c2aSMatthew G. Knepley } 1735dd400576SPatrick Sanan if (rank == 0) { 173624119c2aSMatthew G. Knepley coords[(2*n+0)*dim+0] = 0.0; coords[(2*n+0)*dim+1] = 0.0; coords[(2*n+0)*dim+2] = 1.0; 173724119c2aSMatthew G. Knepley coords[(2*n+1)*dim+0] = 0.0; coords[(2*n+1)*dim+1] = 0.0; coords[(2*n+1)*dim+2] = 0.0; 17389fe9f049SMatthew G. Knepley } 17395f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 17405f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 17415f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 174224119c2aSMatthew G. Knepley } 17439318fe57SMatthew G. Knepley /* Interpolate */ 17445f80ce2aSJacob Faibussowitsch if (interpolate) CHKERRQ(DMPlexInterpolateInPlace_Internal(dm)); 17459318fe57SMatthew G. Knepley PetscFunctionReturn(0); 17469318fe57SMatthew G. Knepley } 17479318fe57SMatthew G. Knepley 17489318fe57SMatthew G. Knepley /*@ 17499318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 17509318fe57SMatthew G. Knepley 17519318fe57SMatthew G. Knepley Collective 17529318fe57SMatthew G. Knepley 17539318fe57SMatthew G. Knepley Input Parameters: 17549318fe57SMatthew G. Knepley + comm - The communicator for the DM object 17559318fe57SMatthew G. Knepley . n - The number of wedges around the origin 17569318fe57SMatthew G. Knepley - interpolate - Create edges and faces 17579318fe57SMatthew G. Knepley 17589318fe57SMatthew G. Knepley Output Parameter: 17599318fe57SMatthew G. Knepley . dm - The DM object 17609318fe57SMatthew G. Knepley 17619318fe57SMatthew G. Knepley Level: beginner 17629318fe57SMatthew G. Knepley 17639318fe57SMatthew G. Knepley .seealso: DMPlexCreateHexCylinderMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 17649318fe57SMatthew G. Knepley @*/ 17659318fe57SMatthew G. Knepley PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 17669318fe57SMatthew G. Knepley { 17679318fe57SMatthew G. Knepley PetscFunctionBegin; 17689318fe57SMatthew G. Knepley PetscValidPointer(dm, 4); 17695f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 17705f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 17715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 177224119c2aSMatthew G. Knepley PetscFunctionReturn(0); 177324119c2aSMatthew G. Knepley } 177424119c2aSMatthew G. Knepley 17759fbee547SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 177665a81367SMatthew G. Knepley { 177765a81367SMatthew G. Knepley PetscReal prod = 0.0; 177865a81367SMatthew G. Knepley PetscInt i; 177965a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 178065a81367SMatthew G. Knepley return PetscSqrtReal(prod); 178165a81367SMatthew G. Knepley } 17829fbee547SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 178365a81367SMatthew G. Knepley { 178465a81367SMatthew G. Knepley PetscReal prod = 0.0; 178565a81367SMatthew G. Knepley PetscInt i; 178665a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i]*y[i]; 178765a81367SMatthew G. Knepley return prod; 178865a81367SMatthew G. Knepley } 178965a81367SMatthew G. Knepley 179051a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 179151a74b61SMatthew G. Knepley static void snapToSphere(PetscInt dim, PetscInt Nf, PetscInt NfAux, 179251a74b61SMatthew G. Knepley const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 179351a74b61SMatthew G. Knepley const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 179451a74b61SMatthew G. Knepley PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 179551a74b61SMatthew G. Knepley { 179651a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 179751a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 179851a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 179951a74b61SMatthew G. Knepley 180051a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 180151a74b61SMatthew G. Knepley fac = r/PetscSqrtReal(norm2); 180251a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d]*fac; 180351a74b61SMatthew G. Knepley } 180451a74b61SMatthew G. Knepley 18059318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 18062829fed8SMatthew G. Knepley { 180765a81367SMatthew G. Knepley const PetscInt embedDim = dim+1; 180865a81367SMatthew G. Knepley PetscSection coordSection; 180965a81367SMatthew G. Knepley Vec coordinates; 181065a81367SMatthew G. Knepley PetscScalar *coords; 181165a81367SMatthew G. Knepley PetscReal *coordsIn; 181265a81367SMatthew G. Knepley PetscInt numCells, numEdges, numVerts, firstVertex, v, firstEdge, coordSize, d, c, e; 181365a81367SMatthew G. Knepley PetscMPIInt rank; 181465a81367SMatthew G. Knepley 181565a81367SMatthew G. Knepley PetscFunctionBegin; 18169318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 18175f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, dim)); 18185f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, dim+1)); 18195f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 182065a81367SMatthew G. Knepley switch (dim) { 182165a81367SMatthew G. Knepley case 2: 182265a81367SMatthew G. Knepley if (simplex) { 182351a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI*PETSC_PHI)/(1.0 + PETSC_PHI); 182451a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0/(1.0 + PETSC_PHI) * (R/radius); 182565a81367SMatthew G. Knepley const PetscInt degree = 5; 182651a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0/(1.0 + PETSC_PHI), PETSC_PHI/(1.0 + PETSC_PHI)}; 182765a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 182865a81367SMatthew G. Knepley PetscInt cone[3]; 182965a81367SMatthew G. Knepley PetscInt *graph, p, i, j, k; 183065a81367SMatthew G. Knepley 183151a74b61SMatthew G. Knepley vertex[0] *= R/radius; vertex[1] *= R/radius; vertex[2] *= R/radius; 1832dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 1833dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 183465a81367SMatthew G. Knepley firstVertex = numCells; 183551a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 183665a81367SMatthew G. Knepley 183765a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 183865a81367SMatthew G. Knepley 183965a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 184051a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 184165a81367SMatthew G. Knepley */ 184265a81367SMatthew G. Knepley /* Construct vertices */ 18435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(numVerts * embedDim, &coordsIn)); 1844dd400576SPatrick Sanan if (rank == 0) { 184565a81367SMatthew G. Knepley for (p = 0, i = 0; p < embedDim; ++p) { 184665a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 184765a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 184865a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[(d+p)%embedDim]*vertex[(d+p)%embedDim]; 184965a81367SMatthew G. Knepley ++i; 185065a81367SMatthew G. Knepley } 185165a81367SMatthew G. Knepley } 185265a81367SMatthew G. Knepley } 185345da822fSValeria Barra } 185465a81367SMatthew G. Knepley /* Construct graph */ 18555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(numVerts * numVerts, &graph)); 185665a81367SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 185765a81367SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 185865a81367SMatthew G. Knepley if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i*embedDim], &coordsIn[j*embedDim]) - edgeLen) < PETSC_SMALL) {graph[i*numVerts+j] = 1; ++k;} 185965a81367SMatthew G. Knepley } 18602c71b3e2SJacob Faibussowitsch PetscCheckFalse(k != degree,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %D degree %D != %D", i, k, degree); 186165a81367SMatthew G. Knepley } 186265a81367SMatthew G. Knepley /* Build Topology */ 18635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVerts)); 186465a81367SMatthew G. Knepley for (c = 0; c < numCells; c++) { 18655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, c, embedDim)); 186665a81367SMatthew G. Knepley } 18675f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */ 186865a81367SMatthew G. Knepley /* Cells */ 186965a81367SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 187065a81367SMatthew G. Knepley for (j = 0; j < i; ++j) { 187165a81367SMatthew G. Knepley for (k = 0; k < j; ++k) { 187265a81367SMatthew G. Knepley if (graph[i*numVerts+j] && graph[j*numVerts+k] && graph[k*numVerts+i]) { 187365a81367SMatthew G. Knepley cone[0] = firstVertex+i; cone[1] = firstVertex+j; cone[2] = firstVertex+k; 187465a81367SMatthew G. Knepley /* Check orientation */ 187565a81367SMatthew G. Knepley { 187665a81367SMatthew G. Knepley const PetscInt epsilon[3][3][3] = {{{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, {{0, 0, -1}, {0, 0, 0}, {1, 0, 0}}, {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0}}}; 187765a81367SMatthew G. Knepley PetscReal normal[3]; 187865a81367SMatthew G. Knepley PetscInt e, f; 187965a81367SMatthew G. Knepley 188065a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 188165a81367SMatthew G. Knepley normal[d] = 0.0; 188265a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 188365a81367SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 188465a81367SMatthew G. Knepley normal[d] += epsilon[d][e][f]*(coordsIn[j*embedDim+e] - coordsIn[i*embedDim+e])*(coordsIn[k*embedDim+f] - coordsIn[i*embedDim+f]); 188565a81367SMatthew G. Knepley } 188665a81367SMatthew G. Knepley } 188765a81367SMatthew G. Knepley } 188865a81367SMatthew G. Knepley if (DotReal(embedDim, normal, &coordsIn[i*embedDim]) < 0) {PetscInt tmp = cone[1]; cone[1] = cone[2]; cone[2] = tmp;} 188965a81367SMatthew G. Knepley } 18905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, c++, cone)); 189165a81367SMatthew G. Knepley } 189265a81367SMatthew G. Knepley } 189365a81367SMatthew G. Knepley } 189465a81367SMatthew G. Knepley } 18955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 18965f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 18975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(graph)); 189865a81367SMatthew G. Knepley } else { 18992829fed8SMatthew G. Knepley /* 19002829fed8SMatthew G. Knepley 12-21--13 19012829fed8SMatthew G. Knepley | | 19022829fed8SMatthew G. Knepley 25 4 24 19032829fed8SMatthew G. Knepley | | 19042829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 19052829fed8SMatthew G. Knepley | | | | 19062829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 19072829fed8SMatthew G. Knepley | | | | 19082829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 19092829fed8SMatthew G. Knepley | | 19102829fed8SMatthew G. Knepley 20 1 19 19112829fed8SMatthew G. Knepley | | 19122829fed8SMatthew G. Knepley 10-18--11 19132829fed8SMatthew G. Knepley | | 19142829fed8SMatthew G. Knepley 23 2 22 19152829fed8SMatthew G. Knepley | | 19162829fed8SMatthew G. Knepley 12-21--13 19172829fed8SMatthew G. Knepley */ 19182829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 19192829fed8SMatthew G. Knepley 1920dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 1921dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 1922dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 192365a81367SMatthew G. Knepley firstVertex = numCells; 192465a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 19252829fed8SMatthew G. Knepley /* Build Topology */ 19265f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numEdges+numVerts)); 19272829fed8SMatthew G. Knepley for (c = 0; c < numCells; c++) { 19285f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, c, 4)); 19292829fed8SMatthew G. Knepley } 19302829fed8SMatthew G. Knepley for (e = firstEdge; e < firstEdge+numEdges; ++e) { 19315f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, e, 2)); 19322829fed8SMatthew G. Knepley } 19335f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */ 1934dd400576SPatrick Sanan if (rank == 0) { 19352829fed8SMatthew G. Knepley /* Cell 0 */ 19362829fed8SMatthew G. Knepley cone[0] = 14; cone[1] = 15; cone[2] = 16; cone[3] = 17; 19375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 0, cone)); 19382829fed8SMatthew G. Knepley ornt[0] = 0; ornt[1] = 0; ornt[2] = 0; ornt[3] = 0; 19395f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, 0, ornt)); 19402829fed8SMatthew G. Knepley /* Cell 1 */ 19412829fed8SMatthew G. Knepley cone[0] = 18; cone[1] = 19; cone[2] = 14; cone[3] = 20; 19425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 1, cone)); 1943b5a892a1SMatthew G. Knepley ornt[0] = 0; ornt[1] = 0; ornt[2] = -1; ornt[3] = 0; 19445f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, 1, ornt)); 19452829fed8SMatthew G. Knepley /* Cell 2 */ 19462829fed8SMatthew G. Knepley cone[0] = 21; cone[1] = 22; cone[2] = 18; cone[3] = 23; 19475f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 2, cone)); 1948b5a892a1SMatthew G. Knepley ornt[0] = 0; ornt[1] = 0; ornt[2] = -1; ornt[3] = 0; 19495f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, 2, ornt)); 19502829fed8SMatthew G. Knepley /* Cell 3 */ 19512829fed8SMatthew G. Knepley cone[0] = 19; cone[1] = 22; cone[2] = 24; cone[3] = 15; 19525f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 3, cone)); 1953b5a892a1SMatthew G. Knepley ornt[0] = -1; ornt[1] = -1; ornt[2] = 0; ornt[3] = -1; 19545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, 3, ornt)); 19552829fed8SMatthew G. Knepley /* Cell 4 */ 19562829fed8SMatthew G. Knepley cone[0] = 16; cone[1] = 24; cone[2] = 21; cone[3] = 25; 19575f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 4, cone)); 1958b5a892a1SMatthew G. Knepley ornt[0] = -1; ornt[1] = -1; ornt[2] = -1; ornt[3] = 0; 19595f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, 4, ornt)); 19602829fed8SMatthew G. Knepley /* Cell 5 */ 19612829fed8SMatthew G. Knepley cone[0] = 20; cone[1] = 17; cone[2] = 25; cone[3] = 23; 19625f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 5, cone)); 1963b5a892a1SMatthew G. Knepley ornt[0] = -1; ornt[1] = -1; ornt[2] = -1; ornt[3] = -1; 19645f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, 5, ornt)); 19652829fed8SMatthew G. Knepley /* Edges */ 19662829fed8SMatthew G. Knepley cone[0] = 6; cone[1] = 7; 19675f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 14, cone)); 19682829fed8SMatthew G. Knepley cone[0] = 7; cone[1] = 8; 19695f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 15, cone)); 19702829fed8SMatthew G. Knepley cone[0] = 8; cone[1] = 9; 19715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 16, cone)); 19722829fed8SMatthew G. Knepley cone[0] = 9; cone[1] = 6; 19735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 17, cone)); 19742829fed8SMatthew G. Knepley cone[0] = 10; cone[1] = 11; 19755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 18, cone)); 19762829fed8SMatthew G. Knepley cone[0] = 11; cone[1] = 7; 19775f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 19, cone)); 19782829fed8SMatthew G. Knepley cone[0] = 6; cone[1] = 10; 19795f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 20, cone)); 19802829fed8SMatthew G. Knepley cone[0] = 12; cone[1] = 13; 19815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 21, cone)); 19822829fed8SMatthew G. Knepley cone[0] = 13; cone[1] = 11; 19835f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 22, cone)); 19842829fed8SMatthew G. Knepley cone[0] = 10; cone[1] = 12; 19855f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 23, cone)); 19862829fed8SMatthew G. Knepley cone[0] = 13; cone[1] = 8; 19875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 24, cone)); 19882829fed8SMatthew G. Knepley cone[0] = 12; cone[1] = 9; 19895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 25, cone)); 199045da822fSValeria Barra } 19915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 19925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 19932829fed8SMatthew G. Knepley /* Build coordinates */ 19945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(numVerts * embedDim, &coordsIn)); 1995dd400576SPatrick Sanan if (rank == 0) { 199651a74b61SMatthew G. Knepley coordsIn[0*embedDim+0] = -R; coordsIn[0*embedDim+1] = R; coordsIn[0*embedDim+2] = -R; 199751a74b61SMatthew G. Knepley coordsIn[1*embedDim+0] = R; coordsIn[1*embedDim+1] = R; coordsIn[1*embedDim+2] = -R; 199851a74b61SMatthew G. Knepley coordsIn[2*embedDim+0] = R; coordsIn[2*embedDim+1] = -R; coordsIn[2*embedDim+2] = -R; 199951a74b61SMatthew G. Knepley coordsIn[3*embedDim+0] = -R; coordsIn[3*embedDim+1] = -R; coordsIn[3*embedDim+2] = -R; 200051a74b61SMatthew G. Knepley coordsIn[4*embedDim+0] = -R; coordsIn[4*embedDim+1] = R; coordsIn[4*embedDim+2] = R; 200151a74b61SMatthew G. Knepley coordsIn[5*embedDim+0] = R; coordsIn[5*embedDim+1] = R; coordsIn[5*embedDim+2] = R; 200251a74b61SMatthew G. Knepley coordsIn[6*embedDim+0] = -R; coordsIn[6*embedDim+1] = -R; coordsIn[6*embedDim+2] = R; 200351a74b61SMatthew G. Knepley coordsIn[7*embedDim+0] = R; coordsIn[7*embedDim+1] = -R; coordsIn[7*embedDim+2] = R; 200465a81367SMatthew G. Knepley } 200545da822fSValeria Barra } 200665a81367SMatthew G. Knepley break; 200765a81367SMatthew G. Knepley case 3: 2008116ded15SMatthew G. Knepley if (simplex) { 2009116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0/PETSC_PHI; 201051a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 201151a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 201251a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5*PETSC_PHI, 0.5/PETSC_PHI, 0.0}; 2013116ded15SMatthew G. Knepley const PetscInt degree = 12; 2014116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 2015116ded15SMatthew G. Knepley PetscInt evenPerm[12][4] = {{0, 1, 2, 3}, {0, 2, 3, 1}, {0, 3, 1, 2}, {1, 0, 3, 2}, {1, 2, 0, 3}, {1, 3, 2, 0}, 2016116ded15SMatthew G. Knepley {2, 0, 1, 3}, {2, 1, 3, 0}, {2, 3, 0, 1}, {3, 0, 2, 1}, {3, 1, 0, 2}, {3, 2, 1, 0}}; 2017116ded15SMatthew G. Knepley PetscInt cone[4]; 2018116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 2019116ded15SMatthew G. Knepley 202051a74b61SMatthew G. Knepley vertexA[0] *= R; vertexA[1] *= R; vertexA[2] *= R; vertexA[3] *= R; 202151a74b61SMatthew G. Knepley vertexB[0] *= R; vertexB[1] *= R; vertexB[2] *= R; vertexB[3] *= R; 202251a74b61SMatthew G. Knepley vertexC[0] *= R; vertexC[1] *= R; vertexC[2] *= R; vertexC[3] *= R; 2023dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 2024dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 2025116ded15SMatthew G. Knepley firstVertex = numCells; 2026116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 2027116ded15SMatthew G. Knepley 2028116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 2029116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 2030116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 2031116ded15SMatthew G. Knepley 2032116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 20336333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 2034116ded15SMatthew G. Knepley 2035116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 2036116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 2037116ded15SMatthew G. Knepley */ 2038116ded15SMatthew G. Knepley /* Construct vertices */ 20395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2040116ded15SMatthew G. Knepley i = 0; 2041dd400576SPatrick Sanan if (rank == 0) { 2042116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2043116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2044116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2045116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 2046116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[d]*vertexA[d]; 2047116ded15SMatthew G. Knepley ++i; 2048116ded15SMatthew G. Knepley } 2049116ded15SMatthew G. Knepley } 2050116ded15SMatthew G. Knepley } 2051116ded15SMatthew G. Knepley } 2052116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 2053116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 2054116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2055116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[(d+p)%embedDim]*vertexB[(d+p)%embedDim]; 2056116ded15SMatthew G. Knepley ++i; 2057116ded15SMatthew G. Knepley } 2058116ded15SMatthew G. Knepley } 2059116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 2060116ded15SMatthew G. Knepley s[3] = 1; 2061116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 2062116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 2063116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 2064116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[evenPerm[p][d]]*vertexC[evenPerm[p][d]]; 2065116ded15SMatthew G. Knepley ++i; 2066116ded15SMatthew G. Knepley } 2067116ded15SMatthew G. Knepley } 2068116ded15SMatthew G. Knepley } 2069116ded15SMatthew G. Knepley } 207045da822fSValeria Barra } 20712c71b3e2SJacob Faibussowitsch PetscCheckFalse(i != numVerts,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %D != %D", i, numVerts); 2072116ded15SMatthew G. Knepley /* Construct graph */ 20735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(numVerts * numVerts, &graph)); 2074116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 2075116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 2076116ded15SMatthew G. Knepley if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i*embedDim], &coordsIn[j*embedDim]) - edgeLen) < PETSC_SMALL) {graph[i*numVerts+j] = 1; ++k;} 2077116ded15SMatthew G. Knepley } 20782c71b3e2SJacob Faibussowitsch PetscCheckFalse(k != degree,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %D degree %D != %D", i, k, degree); 2079116ded15SMatthew G. Knepley } 2080116ded15SMatthew G. Knepley /* Build Topology */ 20815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVerts)); 2082116ded15SMatthew G. Knepley for (c = 0; c < numCells; c++) { 20835f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, c, embedDim)); 2084116ded15SMatthew G. Knepley } 20855f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */ 2086116ded15SMatthew G. Knepley /* Cells */ 2087dd400576SPatrick Sanan if (rank == 0) { 2088116ded15SMatthew G. Knepley for (i = 0, c = 0; i < numVerts; ++i) { 2089116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 2090116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 2091116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 2092116ded15SMatthew G. Knepley if (graph[i*numVerts+j] && graph[j*numVerts+k] && graph[k*numVerts+i] && 2093116ded15SMatthew G. Knepley graph[l*numVerts+i] && graph[l*numVerts+j] && graph[l*numVerts+k]) { 2094116ded15SMatthew G. Knepley cone[0] = firstVertex+i; cone[1] = firstVertex+j; cone[2] = firstVertex+k; cone[3] = firstVertex+l; 2095116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 2096116ded15SMatthew G. Knepley { 2097116ded15SMatthew G. Knepley const PetscInt epsilon[4][4][4][4] = {{{{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 2098116ded15SMatthew G. Knepley {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 1}, { 0, 0, -1, 0}}, 2099116ded15SMatthew G. Knepley {{0, 0, 0, 0}, { 0, 0, 0, -1}, { 0, 0, 0, 0}, { 0, 1, 0, 0}}, 2100116ded15SMatthew G. Knepley {{0, 0, 0, 0}, { 0, 0, 1, 0}, { 0, -1, 0, 0}, { 0, 0, 0, 0}}}, 2101116ded15SMatthew G. Knepley 2102116ded15SMatthew G. Knepley {{{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, -1}, { 0, 0, 1, 0}}, 2103116ded15SMatthew G. Knepley {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 2104116ded15SMatthew G. Knepley {{0, 0, 0, 1}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, {-1, 0, 0, 0}}, 2105116ded15SMatthew G. Knepley {{0, 0, -1, 0}, { 0, 0, 0, 0}, { 1, 0, 0, 0}, { 0, 0, 0, 0}}}, 2106116ded15SMatthew G. Knepley 2107116ded15SMatthew G. Knepley {{{0, 0, 0, 0}, { 0, 0, 0, 1}, { 0, 0, 0, 0}, { 0, -1, 0, 0}}, 2108116ded15SMatthew G. Knepley {{0, 0, 0, -1}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 1, 0, 0, 0}}, 2109116ded15SMatthew G. Knepley {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 2110116ded15SMatthew G. Knepley {{0, 1, 0, 0}, {-1, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}}, 2111116ded15SMatthew G. Knepley 2112116ded15SMatthew G. Knepley {{{0, 0, 0, 0}, { 0, 0, -1, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 0}}, 2113116ded15SMatthew G. Knepley {{0, 0, 1, 0}, { 0, 0, 0, 0}, {-1, 0, 0, 0}, { 0, 0, 0, 0}}, 2114116ded15SMatthew G. Knepley {{0, -1, 0, 0}, { 1, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 2115116ded15SMatthew G. Knepley {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}}}; 2116116ded15SMatthew G. Knepley PetscReal normal[4]; 2117116ded15SMatthew G. Knepley PetscInt e, f, g; 2118116ded15SMatthew G. Knepley 2119116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 2120116ded15SMatthew G. Knepley normal[d] = 0.0; 2121116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 2122116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 2123116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 2124116ded15SMatthew 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]); 2125116ded15SMatthew G. Knepley } 2126116ded15SMatthew G. Knepley } 2127116ded15SMatthew G. Knepley } 2128116ded15SMatthew G. Knepley } 2129116ded15SMatthew G. Knepley if (DotReal(embedDim, normal, &coordsIn[i*embedDim]) < 0) {PetscInt tmp = cone[1]; cone[1] = cone[2]; cone[2] = tmp;} 2130116ded15SMatthew G. Knepley } 21315f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, c++, cone)); 2132116ded15SMatthew G. Knepley } 2133116ded15SMatthew G. Knepley } 2134116ded15SMatthew G. Knepley } 2135116ded15SMatthew G. Knepley } 2136116ded15SMatthew G. Knepley } 213745da822fSValeria Barra } 21385f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 21395f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 21405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(graph)); 2141116ded15SMatthew G. Knepley break; 2142116ded15SMatthew G. Knepley } 214398921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %D", dim); 214465a81367SMatthew G. Knepley } 214565a81367SMatthew G. Knepley /* Create coordinates */ 21465f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 21475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 21485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 21495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVerts)); 21502829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex+numVerts; ++v) { 21515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, embedDim)); 21525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 21532829fed8SMatthew G. Knepley } 21545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 21555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 21565f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 21575f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, embedDim)); 21585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 21595f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 21605f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 21615f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 216265a81367SMatthew G. Knepley for (v = 0; v < numVerts; ++v) for (d = 0; d < embedDim; ++d) {coords[v*embedDim+d] = coordsIn[v*embedDim+d];} 21635f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 21645f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 21655f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 21665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(coordsIn)); 216751a74b61SMatthew G. Knepley { 216851a74b61SMatthew G. Knepley DM cdm; 216951a74b61SMatthew G. Knepley PetscDS cds; 21709318fe57SMatthew G. Knepley PetscScalar c = R; 217151a74b61SMatthew G. Knepley 21725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere)); 21735f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 21745f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(cdm, &cds)); 21755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetConstants(cds, 1, &c)); 217651a74b61SMatthew G. Knepley } 21779318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 21785f80ce2aSJacob Faibussowitsch if (simplex) CHKERRQ(DMPlexInterpolateInPlace_Internal(dm)); 21799318fe57SMatthew G. Knepley PetscFunctionReturn(0); 21809318fe57SMatthew G. Knepley } 21819318fe57SMatthew G. Knepley 2182b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal*, PetscReal[], PetscReal(*)[3]); 2183b7f5c055SJed Brown 2184b7f5c055SJed Brown /* 2185b7f5c055SJed Brown The Schwarz P implicit surface is 2186b7f5c055SJed Brown 2187b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 2188b7f5c055SJed Brown */ 2189b7f5c055SJed Brown static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2190b7f5c055SJed Brown { 2191b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 2192b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 2193b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 2194b7f5c055SJed Brown for (PetscInt i=0; i<3; i++) { 2195b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 2196b7f5c055SJed Brown for (PetscInt j=0; j<3; j++) { 2197b7f5c055SJed Brown hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 2198b7f5c055SJed Brown } 2199b7f5c055SJed Brown } 2200b7f5c055SJed Brown } 2201b7f5c055SJed Brown 2202b7f5c055SJed Brown /* 2203b7f5c055SJed Brown The Gyroid implicit surface is 2204b7f5c055SJed Brown 2205b7f5c055SJed 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) 2206b7f5c055SJed Brown 2207b7f5c055SJed Brown */ 2208b7f5c055SJed Brown static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 2209b7f5c055SJed Brown { 2210b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 2211b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 2212b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 2213b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 2214b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 2215b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 2216b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 2217b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2218b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2219b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 2220b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2221b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 2222b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 2223b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 2224b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 2225b7f5c055SJed Brown } 2226b7f5c055SJed Brown 2227b7f5c055SJed Brown /* 2228b7f5c055SJed Brown We wish to solve 2229b7f5c055SJed Brown 2230b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 2231b7f5c055SJed Brown 2232b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 2233b7f5c055SJed 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 2234b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 2235b7f5c055SJed Brown 2236b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 2237b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 2238b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 2239b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 2240b7f5c055SJed Brown Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries. 2241b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 2242b7f5c055SJed Brown 2243b7f5c055SJed Brown f(y) = 0 1 equation 2244b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 2245b7f5c055SJed Brown 2246b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 2247b7f5c055SJed Brown */ 2248b7f5c055SJed Brown static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 2249b7f5c055SJed Brown { 2250b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 2251b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 2252b7f5c055SJed Brown PetscReal f, grad[3], n[3], n_y[3][3], norm, norm_y[3], nd, nd_y[3], sign; 2253b7f5c055SJed Brown 2254b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 2255b7f5c055SJed Brown 2256b7f5c055SJed Brown for (PetscInt i=0; i<3; i++) n[i] = grad[i]; 2257b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2258b7f5c055SJed Brown for (PetscInt i=0; i<3; i++) { 2259b7f5c055SJed Brown norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 2260b7f5c055SJed Brown } 2261b7f5c055SJed Brown 2262b7f5c055SJed Brown // Define the Householder reflector 2263b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 2264b7f5c055SJed Brown n[0] += norm * sign; 2265b7f5c055SJed Brown for (PetscInt i=0; i<3; i++) n_y[0][i] += norm_y[i] * sign; 2266b7f5c055SJed Brown 2267b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 2268b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 2269b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 2270b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 2271b7f5c055SJed Brown 2272b7f5c055SJed Brown for (PetscInt i=0; i<3; i++) { 2273b7f5c055SJed Brown n[i] /= norm; 2274b7f5c055SJed Brown for (PetscInt j=0; j<3; j++) { 2275b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 2276b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 2277b7f5c055SJed Brown } 2278b7f5c055SJed Brown } 2279b7f5c055SJed Brown 2280b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 2281b7f5c055SJed 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]; 2282b7f5c055SJed Brown 2283b7f5c055SJed Brown res[0] = f; 2284b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 2285b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 2286b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 2287b7f5c055SJed Brown for (PetscInt j=0; j<3; j++) { 2288b7f5c055SJed Brown J[0 + j*3] = grad[j]; 2289b7f5c055SJed Brown J[1 + j*3] = (j == 1)*1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 2290b7f5c055SJed Brown J[2 + j*3] = (j == 2)*1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 2291b7f5c055SJed Brown } 2292b7f5c055SJed Brown } 2293b7f5c055SJed Brown 2294b7f5c055SJed Brown /* 2295b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 2296b7f5c055SJed Brown */ 2297b7f5c055SJed Brown static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 2298b7f5c055SJed Brown { 2299b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 2300b7f5c055SJed Brown 2301b7f5c055SJed Brown PetscFunctionBegin; 2302b7f5c055SJed Brown for (PetscInt iter=0; iter<10; iter++) { 2303b7f5c055SJed Brown PetscScalar res[3], J[9]; 2304b7f5c055SJed Brown PetscReal resnorm; 2305b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 2306b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 2307b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 23085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "[%D] res [%g %g %g]\n", iter, PetscRealPart(res[0]), PetscRealPart(res[1]), PetscRealPart(res[2]))); 2309b7f5c055SJed Brown } 2310b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 2311b7f5c055SJed Brown 2312b7f5c055SJed Brown // Take the Newton step 23135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 2314b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 2315b7f5c055SJed Brown } 2316b7f5c055SJed Brown for (PetscInt i=0; i<3; i++) x[i] = y[i]; 2317b7f5c055SJed Brown PetscFunctionReturn(0); 2318b7f5c055SJed Brown } 2319b7f5c055SJed Brown 2320b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 2321b7f5c055SJed Brown 23221436d7faSJed Brown static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 2323b7f5c055SJed Brown { 2324b7f5c055SJed Brown PetscMPIInt rank; 2325b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 2326b7f5c055SJed Brown PetscInt (*edges)[2] = NULL, *edgeSets = NULL; 2327b7f5c055SJed Brown PetscInt *cells_flat = NULL; 2328b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 2329b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 2330b7f5c055SJed Brown DMLabel label; 2331b7f5c055SJed Brown 2332b7f5c055SJed Brown PetscFunctionBegin; 23335f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 2334b7f5c055SJed Brown PetscCheck((layers != 0) ^ (thickness == 0.), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Layers %D must be nonzero iff thickness %g is nonzero", layers, (double)thickness); 2335b7f5c055SJed Brown switch (tpstype) { 2336b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 2337b7f5c055SJed 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"); 2338b7f5c055SJed Brown if (!rank) { 2339b7f5c055SJed Brown PetscInt (*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 2340b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 2341b7f5c055SJed Brown PetscReal L = 1; 2342b7f5c055SJed Brown 2343b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 2344b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 2345b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 2346b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 2347b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 2348b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 23495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(3*numVertices, &vtxCoords)); 23505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(Njunctions, &cells)); 23515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(Ncuts*4, &edges)); 23525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(Ncuts*4, &edgeSets)); 2353b7f5c055SJed Brown // x-normal pipes 2354b7f5c055SJed Brown vcount = 0; 2355b7f5c055SJed Brown for (PetscInt i=0; i<extent[0]+1; i++) { 2356b7f5c055SJed Brown for (PetscInt j=0; j<extent[1]; j++) { 2357b7f5c055SJed Brown for (PetscInt k=0; k<extent[2]; k++) { 2358b7f5c055SJed Brown for (PetscInt l=0; l<4; l++) { 2359b7f5c055SJed Brown vtxCoords[vcount++] = (2*i - 1) * L; 2360b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2*l + 1) * PETSC_PI / 4) * L / 2; 2361b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2*l + 1) * PETSC_PI / 4) * L / 2; 2362b7f5c055SJed Brown } 2363b7f5c055SJed Brown } 2364b7f5c055SJed Brown } 2365b7f5c055SJed Brown } 2366b7f5c055SJed Brown // y-normal pipes 2367b7f5c055SJed Brown for (PetscInt i=0; i<extent[0]; i++) { 2368b7f5c055SJed Brown for (PetscInt j=0; j<extent[1]+1; j++) { 2369b7f5c055SJed Brown for (PetscInt k=0; k<extent[2]; k++) { 2370b7f5c055SJed Brown for (PetscInt l=0; l<4; l++) { 2371b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2*l + 1) * PETSC_PI / 4) * L / 2; 2372b7f5c055SJed Brown vtxCoords[vcount++] = (2*j - 1) * L; 2373b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2*l + 1) * PETSC_PI / 4) * L / 2; 2374b7f5c055SJed Brown } 2375b7f5c055SJed Brown } 2376b7f5c055SJed Brown } 2377b7f5c055SJed Brown } 2378b7f5c055SJed Brown // z-normal pipes 2379b7f5c055SJed Brown for (PetscInt i=0; i<extent[0]; i++) { 2380b7f5c055SJed Brown for (PetscInt j=0; j<extent[1]; j++) { 2381b7f5c055SJed Brown for (PetscInt k=0; k<extent[2]+1; k++) { 2382b7f5c055SJed Brown for (PetscInt l=0; l<4; l++) { 2383b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2*l + 1) * PETSC_PI / 4) * L / 2; 2384b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2*l + 1) * PETSC_PI / 4) * L / 2; 2385b7f5c055SJed Brown vtxCoords[vcount++] = (2*k - 1) * L; 2386b7f5c055SJed Brown } 2387b7f5c055SJed Brown } 2388b7f5c055SJed Brown } 2389b7f5c055SJed Brown } 2390b7f5c055SJed Brown // junctions 2391b7f5c055SJed Brown for (PetscInt i=0; i<extent[0]; i++) { 2392b7f5c055SJed Brown for (PetscInt j=0; j<extent[1]; j++) { 2393b7f5c055SJed Brown for (PetscInt k=0; k<extent[2]; k++) { 2394b7f5c055SJed Brown const PetscInt J = (i*extent[1] + j)*extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2])*4 + J*8; 2395b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 2396b7f5c055SJed Brown for (PetscInt ii=0; ii<2; ii++) { 2397b7f5c055SJed Brown for (PetscInt jj=0; jj<2; jj++) { 2398b7f5c055SJed Brown for (PetscInt kk=0; kk<2; kk++) { 2399b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 2400b7f5c055SJed Brown vtxCoords[vcount++] = 2*i*L + (2*ii-1) * Ls; 2401b7f5c055SJed Brown vtxCoords[vcount++] = 2*j*L + (2*jj-1) * Ls; 2402b7f5c055SJed Brown vtxCoords[vcount++] = 2*k*L + (2*kk-1) * Ls; 2403b7f5c055SJed Brown } 2404b7f5c055SJed Brown } 2405b7f5c055SJed Brown } 2406b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 2407b7f5c055SJed Brown {{3,1,0,2}, {7,5,4,6}}, // x-aligned 2408b7f5c055SJed Brown {{5,4,0,1}, {7,6,2,3}}, // y-aligned 2409b7f5c055SJed Brown {{6,2,0,4}, {7,3,1,5}} // z-aligned 2410b7f5c055SJed Brown }; 2411b7f5c055SJed Brown const PetscInt pipe_lo[3] = { // vertex numbers of pipes 2412b7f5c055SJed Brown ((i * extent[1] + j) * extent[2] + k)*4, 2413b7f5c055SJed Brown ((i * (extent[1] + 1) + j) * extent[2] + k + Npipes[0])*4, 2414b7f5c055SJed Brown ((i * extent[1] + j) * (extent[2]+1) + k + Npipes[0] + Npipes[1])*4 2415b7f5c055SJed Brown }; 2416b7f5c055SJed Brown const PetscInt pipe_hi[3] = { // vertex numbers of pipes 2417b7f5c055SJed Brown (((i + 1) * extent[1] + j) * extent[2] + k)*4, 2418b7f5c055SJed Brown ((i * (extent[1] + 1) + j + 1) * extent[2] + k + Npipes[0])*4, 2419b7f5c055SJed Brown ((i * extent[1] + j) * (extent[2]+1) + k + 1 + Npipes[0] + Npipes[1])*4 2420b7f5c055SJed Brown }; 2421b7f5c055SJed Brown for (PetscInt dir=0; dir<3; dir++) { // x,y,z 2422b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 2423b7f5c055SJed Brown for (PetscInt l=0; l<4; l++) { // rotations 2424b7f5c055SJed Brown cells[J][dir*2+0][l][0] = pipe_lo[dir] + l; 2425b7f5c055SJed Brown cells[J][dir*2+0][l][1] = Jvoff + jfaces[dir][0][l]; 2426b7f5c055SJed Brown cells[J][dir*2+0][l][2] = Jvoff + jfaces[dir][0][(l-1+4)%4]; 2427b7f5c055SJed Brown cells[J][dir*2+0][l][3] = pipe_lo[dir] + (l-1+4)%4; 2428b7f5c055SJed Brown cells[J][dir*2+1][l][0] = Jvoff + jfaces[dir][1][l]; 2429b7f5c055SJed Brown cells[J][dir*2+1][l][1] = pipe_hi[dir] + l; 2430b7f5c055SJed Brown cells[J][dir*2+1][l][2] = pipe_hi[dir] + (l-1+4)%4; 2431b7f5c055SJed Brown cells[J][dir*2+1][l][3] = Jvoff + jfaces[dir][1][(l-1+4)%4]; 2432b7f5c055SJed Brown if (ijk[dir] == 0) { 2433b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 2434b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l+1) % 4; 2435b7f5c055SJed Brown edgeSets[numEdges] = dir*2 + 1; 2436b7f5c055SJed Brown numEdges++; 2437b7f5c055SJed Brown } 2438b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 2439b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 2440b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l+1) % 4; 2441b7f5c055SJed Brown edgeSets[numEdges] = dir*2 + 2; 2442b7f5c055SJed Brown numEdges++; 2443b7f5c055SJed Brown } 2444b7f5c055SJed Brown } 2445b7f5c055SJed Brown } 2446b7f5c055SJed Brown } 2447b7f5c055SJed Brown } 2448b7f5c055SJed Brown } 2449b7f5c055SJed Brown PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %D incompatible with number of cuts %D", numEdges, Ncuts); 2450b7f5c055SJed Brown numFaces = 24 * Njunctions; 2451b7f5c055SJed Brown cells_flat = cells[0][0][0]; 2452b7f5c055SJed Brown } 2453b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 2454b7f5c055SJed Brown break; 2455b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 2456b7f5c055SJed Brown if (!rank) { 2457b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 2458b7f5c055SJed Brown // 2459b7f5c055SJed 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) 2460b7f5c055SJed Brown // 2461b7f5c055SJed Brown // on the cell [0,2]^3. 2462b7f5c055SJed Brown // 2463b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 2464b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 2465b7f5c055SJed Brown // like a boomerang: 2466b7f5c055SJed Brown // 2467b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 2468b7f5c055SJed Brown // ----- ------- ------- ------- // 2469b7f5c055SJed Brown // // 2470b7f5c055SJed Brown // + + + + + + + \ + // 2471b7f5c055SJed Brown // \ / \ // 2472b7f5c055SJed Brown // \ `-_ _-' / } // 2473b7f5c055SJed Brown // *-_ `-' _-' / // 2474b7f5c055SJed Brown // + `-+ + + +-' + + / + // 2475b7f5c055SJed Brown // // 2476b7f5c055SJed Brown // // 2477b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 2478b7f5c055SJed Brown // ----- ------- ------- ------- // 2479b7f5c055SJed Brown // // 2480b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 2481b7f5c055SJed Brown // `-_ _-_ _-` / // 2482b7f5c055SJed Brown // \ _-' `-_ / { // 2483b7f5c055SJed Brown // \ / \ // 2484b7f5c055SJed Brown // + + + + + + + \ + // 2485b7f5c055SJed Brown // 2486b7f5c055SJed Brown // 2487b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 2488b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 2489b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 2490b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 2491b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 2492b7f5c055SJed Brown // 2493b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 2494b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 2495b7f5c055SJed Brown // 2496b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 2497b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 2498b7f5c055SJed Brown 2499b7f5c055SJed Brown PetscInt facesPerBlock = 64; 2500b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 2501b7f5c055SJed Brown PetscInt extentPlus[3]; 2502b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 2503b7f5c055SJed Brown const PetscInt A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, 2504b7f5c055SJed Brown II = 8, J = 9, K = 10, L = 11, M = 12, N = 13, O = 14, P = 15, 2505b7f5c055SJed Brown Q = 16, R = 17, S = 18, T = 19, U = 20, V = 21, W = 22, X = 23, 2506b7f5c055SJed Brown Y = 24, Z = 25, Ap = 26, Bp = 27, Cp = 28, Dp = 29, Ep = 30, Fp = 31, 2507b7f5c055SJed Brown Gp = 32, Hp = 33, Ip = 34, Jp = 35, Kp = 36, Lp = 37, Mp = 38, Np = 39, 2508b7f5c055SJed Brown Op = 40, Pp = 41, Qp = 42, Rp = 43, Sp = 44, Tp = 45, Up = 46, Vp = 47, 2509b7f5c055SJed Brown Wp = 48, Xp = 49, Yp = 50, Zp = 51, Aq = 52, Bq = 53, Cq = 54, Dq = 55; 2510b7f5c055SJed Brown const PetscInt pattern[64][4] = 2511b7f5c055SJed Brown { /* face to vertex within the coarse discretization of a single gyroid block */ 2512b7f5c055SJed Brown /* layer 0 */ 2513b7f5c055SJed Brown {A,C,K,G},{C,B,II,K},{D,A,H,L},{B+56*1,D,L,J},{E,B+56*1,J,N},{A+56*2,E,N,H+56*2},{F,A+56*2,G+56*2,M},{B,F,M,II}, 2514b7f5c055SJed Brown /* layer 1 */ 2515b7f5c055SJed Brown {G,K,Q,O},{K,II,P,Q},{L,H,O+56*1,R},{J,L,R,P},{N,J,P,S},{H+56*2,N,S,O+56*3},{M,G+56*2,O+56*2,T},{II,M,T,P}, 2516b7f5c055SJed Brown /* layer 2 */ 2517b7f5c055SJed Brown {O,Q,Y,U},{Q,P,W,Y},{R,O+56*1,U+56*1,Ap},{P,R,Ap,W},{S,P,X,Bp},{O+56*3,S,Bp,V+56*1},{T,O+56*2,V,Z},{P,T,Z,X}, 2518b7f5c055SJed Brown /* layer 3 */ 2519b7f5c055SJed Brown {U,Y,Ep,Dp},{Y,W,Cp,Ep},{Ap,U+56*1,Dp+56*1,Gp},{W,Ap,Gp,Cp},{Bp,X,Cp+56*2,Fp},{V+56*1,Bp,Fp,Dp+56*1},{Z,V,Dp,Hp},{X,Z,Hp,Cp+56*2}, 2520b7f5c055SJed Brown /* layer 4 */ 2521b7f5c055SJed Brown {Dp,Ep,Mp,Kp},{Ep,Cp,Ip,Mp},{Gp,Dp+56*1,Lp,Np},{Cp,Gp,Np,Jp},{Fp,Cp+56*2,Jp+56*2,Pp},{Dp+56*1,Fp,Pp,Lp},{Hp,Dp,Kp,Op},{Cp+56*2,Hp,Op,Ip+56*2}, 2522b7f5c055SJed Brown /* layer 5 */ 2523b7f5c055SJed Brown {Kp,Mp,Sp,Rp},{Mp,Ip,Qp,Sp},{Np,Lp,Rp,Tp},{Jp,Np,Tp,Qp+56*1},{Pp,Jp+56*2,Qp+56*3,Up},{Lp,Pp,Up,Rp},{Op,Kp,Rp,Vp},{Ip+56*2,Op,Vp,Qp+56*2}, 2524b7f5c055SJed Brown /* layer 6 */ 2525b7f5c055SJed Brown {Rp,Sp,Aq,Yp},{Sp,Qp,Wp,Aq},{Tp,Rp,Yp,Cq},{Qp+56*1,Tp,Cq,Wp+56*1},{Up,Qp+56*3,Xp+56*1,Dq},{Rp,Up,Dq,Zp},{Vp,Rp,Zp,Bq},{Qp+56*2,Vp,Bq,Xp}, 2526b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 2527b7f5c055SJed Brown {Yp,Aq,C+56*4,A+56*4},{Aq,Wp,B+56*4,C+56*4},{Cq,Yp,A+56*4,D+56*4},{Wp+56*1,Cq,D+56*4,B+56*5},{Dq,Xp+56*1,B+56*5,E+56*4},{Zp,Dq,E+56*4,A+56*6},{Bq,Zp,A+56*6,F+56*4},{Xp,Bq,F+56*4,B+56*4} 2528b7f5c055SJed Brown }; 2529b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.)-1.) / PetscSqrtReal(2.)) / PETSC_PI; 2530b7f5c055SJed Brown const PetscReal patternCoords[56][3] = 2531b7f5c055SJed Brown { 2532b7f5c055SJed Brown /* A */ {1.,0.,0.}, 2533b7f5c055SJed Brown /* B */ {0.,1.,0.}, 2534b7f5c055SJed Brown /* C */ {gamma,gamma,0.}, 2535b7f5c055SJed Brown /* D */ {1+gamma,1-gamma,0.}, 2536b7f5c055SJed Brown /* E */ {2-gamma,2-gamma,0.}, 2537b7f5c055SJed Brown /* F */ {1-gamma,1+gamma,0.}, 2538b7f5c055SJed Brown 2539b7f5c055SJed Brown /* G */ {.5,0,.25}, 2540b7f5c055SJed Brown /* H */ {1.5,0.,.25}, 2541b7f5c055SJed Brown /* II */ {.5,1.,.25}, 2542b7f5c055SJed Brown /* J */ {1.5,1.,.25}, 2543b7f5c055SJed Brown /* K */ {.25,.5,.25}, 2544b7f5c055SJed Brown /* L */ {1.25,.5,.25}, 2545b7f5c055SJed Brown /* M */ {.75,1.5,.25}, 2546b7f5c055SJed Brown /* N */ {1.75,1.5,.25}, 2547b7f5c055SJed Brown 2548b7f5c055SJed Brown /* O */ {0.,0.,.5}, 2549b7f5c055SJed Brown /* P */ {1.,1.,.5}, 2550b7f5c055SJed Brown /* Q */ {gamma,1-gamma,.5}, 2551b7f5c055SJed Brown /* R */ {1+gamma,gamma,.5}, 2552b7f5c055SJed Brown /* S */ {2-gamma,1+gamma,.5}, 2553b7f5c055SJed Brown /* T */ {1-gamma,2-gamma,.5}, 2554b7f5c055SJed Brown 2555b7f5c055SJed Brown /* U */ {0.,.5,.75}, 2556b7f5c055SJed Brown /* V */ {0.,1.5,.75}, 2557b7f5c055SJed Brown /* W */ {1.,.5,.75}, 2558b7f5c055SJed Brown /* X */ {1.,1.5,.75}, 2559b7f5c055SJed Brown /* Y */ {.5,.75,.75}, 2560b7f5c055SJed Brown /* Z */ {.5,1.75,.75}, 2561b7f5c055SJed Brown /* Ap */ {1.5,.25,.75}, 2562b7f5c055SJed Brown /* Bp */ {1.5,1.25,.75}, 2563b7f5c055SJed Brown 2564b7f5c055SJed Brown /* Cp */ {1.,0.,1.}, 2565b7f5c055SJed Brown /* Dp */ {0.,1.,1.}, 2566b7f5c055SJed Brown /* Ep */ {1-gamma,1-gamma,1.}, 2567b7f5c055SJed Brown /* Fp */ {1+gamma,1+gamma,1.}, 2568b7f5c055SJed Brown /* Gp */ {2-gamma,gamma,1.}, 2569b7f5c055SJed Brown /* Hp */ {gamma,2-gamma,1.}, 2570b7f5c055SJed Brown 2571b7f5c055SJed Brown /* Ip */ {.5,0.,1.25}, 2572b7f5c055SJed Brown /* Jp */ {1.5,0.,1.25}, 2573b7f5c055SJed Brown /* Kp */ {.5,1.,1.25}, 2574b7f5c055SJed Brown /* Lp */ {1.5,1.,1.25}, 2575b7f5c055SJed Brown /* Mp */ {.75,.5,1.25}, 2576b7f5c055SJed Brown /* Np */ {1.75,.5,1.25}, 2577b7f5c055SJed Brown /* Op */ {.25,1.5,1.25}, 2578b7f5c055SJed Brown /* Pp */ {1.25,1.5,1.25}, 2579b7f5c055SJed Brown 2580b7f5c055SJed Brown /* Qp */ {0.,0.,1.5}, 2581b7f5c055SJed Brown /* Rp */ {1.,1.,1.5}, 2582b7f5c055SJed Brown /* Sp */ {1-gamma,gamma,1.5}, 2583b7f5c055SJed Brown /* Tp */ {2-gamma,1-gamma,1.5}, 2584b7f5c055SJed Brown /* Up */ {1+gamma,2-gamma,1.5}, 2585b7f5c055SJed Brown /* Vp */ {gamma,1+gamma,1.5}, 2586b7f5c055SJed Brown 2587b7f5c055SJed Brown /* Wp */ {0.,.5,1.75}, 2588b7f5c055SJed Brown /* Xp */ {0.,1.5,1.75}, 2589b7f5c055SJed Brown /* Yp */ {1.,.5,1.75}, 2590b7f5c055SJed Brown /* Zp */ {1.,1.5,1.75}, 2591b7f5c055SJed Brown /* Aq */ {.5,.25,1.75}, 2592b7f5c055SJed Brown /* Bq */ {.5,1.25,1.75}, 2593b7f5c055SJed Brown /* Cq */ {1.5,.75,1.75}, 2594b7f5c055SJed Brown /* Dq */ {1.5,1.75,1.75}, 2595b7f5c055SJed Brown }; 2596b7f5c055SJed Brown PetscInt (*cells)[64][4] = NULL; 2597b7f5c055SJed Brown PetscBool *seen; 2598b7f5c055SJed Brown PetscInt *vertToTrueVert; 2599b7f5c055SJed Brown PetscInt count; 2600b7f5c055SJed Brown 2601b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 2602b7f5c055SJed Brown numBlocks = 1; 2603b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 2604b7f5c055SJed Brown numBlocksPlus = 1; 2605b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 2606b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 26075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numBlocks, &cells)); 26085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(numBlocksPlus * vertsPerBlock,&seen)); 2609b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 2610b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 2611b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 2612b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 2613b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 2614b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 2615b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 2616b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 2617b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 2618b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 2619b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 2620b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 2621b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 2622b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 2623b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 2624b7f5c055SJed Brown 2625b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 2626b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 2627b7f5c055SJed Brown } 2628b7f5c055SJed Brown } 2629b7f5c055SJed Brown } 2630b7f5c055SJed Brown } 2631b7f5c055SJed Brown } 2632b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) if (seen[i]) numVertices++; 2633b7f5c055SJed Brown count = 0; 26345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 26355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numVertices * 3, &vtxCoords)); 2636b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 2637b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 2638b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 2639b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 2640b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 2641b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 2642b7f5c055SJed Brown 2643b7f5c055SJed Brown if (seen[vIdx]) { 2644b7f5c055SJed Brown PetscInt thisVert; 2645b7f5c055SJed Brown 2646b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 2647b7f5c055SJed Brown 2648b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 2649b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 2650b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 2651b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 2652b7f5c055SJed Brown } 2653b7f5c055SJed Brown } 2654b7f5c055SJed Brown } 2655b7f5c055SJed Brown } 2656b7f5c055SJed Brown } 2657b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 2658b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 2659b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 2660b7f5c055SJed Brown cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 2661b7f5c055SJed Brown } 2662b7f5c055SJed Brown } 2663b7f5c055SJed Brown } 26645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vertToTrueVert)); 26655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(seen)); 2666b7f5c055SJed Brown cells_flat = cells[0][0]; 2667b7f5c055SJed Brown numEdges = 0; 2668b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 2669b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 2670b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i*4 + e], cells_flat[i*4 + ((e+1)%4)]}; 2671b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3*ev[0]], &vtxCoords[3*ev[1]]}; 2672b7f5c055SJed Brown 2673b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 2674b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 2675b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 2676b7f5c055SJed Brown if (evCoords[0][d] == 2.*extent[d] && evCoords[1][d] == 2.*extent[d]) numEdges++; 2677b7f5c055SJed Brown } 2678b7f5c055SJed Brown } 2679b7f5c055SJed Brown } 2680b7f5c055SJed Brown } 26815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numEdges, &edges)); 26825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numEdges, &edgeSets)); 2683b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 2684b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 2685b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i*4 + e], cells_flat[i*4 + ((e+1)%4)]}; 2686b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3*ev[0]], &vtxCoords[3*ev[1]]}; 2687b7f5c055SJed Brown 2688b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 2689b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 2690b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 2691b7f5c055SJed Brown edges[edge][0] = ev[0]; 2692b7f5c055SJed Brown edges[edge][1] = ev[1]; 2693b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 2694b7f5c055SJed Brown } 2695b7f5c055SJed Brown if (evCoords[0][d] == 2.*extent[d] && evCoords[1][d] == 2.*extent[d]) { 2696b7f5c055SJed Brown edges[edge][0] = ev[0]; 2697b7f5c055SJed Brown edges[edge][1] = ev[1]; 2698b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 2699b7f5c055SJed Brown } 2700b7f5c055SJed Brown } 2701b7f5c055SJed Brown } 2702b7f5c055SJed Brown } 2703b7f5c055SJed Brown } 2704b7f5c055SJed Brown } 2705b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 2706b7f5c055SJed Brown break; 2707b7f5c055SJed Brown } 2708b7f5c055SJed Brown 27095f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, topoDim)); 27105f80ce2aSJacob Faibussowitsch if (!rank) CHKERRQ(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 27115f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 27125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(cells_flat)); 2713b7f5c055SJed Brown { 2714b7f5c055SJed Brown DM idm; 27155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(dm, &idm)); 27165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &idm)); 2717b7f5c055SJed Brown } 27185f80ce2aSJacob Faibussowitsch if (!rank) CHKERRQ(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 27195f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 27205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vtxCoords)); 2721b7f5c055SJed Brown 27225f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm, "Face Sets")); 27235f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, "Face Sets", &label)); 2724b7f5c055SJed Brown for (PetscInt e=0; e<numEdges; e++) { 2725b7f5c055SJed Brown PetscInt njoin; 2726b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 27275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 2728b7f5c055SJed Brown PetscCheck(njoin == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected unique join of vertices %D and %D", edges[e][0], edges[e][1]); 27295f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(label, join[0], edgeSets[e])); 27305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 2731b7f5c055SJed Brown } 27325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(edges)); 27335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(edgeSets)); 27341436d7faSJed Brown if (tps_distribute) { 27351436d7faSJed Brown DM pdm = NULL; 27361436d7faSJed Brown PetscPartitioner part; 27371436d7faSJed Brown 27385f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetPartitioner(dm, &part)); 27395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerSetFromOptions(part)); 27405f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistribute(dm, 0, NULL, &pdm)); 27411436d7faSJed Brown if (pdm) { 27425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &pdm)); 27431436d7faSJed Brown } 27441436d7faSJed Brown // Do not auto-distribute again 27455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 27461436d7faSJed Brown } 2747b7f5c055SJed Brown 27485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 2749b7f5c055SJed Brown for (PetscInt refine=0; refine<refinements; refine++) { 2750b7f5c055SJed Brown PetscInt m; 2751b7f5c055SJed Brown DM dmf; 2752b7f5c055SJed Brown Vec X; 2753b7f5c055SJed Brown PetscScalar *x; 27545f80ce2aSJacob Faibussowitsch CHKERRQ(DMRefine(dm, MPI_COMM_NULL, &dmf)); 27555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &dmf)); 2756b7f5c055SJed Brown 27575f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &X)); 27585f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(X, &m)); 27595f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(X, &x)); 2760b7f5c055SJed Brown for (PetscInt i=0; i<m; i+=3) { 27615f80ce2aSJacob Faibussowitsch CHKERRQ(TPSNearestPoint(evalFunc, &x[i])); 2762b7f5c055SJed Brown } 27635f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(X, &x)); 2764b7f5c055SJed Brown } 2765b7f5c055SJed Brown 2766b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 27675f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, "Face Sets", &label)); 27685f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexLabelComplete(dm, label)); 2769b7f5c055SJed Brown 2770b7f5c055SJed Brown if (thickness > 0) { 2771b7f5c055SJed Brown DM dm3; 27725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexExtrude(dm, layers, thickness, PETSC_FALSE, PETSC_TRUE, NULL, NULL, &dm3)); 27735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &dm3)); 2774b7f5c055SJed Brown } 2775b7f5c055SJed Brown PetscFunctionReturn(0); 2776b7f5c055SJed Brown } 2777b7f5c055SJed Brown 2778b7f5c055SJed Brown /*@ 2779b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 2780b7f5c055SJed Brown 2781b7f5c055SJed Brown Collective 2782b7f5c055SJed Brown 2783b7f5c055SJed Brown Input Parameters: 2784b7f5c055SJed Brown + comm - The communicator for the DM object 2785b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 2786b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 2787b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic 27881436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 2789817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 27901436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 2791817da375SSatish Balay - thickness - Thickness in normal direction 2792b7f5c055SJed Brown 2793b7f5c055SJed Brown Output Parameter: 2794b7f5c055SJed Brown . dm - The DM object 2795b7f5c055SJed Brown 2796b7f5c055SJed Brown Notes: 2797b7f5c055SJed 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. 2798b7f5c055SJed Brown https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries. 2799b7f5c055SJed 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. 2800b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 2801b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 2802b7f5c055SJed Brown This projection could readily be extended to related surfaces. 2803b7f5c055SJed Brown 2804b7f5c055SJed Brown The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z). 2805b7f5c055SJed Brown When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). Use DMPlexLabelComplete() to propagate to coarse-level vertices. 2806b7f5c055SJed Brown 2807b7f5c055SJed Brown References: 2808606c0280SSatish 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 2809b7f5c055SJed Brown 2810b7f5c055SJed Brown Developer Notes: 2811b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 2812b7f5c055SJed Brown 2813b7f5c055SJed Brown Level: beginner 2814b7f5c055SJed Brown 2815b7f5c055SJed Brown .seealso: DMPlexCreateSphereMesh(), DMSetType(), DMCreate() 2816b7f5c055SJed Brown @*/ 28171436d7faSJed Brown PetscErrorCode DMPlexCreateTPSMesh(MPI_Comm comm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness, DM *dm) 2818b7f5c055SJed Brown { 2819b7f5c055SJed Brown PetscFunctionBegin; 28205f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 28215f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 28225f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 2823b7f5c055SJed Brown PetscFunctionReturn(0); 2824b7f5c055SJed Brown } 2825b7f5c055SJed Brown 28269318fe57SMatthew G. Knepley /*@ 28279318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 28289318fe57SMatthew G. Knepley 28299318fe57SMatthew G. Knepley Collective 28309318fe57SMatthew G. Knepley 28319318fe57SMatthew G. Knepley Input Parameters: 28329318fe57SMatthew G. Knepley + comm - The communicator for the DM object 28339318fe57SMatthew G. Knepley . dim - The dimension 28349318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 28359318fe57SMatthew G. Knepley - R - The radius 28369318fe57SMatthew G. Knepley 28379318fe57SMatthew G. Knepley Output Parameter: 28389318fe57SMatthew G. Knepley . dm - The DM object 28399318fe57SMatthew G. Knepley 28409318fe57SMatthew G. Knepley Level: beginner 28419318fe57SMatthew G. Knepley 28429318fe57SMatthew G. Knepley .seealso: DMPlexCreateBallMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 28439318fe57SMatthew G. Knepley @*/ 28449318fe57SMatthew G. Knepley PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 28459318fe57SMatthew G. Knepley { 28469318fe57SMatthew G. Knepley PetscFunctionBegin; 28479318fe57SMatthew G. Knepley PetscValidPointer(dm, 5); 28485f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 28495f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 28505f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 28519318fe57SMatthew G. Knepley PetscFunctionReturn(0); 28529318fe57SMatthew G. Knepley } 28539318fe57SMatthew G. Knepley 28549318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 28559318fe57SMatthew G. Knepley { 28569318fe57SMatthew G. Knepley DM sdm, vol; 28579318fe57SMatthew G. Knepley DMLabel bdlabel; 28589318fe57SMatthew G. Knepley 28599318fe57SMatthew G. Knepley PetscFunctionBegin; 28605f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), &sdm)); 28615f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(sdm, DMPLEX)); 28625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) sdm, "bd_")); 28635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateSphereMesh_Internal(sdm, dim-1, PETSC_TRUE, R)); 28645f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions(sdm)); 28655f80ce2aSJacob Faibussowitsch CHKERRQ(DMViewFromOptions(sdm, NULL, "-dm_view")); 28665f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 28675f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&sdm)); 28685f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &vol)); 28695f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm, "marker")); 28705f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, "marker", &bdlabel)); 28715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 28725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexLabelComplete(dm, bdlabel)); 287351a74b61SMatthew G. Knepley PetscFunctionReturn(0); 287451a74b61SMatthew G. Knepley } 287551a74b61SMatthew G. Knepley 287651a74b61SMatthew G. Knepley /*@ 287751a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 287851a74b61SMatthew G. Knepley 287951a74b61SMatthew G. Knepley Collective 288051a74b61SMatthew G. Knepley 288151a74b61SMatthew G. Knepley Input Parameters: 288251a74b61SMatthew G. Knepley + comm - The communicator for the DM object 288351a74b61SMatthew G. Knepley . dim - The dimension 288451a74b61SMatthew G. Knepley - R - The radius 288551a74b61SMatthew G. Knepley 288651a74b61SMatthew G. Knepley Output Parameter: 288751a74b61SMatthew G. Knepley . dm - The DM object 288851a74b61SMatthew G. Knepley 288951a74b61SMatthew G. Knepley Options Database Keys: 289051a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 289151a74b61SMatthew G. Knepley 289251a74b61SMatthew G. Knepley Level: beginner 289351a74b61SMatthew G. Knepley 289451a74b61SMatthew G. Knepley .seealso: DMPlexCreateSphereMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 289551a74b61SMatthew G. Knepley @*/ 289651a74b61SMatthew G. Knepley PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 289751a74b61SMatthew G. Knepley { 289851a74b61SMatthew G. Knepley PetscFunctionBegin; 28995f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 29005f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 29015f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 29022829fed8SMatthew G. Knepley PetscFunctionReturn(0); 29032829fed8SMatthew G. Knepley } 29042829fed8SMatthew G. Knepley 29059318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 29060a6ba040SMatthew G. Knepley { 29070a6ba040SMatthew G. Knepley PetscFunctionBegin; 29089318fe57SMatthew G. Knepley switch (ct) { 29099318fe57SMatthew G. Knepley case DM_POLYTOPE_POINT: 29109318fe57SMatthew G. Knepley { 29119318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 29129318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 29139318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 29149318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 29159318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 29169318fe57SMatthew G. Knepley 29175f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 0)); 29185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 29199318fe57SMatthew G. Knepley } 29209318fe57SMatthew G. Knepley break; 29219318fe57SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 29229318fe57SMatthew G. Knepley { 29239318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 29249318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 29259318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 29269318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 29279318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 29289318fe57SMatthew G. Knepley 29295f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 1)); 29305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 29319318fe57SMatthew G. Knepley } 29329318fe57SMatthew G. Knepley break; 2933b5a892a1SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 2934b5a892a1SMatthew G. Knepley { 2935b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 2936b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 2937b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 2938b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 2939b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 2940b5a892a1SMatthew G. Knepley 29415f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 1)); 29425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 2943b5a892a1SMatthew G. Knepley } 2944b5a892a1SMatthew G. Knepley break; 29459318fe57SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 29469318fe57SMatthew G. Knepley { 29479318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 29489318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 29499318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 29509318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 29519318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 29529318fe57SMatthew G. Knepley 29535f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 2)); 29545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 29559318fe57SMatthew G. Knepley } 29569318fe57SMatthew G. Knepley break; 29579318fe57SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 29589318fe57SMatthew G. Knepley { 29599318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 29609318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 29619318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 29629318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 29639318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 29649318fe57SMatthew G. Knepley 29655f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 2)); 29665f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 29679318fe57SMatthew G. Knepley } 29689318fe57SMatthew G. Knepley break; 29699318fe57SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 29709318fe57SMatthew G. Knepley { 29719318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 29729318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 29739318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 29749318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 29759318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 29769318fe57SMatthew G. Knepley 29775f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 2)); 29785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 29799318fe57SMatthew G. Knepley } 29809318fe57SMatthew G. Knepley break; 29819318fe57SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 29829318fe57SMatthew G. Knepley { 29839318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 29849318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 2985f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 29869318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 2987f0edb160SMatthew 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}; 29889318fe57SMatthew G. Knepley 29895f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 3)); 29905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 29919318fe57SMatthew G. Knepley } 29929318fe57SMatthew G. Knepley break; 29939318fe57SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: 29949318fe57SMatthew G. Knepley { 29959318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 29969318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 2997f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 29989318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2999f0edb160SMatthew G. Knepley 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, 30009318fe57SMatthew G. Knepley -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; 30019318fe57SMatthew G. Knepley 30025f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 3)); 30035f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 30049318fe57SMatthew G. Knepley } 30059318fe57SMatthew G. Knepley break; 30069318fe57SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 30079318fe57SMatthew G. Knepley { 30089318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 30099318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 3010f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 30119318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 3012f0edb160SMatthew G. Knepley PetscScalar vertexCoords[18] = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 30139318fe57SMatthew G. Knepley -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0}; 30149318fe57SMatthew G. Knepley 30155f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 3)); 30165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 30179318fe57SMatthew G. Knepley } 30189318fe57SMatthew G. Knepley break; 30199318fe57SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 30209318fe57SMatthew G. Knepley { 30219318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 30229318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 30239318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 30249318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 30259318fe57SMatthew G. Knepley PetscScalar vertexCoords[18] = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 30269318fe57SMatthew G. Knepley -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0}; 30279318fe57SMatthew G. Knepley 30285f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 3)); 30295f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 30309318fe57SMatthew G. Knepley } 30319318fe57SMatthew G. Knepley break; 30329318fe57SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 30339318fe57SMatthew G. Knepley { 30349318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 30359318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 30369318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 30379318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 30389318fe57SMatthew G. Knepley 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, 30399318fe57SMatthew G. Knepley -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; 30409318fe57SMatthew G. Knepley 30415f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 3)); 30425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 30439318fe57SMatthew G. Knepley } 30449318fe57SMatthew G. Knepley break; 30459318fe57SMatthew G. Knepley case DM_POLYTOPE_PYRAMID: 30469318fe57SMatthew G. Knepley { 30479318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 30489318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 3049f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 30509318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 3051f0edb160SMatthew G. Knepley 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, 30529318fe57SMatthew G. Knepley 0.0, 0.0, 1.0}; 30539318fe57SMatthew G. Knepley 30545f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 3)); 30555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 30569318fe57SMatthew G. Knepley } 30579318fe57SMatthew G. Knepley break; 305898921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 30599318fe57SMatthew G. Knepley } 30609318fe57SMatthew G. Knepley { 30619318fe57SMatthew G. Knepley PetscInt Nv, v; 30629318fe57SMatthew G. Knepley 30639318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 30645f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(rdm, "celltype")); 30655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCellType(rdm, 0, ct)); 30665f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(rdm, NULL, &Nv)); 30675f80ce2aSJacob Faibussowitsch for (v = 1; v < Nv; ++v) CHKERRQ(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 30689318fe57SMatthew G. Knepley } 30695f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolateInPlace_Internal(rdm)); 30705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) rdm, DMPolytopeTypes[ct])); 30710a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 30720a6ba040SMatthew G. Knepley } 30730a6ba040SMatthew G. Knepley 30749318fe57SMatthew G. Knepley /*@ 30759318fe57SMatthew G. Knepley DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell 30769318fe57SMatthew G. Knepley 30779318fe57SMatthew G. Knepley Collective 30789318fe57SMatthew G. Knepley 30799318fe57SMatthew G. Knepley Input Parameters: 30809318fe57SMatthew G. Knepley + comm - The communicator 30819318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 30829318fe57SMatthew G. Knepley 30839318fe57SMatthew G. Knepley Output Parameter: 30849318fe57SMatthew G. Knepley . refdm - The reference cell 30859318fe57SMatthew G. Knepley 30869318fe57SMatthew G. Knepley Level: intermediate 30879318fe57SMatthew G. Knepley 30889318fe57SMatthew G. Knepley .seealso: DMPlexCreateReferenceCell(), DMPlexCreateBoxMesh() 30899318fe57SMatthew G. Knepley @*/ 30909318fe57SMatthew G. Knepley PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 30910a6ba040SMatthew G. Knepley { 30920a6ba040SMatthew G. Knepley PetscFunctionBegin; 30935f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, refdm)); 30945f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*refdm, DMPLEX)); 30955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 30969318fe57SMatthew G. Knepley PetscFunctionReturn(0); 30979318fe57SMatthew G. Knepley } 309879a015ccSMatthew G. Knepley 30999318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 31009318fe57SMatthew G. Knepley { 31019318fe57SMatthew G. Knepley DM plex; 31029318fe57SMatthew G. Knepley DMLabel label; 31039318fe57SMatthew G. Knepley PetscBool hasLabel; 31040a6ba040SMatthew G. Knepley 31059318fe57SMatthew G. Knepley PetscFunctionBeginUser; 31065f80ce2aSJacob Faibussowitsch CHKERRQ(DMHasLabel(dm, name, &hasLabel)); 31079318fe57SMatthew G. Knepley if (hasLabel) PetscFunctionReturn(0); 31085f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm, name)); 31095f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, name, &label)); 31105f80ce2aSJacob Faibussowitsch CHKERRQ(DMConvert(dm, DMPLEX, &plex)); 31115f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMarkBoundaryFaces(plex, 1, label)); 31125f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&plex)); 31139318fe57SMatthew G. Knepley PetscFunctionReturn(0); 31149318fe57SMatthew G. Knepley } 3115acdc6f61SToby Isaac 3116b7f5c055SJed Brown const char * const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 31179318fe57SMatthew G. Knepley 311861a622f3SMatthew G. Knepley static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 31199318fe57SMatthew G. Knepley { 31209318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 31219318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 31229318fe57SMatthew G. Knepley PetscInt dim = 2; 31239318fe57SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 3124cd7e8a5eSksagiyam PetscBool flg, flg2, fflg, bdfflg, nameflg; 31259318fe57SMatthew G. Knepley MPI_Comm comm; 3126ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3127ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 3128ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 31299318fe57SMatthew G. Knepley 31309318fe57SMatthew G. Knepley PetscFunctionBegin; 31315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 31329318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 31335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 31345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 31355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 31365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum) cell, (PetscEnum *) &cell, NULL)); 31375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 31385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum) shape, (PetscEnum *) &shape, &flg)); 31395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 31402c71b3e2SJacob Faibussowitsch PetscCheckFalse((dim < 0) || (dim > 3),comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D should be in [1, 3]", dim); 31415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 31425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 31435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 31445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 31455f80ce2aSJacob Faibussowitsch if (flg || flg2) CHKERRQ(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 31469318fe57SMatthew G. Knepley 314761a622f3SMatthew G. Knepley switch (cell) { 314861a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 314961a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 315061a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 315161a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 315261a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 315361a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 315461a622f3SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: 315561a622f3SMatthew G. Knepley *useCoordSpace = PETSC_TRUE;break; 315661a622f3SMatthew G. Knepley default: *useCoordSpace = PETSC_FALSE;break; 315761a622f3SMatthew G. Knepley } 315861a622f3SMatthew G. Knepley 31599318fe57SMatthew G. Knepley if (fflg) { 31609318fe57SMatthew G. Knepley DM dmnew; 31619318fe57SMatthew G. Knepley 31625f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromFile(PetscObjectComm((PetscObject) dm), filename, plexname, interpolate, &dmnew)); 31635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopy_Internal(dm, PETSC_FALSE, dmnew)); 31645f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &dmnew)); 31659318fe57SMatthew G. Knepley } else if (refDomain) { 31665f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateReferenceCell_Internal(dm, cell)); 31679318fe57SMatthew G. Knepley } else if (bdfflg) { 31689318fe57SMatthew G. Knepley DM bdm, dmnew; 31699318fe57SMatthew G. Knepley 31705f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromFile(PetscObjectComm((PetscObject) dm), bdFilename, plexname, interpolate, &bdm)); 31715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) bdm, "bd_")); 31725f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions(bdm)); 31735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 31745f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&bdm)); 31755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopy_Internal(dm, PETSC_FALSE, dmnew)); 31765f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &dmnew)); 31779318fe57SMatthew G. Knepley } else { 31785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) dm, DMPlexShapes[shape])); 31799318fe57SMatthew G. Knepley switch (shape) { 31809318fe57SMatthew G. Knepley case DM_SHAPE_BOX: 31819318fe57SMatthew G. Knepley { 31829318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 31839318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 31849318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 31859318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 31869318fe57SMatthew G. Knepley PetscInt i, n; 31879318fe57SMatthew G. Knepley 31889318fe57SMatthew G. Knepley n = dim; 31899318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4-dim); 31905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 31919318fe57SMatthew G. Knepley n = 3; 31925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 31932c71b3e2SJacob Faibussowitsch PetscCheckFalse(flg && (n != dim),comm, PETSC_ERR_ARG_SIZ, "Lower box point had %D values, should have been %D", n, dim); 31949318fe57SMatthew G. Knepley n = 3; 31955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 31962c71b3e2SJacob Faibussowitsch PetscCheckFalse(flg && (n != dim),comm, PETSC_ERR_ARG_SIZ, "Upper box point had %D values, should have been %D", n, dim); 31979318fe57SMatthew G. Knepley n = 3; 31985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *) bdt, &n, &flg)); 31992c71b3e2SJacob Faibussowitsch PetscCheckFalse(flg && (n != dim),comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %D values, should have been %D", n, dim); 32009318fe57SMatthew G. Knepley switch (cell) { 320161a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 32025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 3203d410b0cfSMatthew G. Knepley if (!interpolate) { 3204d410b0cfSMatthew G. Knepley DM udm; 3205d410b0cfSMatthew G. Knepley 32065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexUninterpolate(dm, &udm)); 32075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &udm)); 3208d410b0cfSMatthew G. Knepley } 32099318fe57SMatthew G. Knepley break; 32109318fe57SMatthew G. Knepley default: 32115f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate)); 32129318fe57SMatthew G. Knepley break; 32139318fe57SMatthew G. Knepley } 32149318fe57SMatthew G. Knepley } 32159318fe57SMatthew G. Knepley break; 32169318fe57SMatthew G. Knepley case DM_SHAPE_BOX_SURFACE: 32179318fe57SMatthew G. Knepley { 32189318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 32199318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 32209318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 32219318fe57SMatthew G. Knepley PetscInt i, n; 32229318fe57SMatthew G. Knepley 32239318fe57SMatthew G. Knepley n = dim+1; 32249318fe57SMatthew G. Knepley for (i = 0; i < dim+1; ++i) faces[i] = (dim+1 == 1 ? 1 : 4-(dim+1)); 32255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 32269318fe57SMatthew G. Knepley n = 3; 32275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 32282c71b3e2SJacob Faibussowitsch PetscCheckFalse(flg && (n != dim+1),comm, PETSC_ERR_ARG_SIZ, "Lower box point had %D values, should have been %D", n, dim+1); 32299318fe57SMatthew G. Knepley n = 3; 32305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 32312c71b3e2SJacob Faibussowitsch PetscCheckFalse(flg && (n != dim+1),comm, PETSC_ERR_ARG_SIZ, "Upper box point had %D values, should have been %D", n, dim+1); 32325f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim+1, faces, lower, upper, interpolate)); 32339318fe57SMatthew G. Knepley } 32349318fe57SMatthew G. Knepley break; 32359318fe57SMatthew G. Knepley case DM_SHAPE_SPHERE: 32369318fe57SMatthew G. Knepley { 32379318fe57SMatthew G. Knepley PetscReal R = 1.0; 32389318fe57SMatthew G. Knepley 32395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 32405f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 32419318fe57SMatthew G. Knepley } 32429318fe57SMatthew G. Knepley break; 32439318fe57SMatthew G. Knepley case DM_SHAPE_BALL: 32449318fe57SMatthew G. Knepley { 32459318fe57SMatthew G. Knepley PetscReal R = 1.0; 32469318fe57SMatthew G. Knepley 32475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 32485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateBallMesh_Internal(dm, dim, R)); 32499318fe57SMatthew G. Knepley } 32509318fe57SMatthew G. Knepley break; 32519318fe57SMatthew G. Knepley case DM_SHAPE_CYLINDER: 32529318fe57SMatthew G. Knepley { 32539318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 32549318fe57SMatthew G. Knepley PetscInt Nw = 6; 32559318fe57SMatthew G. Knepley 32565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum) bdt, (PetscEnum *) &bdt, NULL)); 32575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 32589318fe57SMatthew G. Knepley switch (cell) { 325961a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 32605f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 32619318fe57SMatthew G. Knepley break; 32629318fe57SMatthew G. Knepley default: 32635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateHexCylinderMesh_Internal(dm, bdt)); 32649318fe57SMatthew G. Knepley break; 32659318fe57SMatthew G. Knepley } 32669318fe57SMatthew G. Knepley } 32679318fe57SMatthew G. Knepley break; 3268b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 3269b7f5c055SJed Brown case DM_SHAPE_GYROID: 3270b7f5c055SJed Brown { 3271b7f5c055SJed Brown PetscInt extent[3] = {1,1,1}, refine = 0, layers = 0, three; 3272b7f5c055SJed Brown PetscReal thickness = 0.; 3273b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 3274b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 32751436d7faSJed Brown PetscBool tps_distribute; 32765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three=3, &three), NULL)); 32775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 32785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum*)periodic, (three=3, &three), NULL)); 32795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 32805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 32815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeGetDefault(dm, &tps_distribute)); 32825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 32835f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 3284b7f5c055SJed Brown } 3285b7f5c055SJed Brown break; 328698921bdaSJacob Faibussowitsch default: SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 32879318fe57SMatthew G. Knepley } 32889318fe57SMatthew G. Knepley } 32895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 3290ed5e4e85SVaclav Hapla if (!((PetscObject)dm)->name && nameflg) { 32915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)dm, plexname)); 3292ed5e4e85SVaclav Hapla } 32930a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 32940a6ba040SMatthew G. Knepley } 32950a6ba040SMatthew G. Knepley 329647920aaeSMatthew G. Knepley PetscErrorCode DMSetFromOptions_NonRefinement_Plex(PetscOptionItems *PetscOptionsObject, DM dm) 32970a6ba040SMatthew G. Knepley { 32980a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 3299c0f0dcc3SMatthew G. Knepley PetscBool flg; 33009318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 33010a6ba040SMatthew G. Knepley 33020a6ba040SMatthew G. Knepley PetscFunctionBegin; 33030a6ba040SMatthew G. Knepley /* Handle viewing */ 33045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 33055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL,0)); 33065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 33075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL,0)); 33085f80ce2aSJacob Faibussowitsch CHKERRQ(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 33095f80ce2aSJacob Faibussowitsch if (flg) CHKERRQ(PetscLogDefaultBegin()); 33109318fe57SMatthew G. Knepley /* Labeling */ 33115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 33125f80ce2aSJacob Faibussowitsch if (flg) CHKERRQ(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 3313953fc75cSMatthew G. Knepley /* Point Location */ 33145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 33150848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 33165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 33172e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 33185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 3319b29cfa1cSToby Isaac /* Projection behavior */ 33205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maxmimum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL,0)); 33215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 3322f12cf164SMatthew G. Knepley /* Checking structure */ 3323f12cf164SMatthew G. Knepley { 3324e902f1eaSVaclav Hapla PetscBool flg = PETSC_FALSE, flg2 = PETSC_FALSE, all = PETSC_FALSE; 3325f12cf164SMatthew G. Knepley 33265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_check_all", "Perform all checks", NULL, PETSC_FALSE, &all, &flg2)); 33275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 33285f80ce2aSJacob Faibussowitsch if (all || (flg && flg2)) CHKERRQ(DMPlexCheckSymmetry(dm)); 33295f80ce2aSJacob Faibussowitsch CHKERRQ(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)); 33305f80ce2aSJacob Faibussowitsch if (all || (flg && flg2)) CHKERRQ(DMPlexCheckSkeleton(dm, 0)); 33315f80ce2aSJacob Faibussowitsch CHKERRQ(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)); 33325f80ce2aSJacob Faibussowitsch if (all || (flg && flg2)) CHKERRQ(DMPlexCheckFaces(dm, 0)); 33335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 33345f80ce2aSJacob Faibussowitsch if (all || (flg && flg2)) CHKERRQ(DMPlexCheckGeometry(dm)); 33355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 33365f80ce2aSJacob Faibussowitsch if (all || (flg && flg2)) CHKERRQ(DMPlexCheckPointSF(dm)); 33375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_check_interface_cones", "Check points on inter-partition interfaces have conforming order of cone points", "DMPlexCheckInterfaceCones", PETSC_FALSE, &flg, &flg2)); 33385f80ce2aSJacob Faibussowitsch if (all || (flg && flg2)) CHKERRQ(DMPlexCheckInterfaceCones(dm)); 33395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 33405f80ce2aSJacob Faibussowitsch if (flg && flg2) CHKERRQ(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 3341f12cf164SMatthew G. Knepley } 33429318fe57SMatthew G. Knepley { 33439318fe57SMatthew G. Knepley PetscReal scale = 1.0; 33444f3833eaSMatthew G. Knepley 33455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 33469318fe57SMatthew G. Knepley if (flg) { 33479318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 33489318fe57SMatthew G. Knepley 33495f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinates(dm, &coordinates)); 33505f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 33515f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(coordinates, scale)); 33525f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(coordinatesLocal, scale)); 33539318fe57SMatthew G. Knepley } 33549318fe57SMatthew G. Knepley } 33555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerSetFromOptions(mesh->partitioner)); 335668d4fef7SMatthew G. Knepley PetscFunctionReturn(0); 335768d4fef7SMatthew G. Knepley } 335868d4fef7SMatthew G. Knepley 335946fa42a0SMatthew G. Knepley static PetscErrorCode DMSetFromOptions_Plex(PetscOptionItems *PetscOptionsObject,DM dm) 336068d4fef7SMatthew G. Knepley { 3361bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 3362bdf63967SMatthew G. Knepley char oname[256]; 3363d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 33649318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 3365e600fa54SMatthew 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; 336668d4fef7SMatthew G. Knepley 336768d4fef7SMatthew G. Knepley PetscFunctionBegin; 3368064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 33695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHead(PetscOptionsObject,"DMPlex Options")); 33709318fe57SMatthew G. Knepley /* Handle automatic creation */ 33715f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 33725f80ce2aSJacob Faibussowitsch if (dim < 0) {CHKERRQ(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));created = PETSC_TRUE;} 3373d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 33745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 3375d89e6e46SMatthew G. Knepley if (flg) { 3376d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 3377d89e6e46SMatthew G. Knepley 33785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsInterpolated(dm, &interpolated)); 3379d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 3380d89e6e46SMatthew G. Knepley DM udm; 3381d89e6e46SMatthew G. Knepley 33825f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexUninterpolate(dm, &udm)); 33835f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &udm)); 3384d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 3385d89e6e46SMatthew G. Knepley DM idm; 3386d89e6e46SMatthew G. Knepley 33875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(dm, &idm)); 33885f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &idm)); 3389d89e6e46SMatthew G. Knepley } 3390d89e6e46SMatthew G. Knepley } 33919b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 33925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg)); 3393c1cad2e7SMatthew G. Knepley if (flg) {((DM_Plex *) dm->data)->ignoreModel = ignoreModel;} 33945f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetRefinementUniform(dm, &uniformOrig)); 33955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL,0)); 33965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 33975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 33985f80ce2aSJacob Faibussowitsch if (flg) CHKERRQ(DMPlexSetRefinementUniform(dm, uniform)); 33995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 34009318fe57SMatthew G. Knepley if (flg) { 34015f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 34025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementLimit(dm, volume)); 34039318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 34049318fe57SMatthew G. Knepley } 34059b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 34069b44eab4SMatthew G. Knepley DM rdm; 34079b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex*) dm->data)->coordFunc; 34089b44eab4SMatthew G. Knepley 34095f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 34105f80ce2aSJacob Faibussowitsch CHKERRQ(DMRefine(dm, PetscObjectComm((PetscObject) dm), &rdm)); 34115f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &rdm)); 34125f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 341361a622f3SMatthew G. Knepley if (coordFunc && remap) { 34145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 34159b44eab4SMatthew G. Knepley ((DM_Plex*) dm->data)->coordFunc = coordFunc; 34169b44eab4SMatthew G. Knepley } 34179b44eab4SMatthew G. Knepley } 34185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementUniform(dm, uniformOrig)); 34199318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 34205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 34219318fe57SMatthew G. Knepley if (extLayers) { 34229318fe57SMatthew G. Knepley DM edm; 34239318fe57SMatthew G. Knepley 34245f80ce2aSJacob Faibussowitsch CHKERRQ(DMExtrude(dm, extLayers, &edm)); 34255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &edm)); 342648d16a33SMatthew G. Knepley ((DM_Plex *) dm->data)->coordFunc = NULL; 34275f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 3428d410b0cfSMatthew G. Knepley extLayers = 0; 34299318fe57SMatthew G. Knepley } 3430bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 34315f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOrderingList(&ordlist)); 34325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 3433bdf63967SMatthew G. Knepley if (flg) { 3434bdf63967SMatthew G. Knepley DM pdm; 3435bdf63967SMatthew G. Knepley IS perm; 3436bdf63967SMatthew G. Knepley 34375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetOrdering(dm, oname, NULL, &perm)); 34385f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPermute(dm, perm, &pdm)); 34395f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&perm)); 34405f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &pdm)); 34415f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 3442bdf63967SMatthew G. Knepley } 34439b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 34445f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeGetDefault(dm, &distribute)); 34455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMCreate", distribute, &distribute, NULL)); 34465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMCreate", overlap, &overlap, NULL, 0)); 34479b44eab4SMatthew G. Knepley if (distribute) { 34489b44eab4SMatthew G. Knepley DM pdm = NULL; 34499b44eab4SMatthew G. Knepley PetscPartitioner part; 34509b44eab4SMatthew G. Knepley 34515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetPartitioner(dm, &part)); 34525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerSetFromOptions(part)); 34535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistribute(dm, overlap, NULL, &pdm)); 34549b44eab4SMatthew G. Knepley if (pdm) { 34555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &pdm)); 34569b44eab4SMatthew G. Knepley } 34579b44eab4SMatthew G. Knepley } 34589318fe57SMatthew G. Knepley /* Create coordinate space */ 34599318fe57SMatthew G. Knepley if (created) { 346061a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 34619318fe57SMatthew G. Knepley PetscInt degree = 1; 346261a622f3SMatthew G. Knepley PetscBool periodic, flg; 34639318fe57SMatthew G. Knepley 34645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg)); 34655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 34665f80ce2aSJacob Faibussowitsch if (coordSpace) CHKERRQ(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc)); 346761a622f3SMatthew G. Knepley if (flg && !coordSpace) { 346861a622f3SMatthew G. Knepley DM cdm; 346961a622f3SMatthew G. Knepley PetscDS cds; 347061a622f3SMatthew G. Knepley PetscObject obj; 347161a622f3SMatthew G. Knepley PetscClassId id; 347261a622f3SMatthew G. Knepley 34735f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 34745f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(cdm, &cds)); 34755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetDiscretization(cds, 0, &obj)); 34765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId(obj, &id)); 347761a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 347861a622f3SMatthew G. Knepley PetscContainer dummy; 347961a622f3SMatthew G. Knepley 34805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 34815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) dummy, "coordinates")); 34825f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(cdm, 0, NULL, (PetscObject) dummy)); 34835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscContainerDestroy(&dummy)); 34845f80ce2aSJacob Faibussowitsch CHKERRQ(DMClearDS(cdm)); 348561a622f3SMatthew G. Knepley } 348661a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 348761a622f3SMatthew G. Knepley } 34885f80ce2aSJacob Faibussowitsch CHKERRQ(DMLocalizeCoordinates(dm)); 34895f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL)); 34905f80ce2aSJacob Faibussowitsch if (periodic) CHKERRQ(DMSetPeriodicity(dm, PETSC_TRUE, NULL, NULL, NULL)); 34919318fe57SMatthew G. Knepley } 349268d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 349361a622f3SMatthew G. Knepley remap = PETSC_TRUE; 34945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL,0)); 34955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 34965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy,0)); 34975f80ce2aSJacob Faibussowitsch if (refine) CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 349868d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 3499acdc6f61SToby Isaac DM *dms, coarseDM; 350068d4fef7SMatthew G. Knepley 35015f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoarseDM(dm, &coarseDM)); 35025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)coarseDM)); 35035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(refine,&dms)); 35045f80ce2aSJacob Faibussowitsch CHKERRQ(DMRefineHierarchy(dm, refine, dms)); 350568d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 35065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSwap_Static(dm, dms[refine-1])); 350768d4fef7SMatthew G. Knepley if (refine == 1) { 35085f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoarseDM(dm, dms[0])); 35095f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 351068d4fef7SMatthew G. Knepley } else { 35115f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoarseDM(dm, dms[refine-2])); 35125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 35135f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoarseDM(dms[0], dms[refine-1])); 35145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 351568d4fef7SMatthew G. Knepley } 35165f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoarseDM(dms[refine-1], coarseDM)); 35175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectDereference((PetscObject)coarseDM)); 351868d4fef7SMatthew G. Knepley /* Free DMs */ 351968d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 35205f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dms[r])); 35215f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dms[r])); 352268d4fef7SMatthew G. Knepley } 35235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(dms)); 352468d4fef7SMatthew G. Knepley } else { 352568d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 35269318fe57SMatthew G. Knepley DM rdm; 352751a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex*) dm->data)->coordFunc; 352868d4fef7SMatthew G. Knepley 35295f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 35305f80ce2aSJacob Faibussowitsch CHKERRQ(DMRefine(dm, PetscObjectComm((PetscObject) dm), &rdm)); 353168d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 35325f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &rdm)); 35335f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 353461a622f3SMatthew G. Knepley if (coordFunc && remap) { 35355f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 353651a74b61SMatthew G. Knepley ((DM_Plex*) dm->data)->coordFunc = coordFunc; 353751a74b61SMatthew G. Knepley } 353868d4fef7SMatthew G. Knepley } 353968d4fef7SMatthew G. Knepley } 35403cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 35415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL,0)); 35425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy,0)); 3543b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 3544b653a561SMatthew G. Knepley DM *dms; 3545b653a561SMatthew G. Knepley 35465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(coarsen, &dms)); 35475f80ce2aSJacob Faibussowitsch CHKERRQ(DMCoarsenHierarchy(dm, coarsen, dms)); 3548b653a561SMatthew G. Knepley /* Free DMs */ 3549b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 35505f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dms[r])); 35515f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dms[r])); 3552b653a561SMatthew G. Knepley } 35535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(dms)); 3554b653a561SMatthew G. Knepley } else { 3555b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 35569318fe57SMatthew G. Knepley DM cdm; 35579318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex*) dm->data)->coordFunc; 35583cf6fe12SMatthew G. Knepley 35595f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 35605f80ce2aSJacob Faibussowitsch CHKERRQ(DMCoarsen(dm, PetscObjectComm((PetscObject) dm), &cdm)); 35613cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 35625f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &cdm)); 35635f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 35649318fe57SMatthew G. Knepley if (coordFunc) { 35655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 35669318fe57SMatthew G. Knepley ((DM_Plex*) dm->data)->coordFunc = coordFunc; 35679318fe57SMatthew G. Knepley } 35683cf6fe12SMatthew G. Knepley } 3569b653a561SMatthew G. Knepley } 3570909dfd52SMatthew G. Knepley /* Handle ghost cells */ 35715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 3572909dfd52SMatthew G. Knepley if (ghostCells) { 3573909dfd52SMatthew G. Knepley DM gdm; 3574909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 3575909dfd52SMatthew G. Knepley 3576909dfd52SMatthew G. Knepley lname[0] = '\0'; 35775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 35785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 35795f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &gdm)); 3580909dfd52SMatthew G. Knepley } 35816913077dSMatthew G. Knepley /* Handle 1D order */ 35826913077dSMatthew G. Knepley { 35836913077dSMatthew G. Knepley DM cdm, rdm; 35846913077dSMatthew G. Knepley PetscDS cds; 35856913077dSMatthew G. Knepley PetscObject obj; 35866913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 35876913077dSMatthew G. Knepley IS perm; 35886913077dSMatthew G. Knepley PetscInt dim, Nf; 35896913077dSMatthew G. Knepley PetscBool distributed; 35906913077dSMatthew G. Knepley 35915f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 35925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsDistributed(dm, &distributed)); 35935f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 35945f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(cdm, &cds)); 35955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(cds, &Nf)); 35966913077dSMatthew G. Knepley if (Nf) { 35975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetDiscretization(cds, 0, &obj)); 35985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId(obj, &id)); 35996913077dSMatthew G. Knepley } 36006913077dSMatthew G. Knepley if (dim == 1 && !distributed && id != PETSCFE_CLASSID) { 36015f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetOrdering1D(dm, &perm)); 36025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPermute(dm, perm, &rdm)); 36035f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &rdm)); 36045f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&perm)); 36056913077dSMatthew G. Knepley } 36066913077dSMatthew G. Knepley } 36073cf6fe12SMatthew G. Knepley /* Handle */ 36085f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 36095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsTail()); 36100a6ba040SMatthew G. Knepley PetscFunctionReturn(0); 36110a6ba040SMatthew G. Knepley } 36120a6ba040SMatthew G. Knepley 3613552f7358SJed Brown static PetscErrorCode DMCreateGlobalVector_Plex(DM dm,Vec *vec) 3614552f7358SJed Brown { 3615552f7358SJed Brown PetscFunctionBegin; 36165f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector_Section_Private(dm,vec)); 36175f80ce2aSJacob Faibussowitsch /* CHKERRQ(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 36185f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Plex)); 36195f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void)) VecView_Plex_Native)); 36205f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void)) VecLoad_Plex)); 36215f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void)) VecLoad_Plex_Native)); 3622552f7358SJed Brown PetscFunctionReturn(0); 3623552f7358SJed Brown } 3624552f7358SJed Brown 3625552f7358SJed Brown static PetscErrorCode DMCreateLocalVector_Plex(DM dm,Vec *vec) 3626552f7358SJed Brown { 3627552f7358SJed Brown PetscFunctionBegin; 36285f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLocalVector_Section_Private(dm,vec)); 36295f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Plex_Local)); 36305f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void)) VecLoad_Plex_Local)); 3631552f7358SJed Brown PetscFunctionReturn(0); 3632552f7358SJed Brown } 3633552f7358SJed Brown 3634793f3fe5SMatthew G. Knepley static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 3635793f3fe5SMatthew G. Knepley { 3636793f3fe5SMatthew G. Knepley PetscInt depth, d; 3637793f3fe5SMatthew G. Knepley 3638793f3fe5SMatthew G. Knepley PetscFunctionBegin; 36395f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 3640793f3fe5SMatthew G. Knepley if (depth == 1) { 36415f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &d)); 36425f80ce2aSJacob Faibussowitsch if (dim == 0) CHKERRQ(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 36435f80ce2aSJacob Faibussowitsch else if (dim == d) CHKERRQ(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 3644793f3fe5SMatthew G. Knepley else {*pStart = 0; *pEnd = 0;} 3645793f3fe5SMatthew G. Knepley } else { 36465f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 3647793f3fe5SMatthew G. Knepley } 3648793f3fe5SMatthew G. Knepley PetscFunctionReturn(0); 3649793f3fe5SMatthew G. Knepley } 3650793f3fe5SMatthew G. Knepley 365128d58a37SPierre Jolivet static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 3652502a2867SDave May { 3653502a2867SDave May PetscSF sf; 36540a19bb7dSprj- PetscInt niranks, njranks, n; 36550a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 36560a19bb7dSprj- DM_Plex *data = (DM_Plex*) dm->data; 3657502a2867SDave May 36582f356facSMatthew G. Knepley PetscFunctionBegin; 36595f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sf)); 36600a19bb7dSprj- if (!data->neighbors) { 36615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetUp(sf)); 36625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 36635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 36645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 36655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 36665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 36670a19bb7dSprj- n = njranks + niranks; 36685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 36690a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 36705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMPIIntCast(n, data->neighbors)); 36710a19bb7dSprj- } 36720a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 36730a19bb7dSprj- if (ranks) { 36740a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 36750a19bb7dSprj- else *ranks = NULL; 36760a19bb7dSprj- } 3677502a2867SDave May PetscFunctionReturn(0); 3678502a2867SDave May } 3679502a2867SDave May 36801eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 36811eb70e55SToby Isaac 368246fa42a0SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm) 3683552f7358SJed Brown { 3684552f7358SJed Brown PetscFunctionBegin; 3685552f7358SJed Brown dm->ops->view = DMView_Plex; 36862c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 3687552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 368838221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 3689552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 36901bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 369166ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 3692552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 3693552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 3694184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 36950298fd71SBarry Smith dm->ops->createfieldis = NULL; 3696552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 3697f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 36980a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 3699552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 3700bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 3701bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 3702b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 37035a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 3704552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 37050a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 37060a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 3707b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 3708d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 37090298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 37100298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 37110298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 37120298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 3713552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 3714552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 37152adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 3716793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 3717552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 37180709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 37190709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 3720bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 37218c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 3722ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 37230709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 3724b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 37252a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 372628d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 37275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C",DMPlexInsertBoundaryValues_Plex)); 37285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertTimeDerviativeBoundaryValues_C",DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 37295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",DMSetUpGLVisViewer_Plex)); 37305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C",DMCreateNeumannOverlap_Plex)); 37315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",DMPlexGetOverlap_Plex)); 37325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeGetDefault_C",DMPlexDistributeGetDefault_Plex)); 37335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeSetDefault_C",DMPlexDistributeSetDefault_Plex)); 37345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C",DMInterpolateSolution_Plex)); 3735552f7358SJed Brown PetscFunctionReturn(0); 3736552f7358SJed Brown } 3737552f7358SJed Brown 373846fa42a0SMatthew G. Knepley PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 373963a16f15SMatthew G. Knepley { 374063a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 374163a16f15SMatthew G. Knepley 374263a16f15SMatthew G. Knepley PetscFunctionBegin; 374363a16f15SMatthew G. Knepley mesh->refct++; 374463a16f15SMatthew G. Knepley (*newdm)->data = mesh; 37455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectChangeTypeName((PetscObject) *newdm, DMPLEX)); 37465f80ce2aSJacob Faibussowitsch CHKERRQ(DMInitialize_Plex(*newdm)); 374763a16f15SMatthew G. Knepley PetscFunctionReturn(0); 374863a16f15SMatthew G. Knepley } 374963a16f15SMatthew G. Knepley 37508818961aSMatthew G Knepley /*MC 37518818961aSMatthew G Knepley DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 37528818961aSMatthew G Knepley In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is 37538818961aSMatthew G Knepley specified by a PetscSection object. Ownership in the global representation is determined by 37548818961aSMatthew G Knepley ownership of the underlying DMPlex points. This is specified by another PetscSection object. 37558818961aSMatthew G Knepley 3756e5893cccSMatthew G. Knepley Options Database Keys: 3757250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 3758250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 3759250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 3760250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 3761250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 3762250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 3763250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 3764ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 3765f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 3766f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 3767f12cf164SMatthew G. Knepley . -dm_plex_max_projection_height - Maxmimum mesh point height used to project locally 3768f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 3769250712c9SMatthew G. Knepley . -dm_plex_check_all - Perform all shecks below 3770f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 3771f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 3772f12cf164SMatthew 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 3773f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 3774f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 3775e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 3776e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 3777e5893cccSMatthew G. Knepley 37788818961aSMatthew G Knepley Level: intermediate 37798818961aSMatthew G Knepley 37808818961aSMatthew G Knepley .seealso: DMType, DMPlexCreate(), DMCreate(), DMSetType() 37818818961aSMatthew G Knepley M*/ 37828818961aSMatthew G Knepley 37838cc058d9SJed Brown PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 3784552f7358SJed Brown { 3785552f7358SJed Brown DM_Plex *mesh; 3786412e9a14SMatthew G. Knepley PetscInt unit; 3787552f7358SJed Brown 3788552f7358SJed Brown PetscFunctionBegin; 3789552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNewLog(dm,&mesh)); 3791552f7358SJed Brown dm->data = mesh; 3792552f7358SJed Brown 3793552f7358SJed Brown mesh->refct = 1; 37945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 3795552f7358SJed Brown mesh->maxConeSize = 0; 37960298fd71SBarry Smith mesh->cones = NULL; 37970298fd71SBarry Smith mesh->coneOrientations = NULL; 37985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 3799552f7358SJed Brown mesh->maxSupportSize = 0; 38000298fd71SBarry Smith mesh->supports = NULL; 3801552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 3802552f7358SJed Brown mesh->refinementLimit = -1.0; 3803e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 38047d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 38057d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 3806552f7358SJed Brown 38070298fd71SBarry Smith mesh->facesTmp = NULL; 3808552f7358SJed Brown 3809d9deefdfSMatthew G. Knepley mesh->tetgenOpts = NULL; 3810d9deefdfSMatthew G. Knepley mesh->triangleOpts = NULL; 38115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 38122e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 3813d9deefdfSMatthew G. Knepley 38140298fd71SBarry Smith mesh->subpointMap = NULL; 3815552f7358SJed Brown 38168865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 3817552f7358SJed Brown 38180aef6b92SMatthew G. Knepley mesh->regularRefinement = PETSC_FALSE; 3819df0420ecSMatthew G. Knepley mesh->depthState = -1; 3820ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 38210298fd71SBarry Smith mesh->globalVertexNumbers = NULL; 38220298fd71SBarry Smith mesh->globalCellNumbers = NULL; 3823a68b90caSToby Isaac mesh->anchorSection = NULL; 3824a68b90caSToby Isaac mesh->anchorIS = NULL; 382541e6d900SToby Isaac mesh->createanchors = NULL; 3826fa73a4e1SToby Isaac mesh->computeanchormatrix = NULL; 3827d961a43aSToby Isaac mesh->parentSection = NULL; 3828d961a43aSToby Isaac mesh->parents = NULL; 3829d961a43aSToby Isaac mesh->childIDs = NULL; 3830d961a43aSToby Isaac mesh->childSection = NULL; 3831d961a43aSToby Isaac mesh->children = NULL; 3832d6a7ad0dSToby Isaac mesh->referenceTree = NULL; 3833dcbd3bf7SToby Isaac mesh->getchildsymmetry = NULL; 3834552f7358SJed Brown mesh->vtkCellHeight = 0; 3835e228b242SToby Isaac mesh->useAnchors = PETSC_FALSE; 3836552f7358SJed Brown 3837b29cfa1cSToby Isaac mesh->maxProjectionHeight = 0; 3838b29cfa1cSToby Isaac 38390a19bb7dSprj- mesh->neighbors = NULL; 38400a19bb7dSprj- 3841552f7358SJed Brown mesh->printSetValues = PETSC_FALSE; 3842552f7358SJed Brown mesh->printFEM = 0; 38436113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 3844552f7358SJed Brown 38455f80ce2aSJacob Faibussowitsch CHKERRQ(DMInitialize_Plex(dm)); 3846552f7358SJed Brown PetscFunctionReturn(0); 3847552f7358SJed Brown } 3848552f7358SJed Brown 3849552f7358SJed Brown /*@ 3850552f7358SJed Brown DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 3851552f7358SJed Brown 3852d083f849SBarry Smith Collective 3853552f7358SJed Brown 3854552f7358SJed Brown Input Parameter: 3855552f7358SJed Brown . comm - The communicator for the DMPlex object 3856552f7358SJed Brown 3857552f7358SJed Brown Output Parameter: 3858552f7358SJed Brown . mesh - The DMPlex object 3859552f7358SJed Brown 3860552f7358SJed Brown Level: beginner 3861552f7358SJed Brown 3862552f7358SJed Brown @*/ 3863552f7358SJed Brown PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 3864552f7358SJed Brown { 3865552f7358SJed Brown PetscFunctionBegin; 3866552f7358SJed Brown PetscValidPointer(mesh,2); 38675f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, mesh)); 38685f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*mesh, DMPLEX)); 3869552f7358SJed Brown PetscFunctionReturn(0); 3870552f7358SJed Brown } 3871552f7358SJed Brown 3872b09969d6SVaclav Hapla /*@C 3873b09969d6SVaclav Hapla DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output) 3874b09969d6SVaclav Hapla 3875b09969d6SVaclav Hapla Input Parameters: 3876b09969d6SVaclav Hapla + dm - The DM 3877b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 3878325d53feSBarry Smith . numVertices - The number of vertices to be owned by this process, or PETSC_DECIDE 3879325d53feSBarry Smith . NVertices - The global number of vertices, or PETSC_DETERMINE 3880b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 38815e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 3882b09969d6SVaclav Hapla 3883be8c289dSNicolas Barral Output Parameters: 3884be8c289dSNicolas Barral + vertexSF - (Optional) SF describing complete vertex ownership 3885be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 3886b09969d6SVaclav Hapla 3887b09969d6SVaclav Hapla Notes: 3888b09969d6SVaclav Hapla Two triangles sharing a face 3889b09969d6SVaclav Hapla $ 3890b09969d6SVaclav Hapla $ 2 3891b09969d6SVaclav Hapla $ / | \ 3892b09969d6SVaclav Hapla $ / | \ 3893b09969d6SVaclav Hapla $ / | \ 3894b09969d6SVaclav Hapla $ 0 0 | 1 3 3895b09969d6SVaclav Hapla $ \ | / 3896b09969d6SVaclav Hapla $ \ | / 3897b09969d6SVaclav Hapla $ \ | / 3898b09969d6SVaclav Hapla $ 1 3899b09969d6SVaclav Hapla would have input 3900b09969d6SVaclav Hapla $ numCells = 2, numVertices = 4 3901b09969d6SVaclav Hapla $ cells = [0 1 2 1 3 2] 3902b09969d6SVaclav Hapla $ 3903b09969d6SVaclav Hapla which would result in the DMPlex 3904b09969d6SVaclav Hapla $ 3905b09969d6SVaclav Hapla $ 4 3906b09969d6SVaclav Hapla $ / | \ 3907b09969d6SVaclav Hapla $ / | \ 3908b09969d6SVaclav Hapla $ / | \ 3909b09969d6SVaclav Hapla $ 2 0 | 1 5 3910b09969d6SVaclav Hapla $ \ | / 3911b09969d6SVaclav Hapla $ \ | / 3912b09969d6SVaclav Hapla $ \ | / 3913b09969d6SVaclav Hapla $ 3 3914b09969d6SVaclav Hapla 391525b6865aSVaclav Hapla Vertices are implicitly numbered consecutively 0,...,NVertices. 391625b6865aSVaclav Hapla Each rank owns a chunk of numVertices consecutive vertices. 391725b6865aSVaclav Hapla If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout. 3918325d53feSBarry Smith If NVertices is PETSC_DETERMINE and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 3919325d53feSBarry Smith If only NVertices is PETSC_DETERMINE, it is computed as the sum of numVertices over all ranks. 392025b6865aSVaclav Hapla 3921b09969d6SVaclav Hapla The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 3922b09969d6SVaclav Hapla 3923b09969d6SVaclav Hapla Not currently supported in Fortran. 3924b09969d6SVaclav Hapla 3925b09969d6SVaclav Hapla Level: advanced 3926b09969d6SVaclav Hapla 3927b09969d6SVaclav Hapla .seealso: DMPlexBuildFromCellList(), DMPlexCreateFromCellListParallelPetsc(), DMPlexBuildCoordinatesFromCellListParallel() 3928b09969d6SVaclav Hapla @*/ 3929be8c289dSNicolas Barral PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved) 3930a47d0d45SMatthew G. Knepley { 39312464107aSksagiyam PetscSF sfPoint; 39322464107aSksagiyam PetscLayout layout; 393382fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 3934a47d0d45SMatthew G. Knepley 3935a47d0d45SMatthew G. Knepley PetscFunctionBegin; 393625b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm,NVertices,4); 39375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_BuildFromCellList,dm,0,0,0)); 393825b6865aSVaclav Hapla /* Get/check global number of vertices */ 393925b6865aSVaclav Hapla { 394025b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 394125b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 394225b6865aSVaclav Hapla 394325b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 394425b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 394525b6865aSVaclav Hapla for (i=0; i<len; i++) if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 394625b6865aSVaclav Hapla ++NVerticesInCells; 39475f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm))); 394825b6865aSVaclav Hapla 394925b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 39502c71b3e2SJacob Faibussowitsch else PetscCheckFalse(NVertices != PETSC_DECIDE && NVertices < NVerticesInCells,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Specified global number of vertices %D must be greater than or equal to the number of vertices in cells %D",NVertices,NVerticesInCells); 395125b6865aSVaclav Hapla } 39529079aca8SVaclav Hapla /* Count locally unique vertices */ 39539079aca8SVaclav Hapla { 39549079aca8SVaclav Hapla PetscHSetI vhash; 39559079aca8SVaclav Hapla PetscInt off = 0; 39569079aca8SVaclav Hapla 39575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetICreate(&vhash)); 3958a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 3959a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 39605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIAdd(vhash, cells[c*numCorners+p])); 3961a47d0d45SMatthew G. Knepley } 3962a47d0d45SMatthew G. Knepley } 39635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIGetSize(vhash, &numVerticesAdj)); 39645f80ce2aSJacob Faibussowitsch if (!verticesAdjSaved) CHKERRQ(PetscMalloc1(numVerticesAdj, &verticesAdj)); 3965be8c289dSNicolas Barral else { verticesAdj = *verticesAdjSaved; } 39665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIGetElems(vhash, &off, verticesAdj)); 39675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIDestroy(&vhash)); 39682c71b3e2SJacob Faibussowitsch PetscCheckFalse(off != numVerticesAdj,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %D should be %D", off, numVerticesAdj); 3969a47d0d45SMatthew G. Knepley } 39705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortInt(numVerticesAdj, verticesAdj)); 3971a47d0d45SMatthew G. Knepley /* Create cones */ 39725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVerticesAdj)); 39735f80ce2aSJacob Faibussowitsch for (c = 0; c < numCells; ++c) CHKERRQ(DMPlexSetConeSize(dm, c, numCorners)); 39745f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); 39755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCones(dm,&cones)); 3976a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 3977a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 3978a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c*numCorners+p]; 3979a47d0d45SMatthew G. Knepley PetscInt lv; 3980a47d0d45SMatthew G. Knepley 39819079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 39829079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 39835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 39842c71b3e2SJacob Faibussowitsch PetscCheckFalse(lv < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %D in local connectivity", gv); 3985961cfab0SVaclav Hapla cones[c*numCorners+p] = lv+numCells; 3986a47d0d45SMatthew G. Knepley } 3987a47d0d45SMatthew G. Knepley } 39882464107aSksagiyam /* Build point sf */ 39895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 39905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetSize(layout, NVertices)); 39915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetLocalSize(layout, numVertices)); 39925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetBlockSize(layout, 1)); 39935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 39945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutDestroy(&layout)); 39955f80ce2aSJacob Faibussowitsch if (!verticesAdjSaved) CHKERRQ(PetscFree(verticesAdj)); 39965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) sfPoint, "point SF")); 39972464107aSksagiyam if (dm->sf) { 39982464107aSksagiyam const char *prefix; 39992464107aSksagiyam 40005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 40015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 40022464107aSksagiyam } 40035f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(dm, sfPoint)); 40045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfPoint)); 40055f80ce2aSJacob Faibussowitsch if (vertexSF) CHKERRQ(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF")); 4006a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 40075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 40085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 40095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_BuildFromCellList,dm,0,0,0)); 4010a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4011a47d0d45SMatthew G. Knepley } 4012a47d0d45SMatthew G. Knepley 4013b09969d6SVaclav Hapla /*@C 4014b09969d6SVaclav Hapla DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4015b09969d6SVaclav Hapla 4016b09969d6SVaclav Hapla Input Parameters: 4017b09969d6SVaclav Hapla + dm - The DM 4018b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4019b09969d6SVaclav Hapla . sfVert - SF describing complete vertex ownership 4020b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4021b09969d6SVaclav Hapla 4022b09969d6SVaclav Hapla Level: advanced 4023b09969d6SVaclav Hapla 4024b09969d6SVaclav Hapla Notes: 4025b09969d6SVaclav Hapla Not currently supported in Fortran. 4026b09969d6SVaclav Hapla 4027b09969d6SVaclav Hapla .seealso: DMPlexBuildCoordinatesFromCellList(), DMPlexCreateFromCellListParallelPetsc(), DMPlexBuildFromCellListParallel() 4028b09969d6SVaclav Hapla @*/ 40291edcf0b2SVaclav Hapla PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 4030a47d0d45SMatthew G. Knepley { 4031a47d0d45SMatthew G. Knepley PetscSection coordSection; 4032a47d0d45SMatthew G. Knepley Vec coordinates; 4033a47d0d45SMatthew G. Knepley PetscScalar *coords; 40341edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 4035a47d0d45SMatthew G. Knepley 4036a47d0d45SMatthew G. Knepley PetscFunctionBegin; 40375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0)); 40385f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 40392c71b3e2SJacob Faibussowitsch PetscCheckFalse(vStart < 0 || vEnd < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 40405f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, spaceDim)); 40415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 40422c71b3e2SJacob Faibussowitsch PetscCheckFalse(vEnd - vStart != numVerticesAdj,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Supplied sfVert has wrong number of leaves = %D != %D = vEnd - vStart",numVerticesAdj,vEnd - vStart); 40435f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 40445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 40455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 40465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, vStart, vEnd)); 40471edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 40485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, spaceDim)); 40495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4050a47d0d45SMatthew G. Knepley } 40515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 40525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 40535f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 40545f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, spaceDim)); 40555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 40565f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 40575f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 40585f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 4059a47d0d45SMatthew G. Knepley { 4060a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 4061a47d0d45SMatthew G. Knepley 4062a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 40635f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype)); 40645f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_commit(&coordtype)); 406521016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 406621016a8bSBarry Smith { 406721016a8bSBarry Smith PetscScalar *svertexCoords; 406821016a8bSBarry Smith PetscInt i; 40695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numVertices*spaceDim,&svertexCoords)); 40703612f820SVaclav Hapla for (i=0; i<numVertices*spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 40715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords,MPI_REPLACE)); 40725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords,MPI_REPLACE)); 40735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(svertexCoords)); 407421016a8bSBarry Smith } 407521016a8bSBarry Smith #else 40765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords,MPI_REPLACE)); 40775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords,MPI_REPLACE)); 407821016a8bSBarry Smith #endif 40795f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_free(&coordtype)); 4080a47d0d45SMatthew G. Knepley } 40815f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 40825f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 40835f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 40845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0)); 4085a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4086a47d0d45SMatthew G. Knepley } 4087a47d0d45SMatthew G. Knepley 4088c3edce3dSSatish Balay /*@ 4089b09969d6SVaclav Hapla DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output) 4090a47d0d45SMatthew G. Knepley 4091a47d0d45SMatthew G. Knepley Input Parameters: 4092a47d0d45SMatthew G. Knepley + comm - The communicator 4093a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 4094a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 409525b6865aSVaclav Hapla . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 409625b6865aSVaclav Hapla . NVertices - The global number of vertices, or PETSC_DECIDE 4097a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 4098a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 4099a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 4100a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 4101a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4102a47d0d45SMatthew G. Knepley 4103d8d19677SJose E. Roman Output Parameters: 410418d54ad4SMichael Lange + dm - The DM 4105be8c289dSNicolas Barral . vertexSF - (Optional) SF describing complete vertex ownership 4106be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 4107a47d0d45SMatthew G. Knepley 4108b09969d6SVaclav Hapla Notes: 4109b09969d6SVaclav Hapla This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), 4110b09969d6SVaclav Hapla DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel() 4111a47d0d45SMatthew G. Knepley 411225b6865aSVaclav Hapla See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters. 411325b6865aSVaclav Hapla See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters. 411425b6865aSVaclav Hapla 4115b09969d6SVaclav Hapla Level: intermediate 4116a47d0d45SMatthew G. Knepley 4117b09969d6SVaclav Hapla .seealso: DMPlexCreateFromCellListPetsc(), DMPlexBuildFromCellListParallel(), DMPlexBuildCoordinatesFromCellListParallel(), DMPlexCreateFromDAG(), DMPlexCreate() 4118a47d0d45SMatthew G. Knepley @*/ 4119be8c289dSNicolas Barral 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) 4120a47d0d45SMatthew G. Knepley { 4121a47d0d45SMatthew G. Knepley PetscSF sfVert; 4122a47d0d45SMatthew G. Knepley 4123a47d0d45SMatthew G. Knepley PetscFunctionBegin; 41245f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 41255f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 4126a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 4127064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 41285f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(*dm, dim)); 41295f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 4130a47d0d45SMatthew G. Knepley if (interpolate) { 41315fd9971aSMatthew G. Knepley DM idm; 4132a47d0d45SMatthew G. Knepley 41335f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(*dm, &idm)); 41345f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(dm)); 4135a47d0d45SMatthew G. Knepley *dm = idm; 4136a47d0d45SMatthew G. Knepley } 41375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 413818d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 41395f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSFDestroy(&sfVert)); 4140a47d0d45SMatthew G. Knepley PetscFunctionReturn(0); 4141a47d0d45SMatthew G. Knepley } 4142a47d0d45SMatthew G. Knepley 4143b09969d6SVaclav Hapla /*@C 4144b09969d6SVaclav Hapla DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output) 41459298eaa6SMatthew G Knepley 41469298eaa6SMatthew G Knepley Input Parameters: 4147b09969d6SVaclav Hapla + dm - The DM 4148b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 4149325d53feSBarry Smith . numVertices - The number of vertices owned by this process, or PETSC_DETERMINE 41509298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 41515e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 41529298eaa6SMatthew G Knepley 4153b09969d6SVaclav Hapla Level: advanced 41549298eaa6SMatthew G Knepley 4155b09969d6SVaclav Hapla Notes: 4156b09969d6SVaclav Hapla Two triangles sharing a face 41579298eaa6SMatthew G Knepley $ 41589298eaa6SMatthew G Knepley $ 2 41599298eaa6SMatthew G Knepley $ / | \ 41609298eaa6SMatthew G Knepley $ / | \ 41619298eaa6SMatthew G Knepley $ / | \ 41629298eaa6SMatthew G Knepley $ 0 0 | 1 3 41639298eaa6SMatthew G Knepley $ \ | / 41649298eaa6SMatthew G Knepley $ \ | / 41659298eaa6SMatthew G Knepley $ \ | / 41669298eaa6SMatthew G Knepley $ 1 41679298eaa6SMatthew G Knepley would have input 41689298eaa6SMatthew G Knepley $ numCells = 2, numVertices = 4 41699298eaa6SMatthew G Knepley $ cells = [0 1 2 1 3 2] 41709298eaa6SMatthew G Knepley $ 41719298eaa6SMatthew G Knepley which would result in the DMPlex 41729298eaa6SMatthew G Knepley $ 41739298eaa6SMatthew G Knepley $ 4 41749298eaa6SMatthew G Knepley $ / | \ 41759298eaa6SMatthew G Knepley $ / | \ 41769298eaa6SMatthew G Knepley $ / | \ 41779298eaa6SMatthew G Knepley $ 2 0 | 1 5 41789298eaa6SMatthew G Knepley $ \ | / 41799298eaa6SMatthew G Knepley $ \ | / 41809298eaa6SMatthew G Knepley $ \ | / 41819298eaa6SMatthew G Knepley $ 3 41829298eaa6SMatthew G Knepley 4183325d53feSBarry Smith If numVertices is PETSC_DETERMINE, it is computed by PETSc as the maximum vertex index in cells + 1. 418425b6865aSVaclav Hapla 4185b09969d6SVaclav Hapla Not currently supported in Fortran. 41869298eaa6SMatthew G Knepley 4187b09969d6SVaclav Hapla .seealso: DMPlexBuildFromCellListParallel(), DMPlexBuildCoordinatesFromCellList(), DMPlexCreateFromCellListPetsc() 4188b09969d6SVaclav Hapla @*/ 41895e488331SVaclav Hapla PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 4190b09969d6SVaclav Hapla { 4191961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 4192b09969d6SVaclav Hapla 4193b09969d6SVaclav Hapla PetscFunctionBegin; 41945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_BuildFromCellList,dm,0,0,0)); 41955f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 419625b6865aSVaclav Hapla /* Get/check global number of vertices */ 419725b6865aSVaclav Hapla { 419825b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 419925b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 420025b6865aSVaclav Hapla 420125b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 420225b6865aSVaclav Hapla NVerticesInCells = PETSC_MIN_INT; 420325b6865aSVaclav Hapla for (i=0; i<len; i++) if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 420425b6865aSVaclav Hapla ++NVerticesInCells; 420525b6865aSVaclav Hapla 420625b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 42072c71b3e2SJacob Faibussowitsch else PetscCheckFalse(numVertices < NVerticesInCells,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Specified number of vertices %D must be greater than or equal to the number of vertices in cells %D",numVertices,NVerticesInCells); 420825b6865aSVaclav Hapla } 42095f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVertices)); 4210b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 42115f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, c, numCorners)); 4212b09969d6SVaclav Hapla } 42135f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); 42145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCones(dm,&cones)); 4215b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 4216b09969d6SVaclav Hapla for (p = 0; p < numCorners; ++p) { 4217961cfab0SVaclav Hapla cones[c*numCorners+p] = cells[c*numCorners+p]+numCells; 4218b09969d6SVaclav Hapla } 4219b09969d6SVaclav Hapla } 42205f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 42215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 42225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_BuildFromCellList,dm,0,0,0)); 4223b09969d6SVaclav Hapla PetscFunctionReturn(0); 4224b09969d6SVaclav Hapla } 4225b09969d6SVaclav Hapla 4226b09969d6SVaclav Hapla /*@C 4227b09969d6SVaclav Hapla DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 4228b09969d6SVaclav Hapla 4229b09969d6SVaclav Hapla Input Parameters: 4230b09969d6SVaclav Hapla + dm - The DM 4231b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 4232b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 4233b09969d6SVaclav Hapla 4234b09969d6SVaclav Hapla Level: advanced 4235b09969d6SVaclav Hapla 4236b09969d6SVaclav Hapla Notes: 4237b09969d6SVaclav Hapla Not currently supported in Fortran. 4238b09969d6SVaclav Hapla 4239b09969d6SVaclav Hapla .seealso: DMPlexBuildCoordinatesFromCellListParallel(), DMPlexCreateFromCellListPetsc(), DMPlexBuildFromCellList() 4240b09969d6SVaclav Hapla @*/ 42411edcf0b2SVaclav Hapla PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 4242b09969d6SVaclav Hapla { 4243b09969d6SVaclav Hapla PetscSection coordSection; 4244b09969d6SVaclav Hapla Vec coordinates; 4245b09969d6SVaclav Hapla DM cdm; 4246b09969d6SVaclav Hapla PetscScalar *coords; 42471edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 4248b09969d6SVaclav Hapla 4249b09969d6SVaclav Hapla PetscFunctionBegin; 42505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0)); 42515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 42522c71b3e2SJacob Faibussowitsch PetscCheckFalse(vStart < 0 || vEnd < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 42535f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, spaceDim)); 42545f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 42555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 42565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 42575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, vStart, vEnd)); 42581edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 42595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, spaceDim)); 42605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4261b09969d6SVaclav Hapla } 42625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 4263b09969d6SVaclav Hapla 42645f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 42655f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLocalVector(cdm, &coordinates)); 42665f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, spaceDim)); 42675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 42685f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayWrite(coordinates, &coords)); 42691edcf0b2SVaclav Hapla for (v = 0; v < vEnd-vStart; ++v) { 4270b09969d6SVaclav Hapla for (d = 0; d < spaceDim; ++d) { 4271b09969d6SVaclav Hapla coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4272b09969d6SVaclav Hapla } 4273b09969d6SVaclav Hapla } 42745f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayWrite(coordinates, &coords)); 42755f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 42765f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 42775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0)); 4278b09969d6SVaclav Hapla PetscFunctionReturn(0); 4279b09969d6SVaclav Hapla } 4280b09969d6SVaclav Hapla 4281b09969d6SVaclav Hapla /*@ 42823df08285SMatthew 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 42833df08285SMatthew G. Knepley 42843df08285SMatthew G. Knepley Collective on comm 4285b09969d6SVaclav Hapla 4286b09969d6SVaclav Hapla Input Parameters: 4287b09969d6SVaclav Hapla + comm - The communicator 4288b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 42893df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 42903df08285SMatthew G. Knepley . numVertices - The number of vertices owned by this process, or PETSC_DECIDE, only on process 0 42913df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 4292b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 42933df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0 4294b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 42953df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0 4296b09969d6SVaclav Hapla 4297b09969d6SVaclav Hapla Output Parameter: 42983df08285SMatthew G. Knepley . dm - The DM, which only has points on process 0 4299b09969d6SVaclav Hapla 4300b09969d6SVaclav Hapla Notes: 4301b09969d6SVaclav Hapla This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(), 4302b09969d6SVaclav Hapla DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList() 4303b09969d6SVaclav Hapla 430425b6865aSVaclav Hapla See DMPlexBuildFromCellList() for an example and details about the topology-related parameters. 430525b6865aSVaclav Hapla See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters. 43063df08285SMatthew G. Knepley See DMPlexCreateFromCellListParallelPetsc() for parallel input 430725b6865aSVaclav Hapla 4308b09969d6SVaclav Hapla Level: intermediate 4309b09969d6SVaclav Hapla 4310b09969d6SVaclav Hapla .seealso: DMPlexCreateFromCellListParallelPetsc(), DMPlexBuildFromCellList(), DMPlexBuildCoordinatesFromCellList(), DMPlexCreateFromDAG(), DMPlexCreate() 43119298eaa6SMatthew G Knepley @*/ 4312a4a685f2SJacob 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) 43139298eaa6SMatthew G Knepley { 43143df08285SMatthew G. Knepley PetscMPIInt rank; 43159298eaa6SMatthew G Knepley 43169298eaa6SMatthew G Knepley PetscFunctionBegin; 4317*28b400f6SJacob 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."); 43185f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 43195f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 43205f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 43215f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(*dm, dim)); 43225f80ce2aSJacob Faibussowitsch if (!rank) CHKERRQ(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 43235f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 43249298eaa6SMatthew G Knepley if (interpolate) { 43255fd9971aSMatthew G. Knepley DM idm; 43269298eaa6SMatthew G Knepley 43275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(*dm, &idm)); 43285f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(dm)); 43299298eaa6SMatthew G Knepley *dm = idm; 43309298eaa6SMatthew G Knepley } 43315f80ce2aSJacob Faibussowitsch if (!rank) CHKERRQ(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 43325f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 43339298eaa6SMatthew G Knepley PetscFunctionReturn(0); 43349298eaa6SMatthew G Knepley } 43359298eaa6SMatthew G Knepley 4336939f6067SMatthew G. Knepley /*@ 4337939f6067SMatthew 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 4338939f6067SMatthew G. Knepley 4339939f6067SMatthew G. Knepley Input Parameters: 4340c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension() 4341939f6067SMatthew G. Knepley . depth - The depth of the DAG 4342367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth 4343939f6067SMatthew G. Knepley . coneSize - The cone size of each point 4344939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 4345939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 4346367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim() 4347939f6067SMatthew G. Knepley 4348939f6067SMatthew G. Knepley Output Parameter: 4349939f6067SMatthew G. Knepley . dm - The DM 4350939f6067SMatthew G. Knepley 4351939f6067SMatthew G. Knepley Note: Two triangles sharing a face would have input 4352939f6067SMatthew G. Knepley $ depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 4353939f6067SMatthew G. Knepley $ cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 4354939f6067SMatthew G. Knepley $ vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 4355939f6067SMatthew G. Knepley $ 4356939f6067SMatthew G. Knepley which would result in the DMPlex 4357939f6067SMatthew G. Knepley $ 4358939f6067SMatthew G. Knepley $ 4 4359939f6067SMatthew G. Knepley $ / | \ 4360939f6067SMatthew G. Knepley $ / | \ 4361939f6067SMatthew G. Knepley $ / | \ 4362939f6067SMatthew G. Knepley $ 2 0 | 1 5 4363939f6067SMatthew G. Knepley $ \ | / 4364939f6067SMatthew G. Knepley $ \ | / 4365939f6067SMatthew G. Knepley $ \ | / 4366939f6067SMatthew G. Knepley $ 3 4367939f6067SMatthew G. Knepley $ 4368a4a685f2SJacob Faibussowitsch $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc() 4369939f6067SMatthew G. Knepley 4370939f6067SMatthew G. Knepley Level: advanced 4371939f6067SMatthew G. Knepley 4372a4a685f2SJacob Faibussowitsch .seealso: DMPlexCreateFromCellListPetsc(), DMPlexCreate() 4373939f6067SMatthew G. Knepley @*/ 43749298eaa6SMatthew G Knepley PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 43759298eaa6SMatthew G Knepley { 43769298eaa6SMatthew G Knepley Vec coordinates; 43779298eaa6SMatthew G Knepley PetscSection coordSection; 43789298eaa6SMatthew G Knepley PetscScalar *coords; 4379811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 43809298eaa6SMatthew G Knepley 43819298eaa6SMatthew G Knepley PetscFunctionBegin; 43825f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 43835f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm, &dimEmbed)); 43842c71b3e2SJacob Faibussowitsch PetscCheckFalse(dimEmbed < dim,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Embedding dimension %D cannot be less than intrinsic dimension %d",dimEmbed,dim); 43859298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 43865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, pStart, pEnd)); 43879298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 43885f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, p, coneSize[p-pStart])); 438997e052ccSToby Isaac if (firstVertex < 0 && !coneSize[p - pStart]) { 439097e052ccSToby Isaac firstVertex = p - pStart; 43919298eaa6SMatthew G Knepley } 439297e052ccSToby Isaac } 43932c71b3e2SJacob Faibussowitsch PetscCheckFalse(firstVertex < 0 && numPoints[0],PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected %D vertices but could not find any", numPoints[0]); 43945f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */ 43959298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p-pStart], ++p) { 43965f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, p, &cones[off])); 43975f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 43989298eaa6SMatthew G Knepley } 43995f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 44005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 44019298eaa6SMatthew G Knepley /* Build coordinates */ 44025f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 44035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 44045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 44055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, firstVertex, firstVertex+numPoints[0])); 44069298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex+numPoints[0]; ++v) { 44075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, dimEmbed)); 44085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 44099298eaa6SMatthew G Knepley } 44105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 44115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 44125f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 44135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 44145f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 44155f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, dimEmbed)); 44165f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 44179318fe57SMatthew G. Knepley if (vertexCoords) { 44185f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 44199298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 44209298eaa6SMatthew G Knepley PetscInt off; 44219298eaa6SMatthew G Knepley 44225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSection, v+firstVertex, &off)); 4423811e8653SToby Isaac for (d = 0; d < dimEmbed; ++d) { 4424811e8653SToby Isaac coords[off+d] = vertexCoords[v*dimEmbed+d]; 44259298eaa6SMatthew G Knepley } 44269298eaa6SMatthew G Knepley } 44279318fe57SMatthew G. Knepley } 44285f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 44295f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 44305f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 44319298eaa6SMatthew G Knepley PetscFunctionReturn(0); 44329298eaa6SMatthew G Knepley } 44338415267dSToby Isaac 4434ca522641SMatthew G. Knepley /*@C 44358ca92349SMatthew G. Knepley DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file. 44368ca92349SMatthew G. Knepley 44378ca92349SMatthew G. Knepley + comm - The MPI communicator 44388ca92349SMatthew G. Knepley . filename - Name of the .dat file 44398ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 44408ca92349SMatthew G. Knepley 44418ca92349SMatthew G. Knepley Output Parameter: 44428ca92349SMatthew G. Knepley . dm - The DM object representing the mesh 44438ca92349SMatthew G. Knepley 44448ca92349SMatthew G. Knepley Note: The format is the simplest possible: 44458ca92349SMatthew G. Knepley $ Ne 44468ca92349SMatthew G. Knepley $ v0 v1 ... vk 44478ca92349SMatthew G. Knepley $ Nv 44488ca92349SMatthew G. Knepley $ x y z marker 44498ca92349SMatthew G. Knepley 44508ca92349SMatthew G. Knepley Level: beginner 44518ca92349SMatthew G. Knepley 44528ca92349SMatthew G. Knepley .seealso: DMPlexCreateFromFile(), DMPlexCreateMedFromFile(), DMPlexCreateGmsh(), DMPlexCreate() 44538ca92349SMatthew G. Knepley @*/ 44548ca92349SMatthew G. Knepley PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 44558ca92349SMatthew G. Knepley { 44568ca92349SMatthew G. Knepley DMLabel marker; 44578ca92349SMatthew G. Knepley PetscViewer viewer; 44588ca92349SMatthew G. Knepley Vec coordinates; 44598ca92349SMatthew G. Knepley PetscSection coordSection; 44608ca92349SMatthew G. Knepley PetscScalar *coords; 44618ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 44628ca92349SMatthew G. Knepley PetscInt dim = 3, cdim = 3, coordSize, v, c, d; 44638ca92349SMatthew G. Knepley PetscMPIInt rank; 4464f8d5e320SMatthew G. Knepley int snum, Nv, Nc, Ncn, Nl; 44658ca92349SMatthew G. Knepley 44668ca92349SMatthew G. Knepley PetscFunctionBegin; 44675f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 44685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerCreate(comm, &viewer)); 44695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 44705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 44715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetName(viewer, filename)); 4472dd400576SPatrick Sanan if (rank == 0) { 44735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING)); 4474f8d5e320SMatthew G. Knepley snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl); 44752c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != 4,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 447625ce1634SJed Brown } else { 4477f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 44788ca92349SMatthew G. Knepley } 44795f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 44805f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 44815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(*dm, 0, Nc+Nv)); 44825f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(*dm, dim)); 44835f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(*dm, cdim)); 44848ca92349SMatthew G. Knepley /* Read topology */ 4485dd400576SPatrick Sanan if (rank == 0) { 4486f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 4487f8d5e320SMatthew G. Knepley PetscInt cone[8]; 44888ca92349SMatthew G. Knepley int vbuf[8], v; 44898ca92349SMatthew G. Knepley 4490f8d5e320SMatthew G. Knepley for (c = 0; c < Ncn; ++c) {format[c*3+0] = '%'; format[c*3+1] = 'd'; format[c*3+2] = ' ';} 4491f8d5e320SMatthew G. Knepley format[Ncn*3-1] = '\0'; 44925f80ce2aSJacob Faibussowitsch for (c = 0; c < Nc; ++c) CHKERRQ(DMPlexSetConeSize(*dm, c, Ncn)); 44935f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(*dm)); 44948ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 44955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 4496f8d5e320SMatthew G. Knepley switch (Ncn) { 4497f8d5e320SMatthew G. Knepley case 2: snum = sscanf(line, format, &vbuf[0], &vbuf[1]);break; 4498f8d5e320SMatthew G. Knepley case 3: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);break; 4499f8d5e320SMatthew G. Knepley case 4: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);break; 4500f8d5e320SMatthew G. Knepley case 6: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);break; 4501f8d5e320SMatthew G. Knepley case 8: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);break; 450298921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %D vertices", Ncn); 4503f8d5e320SMatthew G. Knepley } 45042c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != Ncn,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 4505f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 45068ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 4507f8d5e320SMatthew G. Knepley if (Ncn == 8) { 45088ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 45098ca92349SMatthew G. Knepley cone[1] = cone[3]; 45108ca92349SMatthew G. Knepley cone[3] = tmp; 45118ca92349SMatthew G. Knepley } 45125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(*dm, c, cone)); 45138ca92349SMatthew G. Knepley } 45148ca92349SMatthew G. Knepley } 45155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(*dm)); 45165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(*dm)); 45178ca92349SMatthew G. Knepley /* Read coordinates */ 45185f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(*dm, &coordSection)); 45195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 45205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 45215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 45228ca92349SMatthew G. Knepley for (v = Nc; v < Nc+Nv; ++v) { 45235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, cdim)); 45245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 45258ca92349SMatthew G. Knepley } 45265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 45275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 45285f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 45295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 45305f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 45315f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, cdim)); 45325f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates, VECSTANDARD)); 45335f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 4534dd400576SPatrick Sanan if (rank == 0) { 4535f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 45368ca92349SMatthew G. Knepley double x[3]; 4537f8d5e320SMatthew G. Knepley int l, val[3]; 45388ca92349SMatthew G. Knepley 4539f8d5e320SMatthew G. Knepley if (Nl) { 4540f8d5e320SMatthew G. Knepley for (l = 0; l < Nl; ++l) {format[l*3+0] = '%'; format[l*3+1] = 'd'; format[l*3+2] = ' ';} 4541f8d5e320SMatthew G. Knepley format[Nl*3-1] = '\0'; 45425f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(*dm, "marker")); 45435f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(*dm, "marker", &marker)); 4544f8d5e320SMatthew G. Knepley } 45458ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 45465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, line, 3+Nl, NULL, PETSC_STRING)); 4547f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 45482c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 4549f8d5e320SMatthew G. Knepley switch (Nl) { 4550f8d5e320SMatthew G. Knepley case 0: snum = 0;break; 4551f8d5e320SMatthew G. Knepley case 1: snum = sscanf(line, format, &val[0]);break; 4552f8d5e320SMatthew G. Knepley case 2: snum = sscanf(line, format, &val[0], &val[1]);break; 4553f8d5e320SMatthew G. Knepley case 3: snum = sscanf(line, format, &val[0], &val[1], &val[2]);break; 455498921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %D labels", Nl); 4555f8d5e320SMatthew G. Knepley } 45562c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != Nl,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 45578ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v*cdim+d] = x[d]; 45585f80ce2aSJacob Faibussowitsch for (l = 0; l < Nl; ++l) CHKERRQ(DMLabelSetValue(marker, v+Nc, val[l])); 45598ca92349SMatthew G. Knepley } 45608ca92349SMatthew G. Knepley } 45615f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 45625f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(*dm, coordinates)); 45635f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 45645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 45658ca92349SMatthew G. Knepley if (interpolate) { 45668ca92349SMatthew G. Knepley DM idm; 45678ca92349SMatthew G. Knepley DMLabel bdlabel; 45688ca92349SMatthew G. Knepley 45695f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(*dm, &idm)); 45705f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(dm)); 45718ca92349SMatthew G. Knepley *dm = idm; 45728ca92349SMatthew G. Knepley 4573f8d5e320SMatthew G. Knepley if (!Nl) { 45745f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(*dm, "marker")); 45755f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(*dm, "marker", &bdlabel)); 45765f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 45775f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexLabelComplete(*dm, bdlabel)); 45788ca92349SMatthew G. Knepley } 4579f8d5e320SMatthew G. Knepley } 45808ca92349SMatthew G. Knepley PetscFunctionReturn(0); 45818ca92349SMatthew G. Knepley } 45828ca92349SMatthew G. Knepley 45838ca92349SMatthew G. Knepley /*@C 4584ca522641SMatthew G. Knepley DMPlexCreateFromFile - This takes a filename and produces a DM 4585ca522641SMatthew G. Knepley 4586ca522641SMatthew G. Knepley Input Parameters: 4587ca522641SMatthew G. Knepley + comm - The communicator 4588ca522641SMatthew G. Knepley . filename - A file name 4589cd7e8a5eSksagiyam . plexname - The object name of the resulting DM, also used for intra-datafile lookup by some formats 4590ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 4591ca522641SMatthew G. Knepley 4592ca522641SMatthew G. Knepley Output Parameter: 4593ca522641SMatthew G. Knepley . dm - The DM 4594ca522641SMatthew G. Knepley 459502ef0d99SVaclav Hapla Options Database Keys: 459602ef0d99SVaclav Hapla . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5 459702ef0d99SVaclav Hapla 4598bca97951SVaclav Hapla Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g. 4599bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 4600bca97951SVaclav Hapla 4601cd7e8a5eSksagiyam Notes: 4602cd7e8a5eSksagiyam Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex 4603cd7e8a5eSksagiyam meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName() 4604cd7e8a5eSksagiyam before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object. 4605cd7e8a5eSksagiyam The input parameter name is thus used to name the DMPlex object when DMPlexCreateFromFile() internally 4606cd7e8a5eSksagiyam calls DMLoad(). Currently, name is ignored for other viewer types and/or formats. 4607cd7e8a5eSksagiyam 4608ca522641SMatthew G. Knepley Level: beginner 4609ca522641SMatthew G. Knepley 4610cd7e8a5eSksagiyam .seealso: DMPlexCreateFromDAG(), DMPlexCreateFromCellListPetsc(), DMPlexCreate(), PetscObjectSetName(), DMView(), DMLoad() 4611ca522641SMatthew G. Knepley @*/ 4612cd7e8a5eSksagiyam PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 4613ca522641SMatthew G. Knepley { 4614ca522641SMatthew G. Knepley const char *extGmsh = ".msh"; 4615de78e4feSLisandro Dalcin const char *extGmsh2 = ".msh2"; 4616de78e4feSLisandro Dalcin const char *extGmsh4 = ".msh4"; 4617ca522641SMatthew G. Knepley const char *extCGNS = ".cgns"; 4618ca522641SMatthew G. Knepley const char *extExodus = ".exo"; 461986a0adb1SJed Brown const char *extExodus_e = ".e"; 462090c68965SMatthew G. Knepley const char *extGenesis = ".gen"; 46212f0bd6dcSMichael Lange const char *extFluent = ".cas"; 4622cc2f8f65SMatthew G. Knepley const char *extHDF5 = ".h5"; 4623707dd687SMichael Lange const char *extMed = ".med"; 4624f2801cd6SMatthew G. Knepley const char *extPLY = ".ply"; 4625c1cad2e7SMatthew G. Knepley const char *extEGADSLite = ".egadslite"; 4626c1cad2e7SMatthew G. Knepley const char *extEGADS = ".egads"; 4627c1cad2e7SMatthew G. Knepley const char *extIGES = ".igs"; 4628c1cad2e7SMatthew G. Knepley const char *extSTEP = ".stp"; 46298ca92349SMatthew G. Knepley const char *extCV = ".dat"; 4630ca522641SMatthew G. Knepley size_t len; 4631c1cad2e7SMatthew G. Knepley PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV; 4632ca522641SMatthew G. Knepley PetscMPIInt rank; 4633ca522641SMatthew G. Knepley 4634ca522641SMatthew G. Knepley PetscFunctionBegin; 46355d80c0bfSVaclav Hapla PetscValidCharPointer(filename, 2); 46360d862eaeSPierre Jolivet if (plexname) PetscValidCharPointer(plexname, 3); 4637cd7e8a5eSksagiyam PetscValidPointer(dm, 5); 46385f80ce2aSJacob Faibussowitsch CHKERRQ(DMInitializePackage()); 46395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_CreateFromFile,0,0,0,0)); 46405f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 46415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(filename, &len)); 4642*28b400f6SJacob Faibussowitsch PetscCheck(len,comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 46435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extGmsh, 4, &isGmsh)); 46445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-5)], extGmsh2, 5, &isGmsh2)); 46455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-5)], extGmsh4, 5, &isGmsh4)); 46465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-5)], extCGNS, 5, &isCGNS)); 46475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extExodus, 4, &isExodus)); 464886a0adb1SJed Brown if (!isExodus) { 46495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-2)], extExodus_e, 2, &isExodus)); 465086a0adb1SJed Brown } 46515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extGenesis, 4, &isGenesis)); 46525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extFluent, 4, &isFluent)); 46535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-3)], extHDF5, 3, &isHDF5)); 46545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extMed, 4, &isMed)); 46555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extPLY, 4, &isPLY)); 46565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-10)], extEGADSLite, 10, &isEGADSLite)); 46575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-6)], extEGADS, 6, &isEGADS)); 46585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extIGES, 4, &isIGES)); 46595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extSTEP, 4, &isSTEP)); 46605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extCV, 4, &isCV)); 4661de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 46625f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 4663ca522641SMatthew G. Knepley } else if (isCGNS) { 46645f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 466590c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 46665f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 46672f0bd6dcSMichael Lange } else if (isFluent) { 46685f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 4669cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 46709c48423bSVaclav Hapla PetscBool load_hdf5_xdmf = PETSC_FALSE; 4671cc2f8f65SMatthew G. Knepley PetscViewer viewer; 4672cc2f8f65SMatthew G. Knepley 467343b242b4SVaclav 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 */ 46745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-8)], ".xdmf", 5, &load_hdf5_xdmf)); 46755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL)); 46765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerCreate(comm, &viewer)); 46775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 46785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 46795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerSetFromOptions(viewer)); 46805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 46815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetName(viewer, filename)); 4682cd7e8a5eSksagiyam 46835f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 46845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)(*dm), plexname)); 46855f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 46865f80ce2aSJacob Faibussowitsch if (load_hdf5_xdmf) CHKERRQ(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 46875f80ce2aSJacob Faibussowitsch CHKERRQ(DMLoad(*dm, viewer)); 46885f80ce2aSJacob Faibussowitsch if (load_hdf5_xdmf) CHKERRQ(PetscViewerPopFormat(viewer)); 46895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 46905fd9971aSMatthew G. Knepley 46915fd9971aSMatthew G. Knepley if (interpolate) { 46925fd9971aSMatthew G. Knepley DM idm; 46935fd9971aSMatthew G. Knepley 46945f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(*dm, &idm)); 46955f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(dm)); 46965fd9971aSMatthew G. Knepley *dm = idm; 46975fd9971aSMatthew G. Knepley } 4698707dd687SMichael Lange } else if (isMed) { 46995f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateMedFromFile(comm, filename, interpolate, dm)); 4700f2801cd6SMatthew G. Knepley } else if (isPLY) { 47015f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 4702c1cad2e7SMatthew G. Knepley } else if (isEGADSLite || isEGADS || isIGES || isSTEP) { 47035f80ce2aSJacob Faibussowitsch if (isEGADSLite) CHKERRQ(DMPlexCreateEGADSLiteFromFile(comm, filename, dm)); 47045f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexCreateEGADSFromFile(comm, filename, dm)); 47057bee2925SMatthew Knepley if (!interpolate) { 47067bee2925SMatthew Knepley DM udm; 47077bee2925SMatthew Knepley 47085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexUninterpolate(*dm, &udm)); 47095f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(dm)); 47107bee2925SMatthew Knepley *dm = udm; 47117bee2925SMatthew Knepley } 47128ca92349SMatthew G. Knepley } else if (isCV) { 47135f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 471498921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 47155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(plexname, &len)); 47165f80ce2aSJacob Faibussowitsch if (len) CHKERRQ(PetscObjectSetName((PetscObject)(*dm), plexname)); 47175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_CreateFromFile,0,0,0,0)); 4718ca522641SMatthew G. Knepley PetscFunctionReturn(0); 4719ca522641SMatthew G. Knepley } 4720