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) { 22*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPeriodicity(dmin, &isper, &maxCell, &L, &bd)); 23*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPeriodicity(dmout, isper, maxCell, L, bd)); 24e600fa54SMatthew G. Knepley } 25*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeGetDefault(dmin, &dist)); 26*5f80ce2aSJacob 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) { 48*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(ndm)); 499318fe57SMatthew G. Knepley PetscFunctionReturn(0); 509318fe57SMatthew G. Knepley } 519318fe57SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 52*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dmNew, &dim)); 53*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, dim)); 54*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dmNew, &cdim)); 55*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, cdim)); 56*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dmNew, &sf)); 57*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(dm, sf)); 58*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dmNew, &coordDM)); 59*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dmNew, &coords)); 60*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDM(dm, coordDM)); 61*5f80ce2aSJacob 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() */ 63*5f80ce2aSJacob 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; 66*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPeriodicity(dmNew, &isper, &maxCell, &L, &bd)); 67*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPeriodicity(dm, isper, maxCell, L, bd)); 68*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy_Plex(dm)); 69*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMInitialize_Plex(dm)); 709318fe57SMatthew G. Knepley dm->data = dmNew->data; 719318fe57SMatthew G. Knepley ((DM_Plex *) dmNew->data)->refct++; 72*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroyLabelLinkList_Internal(dm)); 73*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 74*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoarseDM(dmNew,&coarseDM)); 75*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoarseDM(dm,coarseDM)); 76*5f80ce2aSJacob 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); 98*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dmA, &sfA)); 99*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dmB, &sfB)); 100*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) sfA)); 101*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(dmA, sfB)); 102*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(dmB, sfA)); 103*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectDereference((PetscObject) sfA)); 1049318fe57SMatthew G. Knepley 105*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dmA, &coordDMA)); 106*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dmB, &coordDMB)); 107*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) coordDMA)); 108*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDM(dmA, coordDMB)); 109*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDM(dmB, coordDMA)); 110*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectDereference((PetscObject) coordDMA)); 1119318fe57SMatthew G. Knepley 112*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dmA, &coordsA)); 113*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dmB, &coordsB)); 114*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) coordsA)); 115*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dmA, coordsB)); 116*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dmB, coordsA)); 117*5f80ce2aSJacob 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; 145*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(dm, &idm)); 146*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopyCoordinates(dm, idm)); 147*5f80ce2aSJacob 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; 174*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 175*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(cdm, &cds)); 176*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetDiscretization(cds, 0, (PetscObject *) &fe)); 177*5f80ce2aSJacob 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; 181*5f80ce2aSJacob Faibussowitsch PetscErrorCode ierr; 1829318fe57SMatthew G. Knepley 183*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 184*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm, &dE)); 185*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsSimplex(dm, &simplex)); 1869318fe57SMatthew G. Knepley qorder = degree; 1879318fe57SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) cdm);CHKERRQ(ierr); 188*5f80ce2aSJacob 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 { 192*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, degree, qorder, &fe)); 193*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(cdm, 0, NULL, (PetscObject) fe)); 194*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateDS(cdm)); 1954f9ab2b4SJed Brown } 196*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMProjectCoordinates(dm, fe)); 197*5f80ce2aSJacob 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; 228*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, &dm)); 229*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(dm, DMPLEX)); 230*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, dim)); 231*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 232ce78fa2fSMatthew G. Knepley switch (dim) { 233ce78fa2fSMatthew G. Knepley case 2: 234*5f80ce2aSJacob Faibussowitsch if (simplex) CHKERRQ(PetscObjectSetName((PetscObject) dm, "triangular")); 235*5f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscObjectSetName((PetscObject) dm, "quadrilateral")); 236ce78fa2fSMatthew G. Knepley break; 237ce78fa2fSMatthew G. Knepley case 3: 238*5f80ce2aSJacob Faibussowitsch if (simplex) CHKERRQ(PetscObjectSetName((PetscObject) dm, "tetrahedral")); 239*5f80ce2aSJacob 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}; 246*5f80ce2aSJacob 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 257*5f80ce2aSJacob 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 265*5f80ce2aSJacob 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 276*5f80ce2aSJacob 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 286*5f80ce2aSJacob 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 298*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 299*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 300*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMRefine(*newdm, comm, &rdm)); 301*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) *newdm, &name)); 302*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) rdm, name)); 303*5f80ce2aSJacob 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 309*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(*newdm, &idm)); 310*5f80ce2aSJacob 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; 330*5f80ce2aSJacob 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 } 335*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 3369318fe57SMatthew G. Knepley if (!rank) { 337*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numVertices)); 338*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */ 339*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", 0, markerLeft)); 340*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", 1, markerRight)); 3419318fe57SMatthew G. Knepley } 342*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 343*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 3449318fe57SMatthew G. Knepley /* Build coordinates */ 345*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, cdim)); 346*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 347*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 348*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, 0, numVertices)); 349*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 3509318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 351*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, cdim)); 352*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 3539318fe57SMatthew G. Knepley } 354*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 355*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 356*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 357*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 358*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 359*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, cdim)); 360*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 361*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 3629318fe57SMatthew G. Knepley coords[0] = lower[0]; 3639318fe57SMatthew G. Knepley coords[1] = upper[0]; 364*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 365*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 366*5f80ce2aSJacob 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; 387*5f80ce2aSJacob 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 } 394*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 395dd400576SPatrick Sanan if (rank == 0) { 396552f7358SJed Brown PetscInt e, ex, ey; 397552f7358SJed Brown 398*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numEdges+numVertices)); 399552f7358SJed Brown for (e = 0; e < numEdges; ++e) { 400*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, e, 2)); 401552f7358SJed Brown } 402*5f80ce2aSJacob 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; 410*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, edge, cone)); 411552f7358SJed Brown if (vx == edges[0]) { 412*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerRight)); 413*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 414552f7358SJed Brown if (ey == edges[1]-1) { 415*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 416*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 417552f7358SJed Brown } 418552f7358SJed Brown } else if (vx == 0) { 419*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerLeft)); 420*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 421552f7358SJed Brown if (ey == edges[1]-1) { 422*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 423*5f80ce2aSJacob 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; 435*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, edge, cone)); 436552f7358SJed Brown if (vy == edges[1]) { 437*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerTop)); 438*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 439552f7358SJed Brown if (ex == edges[0]-1) { 440*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 441*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 442552f7358SJed Brown } 443552f7358SJed Brown } else if (vy == 0) { 444*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBottom)); 445*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 446552f7358SJed Brown if (ex == edges[0]-1) { 447*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 448*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 449552f7358SJed Brown } 450552f7358SJed Brown } 451552f7358SJed Brown } 452552f7358SJed Brown } 453552f7358SJed Brown } 454*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 455*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 456552f7358SJed Brown /* Build coordinates */ 457*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, 2)); 458*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 459*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 460*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 461*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, 2)); 462552f7358SJed Brown for (v = numEdges; v < numEdges+numVertices; ++v) { 463*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, 2)); 464*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 465552f7358SJed Brown } 466*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 467*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 468*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 469*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 470*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 471*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, 2)); 472*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 473*5f80ce2aSJacob 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 } 480*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 481*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 482*5f80ce2aSJacob 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"); 500*5f80ce2aSJacob 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 506*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numFaces+numVertices)); 507552f7358SJed Brown for (f = 0; f < numFaces; ++f) { 508*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, f, 4)); 509552f7358SJed Brown } 510*5f80ce2aSJacob 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]; 517*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, iface, cone)); 518*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1)); 519*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1)); 520*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+1, 1)); 521*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1)); 522*5f80ce2aSJacob 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; 532*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, iface, cone)); 533*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1)); 534*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1)); 535*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+1, 1)); 536*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1)); 537*5f80ce2aSJacob 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]; 547*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, iface, cone)); 548*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1)); 549*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1)); 550*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+1, 1)); 551*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+0, 1)); 552*5f80ce2aSJacob 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; 563*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, iface, cone)); 564*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1)); 565*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1)); 566*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+1, 1)); 567*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+0, 1)); 568*5f80ce2aSJacob 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]; 579*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, iface, cone)); 580*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1)); 581*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1)); 582*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1)); 583*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[1]+0, 1)); 584*5f80ce2aSJacob 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]; 595*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, iface, cone)); 596*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1)); 597*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1)); 598*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1)); 599*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+0, 1)); 600*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+vertices[0], 1)); 6017b59f5a9SMichael Lange iface++; 6027b59f5a9SMichael Lange } 603552f7358SJed Brown } 604552f7358SJed Brown } 605*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 606*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 607552f7358SJed Brown /* Build coordinates */ 608*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, 3)); 609*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 610*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 611*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 612*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, 3)); 613552f7358SJed Brown for (v = numFaces; v < numFaces+numVertices; ++v) { 614*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, 3)); 615*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 616552f7358SJed Brown } 617*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 618*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 619*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 620*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 621*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 622*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, 3)); 623*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 624*5f80ce2aSJacob 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 } 634*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 635*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 636*5f80ce2aSJacob 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); 644*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, dim-1)); 645*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, dim)); 6469318fe57SMatthew G. Knepley switch (dim) { 647*5f80ce2aSJacob Faibussowitsch case 1: CHKERRQ(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces));break; 648*5f80ce2aSJacob Faibussowitsch case 2: CHKERRQ(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces));break; 649*5f80ce2aSJacob 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 } 652*5f80ce2aSJacob 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; 683*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm,dm)); 684*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm,DMPLEX)); 685*5f80ce2aSJacob 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 704*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm,1)); 705*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm,"marker")); 706*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm,"Face Sets")); 707fdbf62faSLisandro Dalcin 708*5f80ce2aSJacob 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; 713*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc4(numCells+numVerts,&coneSize,numCells*2,&cones,numCells+numVerts,&coneOrientations,numVerts,&vertexCoords)); 714*5f80ce2aSJacob 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); } 719*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(dm,1,numPoints,coneSize,cones,coneOrientations,vertexCoords)); 720*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree4(coneSize,cones,coneOrientations,vertexCoords)); 721fdbf62faSLisandro Dalcin 722*5f80ce2aSJacob 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) { 725*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm,1,&fStart,&fEnd)); 726*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm,"marker",fStart,markerLeft)); 727*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm,"marker",fEnd-1,markerRight)); 728*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm,"Face Sets",fStart,faceMarkerLeft)); 729*5f80ce2aSJacob 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)); 734*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPeriodicity(dm,PETSC_TRUE,&maxCell,&L,&bd)); 735fdbf62faSLisandro Dalcin } 736*5f80ce2aSJacob 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"); 748*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), &boundary)); 749*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(boundary, DMPLEX)); 750*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 751*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 752*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopy_Internal(dm, PETSC_TRUE, vol)); 753*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &vol)); 754*5f80ce2aSJacob 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; 772*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm,&dim)); 773*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 774*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm,"marker")); 775*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm,"Face Sets")); 776*5f80ce2aSJacob 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 781*5f80ce2aSJacob 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 } 801*5f80ce2aSJacob 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 844*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numFaces+numEdges+numVertices)); 8453dfda0b1SToby Isaac for (c = 0; c < numCells; c++) { 846*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, c, 6)); 8473dfda0b1SToby Isaac } 8483dfda0b1SToby Isaac for (f = firstXFace; f < firstXFace+numFaces; ++f) { 849*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, f, 4)); 8503dfda0b1SToby Isaac } 8513dfda0b1SToby Isaac for (e = firstXEdge; e < firstXEdge+numEdges; ++e) { 852*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, e, 2)); 8533dfda0b1SToby Isaac } 854*5f80ce2aSJacob 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; 872*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, cell, cone)); 873*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, cell, ornt)); 874*5f80ce2aSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, cell, 2)); 875*5f80ce2aSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, cell, 2)); 876*5f80ce2aSJacob 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) { 896*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 897*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", face, markerRight)); 8983dfda0b1SToby Isaac } 8993dfda0b1SToby Isaac else if (fx == 0) { 900*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 901*5f80ce2aSJacob 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; 906*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, face, cone)); 907*5f80ce2aSJacob 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) { 927*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 928*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", face, markerBack)); 9293dfda0b1SToby Isaac } 9303dfda0b1SToby Isaac else if (fy == 0) { 931*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 932*5f80ce2aSJacob 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; 937*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, face, cone)); 938*5f80ce2aSJacob 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;} 957*5f80ce2aSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, face, 2)); 958*5f80ce2aSJacob 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) { 963*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 964*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", face, markerTop)); 9653dfda0b1SToby Isaac } 9663dfda0b1SToby Isaac else if (fz == 0) { 967*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 968*5f80ce2aSJacob 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; 973*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, face, cone)); 974*5f80ce2aSJacob 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) { 990*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerRight)); 9913dfda0b1SToby Isaac } 9923dfda0b1SToby Isaac else if (vx == 0) { 993*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerLeft)); 9943dfda0b1SToby Isaac } 9953dfda0b1SToby Isaac } 9963dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 9973dfda0b1SToby Isaac if (vy == numYVertices-1) { 998*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBack)); 9993dfda0b1SToby Isaac } 10003dfda0b1SToby Isaac else if (vy == 0) { 1001*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerFront)); 10023dfda0b1SToby Isaac } 10033dfda0b1SToby Isaac } 10043dfda0b1SToby Isaac } 10053dfda0b1SToby Isaac cone[0] = vertexB; cone[1] = vertexT; 1006*5f80ce2aSJacob 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; 1021*5f80ce2aSJacob 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) { 1025*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 1026*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerRight)); 1027*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 10283dfda0b1SToby Isaac if (ey == numYEdges-1) { 1029*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 10303dfda0b1SToby Isaac } 1031d8211ee3SMatthew G. Knepley } else if (vx == 0) { 1032*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 1033*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1034*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 10353dfda0b1SToby Isaac if (ey == numYEdges-1) { 1036*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 10373dfda0b1SToby Isaac } 10383dfda0b1SToby Isaac } 1039d8211ee3SMatthew G. Knepley } else { 10404c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 1041*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(cutLabel, edge, 1)); 1042*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(cutLabel, cone[0], 1)); 1043d8211ee3SMatthew G. Knepley if (ey == numYEdges-1) { 1044*5f80ce2aSJacob 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) { 1051*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerRight)); 1052d8211ee3SMatthew G. Knepley } else if (vx == 0) { 1053*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerLeft)); 10543dfda0b1SToby Isaac } 10553dfda0b1SToby Isaac } 10563dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 10573dfda0b1SToby Isaac if (vz == numZVertices-1) { 1058*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerTop)); 1059d8211ee3SMatthew G. Knepley } else if (vz == 0) { 1060*5f80ce2aSJacob 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; 1078*5f80ce2aSJacob 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) { 1082*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 1083*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerTop)); 1084*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 10853dfda0b1SToby Isaac if (ex == numXEdges-1) { 1086*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 10873dfda0b1SToby Isaac } 1088d8211ee3SMatthew G. Knepley } else if (vy == 0) { 1089*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 1090*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1091*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 10923dfda0b1SToby Isaac if (ex == numXEdges-1) { 1093*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 10943dfda0b1SToby Isaac } 10953dfda0b1SToby Isaac } 1096d8211ee3SMatthew G. Knepley } else { 10974c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 1098*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(cutLabel, edge, 1)); 1099*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(cutLabel, cone[0], 1)); 1100d8211ee3SMatthew G. Knepley if (ex == numXEdges-1) { 1101*5f80ce2aSJacob 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) { 1108*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBack)); 11093dfda0b1SToby Isaac } 11103dfda0b1SToby Isaac else if (vy == 0) { 1111*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerFront)); 11123dfda0b1SToby Isaac } 11133dfda0b1SToby Isaac } 11143dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 11153dfda0b1SToby Isaac if (vz == numZVertices-1) { 1116*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerTop)); 11173dfda0b1SToby Isaac } 11183dfda0b1SToby Isaac else if (vz == 0) { 1119*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBottom)); 11203dfda0b1SToby Isaac } 11213dfda0b1SToby Isaac } 11223dfda0b1SToby Isaac } 11233dfda0b1SToby Isaac } 11243dfda0b1SToby Isaac } 11253dfda0b1SToby Isaac } 1126*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 1127*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 11283dfda0b1SToby Isaac /* Build coordinates */ 1129*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 1130*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 1131*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dim)); 1132*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVertices)); 11333dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex+numVertices; ++v) { 1134*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, dim)); 1135*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 11363dfda0b1SToby Isaac } 1137*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 1138*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 1139*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 1140*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 1141*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 1142*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, dim)); 1143*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 1144*5f80ce2aSJacob 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 } 1156*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 1157*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 1158*5f80ce2aSJacob 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); 1171*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, dim)); 11729318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) {fac[d] = faces[d]; bdt[d] = periodicity[d];} 1173*5f80ce2aSJacob 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 } 1184*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPeriodicity(dm, PETSC_TRUE, maxCell, L, periodicity)); 1185768d5fceSMatthew G. Knepley } 1186*5f80ce2aSJacob 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; 1193*5f80ce2aSJacob Faibussowitsch if (dim == 1) CHKERRQ(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 1194*5f80ce2aSJacob Faibussowitsch else if (simplex) CHKERRQ(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 1195*5f80ce2aSJacob 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 1199*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexUninterpolate(dm, &udm)); 1200*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopyCoordinates(dm, udm)); 1201*5f80ce2aSJacob 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; 1273*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm,dm)); 1274*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm,DMPLEX)); 1275*5f80ce2aSJacob 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"); 1286*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), &bdm)); 1287*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(bdm, DMPLEX)); 1288*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(bdm, 2)); 1289*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 1290*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol)); 1291*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&bdm)); 1292*5f80ce2aSJacob 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 1298*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &v)); 1299*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetBlockSize(v, &cDim)); 1300*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(v, &n)); 1301*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(v, &x)); 13029318fe57SMatthew G. Knepley x += cDim; 13039318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 1304*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(v,&x)); 1305*5f80ce2aSJacob 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; 1339*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm,dm)); 1340*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm,DMPLEX)); 1341*5f80ce2aSJacob 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 1345*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexUninterpolate(*dm, &udm)); 1346*5f80ce2aSJacob 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); 1374*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) dm, prefix)); 1375*5f80ce2aSJacob 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; 1440*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 1441*5f80ce2aSJacob 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 } 1452*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVertices)); 1453*5f80ce2aSJacob Faibussowitsch for (c = 0; c < numCells; c++) CHKERRQ(DMPlexSetConeSize(dm, c, 8)); 1454*5f80ce2aSJacob 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; 1459*5f80ce2aSJacob 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 */ 1462*5f80ce2aSJacob 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; 1465*5f80ce2aSJacob 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; 1468*5f80ce2aSJacob 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; 1471*5f80ce2aSJacob 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; 1475*5f80ce2aSJacob 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; 1478*5f80ce2aSJacob 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; 1481*5f80ce2aSJacob 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; 1484*5f80ce2aSJacob 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; 1487*5f80ce2aSJacob 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; 1491*5f80ce2aSJacob 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; 1494*5f80ce2aSJacob 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; 1497*5f80ce2aSJacob 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; 1500*5f80ce2aSJacob 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; 1503*5f80ce2aSJacob 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; 1507*5f80ce2aSJacob 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; 1510*5f80ce2aSJacob 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; 1513*5f80ce2aSJacob 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; 1516*5f80ce2aSJacob 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; 1519*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 4, cone)); 1520006a8963SMatthew G. Knepley } 1521d8c47e87SMatthew G. Knepley } 1522*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 1523*5f80ce2aSJacob 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 */ 1535*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 1536*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 1537*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dim)); 1538*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, numCells, numCells+numVertices)); 15390510c589SMatthew G. Knepley for (v = numCells; v < numCells+numVertices; ++v) { 1540*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, dim)); 1541*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 15420510c589SMatthew G. Knepley } 1543*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 1544*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 1545*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 1546*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 1547*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 1548*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, dim)); 1549*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 1550*5f80ce2aSJacob 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 } 1579*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 1580*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 1581*5f80ce2aSJacob 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 } 1599*5f80ce2aSJacob 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 1606*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder)); 1607*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 1608*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(cdm, &cds)); 1609*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetConstants(cds, 2, c)); 1610dbc1dc17SMatthew G. Knepley } 16119318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 1612*5f80ce2aSJacob 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); 1668*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 1669*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 1670*5f80ce2aSJacob 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); 1682*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 1683*5f80ce2aSJacob 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 */ 1685*5f80ce2aSJacob 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; 1692*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVertices)); 1693*5f80ce2aSJacob Faibussowitsch for (c = 0; c < numCells; c++) CHKERRQ(DMPlexSetConeSize(dm, c, 6)); 1694*5f80ce2aSJacob 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; 1698*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, c, cone)); 1699*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 170024119c2aSMatthew G. Knepley } 1701*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 1702*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 170324119c2aSMatthew G. Knepley } 1704412e9a14SMatthew G. Knepley for (v = numCells; v < numCells+numVertices; ++v) { 1705*5f80ce2aSJacob 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 */ 1715*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 1716*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 1717*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dim)); 1718*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, numCells, numCells+numVertices)); 171924119c2aSMatthew G. Knepley for (v = numCells; v < numCells+numVertices; ++v) { 1720*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, dim)); 1721*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 172224119c2aSMatthew G. Knepley } 1723*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 1724*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 1725*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 1726*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 1727*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 1728*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, dim)); 1729*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 1730*5f80ce2aSJacob 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 } 1739*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 1740*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 1741*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 174224119c2aSMatthew G. Knepley } 17439318fe57SMatthew G. Knepley /* Interpolate */ 1744*5f80ce2aSJacob 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); 1769*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 1770*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 1771*5f80ce2aSJacob 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); 1817*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, dim)); 1818*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, dim+1)); 1819*5f80ce2aSJacob 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 */ 1843*5f80ce2aSJacob 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 */ 1855*5f80ce2aSJacob 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 */ 1863*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVerts)); 186465a81367SMatthew G. Knepley for (c = 0; c < numCells; c++) { 1865*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, c, embedDim)); 186665a81367SMatthew G. Knepley } 1867*5f80ce2aSJacob 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 } 1890*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, c++, cone)); 189165a81367SMatthew G. Knepley } 189265a81367SMatthew G. Knepley } 189365a81367SMatthew G. Knepley } 189465a81367SMatthew G. Knepley } 1895*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 1896*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 1897*5f80ce2aSJacob 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 */ 1926*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numEdges+numVerts)); 19272829fed8SMatthew G. Knepley for (c = 0; c < numCells; c++) { 1928*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, c, 4)); 19292829fed8SMatthew G. Knepley } 19302829fed8SMatthew G. Knepley for (e = firstEdge; e < firstEdge+numEdges; ++e) { 1931*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, e, 2)); 19322829fed8SMatthew G. Knepley } 1933*5f80ce2aSJacob 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; 1937*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 0, cone)); 19382829fed8SMatthew G. Knepley ornt[0] = 0; ornt[1] = 0; ornt[2] = 0; ornt[3] = 0; 1939*5f80ce2aSJacob 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; 1942*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 1, cone)); 1943b5a892a1SMatthew G. Knepley ornt[0] = 0; ornt[1] = 0; ornt[2] = -1; ornt[3] = 0; 1944*5f80ce2aSJacob 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; 1947*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 2, cone)); 1948b5a892a1SMatthew G. Knepley ornt[0] = 0; ornt[1] = 0; ornt[2] = -1; ornt[3] = 0; 1949*5f80ce2aSJacob 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; 1952*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 3, cone)); 1953b5a892a1SMatthew G. Knepley ornt[0] = -1; ornt[1] = -1; ornt[2] = 0; ornt[3] = -1; 1954*5f80ce2aSJacob 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; 1957*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 4, cone)); 1958b5a892a1SMatthew G. Knepley ornt[0] = -1; ornt[1] = -1; ornt[2] = -1; ornt[3] = 0; 1959*5f80ce2aSJacob 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; 1962*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 5, cone)); 1963b5a892a1SMatthew G. Knepley ornt[0] = -1; ornt[1] = -1; ornt[2] = -1; ornt[3] = -1; 1964*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, 5, ornt)); 19652829fed8SMatthew G. Knepley /* Edges */ 19662829fed8SMatthew G. Knepley cone[0] = 6; cone[1] = 7; 1967*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 14, cone)); 19682829fed8SMatthew G. Knepley cone[0] = 7; cone[1] = 8; 1969*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 15, cone)); 19702829fed8SMatthew G. Knepley cone[0] = 8; cone[1] = 9; 1971*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 16, cone)); 19722829fed8SMatthew G. Knepley cone[0] = 9; cone[1] = 6; 1973*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 17, cone)); 19742829fed8SMatthew G. Knepley cone[0] = 10; cone[1] = 11; 1975*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 18, cone)); 19762829fed8SMatthew G. Knepley cone[0] = 11; cone[1] = 7; 1977*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 19, cone)); 19782829fed8SMatthew G. Knepley cone[0] = 6; cone[1] = 10; 1979*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 20, cone)); 19802829fed8SMatthew G. Knepley cone[0] = 12; cone[1] = 13; 1981*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 21, cone)); 19822829fed8SMatthew G. Knepley cone[0] = 13; cone[1] = 11; 1983*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 22, cone)); 19842829fed8SMatthew G. Knepley cone[0] = 10; cone[1] = 12; 1985*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 23, cone)); 19862829fed8SMatthew G. Knepley cone[0] = 13; cone[1] = 8; 1987*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 24, cone)); 19882829fed8SMatthew G. Knepley cone[0] = 12; cone[1] = 9; 1989*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, 25, cone)); 199045da822fSValeria Barra } 1991*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 1992*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 19932829fed8SMatthew G. Knepley /* Build coordinates */ 1994*5f80ce2aSJacob 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 */ 2039*5f80ce2aSJacob 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 */ 2073*5f80ce2aSJacob 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 */ 2081*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVerts)); 2082116ded15SMatthew G. Knepley for (c = 0; c < numCells; c++) { 2083*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, c, embedDim)); 2084116ded15SMatthew G. Knepley } 2085*5f80ce2aSJacob 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 } 2131*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, c++, cone)); 2132116ded15SMatthew G. Knepley } 2133116ded15SMatthew G. Knepley } 2134116ded15SMatthew G. Knepley } 2135116ded15SMatthew G. Knepley } 2136116ded15SMatthew G. Knepley } 213745da822fSValeria Barra } 2138*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 2139*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 2140*5f80ce2aSJacob 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 */ 2146*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 2147*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 2148*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 2149*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVerts)); 21502829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex+numVerts; ++v) { 2151*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, embedDim)); 2152*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 21532829fed8SMatthew G. Knepley } 2154*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 2155*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 2156*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 2157*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, embedDim)); 2158*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 2159*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 2160*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 2161*5f80ce2aSJacob 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];} 2163*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 2164*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 2165*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 2166*5f80ce2aSJacob 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 2172*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere)); 2173*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 2174*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(cdm, &cds)); 2175*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetConstants(cds, 1, &c)); 217651a74b61SMatthew G. Knepley } 21779318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 2178*5f80ce2aSJacob 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 2308*5f80ce2aSJacob 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 2313*5f80ce2aSJacob 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; 2333*5f80ce2aSJacob 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; 2349*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(3*numVertices, &vtxCoords)); 2350*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(Njunctions, &cells)); 2351*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(Ncuts*4, &edges)); 2352*5f80ce2aSJacob 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; 2607*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numBlocks, &cells)); 2608*5f80ce2aSJacob 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; 2634*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 2635*5f80ce2aSJacob 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 } 2664*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vertToTrueVert)); 2665*5f80ce2aSJacob 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 } 2681*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numEdges, &edges)); 2682*5f80ce2aSJacob 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 2709*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(dm, topoDim)); 2710*5f80ce2aSJacob Faibussowitsch if (!rank) CHKERRQ(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 2711*5f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 2712*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(cells_flat)); 2713b7f5c055SJed Brown { 2714b7f5c055SJed Brown DM idm; 2715*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(dm, &idm)); 2716*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &idm)); 2717b7f5c055SJed Brown } 2718*5f80ce2aSJacob Faibussowitsch if (!rank) CHKERRQ(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 2719*5f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 2720*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vtxCoords)); 2721b7f5c055SJed Brown 2722*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm, "Face Sets")); 2723*5f80ce2aSJacob 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]}; 2727*5f80ce2aSJacob 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]); 2729*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(label, join[0], edgeSets[e])); 2730*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 2731b7f5c055SJed Brown } 2732*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(edges)); 2733*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(edgeSets)); 27341436d7faSJed Brown if (tps_distribute) { 27351436d7faSJed Brown DM pdm = NULL; 27361436d7faSJed Brown PetscPartitioner part; 27371436d7faSJed Brown 2738*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetPartitioner(dm, &part)); 2739*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerSetFromOptions(part)); 2740*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistribute(dm, 0, NULL, &pdm)); 27411436d7faSJed Brown if (pdm) { 2742*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &pdm)); 27431436d7faSJed Brown } 27441436d7faSJed Brown // Do not auto-distribute again 2745*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 27461436d7faSJed Brown } 2747b7f5c055SJed Brown 2748*5f80ce2aSJacob 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; 2754*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMRefine(dm, MPI_COMM_NULL, &dmf)); 2755*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &dmf)); 2756b7f5c055SJed Brown 2757*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &X)); 2758*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(X, &m)); 2759*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(X, &x)); 2760b7f5c055SJed Brown for (PetscInt i=0; i<m; i+=3) { 2761*5f80ce2aSJacob Faibussowitsch CHKERRQ(TPSNearestPoint(evalFunc, &x[i])); 2762b7f5c055SJed Brown } 2763*5f80ce2aSJacob 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. 2767*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, "Face Sets", &label)); 2768*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexLabelComplete(dm, label)); 2769b7f5c055SJed Brown 2770b7f5c055SJed Brown if (thickness > 0) { 2771b7f5c055SJed Brown DM dm3; 2772*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexExtrude(dm, layers, thickness, PETSC_FALSE, PETSC_TRUE, NULL, NULL, &dm3)); 2773*5f80ce2aSJacob 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; 2820*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 2821*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 2822*5f80ce2aSJacob 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); 2848*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 2849*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 2850*5f80ce2aSJacob 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; 2860*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), &sdm)); 2861*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(sdm, DMPLEX)); 2862*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) sdm, "bd_")); 2863*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateSphereMesh_Internal(sdm, dim-1, PETSC_TRUE, R)); 2864*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions(sdm)); 2865*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMViewFromOptions(sdm, NULL, "-dm_view")); 2866*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 2867*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&sdm)); 2868*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &vol)); 2869*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm, "marker")); 2870*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, "marker", &bdlabel)); 2871*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 2872*5f80ce2aSJacob 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; 2899*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 2900*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 2901*5f80ce2aSJacob 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 2917*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 0)); 2918*5f80ce2aSJacob 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 2929*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 1)); 2930*5f80ce2aSJacob 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 2941*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 1)); 2942*5f80ce2aSJacob 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 2953*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 2)); 2954*5f80ce2aSJacob 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 2965*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 2)); 2966*5f80ce2aSJacob 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 2977*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 2)); 2978*5f80ce2aSJacob 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 2989*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 3)); 2990*5f80ce2aSJacob 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 3002*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 3)); 3003*5f80ce2aSJacob 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 3015*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 3)); 3016*5f80ce2aSJacob 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 3028*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 3)); 3029*5f80ce2aSJacob 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 3041*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 3)); 3042*5f80ce2aSJacob 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 3054*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(rdm, 3)); 3055*5f80ce2aSJacob 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 */ 3064*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(rdm, "celltype")); 3065*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCellType(rdm, 0, ct)); 3066*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(rdm, NULL, &Nv)); 3067*5f80ce2aSJacob Faibussowitsch for (v = 1; v < Nv; ++v) CHKERRQ(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 30689318fe57SMatthew G. Knepley } 3069*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolateInPlace_Internal(rdm)); 3070*5f80ce2aSJacob 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; 3093*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, refdm)); 3094*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*refdm, DMPLEX)); 3095*5f80ce2aSJacob 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; 3106*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMHasLabel(dm, name, &hasLabel)); 31079318fe57SMatthew G. Knepley if (hasLabel) PetscFunctionReturn(0); 3108*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm, name)); 3109*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, name, &label)); 3110*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMConvert(dm, DMPLEX, &plex)); 3111*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMarkBoundaryFaces(plex, 1, label)); 3112*5f80ce2aSJacob 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; 3131*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 31329318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 3133*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 3134*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 3135*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 3136*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum) cell, (PetscEnum *) &cell, NULL)); 3137*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 3138*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum) shape, (PetscEnum *) &shape, &flg)); 3139*5f80ce2aSJacob 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); 3141*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 3142*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 3143*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 3144*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 3145*5f80ce2aSJacob 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 3162*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromFile(PetscObjectComm((PetscObject) dm), filename, plexname, interpolate, &dmnew)); 3163*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopy_Internal(dm, PETSC_FALSE, dmnew)); 3164*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &dmnew)); 31659318fe57SMatthew G. Knepley } else if (refDomain) { 3166*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateReferenceCell_Internal(dm, cell)); 31679318fe57SMatthew G. Knepley } else if (bdfflg) { 31689318fe57SMatthew G. Knepley DM bdm, dmnew; 31699318fe57SMatthew G. Knepley 3170*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromFile(PetscObjectComm((PetscObject) dm), bdFilename, plexname, interpolate, &bdm)); 3171*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) bdm, "bd_")); 3172*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions(bdm)); 3173*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 3174*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&bdm)); 3175*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopy_Internal(dm, PETSC_FALSE, dmnew)); 3176*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &dmnew)); 31779318fe57SMatthew G. Knepley } else { 3178*5f80ce2aSJacob 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); 3190*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 31919318fe57SMatthew G. Knepley n = 3; 3192*5f80ce2aSJacob 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; 3195*5f80ce2aSJacob 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; 3198*5f80ce2aSJacob 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: 3202*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 3203d410b0cfSMatthew G. Knepley if (!interpolate) { 3204d410b0cfSMatthew G. Knepley DM udm; 3205d410b0cfSMatthew G. Knepley 3206*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexUninterpolate(dm, &udm)); 3207*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &udm)); 3208d410b0cfSMatthew G. Knepley } 32099318fe57SMatthew G. Knepley break; 32109318fe57SMatthew G. Knepley default: 3211*5f80ce2aSJacob 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)); 3225*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 32269318fe57SMatthew G. Knepley n = 3; 3227*5f80ce2aSJacob 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; 3230*5f80ce2aSJacob 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); 3232*5f80ce2aSJacob 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 3239*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 3240*5f80ce2aSJacob 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 3247*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 3248*5f80ce2aSJacob 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 3256*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum) bdt, (PetscEnum *) &bdt, NULL)); 3257*5f80ce2aSJacob 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: 3260*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 32619318fe57SMatthew G. Knepley break; 32629318fe57SMatthew G. Knepley default: 3263*5f80ce2aSJacob 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; 3276*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three=3, &three), NULL)); 3277*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 3278*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum*)periodic, (three=3, &three), NULL)); 3279*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 3280*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 3281*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeGetDefault(dm, &tps_distribute)); 3282*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 3283*5f80ce2aSJacob 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 } 3289*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 3290ed5e4e85SVaclav Hapla if (!((PetscObject)dm)->name && nameflg) { 3291*5f80ce2aSJacob 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 */ 3304*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 3305*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL,0)); 3306*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 3307*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL,0)); 3308*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 3309*5f80ce2aSJacob Faibussowitsch if (flg) CHKERRQ(PetscLogDefaultBegin()); 33109318fe57SMatthew G. Knepley /* Labeling */ 3311*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 3312*5f80ce2aSJacob Faibussowitsch if (flg) CHKERRQ(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 3313953fc75cSMatthew G. Knepley /* Point Location */ 3314*5f80ce2aSJacob 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 */ 3316*5f80ce2aSJacob 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 */ 3318*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 3319b29cfa1cSToby Isaac /* Projection behavior */ 3320*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maxmimum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL,0)); 3321*5f80ce2aSJacob 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 3326*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_check_all", "Perform all checks", NULL, PETSC_FALSE, &all, &flg2)); 3327*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 3328*5f80ce2aSJacob Faibussowitsch if (all || (flg && flg2)) CHKERRQ(DMPlexCheckSymmetry(dm)); 3329*5f80ce2aSJacob 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)); 3330*5f80ce2aSJacob Faibussowitsch if (all || (flg && flg2)) CHKERRQ(DMPlexCheckSkeleton(dm, 0)); 3331*5f80ce2aSJacob 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)); 3332*5f80ce2aSJacob Faibussowitsch if (all || (flg && flg2)) CHKERRQ(DMPlexCheckFaces(dm, 0)); 3333*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 3334*5f80ce2aSJacob Faibussowitsch if (all || (flg && flg2)) CHKERRQ(DMPlexCheckGeometry(dm)); 3335*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 3336*5f80ce2aSJacob Faibussowitsch if (all || (flg && flg2)) CHKERRQ(DMPlexCheckPointSF(dm)); 3337*5f80ce2aSJacob 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)); 3338*5f80ce2aSJacob Faibussowitsch if (all || (flg && flg2)) CHKERRQ(DMPlexCheckInterfaceCones(dm)); 3339*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 3340*5f80ce2aSJacob 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 3345*5f80ce2aSJacob 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 3349*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinates(dm, &coordinates)); 3350*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 3351*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(coordinates, scale)); 3352*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(coordinatesLocal, scale)); 33539318fe57SMatthew G. Knepley } 33549318fe57SMatthew G. Knepley } 3355*5f80ce2aSJacob 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); 3369*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHead(PetscOptionsObject,"DMPlex Options")); 33709318fe57SMatthew G. Knepley /* Handle automatic creation */ 3371*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 3372*5f80ce2aSJacob Faibussowitsch if (dim < 0) {CHKERRQ(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));created = PETSC_TRUE;} 3373d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 3374*5f80ce2aSJacob 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 3378*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsInterpolated(dm, &interpolated)); 3379d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 3380d89e6e46SMatthew G. Knepley DM udm; 3381d89e6e46SMatthew G. Knepley 3382*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexUninterpolate(dm, &udm)); 3383*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &udm)); 3384d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 3385d89e6e46SMatthew G. Knepley DM idm; 3386d89e6e46SMatthew G. Knepley 3387*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(dm, &idm)); 3388*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &idm)); 3389d89e6e46SMatthew G. Knepley } 3390d89e6e46SMatthew G. Knepley } 33919b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 3392*5f80ce2aSJacob 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;} 3394*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetRefinementUniform(dm, &uniformOrig)); 3395*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL,0)); 3396*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 3397*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 3398*5f80ce2aSJacob Faibussowitsch if (flg) CHKERRQ(DMPlexSetRefinementUniform(dm, uniform)); 3399*5f80ce2aSJacob 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) { 3401*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 3402*5f80ce2aSJacob 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 3409*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 3410*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMRefine(dm, PetscObjectComm((PetscObject) dm), &rdm)); 3411*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &rdm)); 3412*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 341361a622f3SMatthew G. Knepley if (coordFunc && remap) { 3414*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 34159b44eab4SMatthew G. Knepley ((DM_Plex*) dm->data)->coordFunc = coordFunc; 34169b44eab4SMatthew G. Knepley } 34179b44eab4SMatthew G. Knepley } 3418*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRefinementUniform(dm, uniformOrig)); 34199318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 3420*5f80ce2aSJacob 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 3424*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMExtrude(dm, extLayers, &edm)); 3425*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &edm)); 342648d16a33SMatthew G. Knepley ((DM_Plex *) dm->data)->coordFunc = NULL; 3427*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 3428d410b0cfSMatthew G. Knepley extLayers = 0; 34299318fe57SMatthew G. Knepley } 3430bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 3431*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOrderingList(&ordlist)); 3432*5f80ce2aSJacob 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 3437*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetOrdering(dm, oname, NULL, &perm)); 3438*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPermute(dm, perm, &pdm)); 3439*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&perm)); 3440*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &pdm)); 3441*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 3442bdf63967SMatthew G. Knepley } 34439b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 3444*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeGetDefault(dm, &distribute)); 3445*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMCreate", distribute, &distribute, NULL)); 3446*5f80ce2aSJacob 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 3451*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetPartitioner(dm, &part)); 3452*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerSetFromOptions(part)); 3453*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistribute(dm, overlap, NULL, &pdm)); 34549b44eab4SMatthew G. Knepley if (pdm) { 3455*5f80ce2aSJacob 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 3464*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg)); 3465*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 3466*5f80ce2aSJacob 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 3473*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 3474*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(cdm, &cds)); 3475*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetDiscretization(cds, 0, &obj)); 3476*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId(obj, &id)); 347761a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 347861a622f3SMatthew G. Knepley PetscContainer dummy; 347961a622f3SMatthew G. Knepley 3480*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 3481*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) dummy, "coordinates")); 3482*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(cdm, 0, NULL, (PetscObject) dummy)); 3483*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscContainerDestroy(&dummy)); 3484*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMClearDS(cdm)); 348561a622f3SMatthew G. Knepley } 348661a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 348761a622f3SMatthew G. Knepley } 3488*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLocalizeCoordinates(dm)); 3489*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL)); 3490*5f80ce2aSJacob 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; 3494*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL,0)); 3495*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 3496*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy,0)); 3497*5f80ce2aSJacob Faibussowitsch if (refine) CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 349868d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 3499acdc6f61SToby Isaac DM *dms, coarseDM; 350068d4fef7SMatthew G. Knepley 3501*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoarseDM(dm, &coarseDM)); 3502*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)coarseDM)); 3503*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(refine,&dms)); 3504*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMRefineHierarchy(dm, refine, dms)); 350568d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 3506*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSwap_Static(dm, dms[refine-1])); 350768d4fef7SMatthew G. Knepley if (refine == 1) { 3508*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoarseDM(dm, dms[0])); 3509*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 351068d4fef7SMatthew G. Knepley } else { 3511*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoarseDM(dm, dms[refine-2])); 3512*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 3513*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoarseDM(dms[0], dms[refine-1])); 3514*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 351568d4fef7SMatthew G. Knepley } 3516*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoarseDM(dms[refine-1], coarseDM)); 3517*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectDereference((PetscObject)coarseDM)); 351868d4fef7SMatthew G. Knepley /* Free DMs */ 351968d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 3520*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dms[r])); 3521*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dms[r])); 352268d4fef7SMatthew G. Knepley } 3523*5f80ce2aSJacob 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 3529*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 3530*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMRefine(dm, PetscObjectComm((PetscObject) dm), &rdm)); 353168d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 3532*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &rdm)); 3533*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 353461a622f3SMatthew G. Knepley if (coordFunc && remap) { 3535*5f80ce2aSJacob 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 */ 3541*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL,0)); 3542*5f80ce2aSJacob 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 3546*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(coarsen, &dms)); 3547*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCoarsenHierarchy(dm, coarsen, dms)); 3548b653a561SMatthew G. Knepley /* Free DMs */ 3549b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 3550*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dms[r])); 3551*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dms[r])); 3552b653a561SMatthew G. Knepley } 3553*5f80ce2aSJacob 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 3559*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 3560*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCoarsen(dm, PetscObjectComm((PetscObject) dm), &cdm)); 35613cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 3562*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &cdm)); 3563*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 35649318fe57SMatthew G. Knepley if (coordFunc) { 3565*5f80ce2aSJacob 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 */ 3571*5f80ce2aSJacob 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'; 3577*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 3578*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 3579*5f80ce2aSJacob 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 3591*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 3592*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsDistributed(dm, &distributed)); 3593*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 3594*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(cdm, &cds)); 3595*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(cds, &Nf)); 35966913077dSMatthew G. Knepley if (Nf) { 3597*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetDiscretization(cds, 0, &obj)); 3598*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId(obj, &id)); 35996913077dSMatthew G. Knepley } 36006913077dSMatthew G. Knepley if (dim == 1 && !distributed && id != PETSCFE_CLASSID) { 3601*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetOrdering1D(dm, &perm)); 3602*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPermute(dm, perm, &rdm)); 3603*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReplace_Static(dm, &rdm)); 3604*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&perm)); 36056913077dSMatthew G. Knepley } 36066913077dSMatthew G. Knepley } 36073cf6fe12SMatthew G. Knepley /* Handle */ 3608*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm)); 3609*5f80ce2aSJacob 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; 3616*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector_Section_Private(dm,vec)); 3617*5f80ce2aSJacob Faibussowitsch /* CHKERRQ(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 3618*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Plex)); 3619*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void)) VecView_Plex_Native)); 3620*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void)) VecLoad_Plex)); 3621*5f80ce2aSJacob 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; 3628*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLocalVector_Section_Private(dm,vec)); 3629*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Plex_Local)); 3630*5f80ce2aSJacob 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; 3639*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 3640793f3fe5SMatthew G. Knepley if (depth == 1) { 3641*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &d)); 3642*5f80ce2aSJacob Faibussowitsch if (dim == 0) CHKERRQ(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 3643*5f80ce2aSJacob Faibussowitsch else if (dim == d) CHKERRQ(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 3644793f3fe5SMatthew G. Knepley else {*pStart = 0; *pEnd = 0;} 3645793f3fe5SMatthew G. Knepley } else { 3646*5f80ce2aSJacob 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; 3659*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sf)); 36600a19bb7dSprj- if (!data->neighbors) { 3661*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetUp(sf)); 3662*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 3663*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 3664*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 3665*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 3666*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 36670a19bb7dSprj- n = njranks + niranks; 3668*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 36690a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 3670*5f80ce2aSJacob 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; 3727*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C",DMPlexInsertBoundaryValues_Plex)); 3728*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertTimeDerviativeBoundaryValues_C",DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 3729*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",DMSetUpGLVisViewer_Plex)); 3730*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C",DMCreateNeumannOverlap_Plex)); 3731*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",DMPlexGetOverlap_Plex)); 3732*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeGetDefault_C",DMPlexDistributeGetDefault_Plex)); 3733*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeSetDefault_C",DMPlexDistributeSetDefault_Plex)); 3734*5f80ce2aSJacob 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; 3745*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectChangeTypeName((PetscObject) *newdm, DMPLEX)); 3746*5f80ce2aSJacob 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); 3790*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNewLog(dm,&mesh)); 3791552f7358SJed Brown dm->data = mesh; 3792552f7358SJed Brown 3793552f7358SJed Brown mesh->refct = 1; 3794*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 3795552f7358SJed Brown mesh->maxConeSize = 0; 37960298fd71SBarry Smith mesh->cones = NULL; 37970298fd71SBarry Smith mesh->coneOrientations = NULL; 3798*5f80ce2aSJacob 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; 3811*5f80ce2aSJacob 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 3845*5f80ce2aSJacob 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); 3867*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, mesh)); 3868*5f80ce2aSJacob 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); 3937*5f80ce2aSJacob 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; 3947*5f80ce2aSJacob 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 3957*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetICreate(&vhash)); 3958a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 3959a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 3960*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIAdd(vhash, cells[c*numCorners+p])); 3961a47d0d45SMatthew G. Knepley } 3962a47d0d45SMatthew G. Knepley } 3963*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIGetSize(vhash, &numVerticesAdj)); 3964*5f80ce2aSJacob Faibussowitsch if (!verticesAdjSaved) CHKERRQ(PetscMalloc1(numVerticesAdj, &verticesAdj)); 3965be8c289dSNicolas Barral else { verticesAdj = *verticesAdjSaved; } 3966*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIGetElems(vhash, &off, verticesAdj)); 3967*5f80ce2aSJacob 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 } 3970*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortInt(numVerticesAdj, verticesAdj)); 3971a47d0d45SMatthew G. Knepley /* Create cones */ 3972*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVerticesAdj)); 3973*5f80ce2aSJacob Faibussowitsch for (c = 0; c < numCells; ++c) CHKERRQ(DMPlexSetConeSize(dm, c, numCorners)); 3974*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); 3975*5f80ce2aSJacob 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) */ 3983*5f80ce2aSJacob 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 */ 3989*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 3990*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetSize(layout, NVertices)); 3991*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetLocalSize(layout, numVertices)); 3992*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetBlockSize(layout, 1)); 3993*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 3994*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutDestroy(&layout)); 3995*5f80ce2aSJacob Faibussowitsch if (!verticesAdjSaved) CHKERRQ(PetscFree(verticesAdj)); 3996*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) sfPoint, "point SF")); 39972464107aSksagiyam if (dm->sf) { 39982464107aSksagiyam const char *prefix; 39992464107aSksagiyam 4000*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 4001*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 40022464107aSksagiyam } 4003*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(dm, sfPoint)); 4004*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfPoint)); 4005*5f80ce2aSJacob Faibussowitsch if (vertexSF) CHKERRQ(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF")); 4006a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 4007*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 4008*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 4009*5f80ce2aSJacob 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; 4037*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0)); 4038*5f80ce2aSJacob 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."); 4040*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, spaceDim)); 4041*5f80ce2aSJacob 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); 4043*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 4044*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 4045*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 4046*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, vStart, vEnd)); 40471edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 4048*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, spaceDim)); 4049*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4050a47d0d45SMatthew G. Knepley } 4051*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 4052*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 4053*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 4054*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, spaceDim)); 4055*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 4056*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 4057*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 4058*5f80ce2aSJacob 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 */ 4063*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype)); 4064*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_commit(&coordtype)); 406521016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 406621016a8bSBarry Smith { 406721016a8bSBarry Smith PetscScalar *svertexCoords; 406821016a8bSBarry Smith PetscInt i; 4069*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numVertices*spaceDim,&svertexCoords)); 40703612f820SVaclav Hapla for (i=0; i<numVertices*spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 4071*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords,MPI_REPLACE)); 4072*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords,MPI_REPLACE)); 4073*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(svertexCoords)); 407421016a8bSBarry Smith } 407521016a8bSBarry Smith #else 4076*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords,MPI_REPLACE)); 4077*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords,MPI_REPLACE)); 407821016a8bSBarry Smith #endif 4079*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_free(&coordtype)); 4080a47d0d45SMatthew G. Knepley } 4081*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 4082*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 4083*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 4084*5f80ce2aSJacob 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; 4124*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 4125*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 4126a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 4127064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 4128*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(*dm, dim)); 4129*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 4130a47d0d45SMatthew G. Knepley if (interpolate) { 41315fd9971aSMatthew G. Knepley DM idm; 4132a47d0d45SMatthew G. Knepley 4133*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(*dm, &idm)); 4134*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(dm)); 4135a47d0d45SMatthew G. Knepley *dm = idm; 4136a47d0d45SMatthew G. Knepley } 4137*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 413818d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 4139*5f80ce2aSJacob 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; 4194*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_BuildFromCellList,dm,0,0,0)); 4195*5f80ce2aSJacob 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 } 4209*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVertices)); 4210b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 4211*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(dm, c, numCorners)); 4212b09969d6SVaclav Hapla } 4213*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); 4214*5f80ce2aSJacob 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 } 4220*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 4221*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 4222*5f80ce2aSJacob 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; 4250*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0)); 4251*5f80ce2aSJacob 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."); 4253*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dm, spaceDim)); 4254*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 4255*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 4256*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 4257*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, vStart, vEnd)); 42581edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 4259*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, spaceDim)); 4260*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 4261b09969d6SVaclav Hapla } 4262*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 4263b09969d6SVaclav Hapla 4264*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 4265*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLocalVector(cdm, &coordinates)); 4266*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, spaceDim)); 4267*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 4268*5f80ce2aSJacob 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 } 4274*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayWrite(coordinates, &coords)); 4275*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 4276*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 4277*5f80ce2aSJacob 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; 43172c71b3e2SJacob Faibussowitsch PetscCheckFalse(!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."); 4318*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 4319*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 4320*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 4321*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(*dm, dim)); 4322*5f80ce2aSJacob Faibussowitsch if (!rank) CHKERRQ(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 4323*5f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 43249298eaa6SMatthew G Knepley if (interpolate) { 43255fd9971aSMatthew G. Knepley DM idm; 43269298eaa6SMatthew G Knepley 4327*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(*dm, &idm)); 4328*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(dm)); 43299298eaa6SMatthew G Knepley *dm = idm; 43309298eaa6SMatthew G Knepley } 4331*5f80ce2aSJacob Faibussowitsch if (!rank) CHKERRQ(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 4332*5f80ce2aSJacob 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; 4382*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 4383*5f80ce2aSJacob 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]; 4386*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(dm, pStart, pEnd)); 43879298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 4388*5f80ce2aSJacob 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]); 4394*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */ 43959298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p-pStart], ++p) { 4396*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(dm, p, &cones[off])); 4397*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 43989298eaa6SMatthew G Knepley } 4399*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dm)); 4400*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dm)); 44019298eaa6SMatthew G Knepley /* Build coordinates */ 4402*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &coordSection)); 4403*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 4404*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 4405*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, firstVertex, firstVertex+numPoints[0])); 44069298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex+numPoints[0]; ++v) { 4407*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, dimEmbed)); 4408*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 44099298eaa6SMatthew G Knepley } 4410*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 4411*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 4412*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 4413*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 4414*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 4415*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, dimEmbed)); 4416*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates,VECSTANDARD)); 44179318fe57SMatthew G. Knepley if (vertexCoords) { 4418*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 44199298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 44209298eaa6SMatthew G Knepley PetscInt off; 44219298eaa6SMatthew G Knepley 4422*5f80ce2aSJacob 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 } 4428*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 4429*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dm, coordinates)); 4430*5f80ce2aSJacob 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; 4467*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 4468*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerCreate(comm, &viewer)); 4469*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 4470*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 4471*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetName(viewer, filename)); 4472dd400576SPatrick Sanan if (rank == 0) { 4473*5f80ce2aSJacob 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 } 4479*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 4480*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 4481*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(*dm, 0, Nc+Nv)); 4482*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(*dm, dim)); 4483*5f80ce2aSJacob 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'; 4492*5f80ce2aSJacob Faibussowitsch for (c = 0; c < Nc; ++c) CHKERRQ(DMPlexSetConeSize(*dm, c, Ncn)); 4493*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(*dm)); 44948ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 4495*5f80ce2aSJacob 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 } 4512*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(*dm, c, cone)); 45138ca92349SMatthew G. Knepley } 45148ca92349SMatthew G. Knepley } 4515*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(*dm)); 4516*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(*dm)); 45178ca92349SMatthew G. Knepley /* Read coordinates */ 4518*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(*dm, &coordSection)); 4519*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 4520*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 4521*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 45228ca92349SMatthew G. Knepley for (v = Nc; v < Nc+Nv; ++v) { 4523*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, cdim)); 4524*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 45258ca92349SMatthew G. Knepley } 4526*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 4527*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize)); 4528*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates)); 4529*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 4530*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 4531*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, cdim)); 4532*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinates, VECSTANDARD)); 4533*5f80ce2aSJacob 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'; 4542*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(*dm, "marker")); 4543*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(*dm, "marker", &marker)); 4544f8d5e320SMatthew G. Knepley } 45458ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 4546*5f80ce2aSJacob 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]; 4558*5f80ce2aSJacob Faibussowitsch for (l = 0; l < Nl; ++l) CHKERRQ(DMLabelSetValue(marker, v+Nc, val[l])); 45598ca92349SMatthew G. Knepley } 45608ca92349SMatthew G. Knepley } 4561*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 4562*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(*dm, coordinates)); 4563*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 4564*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 45658ca92349SMatthew G. Knepley if (interpolate) { 45668ca92349SMatthew G. Knepley DM idm; 45678ca92349SMatthew G. Knepley DMLabel bdlabel; 45688ca92349SMatthew G. Knepley 4569*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(*dm, &idm)); 4570*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(dm)); 45718ca92349SMatthew G. Knepley *dm = idm; 45728ca92349SMatthew G. Knepley 4573f8d5e320SMatthew G. Knepley if (!Nl) { 4574*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(*dm, "marker")); 4575*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(*dm, "marker", &bdlabel)); 4576*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 4577*5f80ce2aSJacob 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); 4638*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMInitializePackage()); 4639*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_CreateFromFile,0,0,0,0)); 4640*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 4641*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(filename, &len)); 46422c71b3e2SJacob Faibussowitsch PetscCheckFalse(!len,comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 4643*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extGmsh, 4, &isGmsh)); 4644*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-5)], extGmsh2, 5, &isGmsh2)); 4645*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-5)], extGmsh4, 5, &isGmsh4)); 4646*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-5)], extCGNS, 5, &isCGNS)); 4647*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extExodus, 4, &isExodus)); 464886a0adb1SJed Brown if (!isExodus) { 4649*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-2)], extExodus_e, 2, &isExodus)); 465086a0adb1SJed Brown } 4651*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extGenesis, 4, &isGenesis)); 4652*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extFluent, 4, &isFluent)); 4653*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-3)], extHDF5, 3, &isHDF5)); 4654*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extMed, 4, &isMed)); 4655*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extPLY, 4, &isPLY)); 4656*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-10)], extEGADSLite, 10, &isEGADSLite)); 4657*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-6)], extEGADS, 6, &isEGADS)); 4658*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extIGES, 4, &isIGES)); 4659*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extSTEP, 4, &isSTEP)); 4660*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)], extCV, 4, &isCV)); 4661de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 4662*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 4663ca522641SMatthew G. Knepley } else if (isCGNS) { 4664*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 466590c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 4666*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 46672f0bd6dcSMichael Lange } else if (isFluent) { 4668*5f80ce2aSJacob 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 */ 4674*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-8)], ".xdmf", 5, &load_hdf5_xdmf)); 4675*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL)); 4676*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerCreate(comm, &viewer)); 4677*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 4678*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 4679*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerSetFromOptions(viewer)); 4680*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 4681*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetName(viewer, filename)); 4682cd7e8a5eSksagiyam 4683*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 4684*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)(*dm), plexname)); 4685*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 4686*5f80ce2aSJacob Faibussowitsch if (load_hdf5_xdmf) CHKERRQ(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 4687*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLoad(*dm, viewer)); 4688*5f80ce2aSJacob Faibussowitsch if (load_hdf5_xdmf) CHKERRQ(PetscViewerPopFormat(viewer)); 4689*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 46905fd9971aSMatthew G. Knepley 46915fd9971aSMatthew G. Knepley if (interpolate) { 46925fd9971aSMatthew G. Knepley DM idm; 46935fd9971aSMatthew G. Knepley 4694*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(*dm, &idm)); 4695*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(dm)); 46965fd9971aSMatthew G. Knepley *dm = idm; 46975fd9971aSMatthew G. Knepley } 4698707dd687SMichael Lange } else if (isMed) { 4699*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateMedFromFile(comm, filename, interpolate, dm)); 4700f2801cd6SMatthew G. Knepley } else if (isPLY) { 4701*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 4702c1cad2e7SMatthew G. Knepley } else if (isEGADSLite || isEGADS || isIGES || isSTEP) { 4703*5f80ce2aSJacob Faibussowitsch if (isEGADSLite) CHKERRQ(DMPlexCreateEGADSLiteFromFile(comm, filename, dm)); 4704*5f80ce2aSJacob Faibussowitsch else CHKERRQ(DMPlexCreateEGADSFromFile(comm, filename, dm)); 47057bee2925SMatthew Knepley if (!interpolate) { 47067bee2925SMatthew Knepley DM udm; 47077bee2925SMatthew Knepley 4708*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexUninterpolate(*dm, &udm)); 4709*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(dm)); 47107bee2925SMatthew Knepley *dm = udm; 47117bee2925SMatthew Knepley } 47128ca92349SMatthew G. Knepley } else if (isCV) { 4713*5f80ce2aSJacob 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); 4715*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(plexname, &len)); 4716*5f80ce2aSJacob Faibussowitsch if (len) CHKERRQ(PetscObjectSetName((PetscObject)(*dm), plexname)); 4717*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_CreateFromFile,0,0,0,0)); 4718ca522641SMatthew G. Knepley PetscFunctionReturn(0); 4719ca522641SMatthew G. Knepley } 4720