xref: /petsc/src/dm/impls/plex/plexgmsh.c (revision d1a54cef007e275f71fd9bf0b5cd82abffef1976)
1331830f3SMatthew G. Knepley #define PETSCDM_DLL
2331830f3SMatthew G. Knepley #include <petsc-private/dmpleximpl.h>    /*I   "petscdmplex.h"   I*/
3331830f3SMatthew G. Knepley 
4331830f3SMatthew G. Knepley #undef __FUNCT__
5331830f3SMatthew G. Knepley #define __FUNCT__ "DMPlexCreateGmsh"
6331830f3SMatthew G. Knepley /*@
7331830f3SMatthew G. Knepley   DMPlexCreateGmsh - Create a DMPlex mesh from a Gmsh file.
8331830f3SMatthew G. Knepley 
9331830f3SMatthew G. Knepley   Collective on comm
10331830f3SMatthew G. Knepley 
11331830f3SMatthew G. Knepley   Input Parameters:
12331830f3SMatthew G. Knepley + comm  - The MPI communicator
13331830f3SMatthew G. Knepley . viewer - The Viewer associated with a Gmsh file
14331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
15331830f3SMatthew G. Knepley 
16331830f3SMatthew G. Knepley   Output Parameter:
17331830f3SMatthew G. Knepley . dm  - The DM object representing the mesh
18331830f3SMatthew G. Knepley 
19331830f3SMatthew G. Knepley   Note: http://www.geuz.org/gmsh/doc/texinfo/#MSH-ASCII-file-format
20331830f3SMatthew G. Knepley 
21331830f3SMatthew G. Knepley   Level: beginner
22331830f3SMatthew G. Knepley 
23331830f3SMatthew G. Knepley .keywords: mesh,Gmsh
24331830f3SMatthew G. Knepley .seealso: DMPLEX, DMCreate()
25331830f3SMatthew G. Knepley @*/
26331830f3SMatthew G. Knepley PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm)
27331830f3SMatthew G. Knepley {
28331830f3SMatthew G. Knepley   FILE          *fd;
29331830f3SMatthew G. Knepley   PetscSection   coordSection;
30331830f3SMatthew G. Knepley   Vec            coordinates;
31331830f3SMatthew G. Knepley   PetscScalar   *coords, *coordsIn = NULL;
3216ad7e67SMichael Lange   PetscInt       dim = 0, tdim = 0, coordSize, c, v, d, cellNum, numCorners, numTags;
3316ad7e67SMichael Lange   int            numVertices = 0, numCells = 0, trueNumCells = 0, numFacets = 0, cone[8], tags[2], snum;
34261b4668SMatthew G. Knepley   long           fpos = 0;
35331830f3SMatthew G. Knepley   PetscMPIInt    num_proc, rank;
36331830f3SMatthew G. Knepley   char           line[PETSC_MAX_PATH_LEN];
37331830f3SMatthew G. Knepley   PetscBool      match;
38331830f3SMatthew G. Knepley   PetscErrorCode ierr;
39331830f3SMatthew G. Knepley 
40331830f3SMatthew G. Knepley   PetscFunctionBegin;
41331830f3SMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
42331830f3SMatthew G. Knepley   ierr = MPI_Comm_size(comm, &num_proc);CHKERRQ(ierr);
43331830f3SMatthew G. Knepley   ierr = DMCreate(comm, dm);CHKERRQ(ierr);
44331830f3SMatthew G. Knepley   ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr);
45331830f3SMatthew G. Knepley   if (!rank) {
46331830f3SMatthew G. Knepley     PetscBool match;
47331830f3SMatthew G. Knepley     int       fileType, dataSize;
48331830f3SMatthew G. Knepley 
49331830f3SMatthew G. Knepley     ierr = PetscViewerASCIIGetPointer(viewer, &fd);CHKERRQ(ierr);
50331830f3SMatthew G. Knepley     /* Read header */
51331830f3SMatthew G. Knepley     fgets(line, PETSC_MAX_PATH_LEN, fd);
52331830f3SMatthew G. Knepley     ierr = PetscStrncmp(line, "$MeshFormat\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
53331830f3SMatthew G. Knepley     if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file");
54331830f3SMatthew G. Knepley     snum = fscanf(fd, "2.2 %d %d\n", &fileType, &dataSize);CHKERRQ(snum != 2);
55331830f3SMatthew G. Knepley     if (fileType) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File type %d is not a valid Gmsh ASCII file", fileType);
56331830f3SMatthew G. Knepley     if (dataSize != sizeof(double)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data size %d is not valid for a Gmsh file", dataSize);
57331830f3SMatthew G. Knepley     fgets(line, PETSC_MAX_PATH_LEN, fd);
58331830f3SMatthew G. Knepley     ierr = PetscStrncmp(line, "$EndMeshFormat\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
59331830f3SMatthew G. Knepley     if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file");
60331830f3SMatthew G. Knepley     /* Read vertices */
61331830f3SMatthew G. Knepley     fgets(line, PETSC_MAX_PATH_LEN, fd);
62331830f3SMatthew G. Knepley     ierr = PetscStrncmp(line, "$Nodes\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
63331830f3SMatthew G. Knepley     if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file");
64331830f3SMatthew G. Knepley     snum = fscanf(fd, "%d\n", &numVertices);CHKERRQ(snum != 1);
65331830f3SMatthew G. Knepley     ierr = PetscMalloc(numVertices*3 * sizeof(PetscScalar), &coordsIn);CHKERRQ(ierr);
66331830f3SMatthew G. Knepley     for (v = 0; v < numVertices; ++v) {
67331830f3SMatthew G. Knepley       double x, y, z;
68331830f3SMatthew G. Knepley       int    i;
69331830f3SMatthew G. Knepley 
70331830f3SMatthew G. Knepley       snum = fscanf(fd, "%d %lg %lg %lg\n", &i, &x, &y, &z);CHKERRQ(snum != 4);
71331830f3SMatthew G. Knepley       coordsIn[v*3+0] = x; coordsIn[v*3+1] = y; coordsIn[v*3+2] = z;
72331830f3SMatthew G. Knepley       if (i != v+1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid node number %d should be %d", i, v+1);
73331830f3SMatthew G. Knepley     }
74331830f3SMatthew G. Knepley     fgets(line, PETSC_MAX_PATH_LEN, fd);
75331830f3SMatthew G. Knepley     ierr = PetscStrncmp(line, "$EndNodes\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
76331830f3SMatthew G. Knepley     if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file");
77331830f3SMatthew G. Knepley     /* Read cells */
78331830f3SMatthew G. Knepley     fgets(line, PETSC_MAX_PATH_LEN, fd);
79331830f3SMatthew G. Knepley     ierr = PetscStrncmp(line, "$Elements\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
80331830f3SMatthew G. Knepley     if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file");
81331830f3SMatthew G. Knepley     snum = fscanf(fd, "%d\n", &numCells);CHKERRQ(snum != 1);
82331830f3SMatthew G. Knepley   }
83db397164SMichael Lange 
84331830f3SMatthew G. Knepley   if (!rank) {
85331830f3SMatthew G. Knepley     fpos = ftell(fd);
86db397164SMichael Lange     /* The Gmsh format disguises facets as elements, so we have to run through all "element" entries
87db397164SMichael Lange        to get the correct numCells and decide the topological dimension of the mesh */
88db397164SMichael Lange     trueNumCells = 0;
89db397164SMichael Lange     for (c = 0; c < numCells; ++c) {
9016ad7e67SMichael Lange       ierr = DMPlexCreateGmsh_ReadElement(fd, &dim, &cellNum, &numCorners, cone, &numTags, tags);CHKERRQ(ierr);
91db397164SMichael Lange       if (dim > tdim) {
92db397164SMichael Lange         tdim = dim;
93db397164SMichael Lange         trueNumCells = 0;
94db397164SMichael Lange       }
95db397164SMichael Lange       trueNumCells++;
96db397164SMichael Lange     }
97db397164SMichael Lange   }
98db397164SMichael Lange   ierr = DMPlexSetChart(*dm, 0, trueNumCells+numVertices);CHKERRQ(ierr);
99db397164SMichael Lange   numFacets = numCells - trueNumCells;
100db397164SMichael Lange   if (!rank) {
101db397164SMichael Lange     ierr = fseek(fd, fpos, SEEK_SET);CHKERRQ(ierr);
102331830f3SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
10316ad7e67SMichael Lange       ierr = DMPlexCreateGmsh_ReadElement(fd, &dim, &cellNum, &numCorners, cone, &numTags, tags);CHKERRQ(ierr);
104db397164SMichael Lange       if (dim == tdim) {
105db397164SMichael Lange         ierr = DMPlexSetConeSize(*dm, c-numFacets, numCorners);CHKERRQ(ierr);
106db397164SMichael Lange       }
10730412aabSMichael Lange       if (cellNum != c+1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell number %d should be %d", cellNum, c+1);
108331830f3SMatthew G. Knepley     }
109331830f3SMatthew G. Knepley   }
110331830f3SMatthew G. Knepley   ierr = DMSetUp(*dm);CHKERRQ(ierr);
111331830f3SMatthew G. Knepley   if (!rank) {
11230412aabSMichael Lange     PetscInt pcone[8], corner;
113*d1a54cefSMatthew G. Knepley 
114*d1a54cefSMatthew G. Knepley     ierr = fseek(fd, fpos, SEEK_SET);CHKERRQ(ierr);
115331830f3SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
11616ad7e67SMichael Lange       ierr = DMPlexCreateGmsh_ReadElement(fd, &dim, &cellNum, &numCorners, cone, &numTags, tags);CHKERRQ(ierr);
117db397164SMichael Lange       if (dim == tdim) {
118db397164SMichael Lange         for (corner = 0; corner < numCorners; ++corner) pcone[corner] = cone[corner] + trueNumCells-1;
119db397164SMichael Lange         ierr = DMPlexSetCone(*dm, c-numFacets, pcone);CHKERRQ(ierr);
120db397164SMichael Lange       }
12130412aabSMichael Lange       if (cellNum != c+1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell number %d should be %d", cellNum, c+1);
122331830f3SMatthew G. Knepley     }
123331830f3SMatthew G. Knepley     fgets(line, PETSC_MAX_PATH_LEN, fd);
124331830f3SMatthew G. Knepley     ierr = PetscStrncmp(line, "$EndElements\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
125331830f3SMatthew G. Knepley     if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file");
126331830f3SMatthew G. Knepley   }
1276228fc9fSJed Brown   ierr = MPI_Bcast(&dim, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
128331830f3SMatthew G. Knepley   ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr);
129331830f3SMatthew G. Knepley   ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr);
130331830f3SMatthew G. Knepley   ierr = DMPlexStratify(*dm);CHKERRQ(ierr);
131331830f3SMatthew G. Knepley   if (interpolate) {
132331830f3SMatthew G. Knepley     DM idm;
133331830f3SMatthew G. Knepley 
134331830f3SMatthew G. Knepley     ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr);
135331830f3SMatthew G. Knepley     ierr = DMDestroy(dm);CHKERRQ(ierr);
136331830f3SMatthew G. Knepley     *dm  = idm;
137331830f3SMatthew G. Knepley   }
13816ad7e67SMichael Lange 
13916ad7e67SMichael Lange   if (!rank) {
14016ad7e67SMichael Lange     /* Apply boundary IDs by finding the relevant facets with vertex joins */
14116ad7e67SMichael Lange     PetscInt pcone[8], corner, vStart, vEnd;
142*d1a54cefSMatthew G. Knepley 
143*d1a54cefSMatthew G. Knepley     ierr = fseek(fd, fpos, SEEK_SET);CHKERRQ(ierr);
14416ad7e67SMichael Lange     ierr = DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
14516ad7e67SMichael Lange     for (c = 0; c < numCells; ++c) {
14616ad7e67SMichael Lange       ierr = DMPlexCreateGmsh_ReadElement(fd, &dim, &cellNum, &numCorners, cone, &numTags, tags);CHKERRQ(ierr);
14716ad7e67SMichael Lange       if (dim == tdim-1) {
14816ad7e67SMichael Lange         PetscInt joinSize;
14916ad7e67SMichael Lange         const PetscInt *join;
15016ad7e67SMichael Lange         for (corner = 0; corner < numCorners; ++corner) pcone[corner] = cone[corner] + vStart - 1;
15116ad7e67SMichael Lange         ierr = DMPlexGetFullJoin(*dm, numCorners, pcone, &joinSize, &join);CHKERRQ(ierr);
15216ad7e67SMichael Lange         if (joinSize != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not determine Plex facet for element %d", cellNum);
15316ad7e67SMichael Lange         ierr = DMPlexSetLabelValue(*dm, "Face Sets", join[0], tags[0]);CHKERRQ(ierr);
15416ad7e67SMichael Lange         ierr = DMPlexRestoreJoin(*dm, numCorners, pcone, &joinSize, &join);CHKERRQ(ierr);
15516ad7e67SMichael Lange       }
15616ad7e67SMichael Lange       if (cellNum != c+1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell number %d should be %d", cellNum, c+1);
15716ad7e67SMichael Lange     }
15816ad7e67SMichael Lange     fgets(line, PETSC_MAX_PATH_LEN, fd);
15916ad7e67SMichael Lange     ierr = PetscStrncmp(line, "$EndElements\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
16016ad7e67SMichael Lange     if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file");
16116ad7e67SMichael Lange   }
16216ad7e67SMichael Lange 
163331830f3SMatthew G. Knepley   /* Read coordinates */
164979c4b60SMatthew G. Knepley   ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr);
165331830f3SMatthew G. Knepley   ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr);
166331830f3SMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr);
167331830f3SMatthew G. Knepley   ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr);
168331830f3SMatthew G. Knepley   for (v = numCells; v < numCells+numVertices; ++v) {
169331830f3SMatthew G. Knepley     ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr);
170331830f3SMatthew G. Knepley     ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr);
171331830f3SMatthew G. Knepley   }
172331830f3SMatthew G. Knepley   ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr);
173331830f3SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr);
174331830f3SMatthew G. Knepley   ierr = VecCreate(comm, &coordinates);CHKERRQ(ierr);
175331830f3SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr);
176331830f3SMatthew G. Knepley   ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr);
177331830f3SMatthew G. Knepley   ierr = VecSetType(coordinates, VECSTANDARD);CHKERRQ(ierr);
178331830f3SMatthew G. Knepley   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
179331830f3SMatthew G. Knepley   if (!rank) {
180331830f3SMatthew G. Knepley     for (v = 0; v < numVertices; ++v) {
181331830f3SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
182331830f3SMatthew G. Knepley         coords[v*dim+d] = coordsIn[v*3+d];
183331830f3SMatthew G. Knepley       }
184331830f3SMatthew G. Knepley     }
185331830f3SMatthew G. Knepley   }
186331830f3SMatthew G. Knepley   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
187331830f3SMatthew G. Knepley   ierr = PetscFree(coordsIn);CHKERRQ(ierr);
188331830f3SMatthew G. Knepley   ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr);
189331830f3SMatthew G. Knepley   ierr = VecDestroy(&coordinates);CHKERRQ(ierr);
190331830f3SMatthew G. Knepley   PetscFunctionReturn(0);
191331830f3SMatthew G. Knepley }
192db397164SMichael Lange 
193db397164SMichael Lange #undef __FUNCT__
19430412aabSMichael Lange #define __FUNCT__ "DMPlexCreateGmsh_ReadElement"
19516ad7e67SMichael Lange PetscErrorCode DMPlexCreateGmsh_ReadElement(FILE *fd, PetscInt *dim, PetscInt *cellNum, PetscInt *numCorners, int cone[], PetscInt *numTags, int tags[])
196db397164SMichael Lange {
19730412aabSMichael Lange   PetscInt t;
19816ad7e67SMichael Lange   int      snum, cellType;
199db397164SMichael Lange 
20030412aabSMichael Lange   PetscFunctionBegin;
20116ad7e67SMichael Lange   snum = fscanf(fd, "%d %d %d", cellNum, &cellType, numTags);CHKERRQ(snum != 3);
20216ad7e67SMichael Lange   if (numTags) for (t = 0; t < *numTags; ++t) {snum = fscanf(fd, "%d", &tags[t]);CHKERRQ(snum != 1);}
20330412aabSMichael Lange   switch (cellType) {
20430412aabSMichael Lange   case 1: /* 2-node line */
20530412aabSMichael Lange     *dim = 1;
20630412aabSMichael Lange     *numCorners = 2;
20730412aabSMichael Lange     snum = fscanf(fd, "%d %d\n", &cone[0], &cone[1]);CHKERRQ(snum != *numCorners);
20830412aabSMichael Lange     break;
20930412aabSMichael Lange   case 2: /* 3-node triangle */
21030412aabSMichael Lange     *dim = 2;
21130412aabSMichael Lange     *numCorners = 3;
21230412aabSMichael Lange     snum = fscanf(fd, "%d %d %d\n", &cone[0], &cone[1], &cone[2]);CHKERRQ(snum != *numCorners);
21330412aabSMichael Lange     break;
21430412aabSMichael Lange   case 3: /* 4-node quadrangle */
21530412aabSMichael Lange     *dim = 2;
21630412aabSMichael Lange     *numCorners = 4;
21730412aabSMichael Lange     snum = fscanf(fd, "%d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3]);CHKERRQ(snum != *numCorners);
21830412aabSMichael Lange     break;
21930412aabSMichael Lange   case 4: /* 4-node tetrahedron */
22030412aabSMichael Lange     *dim  = 3;
22130412aabSMichael Lange     *numCorners = 4;
22230412aabSMichael Lange     snum = fscanf(fd, "%d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3]);CHKERRQ(snum != *numCorners);
22330412aabSMichael Lange     break;
22430412aabSMichael Lange   case 5: /* 8-node hexahedron */
22530412aabSMichael Lange     *dim = 3;
22630412aabSMichael Lange     *numCorners = 8;
22730412aabSMichael Lange     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);
22830412aabSMichael Lange     break;
22930412aabSMichael Lange   default:
23030412aabSMichael Lange     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported Gmsh element type %d", cellType);
23130412aabSMichael Lange   }
23230412aabSMichael Lange   PetscFunctionReturn(0);
233db397164SMichael Lange }
234