RINGMesh  Version 5.0.0
A programming library for geological model meshes
io_msh.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2017, Association Scientifique pour la Geologie et ses
3  * Applications (ASGA). All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of ASGA nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ASGA BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * http://www.ring-team.org
28  *
29  * RING Project
30  * Ecole Nationale Superieure de Geologie - GeoRessources
31  * 2 Rue du Doyen Marcel Roubault - TSA 70605
32  * 54518 VANDOEUVRE-LES-NANCY
33  * FRANCE
34  */
35 
36 namespace {
37  // Vertices order for a vertex in GMSH
38  static index_t vertices_in_vertex[1] = { 0 };
39  // Vertices order for an edge in GMSH
40  static index_t vertices_in_edge[2] = { 0, 1 };
41  // Vertices order for a triangle in GMSH
42  static index_t vertices_in_triangle[3] = { 0, 1, 2 };
43  // Vertices order for a quad in GMSH
44  static index_t vertices_in_quad[4] = { 0, 1, 2, 3 };
45  // Vertices order for a tetrahedron in GMSH
46  static index_t vertices_in_tetrahedron[4] = { 0, 1, 2, 3 };
47  // Vertices order for an hexahedron in GMSH
48  static index_t vertices_in_hexahedron[8] = { 4, 0, 5, 1, 7, 3, 6, 2 };
49  // Vertices order for a prism in GMSH
50  static index_t vertices_in_prism[6] = { 0, 1, 2, 3, 4, 5 };
51  // Vertices order for a pyramid in GMSH
52  static index_t vertices_in_pyramid[5] = { 0, 1, 2, 3, 4 };
53 
54  // GMSH count begin at 1
55  index_t gmsh_offset = 1;
56 
57  // This is a tricky table that associate an unique id with the id of elements
58  // in GMSH. The unique id is computed as the sum of the MeshEntityType index
59  // and the number of vertices of the elements
60  // Vertex : 0 + 1 = 1
61  // Edge : 1 + 2 = 3
62  // Triangle : 2 + 3 = 5
63  // Quad : 2 + 4 = 6
64  // Tetrahedron : 3 + 4 = 7
65  // Pyramid : 3 + 5 = 8
66  // Prism 3 + 6 = 9
67  // Hexahedron : 3 + 8 = 11
68  index_t element_type[12] =
69  { NO_ID, 15, NO_ID, 1, NO_ID, 2, 3, 4, 7, 6, NO_ID, 5 };
70 
71  // This is a tricky table that associate an unique id with another table
72  // containing the ordering of vertices inside the elementS
73  index_t * vertices_in_elements[12] = { nullptr, vertices_in_vertex, nullptr,
74  vertices_in_edge, nullptr,
75  vertices_in_triangle, vertices_in_quad,
76  vertices_in_tetrahedron,
77  vertices_in_pyramid, vertices_in_prism,
78  nullptr, vertices_in_hexahedron };
79 
80  // The physical id is a mandatory value for GMSH which is not used
81  index_t physical_id = 0;
82 
83  // in GMSH, a tag is a physical id (not used) or a geometry id
84  index_t nb_of_tags = 2;
85 
91  class MSHIOHandler final: public GeoModelIOHandler< 3 > {
92  public:
93  void load( const std::string& filename, GeoModel< 3 >& geomodel ) final
94  {
95  ringmesh_unused( filename );
96  ringmesh_unused( geomodel );
97  throw RINGMeshException( "I/O",
98  "Loading of a GeoModel from GMSH not implemented yet" );
99  }
100  void save( const GeoModel< 3 >& geomodel, const std::string& filename ) final
101  {
102  std::ofstream out( filename.c_str() );
103  out.precision( 16 );
104 
105  out << "$MeshFormat" << EOL;
106  out << "2.2 0 8" << EOL;
107  out << "$EndMeshFormat" << EOL;
108 
109  out << "$Nodes" << EOL;
110  out << geomodel.mesh.vertices.nb() << EOL;
111  for( auto v : range( geomodel.mesh.vertices.nb() ) ) {
112  out << v + gmsh_offset << SPACE << geomodel.mesh.vertices.vertex( v )
113  << EOL;
114  }
115  out << "$EndNodes" << EOL;
116 
117  out << "$Elements" << EOL;
118  out << count_elements( geomodel ) << EOL;
119  const std::vector< MeshEntityType >& gmme_types =
120  geomodel.entity_type_manager().mesh_entity_manager.mesh_entity_types();
121 
122  index_t element_index = 1;
123  for( auto gmme_type_index : range(
124  geomodel.entity_type_manager().mesh_entity_manager.nb_mesh_entity_types() ) ) {
125  MeshEntityType cur_mesh_entity_type = gmme_types[gmme_type_index];
126  for( auto index_of_gmme_of_the_current_type : range(
127  geomodel.nb_mesh_entities( cur_mesh_entity_type ) ) ) {
128  gmme_id cur_gmme_id = gmme_id( cur_mesh_entity_type,
129  index_of_gmme_of_the_current_type );
130  const GeoModelMeshEntity< 3 >& cur_gmme = geomodel.mesh_entity(
131  cur_gmme_id );
132  for( auto elem_in_cur_gmme : range(
133  cur_gmme.nb_mesh_elements() ) ) {
134  index_t nb_vertices_in_cur_element =
135  cur_gmme.nb_mesh_element_vertices( elem_in_cur_gmme );
136  index_t gmsh_element_type = find_gmsh_element_type(
137  nb_vertices_in_cur_element, gmme_type_index );
138  out << element_index++ << SPACE << gmsh_element_type << SPACE
139  << nb_of_tags << SPACE << physical_id << SPACE
140  << index_of_gmme_of_the_current_type + gmsh_offset
141  << SPACE /*<< nb_vertices_in_cur_element << SPACE*/;
142  for( auto v_index_in_cur_element : range(
143  nb_vertices_in_cur_element ) ) {
144  out
145  << geomodel.mesh.vertices.geomodel_vertex_id(
146  cur_gmme_id,
147  cur_gmme.mesh_element_vertex_index(
148  ElementLocalVertex( elem_in_cur_gmme,
149  find_gmsh_element_local_vertex_id(
150  nb_vertices_in_cur_element,
151  gmme_type_index,
152  v_index_in_cur_element ) ) ) )
153  + gmsh_offset << SPACE;
154  }
155  out << EOL;
156  }
157  }
158  }
159  out << "$EndElements" << EOL;
160  out << std::flush;
161  }
162 
163  private:
169  index_t find_gmsh_element_type(
170  index_t nb_vertices,
171  index_t mesh_entity_type_index )
172  {
173  return element_type[nb_vertices + mesh_entity_type_index];
174  }
175 
181  index_t find_gmsh_element_local_vertex_id(
182  index_t nb_vertices,
183  index_t mesh_entity_type_index,
184  index_t local_vertex_index )
185  {
186  return vertices_in_elements[nb_vertices + mesh_entity_type_index][local_vertex_index];
187  }
188 
201  index_t count_elements( const GeoModel< 3 >& geomodel )
202  {
203  index_t nb_elements = 0;
204  const std::vector< MeshEntityType >& gmme_types =
205  geomodel.entity_type_manager().mesh_entity_manager.mesh_entity_types();
206  for( const MeshEntityType& cur_mesh_entity_type : gmme_types ) {
207  for( auto index_of_gmme_of_the_current_type : range(
208  geomodel.nb_mesh_entities( cur_mesh_entity_type ) ) ) {
209  gmme_id cur_gmme_id = gmme_id( cur_mesh_entity_type,
210  index_of_gmme_of_the_current_type );
211  const GeoModelMeshEntity< 3 >& cur_gmme = geomodel.mesh_entity(
212  cur_gmme_id );
213  nb_elements += cur_gmme.nb_mesh_elements();
214  }
215  }
216  return nb_elements;
217  }
218  };
219 }
const char SPACE
Definition: io.h:46
void ringmesh_unused(const T &)
Definition: common.h:105
const char EOL
Definition: io.h:45
template class RINGMESH_API GeoModelMeshEntity< 3 >