RINGMesh  Version 5.0.0
A programming library for geological model meshes
io_mfem.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 {
39  static const index_t cell_type_mfem[4] = { 4, 5, NO_ID, NO_ID };
40 
43  static const index_t polygon_type_mfem[3] = { 2, 3, NO_ID };
44 
49  static const index_t cell2mfem[8] = { 0, 1, 3, 2, 4, 5, 7, 6 };
50 
52  static const index_t mfem_offset = 1;
53 
55  POINT = 0, SEGMENT = 1, TRIANGLE = 2, SQUARE = 3, TETRAHEDRON = 4, CUBE = 5
56  };
57 
64  template< index_t DIMENSION >
65  class MFEMIOHandler final: public GeoModelIOHandler< DIMENSION > {
66  public:
67  void load( const std::string& filename, GeoModel< DIMENSION >& geomodel ) final
68  {
69  ringmesh_unused( filename );
70  ringmesh_unused( geomodel );
71  throw RINGMeshException( "I/O",
72  "Loading of a GeoModel from MFEM not implemented yet" );
73  }
74  void save(
75  const GeoModel< DIMENSION >& geomodel,
76  const std::string& filename ) final
77  {
78  const auto& geomodel_mesh = geomodel.mesh;
79  test_if_mesh_is_valid( geomodel.mesh );
80 
81  std::ofstream out( filename.c_str() );
82  out.precision( 16 );
83 
84  write_header( out );
85  write_elements( geomodel_mesh, out );
86  write_boundaries( geomodel_mesh, out );
87  write_vertices( geomodel_mesh, out );
88  out << std::flush;
89  }
90 
91  private:
92  void test_if_mesh_is_valid( const GeoModelMesh< DIMENSION >& geomodel_mesh );
93 
99  void write_header( std::ofstream& out ) const
100  {
101  out << "MFEM mesh v1.0" << EOL;
102  out << EOL;
103  out << "dimension" << EOL;
104  out << DIMENSION << EOL;
105  out << EOL;
106  }
107 
108  void write_elements(
109  const GeoModelMesh< DIMENSION >& geomodel_mesh,
110  std::ofstream& out ) const;
111 
112  void write_boundaries(
113  const GeoModelMesh< DIMENSION >& geomodel_mesh,
114  std::ofstream& out ) const;
115 
123  void write_vertices(
124  const GeoModelMesh< DIMENSION >& geomodel_mesh,
125  std::ofstream& out ) const
126  {
127  out << "vertices" << EOL;
128  out << geomodel_mesh.vertices.nb() << EOL;
129  out << DIMENSION << EOL;
130  for( auto v : range( geomodel_mesh.vertices.nb() ) ) {
131  out << geomodel_mesh.vertices.vertex( v ) << EOL;
132  }
133  }
134  };
135 
136  ALIAS_2D_AND_3D (MFEMIOHandler);
137 
138  template< >
139  void MFEMIOHandler3D::test_if_mesh_is_valid(
140  const GeoModelMesh3D& geomodel_mesh )
141  {
142  index_t nb_cells { geomodel_mesh.cells.nb() };
143  if( geomodel_mesh.cells.nb_tet() != nb_cells
144  && geomodel_mesh.cells.nb_hex() != nb_cells ) {
145  throw RINGMeshException( "I/O",
146  "Export to MFEM format works only with full tet or full hex format" );
147  }
148  }
149 
150  template< >
151  void MFEMIOHandler2D::test_if_mesh_is_valid(
152  const GeoModelMesh2D& geomodel_mesh )
153  {
154  if( geomodel_mesh.polygons.nb() != geomodel_mesh.polygons.nb_triangle() ) {
155  throw RINGMeshException( "I/O",
156  "Export to MFEM format works only with triangles in 2D" );
157  }
158  }
159 
170  template< >
171  void MFEMIOHandler3D::write_elements(
172  const GeoModelMesh3D& geomodel_mesh,
173  std::ofstream& out ) const
174  {
175  index_t nb_cells { geomodel_mesh.cells.nb() };
176  out << "elements" << EOL;
177  out << nb_cells << EOL;
178  for( auto c : range( nb_cells ) ) {
179  out << geomodel_mesh.cells.region( c ) + mfem_offset << " ";
180  out
181  << cell_type_mfem[to_underlying_type( geomodel_mesh.cells.type( c ) )]
182  << " ";
183  for( auto v : range( geomodel_mesh.cells.nb_vertices( c ) ) ) {
184  out
185  << geomodel_mesh.cells.vertex(
186  ElementLocalVertex( c, cell2mfem[v] ) ) << " ";
187  }
188  out << EOL;
189  }
190  out << EOL;
191  }
192 
193  template< >
194  void MFEMIOHandler2D::write_elements(
195  const GeoModelMesh2D& geomodel_mesh,
196  std::ofstream& out ) const
197  {
198  index_t nb_triangles { geomodel_mesh.polygons.nb_triangle() };
199  out << "elements" << EOL;
200  out << nb_triangles << EOL;
201  for( auto c : range( nb_triangles ) ) {
202  out << geomodel_mesh.polygons.surface( c ) + mfem_offset << " ";
203  out << TRIANGLE << " ";
204  for( auto v : range( geomodel_mesh.polygons.nb_vertices( c ) ) ) {
205  out << geomodel_mesh.polygons.vertex( ElementLocalVertex( c, v ) )
206  << " ";
207  }
208  out << EOL;
209  }
210  out << EOL;
211  }
212 
223  template< >
224  void MFEMIOHandler3D::write_boundaries(
225  const GeoModelMesh3D& geomodel_mesh,
226  std::ofstream& out ) const
227  {
228  const GeoModelMeshPolygons3D& polygons = geomodel_mesh.polygons;
229  out << "boundary" << EOL;
230  out << polygons.nb() << EOL;
231  for( auto p : range( polygons.nb() ) ) {
232  out << polygons.surface( p ) + mfem_offset << " ";
233  PolygonType polygon_type;
234  std::tie( polygon_type, std::ignore ) = polygons.type( p );
235  out << polygon_type_mfem[to_underlying_type( polygon_type )] << " ";
236  for( auto v : range( polygons.nb_vertices( p ) ) ) {
237  out << polygons.vertex( ElementLocalVertex( p, v ) ) << " ";
238  }
239  out << EOL;
240  }
241  out << EOL;
242  }
243 
244  template< >
245  void MFEMIOHandler2D::write_boundaries(
246  const GeoModelMesh2D& geomodel_mesh,
247  std::ofstream& out ) const
248  {
249  const GeoModelMeshEdges2D& edges = geomodel_mesh.edges;
250  out << "boundary" << EOL;
251  out << edges.nb() << EOL;
252  for( auto p : range( edges.nb() ) ) {
253  out << edges.line( p ) + mfem_offset << " ";
254  out << SEGMENT << " ";
255  for( auto v : range( 2 ) ) {
256  out << edges.vertex( ElementLocalVertex( p, v ) ) << " ";
257  }
258  out << EOL;
259  }
260  out << EOL;
261  }
262 }
MFEM_geometry_type
Definition: io_mfem.cpp:54
void ringmesh_unused(const T &)
Definition: common.h:105
auto to_underlying_type(Enum e) -> typename std::underlying_type< Enum >::type
Definition: types.h:114
PolygonType
Definition: types.h:105
#define ALIAS_2D_AND_3D(Class)
Definition: common.h:91
const char EOL
Definition: io.h:45