RINGMesh  Version 5.0.0
A programming library for geological model meshes
io_feflow.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 
38  struct RINGMesh2Feflow {
39  index_t entity_type;
40  index_t vertices[8];
41  };
42 
43  static RINGMesh2Feflow feflow_tet_descriptor = { 6, { 0, 1, 2, 3 } };
44 
45  static RINGMesh2Feflow feflow_hex_descriptor = { 8, { 2, 6, 7, 3, 0, 4, 5, 1 } };
46 
47  static RINGMesh2Feflow feflow_prism_descriptor = { 7, { 3, 4, 5, 0, 1, 2 } };
48 
49  static RINGMesh2Feflow feflow_pyramid_descriptor = { 9, { 0, 1, 2, 3, 4 } };
50 
51  static RINGMesh2Feflow* cell_type_to_feflow_cell_descriptor[4] = {
52  &feflow_tet_descriptor, &feflow_hex_descriptor, &feflow_prism_descriptor,
53  &feflow_pyramid_descriptor };
54 
55  class FeflowIOHandler final: public GeoModelIOHandler< 3 > {
56  public:
57  static const index_t STARTING_OFFSET = 1;
58 
59  void load( const std::string& filename, GeoModel3D& geomodel ) final
60  {
61  ringmesh_unused( filename );
62  ringmesh_unused( geomodel );
63  throw RINGMeshException( "I/O",
64  "Loading of a GeoModel from Feflow not implemented yet" );
65  }
66  void save( const GeoModel3D& geomodel, const std::string& filename ) final
67  {
68  std::ofstream out( filename.c_str() );
69  out.precision( 16 );
70 
71  write_header( out );
72  write_dimensions( geomodel, out );
73  write_elements( geomodel, out );
74  write_vertices( geomodel, out );
75  write_regions( geomodel, out );
76  write_wells( geomodel, out );
77 
78  out << "END" << std::endl;
79  }
80 
81  private:
82 
83  void write_header( std::ofstream& out ) const
84  {
85  out << "PROBLEM:\n";
86  out << "CLASS (v.7.006.14742)\n";
87  // 3 is for defining a 3D problem
88  // 8 is for using double precision
89  // More information on the CLASS keyword Feflow documentation
90  out << " 0 0 0 3 0 0 8 8 0 0\n";
91  }
92  void write_dimensions( const GeoModel3D& geomodel, std::ofstream& out ) const
93  {
94  const GeoModelMesh3D& mesh = geomodel.mesh;
95  out << "DIMENS\n";
96  out << SPACE << mesh.vertices.nb() << SPACE << mesh.cells.nb()
97  << " 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0\n";
98  out << "SCALE\n\n";
99  }
100  void write_elements( const GeoModel3D& geomodel, std::ofstream& out ) const
101  {
102  const GeoModelMeshCells3D& cells = geomodel.mesh.cells;
103  out << "VARNODE\n";
104  out << SPACE << cells.nb();
105  index_t min_nb_vertices_per_element { 0 };
106  index_t max_nb_vertices_per_element { 0 };
107  if( cells.nb_tet() > 0 ) {
108  min_nb_vertices_per_element = 4;
109  } else if( cells.nb_pyramid() > 0 ) {
110  min_nb_vertices_per_element = 5;
111  } else if( cells.nb_prism() > 0 ) {
112  min_nb_vertices_per_element = 6;
113  } else if( cells.nb_hex() > 0 ) {
114  min_nb_vertices_per_element = 8;
115  } else {
117  }
118  if( cells.nb_hex() > 0 ) {
119  max_nb_vertices_per_element = 8;
120  } else if( cells.nb_prism() > 0 ) {
121  max_nb_vertices_per_element = 6;
122  } else if( cells.nb_pyramid() > 0 ) {
123  max_nb_vertices_per_element = 5;
124  } else if( cells.nb_tet() > 0 ) {
125  max_nb_vertices_per_element = 4;
126  } else {
128  }
129  out << SPACE << min_nb_vertices_per_element << SPACE
130  << max_nb_vertices_per_element << "\n";
131 
132  for( auto c : range( cells.nb() ) ) {
133  const RINGMesh2Feflow& descriptor =
134  *cell_type_to_feflow_cell_descriptor[to_underlying_type(
135  cells.type( c ) )];
136  out << SPACE << descriptor.entity_type;
137  for( auto v : range( cells.nb_vertices( c ) ) ) {
138  out << SPACE
139  << cells.vertex(
140  ElementLocalVertex( c, descriptor.vertices[v] ) )
141  + STARTING_OFFSET;
142  }
143  out << "\n";
144  }
145  }
146  void write_vertices( const GeoModel3D& geomodel, std::ofstream& out ) const
147  {
148  const GeoModelMeshVertices3D& vertices = geomodel.mesh.vertices;
149  out << "XYZCOOR\n" << std::scientific;
150  for( auto v : range( vertices.nb() ) ) {
151  const vec3& point = vertices.vertex( v );
152  std::string sep = "";
153  for( auto i : range( 3 ) ) {
154  out << sep << SPACE << point[i];
155  sep = ",";
156  }
157  out << "\n";
158  }
159  out << std::fixed;
160  }
161  void write_regions( const GeoModel3D& geomodel, std::ofstream& out ) const
162  {
163  out << "ELEMENTALSETS\n";
164  index_t offset = 0;
165  for( const auto& region : geomodel.regions() ) {
166  out << SPACE << region.name() << SPACE << offset + STARTING_OFFSET;
167  offset += region.nb_mesh_elements();
168  out << "-" << offset << "\n";
169  }
170  }
171  void write_wells( const GeoModel3D& geomodel, std::ofstream& out ) const
172  {
173  const WellGroup3D* wells = geomodel.wells();
174  if( !wells ) {
175  return;
176  }
177  out << "DFE\n";
178  out
179  << " <?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\" ?>\n";
180  out << " <fractures>\n";
181  write_well_edges( geomodel, out );
182  out << " <properties>\n";
183  out << " </properties>\n";
184  write_well_groups( geomodel, out );
185  out << " </fractures>\n";
186  }
187  void write_well_edges( const GeoModel3D& geomodel, std::ofstream& out ) const
188  {
189  const GeoModelMeshWells3D& wells = geomodel.mesh.wells;
190  out << " <nop count=\"" << wells.nb_edges() << "\">\n";
191  out << " <![CDATA[";
192  for( auto w : range( wells.nb_wells() ) ) {
193  for( auto e : range( wells.nb_edges( w ) ) ) {
194  out << "\n 0, 2, " << wells.vertex( w, e, 0 ) + STARTING_OFFSET
195  << ", " << wells.vertex( w, e, 1 ) + STARTING_OFFSET;
196  }
197  }
198  out << "]]>\n";
199  out << " </nop>\n";
200  }
201  void write_well_groups(
202  const GeoModel3D& geomodel,
203  std::ofstream& out ) const
204  {
205  const GeoModelMeshWells3D& well_edges = geomodel.mesh.wells;
206  const WellGroup3D* wells = geomodel.wells();
207  index_t offset = 0;
208  out << " <groups count=\"" << well_edges.nb_wells() << "\">\n";
209  for( auto w : range( well_edges.nb_wells() ) ) {
210  out << " <group name=\"" << wells->well( w ).name()
211  << "\" mode=\"unstructured\">\n";
212  out << " <elements count=\"" << well_edges.nb_edges( w ) << "\">\n";
213  out << " <![CDATA[ " << offset + STARTING_OFFSET;
214  offset += well_edges.nb_edges( w );
215  out << "-" << offset << "]]>\n";
216  out << " </elements>\n";
217  out << " </group>\n";
218  }
219  out << " </groups>\n";
220  }
221  };
222 
223 }
const char SPACE
Definition: io.h:46
vecn< 3 > vec3
Definition: types.h:76
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
#define ringmesh_assert_not_reached