PetscErrorCode CreateTensorProductHybrid_2D(MPI_Comm comm, PetscInt testNum, DM *dm) { DM idm, hdm = NULL; DMLabel faultLabel, hybridLabel; PetscInt p; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); if (!rank) { PetscInt numPoints[2] = {6, 2}; PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4,}; PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 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}; PetscInt faultPoints[2] = {3, 4}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 2; ++p) {ierr = DMSetLabelValue(*dm, "fault", faultPoints[p], 1);CHKERRQ(ierr);} ierr = PetscObjectSetOptionsPrefix((PetscObject) *dm, "orig_");CHKERRQ(ierr); ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject) idm, "in_");CHKERRQ(ierr); ierr = DMSetFromOptions(idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-dm_view");CHKERRQ(ierr); ierr = DMGetLabel(*dm, "fault", &faultLabel);CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, faultLabel, NULL, &hybridLabel, NULL, NULL, &hdm);CHKERRQ(ierr); ierr = DMLabelDestroy(&hybridLabel);CHKERRQ(ierr); } else { PetscInt numPoints[3] = {0, 0, 0}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, NULL, NULL, NULL, NULL, NULL, &hdm);CHKERRQ(ierr); } ierr = DMDestroy(&idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = hdm; PetscFunctionReturn(0); }
static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *newdm) { PetscInt dim = user->dim; PetscBool cellSimplex = user->cellSimplex; PetscErrorCode ierr; PetscFunctionBegin; switch (dim) { case 2: if (cellSimplex) { ierr = CreateSimplex_2D(comm, newdm);CHKERRQ(ierr); } else { ierr = CreateQuad_2D(comm, newdm);CHKERRQ(ierr); } break; case 3: if (cellSimplex) { ierr = CreateSimplex_3D(comm, newdm);CHKERRQ(ierr); } else { ierr = CreateHex_3D(comm, newdm);CHKERRQ(ierr); } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim); } if (user->refinementLimit > 0.0) { DM rdm; const char *name; ierr = DMPlexSetRefinementUniform(*newdm, PETSC_FALSE);CHKERRQ(ierr); ierr = DMPlexSetRefinementLimit(*newdm, user->refinementLimit);CHKERRQ(ierr); ierr = DMRefine(*newdm, PETSC_COMM_SELF, &rdm);CHKERRQ(ierr); ierr = PetscObjectGetName((PetscObject) *newdm, &name);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) rdm, name);CHKERRQ(ierr); ierr = DMDestroy(newdm);CHKERRQ(ierr); *newdm = rdm; } if (user->interpolate) { DM idm = NULL; const char *name; ierr = DMPlexInterpolate(*newdm, &idm);CHKERRQ(ierr); ierr = PetscObjectGetName((PetscObject) *newdm, &name);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) idm, name);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*newdm, idm);CHKERRQ(ierr); ierr = DMDestroy(newdm);CHKERRQ(ierr); *newdm = idm; } ierr = DMSetFromOptions(*newdm);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode CreateTensorProduct_3D(MPI_Comm comm, PetscInt testNum, DM *dm) { DM idm = NULL; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); if (!rank) { switch (testNum) { case 0: { PetscInt numPoints[2] = {12, 2}; PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[36] = {-1.0, -0.5, -0.5, -1.0, 0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5, -1.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5, 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, 0.5, 0.5}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); } break; case 1: { PetscInt numPoints[2] = {8, 1}; PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[24] = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); } } else { PetscInt numPoints[4] = {0, 0, 0, 0}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); } ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; PetscFunctionReturn(0); }
/*@C DMPlexCreateFromCellList - This takes as input common mesh generator output, a list of the vertices for each cell, and produces a DM Input Parameters: + comm - The communicator . dim - The topological dimension of the mesh . numCells - The number of cells . numVertices - The number of vertices . numCorners - The number of vertices for each cell . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically . cells - An array of numCells*numCorners numbers, the vertices for each cell . spaceDim - The spatial dimension used for coordinates - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex Output Parameter: . dm - The DM Note: Two triangles sharing a face $ $ 2 $ / | \ $ / | \ $ / | \ $ 0 0 | 1 3 $ \ | / $ \ | / $ \ | / $ 1 would have input $ numCells = 2, numVertices = 4 $ cells = [0 1 2 1 3 2] $ which would result in the DMPlex $ $ 4 $ / | \ $ / | \ $ / | \ $ 2 0 | 1 5 $ \ | / $ \ | / $ \ | / $ 3 Level: beginner .seealso: DMPlexCreate() @*/ PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], PetscInt spaceDim, const double vertexCoords[], DM *dm) { PetscErrorCode ierr; PetscFunctionBegin; ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); if (interpolate) { DM idm; ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } ierr = DMPlexBuildCoordinates_Private(*dm, spaceDim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode CreateTensorProductHybrid_3D(MPI_Comm comm, PetscInt testNum, DM *dm) { DM idm, hdm = NULL; DMLabel faultLabel; PetscInt p; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); if (!rank) { switch (testNum) { case 0: { PetscInt numPoints[2] = {12, 2}; PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[36] = {-1.0, -0.5, -0.5, -1.0, 0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5, -1.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5, 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, 0.5, 0.5}; PetscInt faultPoints[4] = {2, 3, 5, 6}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 4; ++p) {ierr = DMSetLabelValue(*dm, "fault", faultPoints[p], 1);CHKERRQ(ierr);} } break; case 1: { PetscInt numPoints[2] = {30, 7}; PetscInt coneSize[37] = {8,8,8,8,8,8,8, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; PetscInt cones[56] = { 8, 21, 20, 7, 13, 12, 23, 24, 14, 15, 10, 9, 13, 8, 21, 24, 15, 16, 11, 10, 24, 21, 22, 25, 30, 29, 28, 21, 35, 24, 33, 34, 24, 21, 30, 35, 25, 36, 31, 22, 27, 20, 21, 28, 32, 33, 24, 23, 15, 24, 13, 14, 19, 18, 17, 26}; PetscInt coneOrientations[56] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; PetscScalar vertexCoords[90] = {-2.0, -2.0, -2.0, -2.0, -1.0, -2.0, -3.0, 0.0, -2.0, -2.0, 1.0, -2.0, -2.0, 2.0, -2.0, -2.0, -2.0, 0.0, -2.0, -1.0, 0.0, -3.0, 0.0, 0.0, -2.0, 1.0, 0.0, -2.0, 2.0, 0.0, -2.0, -1.0, 2.0, -3.0, 0.0, 2.0, -2.0, 1.0, 2.0, 0.0, -2.0, -2.0, 0.0, 0.0, -2.0, 0.0, 2.0, -2.0, 0.0, -2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0, 2.0, -2.0, -2.0, 2.0, -1.0, -2.0, 3.0, 0.0, -2.0, 2.0, 1.0, -2.0, 2.0, 2.0, -2.0, 2.0, -2.0, 0.0, 2.0, -1.0, 0.0, 3.0, 0.0, 0.0, 2.0, 1.0, 0.0, 2.0, 2.0, 0.0}; PetscInt faultPoints[6] = {20, 21, 22, 23, 24, 25}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 6; ++p) {ierr = DMSetLabelValue(*dm, "fault", faultPoints[p], 1);CHKERRQ(ierr);} } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); } ierr = PetscObjectSetOptionsPrefix((PetscObject) *dm, "orig_");CHKERRQ(ierr); ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject) idm, "in_");CHKERRQ(ierr); ierr = DMSetFromOptions(idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-dm_view");CHKERRQ(ierr); ierr = DMGetLabel(*dm, "fault", &faultLabel);CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, faultLabel, NULL, NULL, NULL, NULL, &hdm);CHKERRQ(ierr); ierr = DMDestroy(&idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = hdm; } else { PetscInt numPoints[4] = {0, 0, 0, 0}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, NULL, NULL, NULL, NULL, NULL, &hdm);CHKERRQ(ierr); ierr = DMDestroy(&idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = hdm; } PetscFunctionReturn(0); }
/* Two tetrahedrons separated by a zero-volume cell with 6 vertices cell 6 ___33___10______ cell 0 / | \ |\ \ 1 21 | 23 | 29 27 /12 24 14\ 30 \ \ 3-20-|----5--32-|---9--26--7 \ 13| 11/ |18 / / 19 | 22 | 28 25 \ | / |/ / 4----31----8------ cell 2 */ PetscErrorCode CreateSimplexHybrid_3D(MPI_Comm comm, PetscInt testNum, DM *dm) { DM idm, hdm = NULL; DMLabel faultLabel, hybridLabel; PetscInt p; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); if (!rank) { switch (testNum) { case 0: { PetscInt numPoints[2] = {5, 2}; PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 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}; PetscInt faultPoints[3] = {3, 4, 5}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "fault", faultPoints[p], 1);CHKERRQ(ierr);} } break; case 1: { /* Tets 0,3,5 and 1,2,4 */ PetscInt numPoints[2] = {9, 6}; PetscInt coneSize[15] = {4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscInt cones[24] = { 7, 9, 8, 6, 11, 9, 13, 14, 10, 13, 11, 9, 10, 9, 11, 7, 9, 13, 14, 12, 7, 11, 8, 9}; PetscInt coneOrientations[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[27] = {-2.0, -1.0, 0.0, -2.0, 0.0, 0.0, -2.0, 0.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, -1.0, 0.0, 2.0, 0.0, 0.0, 2.0, 0.0, 1.0}; PetscInt faultPoints[3] = {9, 10, 11}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "fault", faultPoints[p], 1);CHKERRQ(ierr);} } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); } ierr = PetscObjectSetOptionsPrefix((PetscObject) *dm, "orig_");CHKERRQ(ierr); ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject) idm, "in_");CHKERRQ(ierr); ierr = DMSetFromOptions(idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-dm_view");CHKERRQ(ierr); ierr = DMGetLabel(*dm, "fault", &faultLabel);CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, faultLabel, NULL, &hybridLabel, NULL, NULL, &hdm);CHKERRQ(ierr); ierr = DMLabelDestroy(&hybridLabel);CHKERRQ(ierr); ierr = DMDestroy(&idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = hdm; } else { PetscInt numPoints[4] = {0, 0, 0, 0}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, NULL, NULL, NULL, NULL, NULL, &hdm);CHKERRQ(ierr); ierr = DMDestroy(&idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = hdm; } PetscFunctionReturn(0); }
/* Two tetrahedrons cell 5 5______ cell 0 / | \ |\ \ 1 17 | 18 | 18 13 21 /8 19 10\ 19 \ \ 2-14-|----4 | 4--22--6 \ 9 | 7 / |10 / / 16 | 15 | 15 12 20 \ | / |/ / 3 3------ */ PetscErrorCode CreateSimplex_3D(MPI_Comm comm, PetscInt testNum, DM *dm) { DM idm; PetscInt depth = 3; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); if (!rank) { switch (testNum) { case 0: { PetscInt numPoints[4] = {5, 9, 7, 2}; PetscInt coneSize[23] = {4, 4, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2}; PetscInt cones[47] = { 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 14, 16, 19, 17, 15, 18, 19, 20, 21, 19, 15, 22, 20, 18, 21, 22, 2, 4, 4, 3, 3, 2, 2, 5, 5, 4, 3, 5, 3, 6, 6, 5, 4, 6}; PetscInt coneOrientations[47] = { 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, 0, -2, -2, -2, -2, 0, 0, -2, -2, 0, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[15] = {0.0, 0.0, -0.5, 0.0, -0.5, 0.0, 1.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5}; ierr = DMPlexCreateFromDAG(*dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); } break; case 1: { PetscInt numPoints[2] = {5, 2}; PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 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}; depth = 1; ierr = DMPlexCreateFromDAG(*dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } break; case 2: { PetscInt numPoints[2] = {4, 1}; PetscInt coneSize[5] = {4, 0, 0, 0, 0}; PetscInt cones[4] = {2, 3, 4, 1}; PetscInt coneOrientations[4] = {0, 0, 0, 0}; PetscScalar vertexCoords[12] = {0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; depth = 1; ierr = DMPlexCreateFromDAG(*dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); } } else { PetscInt numPoints[4] = {0, 0, 0, 0}; ierr = DMPlexCreateFromDAG(*dm, depth, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); switch (testNum) { case 1: ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; break; } } PetscFunctionReturn(0); }
PetscErrorCode TestTriangle(MPI_Comm comm, PetscBool interpolate, PetscBool transform) { DM dm; PetscRandom r, ang, ang2; PetscInt dim, t; PetscErrorCode ierr; PetscFunctionBegin; /* Create reference triangle */ dim = 2; ierr = DMCreate(comm, &dm);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) dm, "triangle");CHKERRQ(ierr); ierr = DMSetType(dm, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(dm, dim);CHKERRQ(ierr); { PetscInt numPoints[2] = {3, 1}; PetscInt coneSize[4] = {3, 0, 0, 0}; PetscInt cones[3] = {1, 2, 3}; PetscInt coneOrientations[3] = {0, 0, 0}; PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; ierr = DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); if (interpolate) { DM idm; ierr = DMPlexInterpolate(dm, &idm);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) idm, "triangle");CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(dm, idm);CHKERRQ(ierr); ierr = DMDestroy(&dm);CHKERRQ(ierr); dm = idm; } ierr = DMSetFromOptions(dm);CHKERRQ(ierr); } /* Check reference geometry: determinant is scaled by reference volume (2.0) */ { PetscReal v0Ex[2] = {-1.0, -1.0}; PetscReal JEx[4] = {1.0, 0.0, 0.0, 1.0}; PetscReal invJEx[4] = {1.0, 0.0, 0.0, 1.0}; PetscReal detJEx = 1.0; PetscReal centroidEx[2] = {-0.333333333333, -0.333333333333}; PetscReal normalEx[2] = {0.0, 0.0}; PetscReal volEx = 2.0; ierr = CheckFEMGeometry(dm, 0, dim, v0Ex, JEx, invJEx, detJEx);CHKERRQ(ierr); if (interpolate) {ierr = CheckFVMGeometry(dm, 0, dim, centroidEx, normalEx, volEx);CHKERRQ(ierr);} } /* Check random triangles: rotate, scale, then translate */ if (transform) { ierr = PetscRandomCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr); ierr = PetscRandomSetInterval(r, 0.0, 10.0);CHKERRQ(ierr); ierr = PetscRandomCreate(PETSC_COMM_SELF, &ang);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(ang);CHKERRQ(ierr); ierr = PetscRandomSetInterval(ang, 0.0, 2*PETSC_PI);CHKERRQ(ierr); for (t = 0; t < 100; ++t) { PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}, trans[2]; PetscReal v0Ex[2] = {-1.0, -1.0}; PetscReal JEx[4] = {1.0, 0.0, 0.0, 1.0}, R[4], rot[2], rotM[4]; PetscReal invJEx[4] = {1.0, 0.0, 0.0, 1.0}; PetscReal detJEx = 1.0, scale, phi; PetscReal centroidEx[2] = {-0.333333333333, -0.333333333333}; PetscReal normalEx[2] = {0.0, 0.0}; PetscReal volEx = 2.0; PetscInt d, e, f, p; ierr = PetscRandomGetValueReal(r, &scale);CHKERRQ(ierr); ierr = PetscRandomGetValueReal(ang, &phi);CHKERRQ(ierr); R[0] = cos(phi); R[1] = -sin(phi); R[2] = sin(phi); R[3] = cos(phi); for (p = 0; p < 3; ++p) { for (d = 0; d < dim; ++d) { for (e = 0, rot[d] = 0.0; e < dim; ++e) { rot[d] += R[d*dim+e] * vertexCoords[p*dim+e]; } } for (d = 0; d < dim; ++d) vertexCoords[p*dim+d] = rot[d]; } for (d = 0; d < dim; ++d) { for (e = 0, rot[d] = 0.0; e < dim; ++e) { rot[d] += R[d*dim+e] * centroidEx[e]; } } for (d = 0; d < dim; ++d) centroidEx[d] = rot[d]; for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { for (f = 0, rotM[d*dim+e] = 0.0; f < dim; ++f) { rotM[d*dim+e] += R[d*dim+f] * JEx[f*dim+e]; } } } for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { JEx[d*dim+e] = rotM[d*dim+e]; } } for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { for (f = 0, rotM[d*dim+e] = 0.0; f < dim; ++f) { rotM[d*dim+e] += invJEx[d*dim+f] * R[e*dim+f]; } } } for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { invJEx[d*dim+e] = rotM[d*dim+e]; } } for (d = 0; d < dim; ++d) { ierr = PetscRandomGetValueReal(r, &trans[d]);CHKERRQ(ierr); for (p = 0; p < 3; ++p) { vertexCoords[p*dim+d] *= scale; vertexCoords[p*dim+d] += trans[d]; } v0Ex[d] = vertexCoords[d]; for (e = 0; e < dim; ++e) { JEx[d*dim+e] *= scale; invJEx[d*dim+e] /= scale; } detJEx *= scale; centroidEx[d] *= scale; centroidEx[d] += trans[d]; volEx *= scale; } ierr = ChangeCoordinates(dm, dim, vertexCoords);CHKERRQ(ierr); ierr = CheckFEMGeometry(dm, 0, dim, v0Ex, JEx, invJEx, detJEx);CHKERRQ(ierr); if (interpolate) {ierr = CheckFVMGeometry(dm, 0, dim, centroidEx, normalEx, volEx);CHKERRQ(ierr);} } ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); ierr = PetscRandomDestroy(&ang);CHKERRQ(ierr); } /* Move to 3D: Check reference geometry: determinant is scaled by reference volume (2.0) */ dim = 3; { PetscScalar vertexCoords[9] = {-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0}; PetscReal v0Ex[3] = {-1.0, -1.0, 0.0}; PetscReal JEx[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; PetscReal invJEx[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; PetscReal detJEx = 1.0; PetscReal centroidEx[3] = {-0.333333333333, -0.333333333333, 0.0}; PetscReal normalEx[3] = {0.0, 0.0, 1.0}; PetscReal volEx = 2.0; ierr = ChangeCoordinates(dm, dim, vertexCoords);CHKERRQ(ierr); ierr = CheckFEMGeometry(dm, 0, dim, v0Ex, JEx, invJEx, detJEx);CHKERRQ(ierr); if (interpolate) {ierr = CheckFVMGeometry(dm, 0, dim, centroidEx, normalEx, volEx);CHKERRQ(ierr);} } /* Rotated reference element */ { PetscScalar vertexCoords[9] = {0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0}; PetscReal v0Ex[3] = {0.0, -1.0, -1.0}; PetscReal JEx[9] = {0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0}; PetscReal invJEx[9] = {0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0}; PetscReal detJEx = 1.0; PetscReal centroidEx[3] = {0.0, -0.333333333333, -0.333333333333}; PetscReal normalEx[3] = {1.0, 0.0, 0.0}; PetscReal volEx = 2.0; ierr = ChangeCoordinates(dm, dim, vertexCoords);CHKERRQ(ierr); ierr = CheckFEMGeometry(dm, 0, dim, v0Ex, JEx, invJEx, detJEx);CHKERRQ(ierr); if (interpolate) {ierr = CheckFVMGeometry(dm, 0, dim, centroidEx, normalEx, volEx);CHKERRQ(ierr);} } /* Check random triangles: scale, translate, then rotate */ if (transform) { ierr = PetscRandomCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr); ierr = PetscRandomSetInterval(r, 0.0, 10.0);CHKERRQ(ierr); ierr = PetscRandomCreate(PETSC_COMM_SELF, &ang);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(ang);CHKERRQ(ierr); ierr = PetscRandomSetInterval(ang, 0.0, 2*PETSC_PI);CHKERRQ(ierr); ierr = PetscRandomCreate(PETSC_COMM_SELF, &ang2);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(ang2);CHKERRQ(ierr); ierr = PetscRandomSetInterval(ang2, 0.0, PETSC_PI);CHKERRQ(ierr); for (t = 0; t < 100; ++t) { PetscScalar vertexCoords[9] = {-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0}, trans[3]; PetscReal v0Ex[3] = {-1.0, -1.0, 0.0}; PetscReal JEx[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}, R[9], rot[3], rotM[9]; PetscReal invJEx[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; PetscReal detJEx = 1.0, scale, phi, theta, psi = 0.0; PetscReal centroidEx[3] = {-0.333333333333, -0.333333333333, 0.0}; PetscReal normalEx[3] = {0.0, 0.0, 1.0}; PetscReal volEx = 2.0; PetscInt d, e, f, p; ierr = PetscRandomGetValueReal(r, &scale);CHKERRQ(ierr); ierr = PetscRandomGetValueReal(ang, &phi);CHKERRQ(ierr); ierr = PetscRandomGetValueReal(ang2, &theta);CHKERRQ(ierr); for (d = 0; d < dim; ++d) { ierr = PetscRandomGetValueReal(r, &trans[d]);CHKERRQ(ierr); for (p = 0; p < 3; ++p) { vertexCoords[p*dim+d] *= scale; vertexCoords[p*dim+d] += trans[d]; } centroidEx[d] *= scale; centroidEx[d] += trans[d]; for (e = 0; e < dim-1; ++e) { JEx[d*dim+e] *= scale; invJEx[d*dim+e] /= scale; } if (d < dim-1) { detJEx *= scale; volEx *= scale; } } R[0] = cos(theta)*cos(psi); R[1] = sin(phi)*sin(theta)*cos(psi) - cos(phi)*sin(psi); R[2] = sin(phi)*sin(psi) + cos(phi)*sin(theta)*cos(psi); R[3] = cos(theta)*sin(psi); R[4] = cos(phi)*cos(psi) + sin(phi)*sin(theta)*sin(psi); R[5] = cos(phi)*sin(theta)*sin(psi) - sin(phi)*cos(psi); R[6] = -sin(theta); R[7] = sin(phi)*cos(theta); R[8] = cos(phi)*cos(theta); for (p = 0; p < 3; ++p) { for (d = 0; d < dim; ++d) { for (e = 0, rot[d] = 0.0; e < dim; ++e) { rot[d] += R[d*dim+e] * vertexCoords[p*dim+e]; } } for (d = 0; d < dim; ++d) vertexCoords[p*dim+d] = rot[d]; } for (d = 0; d < dim; ++d) { for (e = 0, rot[d] = 0.0; e < dim; ++e) { rot[d] += R[d*dim+e] * centroidEx[e]; } } for (d = 0; d < dim; ++d) centroidEx[d] = rot[d]; for (d = 0; d < dim; ++d) { for (e = 0, rot[d] = 0.0; e < dim; ++e) { rot[d] += R[d*dim+e] * normalEx[e]; } } for (d = 0; d < dim; ++d) normalEx[d] = rot[d]; for (d = 0; d < dim; ++d) { v0Ex[d] = vertexCoords[d]; for (e = 0; e < dim; ++e) { for (f = 0, rotM[d*dim+e] = 0.0; f < dim; ++f) { rotM[d*dim+e] += R[d*dim+f] * JEx[f*dim+e]; } } } for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { JEx[d*dim+e] = rotM[d*dim+e]; } } for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { for (f = 0, rotM[d*dim+e] = 0.0; f < dim; ++f) { rotM[d*dim+e] += invJEx[d*dim+f] * R[e*dim+f]; } } } for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { invJEx[d*dim+e] = rotM[d*dim+e]; } } ierr = ChangeCoordinates(dm, dim, vertexCoords);CHKERRQ(ierr); ierr = CheckFEMGeometry(dm, 0, dim, v0Ex, JEx, invJEx, detJEx);CHKERRQ(ierr); if (interpolate) {ierr = CheckFVMGeometry(dm, 0, dim, centroidEx, normalEx, volEx);CHKERRQ(ierr);} } ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); ierr = PetscRandomDestroy(&ang);CHKERRQ(ierr); ierr = PetscRandomDestroy(&ang2);CHKERRQ(ierr); } /* Cleanup */ ierr = DMDestroy(&dm);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode CreateMesh(MPI_Comm comm, PetscInt testNum, AppCtx *user, DM *dm) { PetscInt dim = user->dim; PetscBool cellSimplex = user->cellSimplex; PetscBool useGenerator = user->useGenerator; const char *filename = user->filename; size_t len; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = PetscStrlen(filename, &len);CHKERRQ(ierr); if (len) { ierr = DMPlexCreateFromFile(comm, filename, PETSC_FALSE, dm);CHKERRQ(ierr); ierr = DMGetDimension(*dm, &dim);CHKERRQ(ierr); } else if (useGenerator) { if (cellSimplex) { ierr = DMPlexCreateBoxMesh(comm, dim, dim == 2 ? 2 : 1, PETSC_FALSE, dm);CHKERRQ(ierr); } else { const PetscInt cells[3] = {2, 2, 2}; ierr = DMPlexCreateHexBoxMesh(comm, dim, cells, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, dm);CHKERRQ(ierr); } } else { ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); switch (dim) { case 2: if (cellSimplex) { ierr = CreateSimplex_2D(comm, *dm);CHKERRQ(ierr); } else { ierr = CreateQuad_2D(comm, testNum, *dm);CHKERRQ(ierr); } break; case 3: if (cellSimplex) { ierr = CreateSimplex_3D(comm, *dm);CHKERRQ(ierr); } else { ierr = CreateHex_3D(comm, *dm);CHKERRQ(ierr); } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim); } } { DM interpolatedMesh = NULL; ierr = CheckMesh(*dm, user);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &interpolatedMesh);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, interpolatedMesh);CHKERRQ(ierr); ierr = CompareCones(*dm, interpolatedMesh);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = interpolatedMesh; } { DM distributedMesh = NULL; /* Distribute mesh over processes */ ierr = DMPlexDistribute(*dm, 0, NULL, &distributedMesh);CHKERRQ(ierr); if (distributedMesh) { ierr = DMViewFromOptions(distributedMesh, NULL, "-dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = distributedMesh; } } ierr = PetscObjectSetName((PetscObject) *dm, "Interpolated Mesh");CHKERRQ(ierr); ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); user->dm = *dm; PetscFunctionReturn(0); }
PetscErrorCode CreateMesh(MPI_Comm comm, PetscInt testNum, AppCtx *user, DM *dm) { PetscInt dim = user->dim; PetscBool cellSimplex = user->cellSimplex; PetscBool useGenerator = user->useGenerator; const char *filename = user->filename; const char *partitioner = "chaco"; size_t len; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = PetscStrlen(filename, &len);CHKERRQ(ierr); if (len) { #if defined(PETSC_HAVE_EXODUSII) int CPU_word_size = 0, IO_word_size = 0, exoid = -1; float version; if (!rank) { exoid = ex_open(filename, EX_READ, &CPU_word_size, &IO_word_size, &version); if (exoid <= 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open(\"%s\",...) did not return a valid file ID", filename); } ierr = DMPlexCreateExodus(comm, exoid, PETSC_FALSE, dm);CHKERRQ(ierr); if (!rank) {ierr = ex_close(exoid);CHKERRQ(ierr);} ierr = DMPlexGetDimension(*dm, &dim);CHKERRQ(ierr); #else SETERRQ(comm, PETSC_ERR_SUP, "Loading meshes requires ExodusII support. Reconfigure using --download-exodusii"); #endif } else if (useGenerator) { if (cellSimplex) { ierr = DMPlexCreateBoxMesh(comm, dim, PETSC_FALSE, dm);CHKERRQ(ierr); } else { ierr = DMPlexCreateHexBoxMesh(comm, dim, PETSC_FALSE, dm);CHKERRQ(ierr); } } else { ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); switch (dim) { case 2: if (cellSimplex) { ierr = CreateSimplex_2D(comm, *dm);CHKERRQ(ierr); } else { ierr = CreateQuad_2D(comm, testNum, *dm);CHKERRQ(ierr); } break; case 3: if (cellSimplex) { ierr = CreateSimplex_3D(comm, *dm);CHKERRQ(ierr); } else { ierr = CreateHex_3D(comm, *dm);CHKERRQ(ierr); } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim); } } { DM interpolatedMesh = NULL; ierr = CheckMesh(*dm);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &interpolatedMesh);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, interpolatedMesh);CHKERRQ(ierr); ierr = CompareCones(*dm, interpolatedMesh);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = interpolatedMesh; } { DM distributedMesh = NULL; /* Distribute mesh over processes */ ierr = DMPlexDistribute(*dm, partitioner, 0, &distributedMesh);CHKERRQ(ierr); if (distributedMesh) { ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = distributedMesh; } } ierr = PetscObjectSetName((PetscObject) *dm, "Interpolated Mesh");CHKERRQ(ierr); ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); user->dm = *dm; PetscFunctionReturn(0); }
/*@ DMPlexCreateCGNS - Create a DMPlex mesh from a CGNS file ID. Collective on comm Input Parameters: + comm - The MPI communicator . cgid - The CG id associated with a file and obtained using cg_open - interpolate - Create faces and edges in the mesh Output Parameter: . dm - The DM object representing the mesh Note: http://www.grc.nasa.gov/WWW/cgns/CGNS_docs_current/index.html Level: beginner .keywords: mesh,CGNS .seealso: DMPlexCreate(), DMPlexCreateExodus() @*/ PetscErrorCode DMPlexCreateCGNS(MPI_Comm comm, PetscInt cgid, PetscBool interpolate, DM *dm) { #if defined(PETSC_HAVE_CGNS) PetscMPIInt num_proc, rank; PetscSection coordSection; Vec coordinates; PetscScalar *coords; PetscInt *cellStart, *vertStart; PetscInt coordSize, v; PetscErrorCode ierr; /* Read from file */ char basename[CGIO_MAX_NAME_LENGTH+1]; char buffer[CGIO_MAX_NAME_LENGTH+1]; int dim = 0, physDim = 0, numVertices = 0, numCells = 0; int nzones = 0; #endif PetscFunctionBegin; #if defined(PETSC_HAVE_CGNS) ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &num_proc);CHKERRQ(ierr); ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); /* Open CGNS II file and read basic informations on rank 0, then broadcast to all processors */ if (!rank) { int nbases, z; ierr = cg_nbases(cgid, &nbases);CHKERRQ(ierr); if (nbases > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CGNS file must have a single base, not %d\n",nbases); ierr = cg_base_read(cgid, 1, basename, &dim, &physDim);CHKERRQ(ierr); ierr = cg_nzones(cgid, 1, &nzones);CHKERRQ(ierr); ierr = PetscCalloc2(nzones+1, &cellStart, nzones+1, &vertStart);CHKERRQ(ierr); for (z = 1; z <= nzones; ++z) { cgsize_t sizes[3]; /* Number of vertices, number of cells, number of boundary vertices */ ierr = cg_zone_read(cgid, 1, z, buffer, sizes);CHKERRQ(ierr); numVertices += sizes[0]; numCells += sizes[1]; cellStart[z] += sizes[1] + cellStart[z-1]; vertStart[z] += sizes[0] + vertStart[z-1]; } for (z = 1; z <= nzones; ++z) { vertStart[z] += numCells; } } ierr = MPI_Bcast(basename, CGIO_MAX_NAME_LENGTH+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); ierr = MPI_Bcast(&dim, 1, MPI_INT, 0, comm);CHKERRQ(ierr); ierr = MPI_Bcast(&nzones, 1, MPI_INT, 0, comm);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) *dm, basename);CHKERRQ(ierr); ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr); /* Read zone information */ if (!rank) { int z, c, c_loc, v, v_loc; /* Read the cell set connectivity table and build mesh topology CGNS standard requires that cells in a zone be numbered sequentially and be pairwise disjoint. */ /* First set sizes */ for (z = 1, c = 0; z <= nzones; ++z) { ZoneType_t zonetype; int nsections; ElementType_t cellType; cgsize_t start, end; int nbndry, parentFlag; PetscInt numCorners; ierr = cg_zone_type(cgid, 1, z, &zonetype);CHKERRQ(ierr); if (zonetype == Structured) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Can only handle Unstructured zones for CGNS"); ierr = cg_nsections(cgid, 1, z, &nsections);CHKERRQ(ierr); if (nsections > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CGNS file must have a single section, not %d\n",nsections); ierr = cg_section_read(cgid, 1, z, 1, buffer, &cellType, &start, &end, &nbndry, &parentFlag);CHKERRQ(ierr); /* This alone is reason enough to bludgeon every single CGNDS developer, this must be what they describe as the "idiocy of crowds" */ if (cellType == MIXED) { cgsize_t elementDataSize, *elements; PetscInt off; ierr = cg_ElementDataSize(cgid, 1, z, 1, &elementDataSize);CHKERRQ(ierr); ierr = PetscMalloc1(elementDataSize, &elements);CHKERRQ(ierr); ierr = cg_elements_read(cgid, 1, z, 1, elements, NULL);CHKERRQ(ierr); for (c_loc = start, off = 0; c_loc <= end; ++c_loc, ++c) { switch (elements[off]) { case TRI_3: numCorners = 3;break; case QUAD_4: numCorners = 4;break; case TETRA_4: numCorners = 4;break; case HEXA_8: numCorners = 8;break; default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell type %d", (int) elements[off]); } ierr = DMPlexSetConeSize(*dm, c, numCorners);CHKERRQ(ierr); off += numCorners+1; } ierr = PetscFree(elements);CHKERRQ(ierr); } else { switch (cellType) { case TRI_3: numCorners = 3;break; case QUAD_4: numCorners = 4;break; case TETRA_4: numCorners = 4;break; case HEXA_8: numCorners = 8;break; default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell type %d", (int) cellType); } for (c_loc = start; c_loc <= end; ++c_loc, ++c) { ierr = DMPlexSetConeSize(*dm, c, numCorners);CHKERRQ(ierr); } } } ierr = DMSetUp(*dm);CHKERRQ(ierr); for (z = 1, c = 0; z <= nzones; ++z) { ElementType_t cellType; cgsize_t *elements, elementDataSize, start, end; int nbndry, parentFlag; PetscInt *cone, numc, numCorners, maxCorners = 27; ierr = cg_section_read(cgid, 1, z, 1, buffer, &cellType, &start, &end, &nbndry, &parentFlag);CHKERRQ(ierr); numc = end - start; /* This alone is reason enough to bludgeon every single CGNDS developer, this must be what they describe as the "idiocy of crowds" */ ierr = cg_ElementDataSize(cgid, 1, z, 1, &elementDataSize);CHKERRQ(ierr); ierr = PetscMalloc2(elementDataSize,&elements,maxCorners,&cone);CHKERRQ(ierr); ierr = cg_elements_read(cgid, 1, z, 1, elements, NULL);CHKERRQ(ierr); if (cellType == MIXED) { /* CGNS uses Fortran-based indexing, sieve uses C-style and numbers cell first then vertices. */ for (c_loc = 0, v = 0; c_loc <= numc; ++c_loc, ++c) { switch (elements[v]) { case TRI_3: numCorners = 3;break; case QUAD_4: numCorners = 4;break; case TETRA_4: numCorners = 4;break; case HEXA_8: numCorners = 8;break; default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell type %d", (int) elements[v]); } ++v; for (v_loc = 0; v_loc < numCorners; ++v_loc, ++v) { cone[v_loc] = elements[v]+numCells-1; } /* Tetrahedra are inverted */ if (elements[v] == TETRA_4) { PetscInt tmp = cone[0]; cone[0] = cone[1]; cone[1] = tmp; } /* Hexahedra are inverted */ if (elements[v] == HEXA_8) { PetscInt tmp = cone[5]; cone[5] = cone[7]; cone[7] = tmp; } ierr = DMPlexSetCone(*dm, c, cone);CHKERRQ(ierr); ierr = DMPlexSetLabelValue(*dm, "zone", c, z);CHKERRQ(ierr); } } else { switch (cellType) { case TRI_3: numCorners = 3;break; case QUAD_4: numCorners = 4;break; case TETRA_4: numCorners = 4;break; case HEXA_8: numCorners = 8;break; default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell type %d", (int) cellType); } /* CGNS uses Fortran-based indexing, sieve uses C-style and numbers cell first then vertices. */ for (c_loc = 0, v = 0; c_loc <= numc; ++c_loc, ++c) { for (v_loc = 0; v_loc < numCorners; ++v_loc, ++v) { cone[v_loc] = elements[v]+numCells-1; } /* Tetrahedra are inverted */ if (cellType == TETRA_4) { PetscInt tmp = cone[0]; cone[0] = cone[1]; cone[1] = tmp; } /* Hexahedra are inverted, and they give the top first */ if (cellType == HEXA_8) { PetscInt tmp = cone[5]; cone[5] = cone[7]; cone[7] = tmp; } ierr = DMPlexSetCone(*dm, c, cone);CHKERRQ(ierr); ierr = DMPlexSetLabelValue(*dm, "zone", c, z);CHKERRQ(ierr); } } ierr = PetscFree2(elements,cone);CHKERRQ(ierr); } } ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); ierr = DMPlexStratify(*dm);CHKERRQ(ierr); if (interpolate) { DM idm = NULL; ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); /* Maintain zone label */ { DMLabel label; ierr = DMPlexRemoveLabel(*dm, "zone", &label);CHKERRQ(ierr); if (label) {ierr = DMPlexAddLabel(idm, label);CHKERRQ(ierr);} } ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } /* Read coordinates */ ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); for (v = numCells; v < numCells+numVertices; ++v) { ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); } ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); ierr = VecCreate(comm, &coordinates);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); if (!rank) { PetscInt off = 0; float *x[3]; int z, d; ierr = PetscMalloc3(numVertices,&x[0],numVertices,&x[1],numVertices,&x[2]);CHKERRQ(ierr); for (z = 1; z <= nzones; ++z) { DataType_t datatype; cgsize_t sizes[3]; /* Number of vertices, number of cells, number of boundary vertices */ cgsize_t range_min[3] = {1, 1, 1}; cgsize_t range_max[3] = {1, 1, 1}; int ngrids, ncoords; ierr = cg_zone_read(cgid, 1, z, buffer, sizes);CHKERRQ(ierr); range_max[0] = sizes[0]; ierr = cg_ngrids(cgid, 1, z, &ngrids);CHKERRQ(ierr); if (ngrids > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CGNS file must have a single grid, not %d\n",ngrids); ierr = cg_ncoords(cgid, 1, z, &ncoords);CHKERRQ(ierr); if (ncoords != dim) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CGNS file must have a coordinate array for each dimension, not %d\n",ncoords); for (d = 0; d < dim; ++d) { ierr = cg_coord_info(cgid, 1, z, 1+d, &datatype, buffer);CHKERRQ(ierr); ierr = cg_coord_read(cgid, 1, z, buffer, RealSingle, range_min, range_max, x[d]);CHKERRQ(ierr); } if (dim > 0) { for (v = 0; v < sizes[0]; ++v) coords[(v+off)*dim+0] = x[0][v]; } if (dim > 1) { for (v = 0; v < sizes[0]; ++v) coords[(v+off)*dim+1] = x[1][v]; } if (dim > 2) { for (v = 0; v < sizes[0]; ++v) coords[(v+off)*dim+2] = x[2][v]; } off += sizes[0]; } ierr = PetscFree3(x[0],x[1],x[2]);CHKERRQ(ierr); } ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); ierr = VecDestroy(&coordinates);CHKERRQ(ierr); /* Read boundary conditions */ if (!rank) { DMLabel label; BCType_t bctype; DataType_t datatype; PointSetType_t pointtype; cgsize_t *points; PetscReal *normals; int normal[3]; char *bcname = buffer; cgsize_t npoints, nnormals; int z, nbc, bc, c, ndatasets; for (z = 1; z <= nzones; ++z) { ierr = cg_nbocos(cgid, 1, z, &nbc);CHKERRQ(ierr); for (bc = 1; bc <= nbc; ++bc) { ierr = cg_boco_info(cgid, 1, z, bc, bcname, &bctype, &pointtype, &npoints, normal, &nnormals, &datatype, &ndatasets);CHKERRQ(ierr); ierr = DMPlexCreateLabel(*dm, bcname);CHKERRQ(ierr); ierr = DMPlexGetLabel(*dm, bcname, &label);CHKERRQ(ierr); ierr = PetscMalloc2(npoints, &points, nnormals, &normals);CHKERRQ(ierr); ierr = cg_boco_read(cgid, 1, z, bc, points, (void *) normals);CHKERRQ(ierr); if (pointtype == ElementRange) { /* Range of cells: assuming half-open interval since the documentation sucks */ for (c = points[0]; c < points[1]; ++c) { ierr = DMLabelSetValue(label, c - cellStart[z-1], 1);CHKERRQ(ierr); } } else if (pointtype == ElementList) { /* List of cells */ for (c = 0; c < npoints; ++c) { ierr = DMLabelSetValue(label, points[c] - cellStart[z-1], 1);CHKERRQ(ierr); } } else if (pointtype == PointRange) { GridLocation_t gridloc; /* List of points: Oh please, someone get the CGNS developers away from a computer. This is unconscionable. */ ierr = cg_goto(cgid, 1, "Zone_t", z, "BC_t", bc, "end");CHKERRQ(ierr); ierr = cg_gridlocation_read(&gridloc);CHKERRQ(ierr); /* Range of points: assuming half-open interval since the documentation sucks */ for (c = points[0]; c < points[1]; ++c) { if (gridloc == Vertex) {ierr = DMLabelSetValue(label, c - vertStart[z-1], 1);CHKERRQ(ierr);} else {ierr = DMLabelSetValue(label, c - cellStart[z-1], 1);CHKERRQ(ierr);} } } else if (pointtype == PointList) { GridLocation_t gridloc; /* List of points: Oh please, someone get the CGNS developers away from a computer. This is unconscionable. */ ierr = cg_goto(cgid, 1, "Zone_t", z, "BC_t", bc, "end"); ierr = cg_gridlocation_read(&gridloc); for (c = 0; c < npoints; ++c) { if (gridloc == Vertex) {ierr = DMLabelSetValue(label, points[c] - vertStart[z-1], 1);CHKERRQ(ierr);} else {ierr = DMLabelSetValue(label, points[c] - cellStart[z-1], 1);CHKERRQ(ierr);} } } else SETERRQ1(comm, PETSC_ERR_SUP, "Unsupported point set type %d", (int) pointtype); ierr = PetscFree2(points, normals);CHKERRQ(ierr); } } ierr = PetscFree2(cellStart, vertStart);CHKERRQ(ierr); } #else SETERRQ(comm, PETSC_ERR_SUP, "This method requires CGNS support. Reconfigure using --with-cgns-dir"); #endif PetscFunctionReturn(0); }
/*@C DMPlexCreateFluent - Create a DMPlex mesh from a Fluent mesh file. Collective on comm Input Parameters: + comm - The MPI communicator . viewer - The Viewer associated with a Fluent mesh file - interpolate - Create faces and edges in the mesh Output Parameter: . dm - The DM object representing the mesh Note: http://aerojet.engr.ucdavis.edu/fluenthelp/html/ug/node1490.htm Level: beginner .keywords: mesh, fluent, case .seealso: DMPLEX, DMCreate() @*/ PetscErrorCode DMPlexCreateFluent(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) { PetscMPIInt rank; PetscInt c, f, v, dim = PETSC_DETERMINE, numCells = 0, numVertices = 0, numCellVertices = PETSC_DETERMINE; PetscInt numFaces = PETSC_DETERMINE, numFaceEntries = PETSC_DETERMINE, numFaceVertices = PETSC_DETERMINE; PetscInt *faces = NULL, *cellVertices, *faceZoneIDs = NULL; PetscInt d, coordSize; PetscScalar *coords, *coordsIn = NULL; PetscSection coordSection; Vec coordinates; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); if (!rank) { FluentSection s; do { ierr = DMPlexCreateFluent_ReadSection(viewer, &s);CHKERRQ(ierr); if (s.index == 2) { /* Dimension */ dim = s.nd; } else if (s.index == 10 || s.index == 2010) { /* Vertices */ if (s.zoneID == 0) numVertices = s.last; else { if (coordsIn) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Currently no support for multiple coordinate sets in Fluent files"); coordsIn = (PetscScalar *) s.data; } } else if (s.index == 12 || s.index == 2012) { /* Cells */ if (s.zoneID == 0) numCells = s.last; else { switch (s.nd) { case 0: numCellVertices = PETSC_DETERMINE; break; case 1: numCellVertices = 3; break; /* triangular */ case 2: numCellVertices = 4; break; /* tetrahedral */ case 3: numCellVertices = 4; break; /* quadrilateral */ case 4: numCellVertices = 8; break; /* hexahedral */ case 5: numCellVertices = 5; break; /* pyramid */ case 6: numCellVertices = 6; break; /* wedge */ default: numCellVertices = PETSC_DETERMINE; } } } else if (s.index == 13 || s.index == 2013) { /* Facets */ if (s.zoneID == 0) { /* Header section */ numFaces = s.last - s.first + 1; if (s.nd == 0 || s.nd == 5) numFaceVertices = PETSC_DETERMINE; else numFaceVertices = s.nd; } else { /* Data section */ if (numFaceVertices != PETSC_DETERMINE && s.nd != numFaceVertices) { SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mixed facets in Fluent files are not supported"); } if (numFaces < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No header section for facets in Fluent file"); if (numFaceVertices == PETSC_DETERMINE) numFaceVertices = s.nd; numFaceEntries = numFaceVertices + 2; if (!faces) {ierr = PetscMalloc1(numFaces*numFaceEntries, &faces);CHKERRQ(ierr);} if (!faceZoneIDs) {ierr = PetscMalloc1(numFaces, &faceZoneIDs);CHKERRQ(ierr);} ierr = PetscMemcpy(&(faces[(s.first-1)*numFaceEntries]), s.data, (s.last-s.first+1)*numFaceEntries*sizeof(PetscInt));CHKERRQ(ierr); /* Record the zoneID for each face set */ for (f = s.first -1; f < s.last; f++) faceZoneIDs[f] = s.zoneID; ierr = PetscFree(s.data);CHKERRQ(ierr); } } } while (s.index >= 0); } ierr = MPI_Bcast(&dim, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); if (dim < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Fluent file does not include dimension"); /* Allocate cell-vertex mesh */ ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); ierr = DMPlexSetChart(*dm, 0, numCells + numVertices);CHKERRQ(ierr); if (!rank) { if (numCells < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown number of cells in Fluent file"); /* If no cell type was given we assume simplices */ if (numCellVertices == PETSC_DETERMINE) numCellVertices = numFaceVertices + 1; for (c = 0; c < numCells; ++c) {ierr = DMPlexSetConeSize(*dm, c, numCellVertices);CHKERRQ(ierr);} } ierr = DMSetUp(*dm);CHKERRQ(ierr); if (!rank) { /* Derive cell-vertex list from face-vertex and face-cell maps */ ierr = PetscMalloc1(numCells*numCellVertices, &cellVertices);CHKERRQ(ierr); for (c = 0; c < numCells*numCellVertices; c++) cellVertices[c] = -1; for (f = 0; f < numFaces; f++) { PetscInt *cell; const PetscInt cl = faces[f*numFaceEntries + numFaceVertices]; const PetscInt cr = faces[f*numFaceEntries + numFaceVertices + 1]; const PetscInt *face = &(faces[f*numFaceEntries]); if (cl > 0) { cell = &(cellVertices[(cl-1) * numCellVertices]); for (v = 0; v < numFaceVertices; v++) { PetscBool found = PETSC_FALSE; for (c = 0; c < numCellVertices; c++) { if (cell[c] < 0) break; if (cell[c] == face[v]-1 + numCells) {found = PETSC_TRUE; break;} } if (!found) cell[c] = face[v]-1 + numCells; } } if (cr > 0) { cell = &(cellVertices[(cr-1) * numCellVertices]); for (v = 0; v < numFaceVertices; v++) { PetscBool found = PETSC_FALSE; for (c = 0; c < numCellVertices; c++) { if (cell[c] < 0) break; if (cell[c] == face[v]-1 + numCells) {found = PETSC_TRUE; break;} } if (!found) cell[c] = face[v]-1 + numCells; } } } for (c = 0; c < numCells; c++) { ierr = DMPlexSetCone(*dm, c, &(cellVertices[c*numCellVertices]));CHKERRQ(ierr); } } ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); ierr = DMPlexStratify(*dm);CHKERRQ(ierr); if (interpolate) { DM idm = NULL; ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } if (!rank) { PetscInt fi, joinSize, meetSize, *fverts, cells[2]; const PetscInt *join, *meet; ierr = PetscMalloc1(numFaceVertices, &fverts);CHKERRQ(ierr); /* Mark facets by finding the full join of all adjacent vertices */ for (f = 0; f < numFaces; f++) { const PetscInt cl = faces[f*numFaceEntries + numFaceVertices] - 1; const PetscInt cr = faces[f*numFaceEntries + numFaceVertices + 1] - 1; if (cl > 0 && cr > 0) { /* If we know both adjoining cells we can use a single-level meet */ cells[0] = cl; cells[1] = cr; ierr = DMPlexGetMeet(*dm, 2, cells, &meetSize, &meet);CHKERRQ(ierr); if (meetSize != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not determine Plex facet for Fluent face %d", f); ierr = DMPlexSetLabelValue(*dm, "Face Sets", meet[0], faceZoneIDs[f]);CHKERRQ(ierr); ierr = DMPlexRestoreMeet(*dm, numFaceVertices, fverts, &meetSize, &meet);CHKERRQ(ierr); } else { for (fi = 0; fi < numFaceVertices; fi++) fverts[fi] = faces[f*numFaceEntries + fi] + numCells - 1; ierr = DMPlexGetFullJoin(*dm, numFaceVertices, fverts, &joinSize, &join);CHKERRQ(ierr); if (joinSize != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not determine Plex facet for Fluent face %d", f); ierr = DMPlexSetLabelValue(*dm, "Face Sets", join[0], faceZoneIDs[f]);CHKERRQ(ierr); ierr = DMPlexRestoreJoin(*dm, numFaceVertices, fverts, &joinSize, &join);CHKERRQ(ierr); } } ierr = PetscFree(fverts);CHKERRQ(ierr); } /* Read coordinates */ ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); for (v = numCells; v < numCells+numVertices; ++v) { ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); } ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); ierr = VecCreate(comm, &coordinates);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); ierr = VecSetType(coordinates, VECSTANDARD);CHKERRQ(ierr); ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); if (!rank) { for (v = 0; v < numVertices; ++v) { for (d = 0; d < dim; ++d) { coords[v*dim+d] = coordsIn[v*dim+d]; } } } ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); ierr = VecDestroy(&coordinates);CHKERRQ(ierr); if (!rank) { ierr = PetscFree(cellVertices);CHKERRQ(ierr); ierr = PetscFree(faces);CHKERRQ(ierr); ierr = PetscFree(faceZoneIDs);CHKERRQ(ierr); ierr = PetscFree(coordsIn);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@ DMPlexCreateGmsh - Create a DMPlex mesh from a Gmsh file viewer Collective on comm Input Parameters: + comm - The MPI communicator . viewer - The Viewer associated with a Gmsh file - interpolate - Create faces and edges in the mesh Output Parameter: . dm - The DM object representing the mesh Note: http://www.geuz.org/gmsh/doc/texinfo/#MSH-ASCII-file-format and http://www.geuz.org/gmsh/doc/texinfo/#MSH-binary-file-format Level: beginner .keywords: mesh,Gmsh .seealso: DMPLEX, DMCreate() @*/ PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) { PetscViewerType vtype; GmshElement *gmsh_elem; PetscSection coordSection; Vec coordinates; PetscScalar *coords, *coordsIn = NULL; PetscInt dim = 0, coordSize, c, v, d, r, cell; int i, numVertices = 0, numCells = 0, trueNumCells = 0, numRegions = 0, snum; PetscMPIInt num_proc, rank; char line[PETSC_MAX_PATH_LEN]; PetscBool match, binary, bswap = PETSC_FALSE; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &num_proc);CHKERRQ(ierr); ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = PetscLogEventBegin(DMPLEX_CreateGmsh,*dm,0,0,0);CHKERRQ(ierr); ierr = PetscViewerGetType(viewer, &vtype);CHKERRQ(ierr); ierr = PetscStrcmp(vtype, PETSCVIEWERBINARY, &binary);CHKERRQ(ierr); if (!rank || binary) { PetscBool match; int fileType, dataSize; float version; /* Read header */ ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); ierr = PetscStrncmp(line, "$MeshFormat", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); ierr = PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING);CHKERRQ(ierr); snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize); if (snum != 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Gmsh file header: %s", line); if (version < 2.0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Gmsh file must be at least version 2.0"); if (dataSize != sizeof(double)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data size %d is not valid for a Gmsh file", dataSize); if (binary) { int checkInt; ierr = PetscViewerRead(viewer, &checkInt, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); if (checkInt != 1) { ierr = PetscByteSwap(&checkInt, PETSC_ENUM, 1);CHKERRQ(ierr); if (checkInt == 1) bswap = PETSC_TRUE; else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File type %d is not a valid Gmsh binary file", fileType); } } else if (fileType) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File type %d is not a valid Gmsh ASCII file", fileType); ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); ierr = PetscStrncmp(line, "$EndMeshFormat", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); /* OPTIONAL Read physical names */ ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); ierr = PetscStrncmp(line, "$PhysicalNames", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (match) { ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); snum = sscanf(line, "%d", &numRegions); if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); for (r = 0; r < numRegions; ++r) { PetscInt rdim, tag; ierr = PetscViewerRead(viewer, &rdim, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); ierr = PetscViewerRead(viewer, &tag, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); } ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); ierr = PetscStrncmp(line, "$EndPhysicalNames", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); /* Initial read for vertex section */ ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); } /* Read vertices */ ierr = PetscStrncmp(line, "$Nodes", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); snum = sscanf(line, "%d", &numVertices); if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); ierr = PetscMalloc1(numVertices*3, &coordsIn);CHKERRQ(ierr); if (binary) { size_t doubleSize, intSize; PetscInt elementSize; char *buffer; PetscScalar *baseptr; ierr = PetscDataTypeGetSize(PETSC_ENUM, &intSize);CHKERRQ(ierr); ierr = PetscDataTypeGetSize(PETSC_DOUBLE, &doubleSize);CHKERRQ(ierr); elementSize = (intSize + 3*doubleSize); ierr = PetscMalloc1(elementSize*numVertices, &buffer);CHKERRQ(ierr); ierr = PetscViewerRead(viewer, buffer, elementSize*numVertices, NULL, PETSC_CHAR);CHKERRQ(ierr); if (bswap) ierr = PetscByteSwap(buffer, PETSC_CHAR, elementSize*numVertices);CHKERRQ(ierr); for (v = 0; v < numVertices; ++v) { baseptr = ((PetscScalar*)(buffer+v*elementSize+intSize)); coordsIn[v*3+0] = baseptr[0]; coordsIn[v*3+1] = baseptr[1]; coordsIn[v*3+2] = baseptr[2]; } ierr = PetscFree(buffer);CHKERRQ(ierr); } else { for (v = 0; v < numVertices; ++v) { ierr = PetscViewerRead(viewer, &i, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); ierr = PetscViewerRead(viewer, &(coordsIn[v*3]), 3, NULL, PETSC_DOUBLE);CHKERRQ(ierr); if (i != (int)v+1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid node number %d should be %d", i, v+1); } } ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);; ierr = PetscStrncmp(line, "$EndNodes", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); /* Read cells */ ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);; ierr = PetscStrncmp(line, "$Elements", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);; snum = sscanf(line, "%d", &numCells); if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); } if (!rank || binary) { /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the file contents multiple times to figure out the true number of cells and facets in the given mesh. To make this more efficient we read the file contents only once and store them in memory, while determining the true number of cells. */ ierr = DMPlexCreateGmsh_ReadElement(viewer, numCells, binary, bswap, &gmsh_elem);CHKERRQ(ierr); for (trueNumCells=0, c = 0; c < numCells; ++c) { if (gmsh_elem[c].dim > dim) {dim = gmsh_elem[c].dim; trueNumCells = 0;} if (gmsh_elem[c].dim == dim) trueNumCells++; } ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);; ierr = PetscStrncmp(line, "$EndElements", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); } /* For binary we read on all ranks, but only build the plex on rank 0 */ if (binary && rank) {trueNumCells = 0; numVertices = 0;}; /* Allocate the cell-vertex mesh */ ierr = DMPlexSetChart(*dm, 0, trueNumCells+numVertices);CHKERRQ(ierr); if (!rank) { for (cell = 0, c = 0; c < numCells; ++c) { if (gmsh_elem[c].dim == dim) { ierr = DMPlexSetConeSize(*dm, cell, gmsh_elem[c].numNodes);CHKERRQ(ierr); cell++; } } } ierr = DMSetUp(*dm);CHKERRQ(ierr); /* Add cell-vertex connections */ if (!rank) { PetscInt pcone[8], corner; for (cell = 0, c = 0; c < numCells; ++c) { if (gmsh_elem[c].dim == dim) { for (corner = 0; corner < gmsh_elem[c].numNodes; ++corner) { pcone[corner] = gmsh_elem[c].nodes[corner] + trueNumCells-1; } if (dim == 3) { /* Tetrahedra are inverted */ if (gmsh_elem[c].numNodes == 4) { PetscInt tmp = pcone[0]; pcone[0] = pcone[1]; pcone[1] = tmp; } /* Hexahedra are inverted */ if (gmsh_elem[c].numNodes == 8) { PetscInt tmp = pcone[1]; pcone[1] = pcone[3]; pcone[3] = tmp; } } ierr = DMPlexSetCone(*dm, cell, pcone);CHKERRQ(ierr); cell++; } } } ierr = MPI_Bcast(&dim, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); ierr = DMPlexStratify(*dm);CHKERRQ(ierr); if (interpolate) { DM idm = NULL; ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } if (!rank) { /* Apply boundary IDs by finding the relevant facets with vertex joins */ PetscInt pcone[8], corner, vStart, vEnd; ierr = DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd);CHKERRQ(ierr); for (c = 0; c < numCells; ++c) { if (gmsh_elem[c].dim == dim-1) { PetscInt joinSize; const PetscInt *join; for (corner = 0; corner < gmsh_elem[c].numNodes; ++corner) { pcone[corner] = gmsh_elem[c].nodes[corner] + vStart - 1; } ierr = DMPlexGetFullJoin(*dm, gmsh_elem[c].numNodes, (const PetscInt *) pcone, &joinSize, &join);CHKERRQ(ierr); if (joinSize != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not determine Plex facet for element %d", gmsh_elem[c].id); ierr = DMSetLabelValue(*dm, "Face Sets", join[0], gmsh_elem[c].tags[0]);CHKERRQ(ierr); ierr = DMPlexRestoreJoin(*dm, gmsh_elem[c].numNodes, (const PetscInt *) pcone, &joinSize, &join);CHKERRQ(ierr); } } /* Create cell sets */ for (cell = 0, c = 0; c < numCells; ++c) { if (gmsh_elem[c].dim == dim) { if (gmsh_elem[c].numTags > 0) { ierr = DMSetLabelValue(*dm, "Cell Sets", cell, gmsh_elem[c].tags[0]);CHKERRQ(ierr); cell++; } } } } /* Read coordinates */ ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); ierr = PetscSectionSetChart(coordSection, trueNumCells, trueNumCells + numVertices);CHKERRQ(ierr); for (v = trueNumCells; v < trueNumCells+numVertices; ++v) { ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); } ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); ierr = VecSetBlockSize(coordinates, dim);CHKERRQ(ierr); ierr = VecSetType(coordinates, VECSTANDARD);CHKERRQ(ierr); ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); if (!rank) { for (v = 0; v < numVertices; ++v) { for (d = 0; d < dim; ++d) { coords[v*dim+d] = coordsIn[v*3+d]; } } } ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); ierr = PetscFree(coordsIn);CHKERRQ(ierr); ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); ierr = VecDestroy(&coordinates);CHKERRQ(ierr); /* Clean up intermediate storage */ if (!rank || binary) ierr = PetscFree(gmsh_elem);CHKERRQ(ierr); ierr = PetscLogEventEnd(DMPLEX_CreateGmsh,*dm,0,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) { PetscInt dim = user->dim; PetscBool cellHybrid = user->cellHybrid; PetscBool cellSimplex = user->cellSimplex; PetscMPIInt rank, size; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); switch (dim) { case 1: if (cellHybrid) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make hybrid meshes for dimension %d", dim); ierr = CreateSimplex_1D(comm, dm);CHKERRQ(ierr); break; case 2: if (cellSimplex) { if (cellHybrid) { ierr = CreateSimplexHybrid_2D(comm, user->testNum, dm);CHKERRQ(ierr); } else { ierr = CreateSimplex_2D(comm, dm);CHKERRQ(ierr); } } else { if (cellHybrid) { ierr = CreateTensorProductHybrid_2D(comm, user->testNum, dm);CHKERRQ(ierr); } else { ierr = CreateTensorProduct_2D(comm, user->testNum, dm);CHKERRQ(ierr); } } break; case 3: if (cellSimplex) { if (cellHybrid) { ierr = CreateSimplexHybrid_3D(comm, user->testNum, dm);CHKERRQ(ierr); } else { ierr = CreateSimplex_3D(comm, user->testNum, dm);CHKERRQ(ierr); } } else { if (cellHybrid) { ierr = CreateTensorProductHybrid_3D(comm, user->testNum, dm);CHKERRQ(ierr); } else { ierr = CreateTensorProduct_3D(comm, user->testNum, dm);CHKERRQ(ierr); } } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim); } if (user->testPartition && size > 1) { PetscPartitioner part; PetscInt *sizes = NULL; PetscInt *points = NULL; if (!rank) { if (dim == 2 && cellSimplex && !cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt triSizes_p2[2] = {1, 1}; PetscInt triPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, triSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, triPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for triangular mesh on 2 procs", user->testNum); } } else if (dim == 2 && cellSimplex && cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt triSizes_p2[2] = {1, 2}; PetscInt triPoints_p2[3] = {0, 1, 2}; ierr = PetscMalloc2(2, &sizes, 3, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, triSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, triPoints_p2, 3 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for triangular hybrid mesh on 2 procs", user->testNum); } } else if (dim == 2 && !cellSimplex && !cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt quadSizes_p2[2] = {1, 1}; PetscInt quadPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, quadSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, quadPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for quadrilateral mesh on 2 procs", user->testNum); } } else if (dim == 2 && !cellSimplex && cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt quadSizes_p2[2] = {1, 2}; PetscInt quadPoints_p2[3] = {0, 1, 2}; ierr = PetscMalloc2(2, &sizes, 3, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, quadSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, quadPoints_p2, 3 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for quadrilateral hybrid mesh on 2 procs", user->testNum); } } else if (dim == 3 && cellSimplex && !cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt tetSizes_p2[2] = {1, 1}; PetscInt tetPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, tetSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, tetPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} case 1: { PetscInt tetSizes_p2[2] = {1, 1}; PetscInt tetPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, tetSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, tetPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for tetrahedral mesh on 2 procs", user->testNum); } } else if (dim == 3 && cellSimplex && cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt tetSizes_p2[2] = {1, 2}; PetscInt tetPoints_p2[3] = {0, 1, 2}; ierr = PetscMalloc2(2, &sizes, 3, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, tetSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, tetPoints_p2, 3 * sizeof(PetscInt));CHKERRQ(ierr);break;} case 1: { PetscInt tetSizes_p2[2] = {3, 4}; PetscInt tetPoints_p2[7] = {0, 3, 5, 1, 2, 4, 6}; ierr = PetscMalloc2(2, &sizes, 7, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, tetSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, tetPoints_p2, 7 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for tetrahedral hybrid mesh on 2 procs", user->testNum); } } else if (dim == 3 && !cellSimplex && !cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt hexSizes_p2[2] = {1, 1}; PetscInt hexPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, hexSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, hexPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for hexahedral mesh on 2 procs", user->testNum); } } else if (dim == 3 && !cellSimplex && cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt hexSizes_p2[2] = {1, 1}; PetscInt hexPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, hexSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, hexPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} case 1: { PetscInt hexSizes_p2[2] = {5, 4}; PetscInt hexPoints_p2[9] = {3, 4, 5, 7, 8, 0, 1, 2, 6}; ierr = PetscMalloc2(2, &sizes, 9, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, hexSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, hexPoints_p2, 9 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for hexahedral hybrid mesh on 2 procs", user->testNum); } } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test partition"); } ierr = DMPlexGetPartitioner(*dm, &part);CHKERRQ(ierr); ierr = PetscPartitionerSetType(part, PETSCPARTITIONERSHELL);CHKERRQ(ierr); ierr = PetscPartitionerShellSetPartition(part, size, sizes, points);CHKERRQ(ierr); ierr = PetscFree2(sizes, points);CHKERRQ(ierr); } else { PetscPartitioner part; ierr = DMPlexGetPartitioner(*dm,&part);CHKERRQ(ierr); ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr); } { DM pdm = NULL; ierr = DMPlexDistribute(*dm, 0, NULL, &pdm);CHKERRQ(ierr); if (pdm) { ierr = DMViewFromOptions(pdm, NULL, "-dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = pdm; } } ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); if (user->simplex2tensor) { DM rdm = NULL; ierr = DMPlexSetRefinementUniform(*dm, PETSC_TRUE);CHKERRQ(ierr); ierr = DMPlexRefineSimplexToTensor(*dm, &rdm);CHKERRQ(ierr); if (rdm) { ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = rdm; } user->cellSimplex = PETSC_FALSE; } if (user->uninterpolate || user->reinterpolate) { DM udm = NULL; ierr = DMPlexUninterpolate(*dm, &udm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, udm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = udm; } if (user->reinterpolate) { DM idm = NULL; ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } ierr = PetscObjectSetName((PetscObject) *dm, "Hybrid Mesh");CHKERRQ(ierr); ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject) *dm, "hyb_");CHKERRQ(ierr); ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ DMPlexCreateExodus - Create a DMPlex mesh from an ExodusII file ID. Collective on comm Input Parameters: + comm - The MPI communicator . exoid - The ExodusII id associated with a exodus file and obtained using ex_open - interpolate - Create faces and edges in the mesh Output Parameter: . dm - The DM object representing the mesh Level: beginner .keywords: mesh,ExodusII .seealso: DMPLEX, DMCreate() @*/ PetscErrorCode DMPlexCreateExodus(MPI_Comm comm, PetscInt exoid, PetscBool interpolate, DM *dm) { #if defined(PETSC_HAVE_EXODUSII) PetscMPIInt num_proc, rank; PetscSection coordSection; Vec coordinates; PetscScalar *coords; PetscInt coordSize, v; PetscErrorCode ierr; /* Read from ex_get_init() */ char title[PETSC_MAX_PATH_LEN+1]; int dim = 0, numVertices = 0, numCells = 0; int num_cs = 0, num_vs = 0, num_fs = 0; #endif PetscFunctionBegin; #if defined(PETSC_HAVE_EXODUSII) ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &num_proc);CHKERRQ(ierr); ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); /* Open EXODUS II file and read basic informations on rank 0, then broadcast to all processors */ if (!rank) { ierr = PetscMemzero(title,(PETSC_MAX_PATH_LEN+1)*sizeof(char));CHKERRQ(ierr); ierr = ex_get_init(exoid, title, &dim, &numVertices, &numCells, &num_cs, &num_vs, &num_fs); if (ierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"ExodusII ex_get_init() failed with error code %D\n",ierr); if (!num_cs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Exodus file does not contain any cell set\n"); } ierr = MPI_Bcast(title, PETSC_MAX_PATH_LEN+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); ierr = MPI_Bcast(&dim, 1, MPI_INT, 0, comm);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) *dm, title);CHKERRQ(ierr); ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr); /* Read cell sets information */ if (!rank) { PetscInt *cone; int c, cs, c_loc, v, v_loc; /* Read from ex_get_elem_blk_ids() */ int *cs_id; /* Read from ex_get_elem_block() */ char buffer[PETSC_MAX_PATH_LEN+1]; int num_cell_in_set, num_vertex_per_cell, num_attr; /* Read from ex_get_elem_conn() */ int *cs_connect; /* Get cell sets IDs */ ierr = PetscMalloc1(num_cs, &cs_id);CHKERRQ(ierr); ierr = ex_get_elem_blk_ids(exoid, cs_id);CHKERRQ(ierr); /* Read the cell set connectivity table and build mesh topology EXO standard requires that cells in cell sets be numbered sequentially and be pairwise disjoint. */ /* First set sizes */ for (cs = 0, c = 0; cs < num_cs; cs++) { ierr = ex_get_elem_block(exoid, cs_id[cs], buffer, &num_cell_in_set, &num_vertex_per_cell, &num_attr);CHKERRQ(ierr); for (c_loc = 0; c_loc < num_cell_in_set; ++c_loc, ++c) { ierr = DMPlexSetConeSize(*dm, c, num_vertex_per_cell);CHKERRQ(ierr); } } ierr = DMSetUp(*dm);CHKERRQ(ierr); for (cs = 0, c = 0; cs < num_cs; cs++) { ierr = ex_get_elem_block(exoid, cs_id[cs], buffer, &num_cell_in_set, &num_vertex_per_cell, &num_attr);CHKERRQ(ierr); ierr = PetscMalloc2(num_vertex_per_cell*num_cell_in_set,&cs_connect,num_vertex_per_cell,&cone);CHKERRQ(ierr); ierr = ex_get_elem_conn(exoid, cs_id[cs], cs_connect);CHKERRQ(ierr); /* EXO uses Fortran-based indexing, sieve uses C-style and numbers cell first then vertices. */ for (c_loc = 0, v = 0; c_loc < num_cell_in_set; ++c_loc, ++c) { for (v_loc = 0; v_loc < num_vertex_per_cell; ++v_loc, ++v) { cone[v_loc] = cs_connect[v]+numCells-1; } if (dim == 3) { /* Tetrahedra are inverted */ if (num_vertex_per_cell == 4) { PetscInt tmp = cone[0]; cone[0] = cone[1]; cone[1] = tmp; } /* Hexahedra are inverted */ if (num_vertex_per_cell == 8) { PetscInt tmp = cone[1]; cone[1] = cone[3]; cone[3] = tmp; } } ierr = DMPlexSetCone(*dm, c, cone);CHKERRQ(ierr); ierr = DMSetLabelValue(*dm, "Cell Sets", c, cs_id[cs]);CHKERRQ(ierr); } ierr = PetscFree2(cs_connect,cone);CHKERRQ(ierr); } ierr = PetscFree(cs_id);CHKERRQ(ierr); } ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); ierr = DMPlexStratify(*dm);CHKERRQ(ierr); if (interpolate) { DM idm = NULL; ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); /* Maintain Cell Sets label */ { DMLabel label; ierr = DMRemoveLabel(*dm, "Cell Sets", &label);CHKERRQ(ierr); if (label) {ierr = DMAddLabel(idm, label);CHKERRQ(ierr);} } ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } /* Create vertex set label */ if (!rank && (num_vs > 0)) { int vs, v; /* Read from ex_get_node_set_ids() */ int *vs_id; /* Read from ex_get_node_set_param() */ int num_vertex_in_set, num_attr; /* Read from ex_get_node_set() */ int *vs_vertex_list; /* Get vertex set ids */ ierr = PetscMalloc1(num_vs, &vs_id);CHKERRQ(ierr); ierr = ex_get_node_set_ids(exoid, vs_id);CHKERRQ(ierr); for (vs = 0; vs < num_vs; ++vs) { ierr = ex_get_node_set_param(exoid, vs_id[vs], &num_vertex_in_set, &num_attr);CHKERRQ(ierr); ierr = PetscMalloc1(num_vertex_in_set, &vs_vertex_list);CHKERRQ(ierr); ierr = ex_get_node_set(exoid, vs_id[vs], vs_vertex_list);CHKERRQ(ierr); for (v = 0; v < num_vertex_in_set; ++v) { ierr = DMSetLabelValue(*dm, "Vertex Sets", vs_vertex_list[v]+numCells-1, vs_id[vs]);CHKERRQ(ierr); } ierr = PetscFree(vs_vertex_list);CHKERRQ(ierr); } ierr = PetscFree(vs_id);CHKERRQ(ierr); } /* Read coordinates */ ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); for (v = numCells; v < numCells+numVertices; ++v) { ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); } ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); ierr = VecSetBlockSize(coordinates, dim);CHKERRQ(ierr); ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); if (!rank) { float *x, *y, *z; ierr = PetscMalloc3(numVertices,&x,numVertices,&y,numVertices,&z);CHKERRQ(ierr); ierr = ex_get_coord(exoid, x, y, z);CHKERRQ(ierr); if (dim > 0) { for (v = 0; v < numVertices; ++v) coords[v*dim+0] = x[v]; } if (dim > 1) { for (v = 0; v < numVertices; ++v) coords[v*dim+1] = y[v]; } if (dim > 2) { for (v = 0; v < numVertices; ++v) coords[v*dim+2] = z[v]; } ierr = PetscFree3(x,y,z);CHKERRQ(ierr); } ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); ierr = VecDestroy(&coordinates);CHKERRQ(ierr); /* Create side set label */ if (!rank && interpolate && (num_fs > 0)) { int fs, f, voff; /* Read from ex_get_side_set_ids() */ int *fs_id; /* Read from ex_get_side_set_param() */ int num_side_in_set, num_dist_fact_in_set; /* Read from ex_get_side_set_node_list() */ int *fs_vertex_count_list, *fs_vertex_list; /* Get side set ids */ ierr = PetscMalloc1(num_fs, &fs_id);CHKERRQ(ierr); ierr = ex_get_side_set_ids(exoid, fs_id);CHKERRQ(ierr); for (fs = 0; fs < num_fs; ++fs) { ierr = ex_get_side_set_param(exoid, fs_id[fs], &num_side_in_set, &num_dist_fact_in_set);CHKERRQ(ierr); ierr = PetscMalloc2(num_side_in_set,&fs_vertex_count_list,num_side_in_set*4,&fs_vertex_list);CHKERRQ(ierr); ierr = ex_get_side_set_node_list(exoid, fs_id[fs], fs_vertex_count_list, fs_vertex_list);CHKERRQ(ierr); for (f = 0, voff = 0; f < num_side_in_set; ++f) { const PetscInt *faces = NULL; PetscInt faceSize = fs_vertex_count_list[f], numFaces; PetscInt faceVertices[4], v; if (faceSize > 4) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "ExodusII side cannot have %d > 4 vertices", faceSize); for (v = 0; v < faceSize; ++v, ++voff) { faceVertices[v] = fs_vertex_list[voff]+numCells-1; } ierr = DMPlexGetFullJoin(*dm, faceSize, faceVertices, &numFaces, &faces);CHKERRQ(ierr); if (numFaces != 1) SETERRQ3(comm, PETSC_ERR_ARG_WRONG, "Invalid ExodusII side %d in set %d maps to %d faces", f, fs, numFaces); ierr = DMSetLabelValue(*dm, "Face Sets", faces[0], fs_id[fs]);CHKERRQ(ierr); ierr = DMPlexRestoreJoin(*dm, faceSize, faceVertices, &numFaces, &faces);CHKERRQ(ierr); } ierr = PetscFree2(fs_vertex_count_list,fs_vertex_list);CHKERRQ(ierr); } ierr = PetscFree(fs_id);CHKERRQ(ierr); } #else SETERRQ(comm, PETSC_ERR_SUP, "This method requires ExodusII support. Reconfigure using --download-exodusii"); #endif PetscFunctionReturn(0); }
/*@ DMPlexCreateGmsh - Create a DMPlex mesh from a Gmsh file. Collective on comm Input Parameters: + comm - The MPI communicator . viewer - The Viewer associated with a Gmsh file - interpolate - Create faces and edges in the mesh Output Parameter: . dm - The DM object representing the mesh Note: http://www.geuz.org/gmsh/doc/texinfo/#MSH-ASCII-file-format Level: beginner .keywords: mesh,Gmsh .seealso: DMPLEX, DMCreate() @*/ PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) { FILE *fd; PetscSection coordSection; Vec coordinates; PetscScalar *coords, *coordsIn = NULL; PetscInt dim = 0, coordSize, c, v, d; int numVertices = 0, numCells = 0, snum; long fpos = 0; PetscMPIInt num_proc, rank; char line[PETSC_MAX_PATH_LEN]; PetscBool match; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &num_proc);CHKERRQ(ierr); ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); if (!rank) { PetscBool match; int fileType, dataSize; ierr = PetscViewerASCIIGetPointer(viewer, &fd);CHKERRQ(ierr); /* Read header */ fgets(line, PETSC_MAX_PATH_LEN, fd); ierr = PetscStrncmp(line, "$MeshFormat\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); snum = fscanf(fd, "2.2 %d %d\n", &fileType, &dataSize);CHKERRQ(snum != 2); if (fileType) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File type %d is not a valid Gmsh ASCII file", fileType); if (dataSize != sizeof(double)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data size %d is not valid for a Gmsh file", dataSize); fgets(line, PETSC_MAX_PATH_LEN, fd); ierr = PetscStrncmp(line, "$EndMeshFormat\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); /* Read vertices */ fgets(line, PETSC_MAX_PATH_LEN, fd); ierr = PetscStrncmp(line, "$Nodes\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); snum = fscanf(fd, "%d\n", &numVertices);CHKERRQ(snum != 1); ierr = PetscMalloc(numVertices*3 * sizeof(PetscScalar), &coordsIn);CHKERRQ(ierr); for (v = 0; v < numVertices; ++v) { double x, y, z; int i; snum = fscanf(fd, "%d %lg %lg %lg\n", &i, &x, &y, &z);CHKERRQ(snum != 4); coordsIn[v*3+0] = x; coordsIn[v*3+1] = y; coordsIn[v*3+2] = z; if (i != v+1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid node number %d should be %d", i, v+1); } fgets(line, PETSC_MAX_PATH_LEN, fd); ierr = PetscStrncmp(line, "$EndNodes\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); /* Read cells */ fgets(line, PETSC_MAX_PATH_LEN, fd); ierr = PetscStrncmp(line, "$Elements\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); snum = fscanf(fd, "%d\n", &numCells);CHKERRQ(snum != 1); } ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr); if (!rank) { fpos = ftell(fd); for (c = 0; c < numCells; ++c) { PetscInt numCorners, t; int cone[8], i, cellType, numTags, tag; snum = fscanf(fd, "%d %d %d", &i, &cellType, &numTags);CHKERRQ(snum != 3); if (numTags) for (t = 0; t < numTags; ++t) {snum = fscanf(fd, "%d", &tag);CHKERRQ(snum != 1);} switch (cellType) { case 1: /* 2-node line */ dim = 1; numCorners = 2; snum = fscanf(fd, "%d %d\n", &cone[0], &cone[1]);CHKERRQ(snum != numCorners); break; case 2: /* 3-node triangle */ dim = 2; numCorners = 3; snum = fscanf(fd, "%d %d %d\n", &cone[0], &cone[1], &cone[2]);CHKERRQ(snum != numCorners); break; case 3: /* 4-node quadrangle */ dim = 2; numCorners = 4; snum = fscanf(fd, "%d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3]);CHKERRQ(snum != numCorners); break; case 4: /* 4-node tetrahedron */ dim = 3; numCorners = 4; snum = fscanf(fd, "%d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3]);CHKERRQ(snum != numCorners); break; case 5: /* 8-node hexahedron */ dim = 3; numCorners = 8; snum = fscanf(fd, "%d %d %d %d %d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3], &cone[4], &cone[5], &cone[6], &cone[7]);CHKERRQ(snum != numCorners); break; default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported Gmsh element type %d", cellType); } ierr = DMPlexSetConeSize(*dm, c, numCorners);CHKERRQ(ierr); if (i != c+1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell number %d should be %d", i, c+1); } } ierr = DMSetUp(*dm);CHKERRQ(ierr); if (!rank) { ierr = fseek(fd, fpos, SEEK_SET);CHKERRQ(ierr); for (c = 0; c < numCells; ++c) { PetscInt pcone[8], numCorners, corner, t; int cone[8], i, cellType, numTags, tag; snum = fscanf(fd, "%d %d %d", &i, &cellType, &numTags);CHKERRQ(snum != 3); if (numTags) for (t = 0; t < numTags; ++t) {snum = fscanf(fd, "%d", &tag);CHKERRQ(snum != 1);} switch (cellType) { case 1: /* 2-node line */ dim = 1; numCorners = 2; snum = fscanf(fd, "%d %d\n", &cone[0], &cone[1]);CHKERRQ(snum != numCorners); break; case 2: /* 3-node triangle */ dim = 2; numCorners = 3; snum = fscanf(fd, "%d %d %d\n", &cone[0], &cone[1], &cone[2]);CHKERRQ(snum != numCorners); break; case 3: /* 4-node quadrangle */ dim = 2; numCorners = 4; snum = fscanf(fd, "%d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3]);CHKERRQ(snum != numCorners); break; case 4: /* 4-node tetrahedron */ dim = 3; numCorners = 4; snum = fscanf(fd, "%d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3]);CHKERRQ(snum != numCorners); ierr = DMPlexInvertCell(dim, numCorners, cone);CHKERRQ(ierr); break; case 5: /* 8-node hexahedron */ dim = 3; numCorners = 8; snum = fscanf(fd, "%d %d %d %d %d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3], &cone[4], &cone[5], &cone[6], &cone[7]);CHKERRQ(snum != numCorners); ierr = DMPlexInvertCell(dim, numCorners, cone);CHKERRQ(ierr); break; default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported Gmsh element type %d", cellType); } for (corner = 0; corner < numCorners; ++corner) pcone[corner] = cone[corner] + numCells-1; ierr = DMPlexSetCone(*dm, c, pcone);CHKERRQ(ierr); if (i != c+1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell number %d should be %d", i, c+1); } fgets(line, PETSC_MAX_PATH_LEN, fd); ierr = PetscStrncmp(line, "$EndElements\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); } ierr = MPI_Bcast(&dim, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); ierr = DMPlexStratify(*dm);CHKERRQ(ierr); if (interpolate) { DM idm; ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } /* Read coordinates */ ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); for (v = numCells; v < numCells+numVertices; ++v) { ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); } ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); ierr = VecCreate(comm, &coordinates);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); ierr = VecSetType(coordinates, VECSTANDARD);CHKERRQ(ierr); ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); if (!rank) { for (v = 0; v < numVertices; ++v) { for (d = 0; d < dim; ++d) { coords[v*dim+d] = coordsIn[v*3+d]; } } } ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); ierr = PetscFree(coordsIn);CHKERRQ(ierr); ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); ierr = VecDestroy(&coordinates);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* Two triangles separated by a zero-volume cell with 4 vertices/2 edges 5--16--8 / | | \ 11 | | 12 / | | \ 3 0 10 2 14 1 6 \ | | / 9 | | 13 \ | | / 4--15--7 */ PetscErrorCode CreateSimplexHybrid_2D(MPI_Comm comm, PetscInt testNum, DM *dm) { DM idm = NULL, hdm = NULL; DMLabel faultLabel, hybridLabel; PetscInt p; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); if (!rank) { switch (testNum) { case 0: { PetscInt numPoints[2] = {4, 2}; PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[8] = {-1.0, -0.5, 0.0, -0.5, 0.0, 0.5, 1.0, 0.5}; PetscInt faultPoints[2] = {3, 4}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 2; ++p) {ierr = DMSetLabelValue(*dm, "fault", faultPoints[p], 1);CHKERRQ(ierr);} } break; case 1: { PetscInt numPoints[2] = {5, 4}; PetscInt coneSize[9] = {3, 3, 3, 3, 0, 0, 0, 0, 0}; PetscInt cones[12] = {4, 5, 6, 6, 7, 4, 6, 5, 8, 6, 8, 7}; PetscInt coneOrientations[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[10] = {-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0}; PetscInt faultPoints[3] = {5, 6, 7}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "fault", faultPoints[p], 1);CHKERRQ(ierr);} } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); } ierr = DMPlexCheckSymmetry(*dm);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMPlexCheckSymmetry(idm);CHKERRQ(ierr); ierr = DMGetLabel(*dm, "fault", &faultLabel);CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, faultLabel, &hybridLabel, &hdm);CHKERRQ(ierr); ierr = DMLabelDestroy(&hybridLabel);CHKERRQ(ierr); ierr = DMDestroy(&idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = hdm; } else { PetscInt numPoints[2] = {0, 0}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, NULL, NULL, &hdm);CHKERRQ(ierr); ierr = DMDestroy(&idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = hdm; } PetscFunctionReturn(0); }