COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
Reader.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2013 von Karman Institute for Fluid Dynamics, Belgium
2 //
3 // This software is distributed under the terms of the
4 // GNU Lesser General Public License version 3 (LGPLv3).
5 // See doc/lgpl.txt and doc/gpl.txt for the license text.
6 
7 #include <iostream>
8 
9 #include <boost/assign/list_of.hpp>
10 
13 #include "common/Foreach.hpp"
14 #include "common/OptionList.hpp"
15 #include "common/PE/Comm.hpp"
16 #include "common/Builder.hpp"
19 
20 #include "common/XML/XmlDoc.hpp"
22 
23 #include "mesh/cf3mesh/Reader.hpp"
24 #include "mesh/GeoShape.hpp"
25 #include "mesh/Mesh.hpp"
26 #include "mesh/MeshAdaptor.hpp"
27 #include "mesh/Region.hpp"
28 #include "mesh/Dictionary.hpp"
29 #include "mesh/Field.hpp"
30 #include "mesh/Connectivity.hpp"
31 #include "mesh/Space.hpp"
33 
35 
37 
38 namespace cf3 {
39 namespace mesh {
40 namespace cf3mesh {
41 
43 
45 
46 Reader::Reader(const std::string& name): MeshReader(name)
47 {
51 }
52 
53 std::vector< std::string > Reader::get_extensions()
54 {
55  std::vector<std::string> extensions;
56  extensions.push_back(".cf3mesh");
57  return extensions;
58 }
59 
61 {
62  m_mesh = mesh.handle<Mesh>();
63 
64  boost::shared_ptr<common::XML::XmlDoc> doc = common::XML::parse_file(path);
65  common::XML::XmlNode mesh_node(doc->content->first_node("mesh"));
66 
68 
69  // Perform some checks of validity
70  if(!mesh_node.is_valid())
71  throw common::FileFormatError(FromHere(), "File " + path.path() + " has no mesh node");
72 
73  if(mesh_node.attribute_value("version") != "1")
74  throw common::FileFormatError(FromHere(), "File " + path.path() + " has incorrect version " + mesh_node.attribute_value("version") + "(expected 1)");
75 
76  common::XML::XmlNode topology_node = mesh_node.content->first_node("topology");
77  if(!topology_node.is_valid())
78  throw common::FileFormatError(FromHere(), "File " + path.path() + " has no topology node");
79 
80  common::XML::XmlNode dictionaries_node(mesh_node.content->first_node("dictionaries"));
81  if(!dictionaries_node.is_valid())
82  throw common::FileFormatError(FromHere(), "File " + path.path() + " has no dictionaries node");
83 
84  data_reader = common::allocate_component<common::BinaryDataReader>("DataReader");
85  data_reader->options().set("file", common::URI(mesh_node.attribute_value("binary_file")));
86 
87  const Uint nb_parts = common::from_str<Uint>(mesh_node.attribute_value("nb_procs"));
88  if(nb_parts == comm.size())
89  {
90  read_mesh_part(topology_node, dictionaries_node, mesh, comm.rank());
91  }
92  else if(comm.size() != 1)
93  {
94  throw common::FileFormatError(FromHere(), "File " + path.path() + " was created for " + mesh_node.attribute_value("nb_procs") + " processes. Use the correct number of processes or use one process to merge the file");
95  }
96  else
97  {
98  MeshAdaptor mesh_adaptor(mesh);
99 
100  for(Uint part=0; part != nb_parts; ++part)
101  {
102  boost::shared_ptr<Mesh> tmp_mesh = common::allocate_component<Mesh>(mesh.name() + common::to_str(part));
103  read_mesh_part(topology_node, dictionaries_node, *tmp_mesh, part);
104  mesh_adaptor.combine_mesh(*tmp_mesh);
105  }
107  mesh_adaptor.fix_node_ranks();
108  mesh_adaptor.finish();
109  }
110 
111  mesh.raise_mesh_loaded();
112 }
113 
114 void Reader::read_mesh_part(const XmlNode& topology_node, const XmlNode& dictionaries_node, Mesh &mesh, const Uint rank)
115 {
116  data_reader->options().set("rank", rank);
117 
118  m_entities.clear();
119  read_topology(topology_node,mesh.topology(),mesh.geometry_fields());
120  read_elements(topology_node,mesh.topology(),mesh.geometry_fields(), mesh);
121 
122  // First import the geometry dictionary with coordinates only
123  common::XML::XmlNode dictionary_node(dictionaries_node.content->first_node("dictionary"));
124  for(; dictionary_node.is_valid(); dictionary_node.content = dictionary_node.content->next_sibling("dictionary"))
125  {
126  const std::string dict_name = dictionary_node.attribute_value("name");
127  if(dict_name == "geometry")
128  {
129  common::XML::XmlNode field_node(dictionary_node.content->first_node("field"));
130  for(; field_node.is_valid(); field_node.content = field_node.content->next_sibling("field"))
131  {
132  if(field_node.attribute_value("name") == "coordinates")
133  {
134  const Uint table_idx = common::from_str<Uint>(field_node.attribute_value("table_idx"));
135  mesh.initialize_nodes(data_reader->block_rows(table_idx), data_reader->block_cols(table_idx));
136  data_reader->read_table(mesh.geometry_fields().coordinates(), table_idx);
137  }
138  }
139 
140  // Periodic links
141  if(is_not_null(dictionary_node.content->first_attribute("periodic_links_nodes")) && is_not_null(dictionary_node.content->first_attribute("periodic_links_active")))
142  {
143  cf3_assert(is_null(mesh.geometry_fields().get_child("periodic_links_nodes")));
144  cf3_assert(is_null(mesh.geometry_fields().get_child("periodic_links_active")));
145  Handle< common::List<Uint> > periodic_links_nodes = mesh.geometry_fields().create_component< common::List<Uint> >("periodic_links_nodes");
147  data_reader->read_list(*periodic_links_nodes, common::from_str<Uint>(dictionary_node.attribute_value("periodic_links_nodes")));
148  data_reader->read_list(*periodic_links_active, common::from_str<Uint>(dictionary_node.attribute_value("periodic_links_active")));
149  }
150  }
151  }
152 
153  // Then import other fields and other dictionaries
154  dictionary_node.content = dictionaries_node.content->first_node("dictionary");
155  for(; dictionary_node.is_valid(); dictionary_node.content = dictionary_node.content->next_sibling("dictionary"))
156  {
157  const std::string dict_name = dictionary_node.attribute_value("name");
158  const std::string space_lib_name = dictionary_node.attribute_value("space_lib_name");
159  const bool continuous = common::from_str<bool>(dictionary_node.attribute_value("continuous"));
160 
161  // The entities used by this dictionary
162  std::vector< Handle<Entities> > entities_list;
163  std::vector<Uint> entities_binary_file_indices;
164  common::XML::XmlNode entities_node = dictionary_node.content->first_node("entities");
165  for(; entities_node.is_valid(); entities_node.content = entities_node.content->next_sibling("entities"))
166  {
168  if(is_null(entities))
169  {
170  throw common::FileFormatError(FromHere(), "Referred entities " + entities_node.attribute_value("path") + " doesn't exist in mesh");
171  }
172  entities_list.push_back(entities);
173  entities_binary_file_indices.push_back(common::from_str<Uint>(entities_node.attribute_value("table_idx")));
174  }
175 
176  Dictionary& dictionary =
177  dict_name == "geometry" ?
178  mesh.geometry_fields()
179  : (continuous ?
180  mesh.create_continuous_space(dict_name, space_lib_name, entities_list)
181  : mesh.create_discontinuous_space(dict_name, space_lib_name, entities_list) );
182 
183  // Read the global indices
184  data_reader->read_list(dictionary.glb_idx(), common::from_str<Uint>(dictionary_node.attribute_value("global_indices")));
185  data_reader->read_list(dictionary.rank(), common::from_str<Uint>(dictionary_node.attribute_value("ranks")));
186 
187  // Read the fields
188  common::XML::XmlNode field_node(dictionary_node.content->first_node("field"));
189  for(; field_node.is_valid(); field_node.content = field_node.content->next_sibling("field"))
190  {
191  if(field_node.attribute_value("name") == "coordinates")
192  continue;
193  const Uint table_idx = common::from_str<Uint>(field_node.attribute_value("table_idx"));
194  Field& field = dictionary.create_field(field_node.attribute_value("name"), field_node.attribute_value("description"));
195  common::XML::XmlNode tag_node = field_node.content->first_node("tag");
196  for(; tag_node.is_valid(); tag_node.content = tag_node.content->next_sibling("tag"))
197  field.add_tag(tag_node.attribute_value("name"));
198 
199  data_reader->read_table(field, table_idx);
200  }
201 
202  // Read in the connectivity tables
203  for(Uint i = 0; i != entities_list.size(); ++i)
204  {
205  data_reader->read_table(entities_list[i]->space(dictionary).connectivity(), entities_binary_file_indices[i]);
206  }
207  }
208 
209  mesh.update_structures();
210  mesh.update_statistics();
211  mesh.check_sanity();
212 }
213 
214 void Reader::read_topology(const common::XML::XmlNode& topology_node, Region& topology, Dictionary& geometry)
215 {
216  common::XML::XmlNode region_node(topology_node.content->first_node("region"));
217  for(; region_node.is_valid(); region_node.content = region_node.content->next_sibling("region"))
218  {
219  Region& region = topology.create_region(region_node.attribute_value("name"));
220  read_topology(region_node,region,geometry);
221  common::XML::XmlNode elements_node(region_node.content->first_node("elements"));
222  for(; elements_node.is_valid(); elements_node.content = elements_node.content->next_sibling("elements"))
223  {
224  Elements& elems = region.create_elements(elements_node.attribute_value("element_type"), geometry);
225  elems.rename(elements_node.attribute_value("name"));
226  const Uint entities_idx = common::from_str<Uint>(elements_node.attribute_value("idx"));
227  if (entities_idx >= m_entities.size()) m_entities.resize( entities_idx+1 );
228  m_entities[entities_idx] = elems.handle<Entities>();
229  }
230  }
231 }
232 
233 void Reader::read_elements(const common::XML::XmlNode& topology_node, Region& topology, Dictionary& geometry, Mesh& mesh)
234 {
235  common::XML::XmlNode region_node(topology_node.content->first_node("region"));
236  for(; region_node.is_valid(); region_node.content = region_node.content->next_sibling("region"))
237  {
238  Region& region = *topology.access_component(region_node.attribute_value("name"))->handle<Region>();
239  read_elements(region_node,region,geometry, mesh);
240  common::XML::XmlNode elements_node(region_node.content->first_node("elements"));
241  for(; elements_node.is_valid(); elements_node.content = elements_node.content->next_sibling("elements"))
242  {
243  Entities& elems = *region.access_component(elements_node.attribute_value("name"))->handle<Entities>();
244 
245  // Read glb_idx
246  data_reader->read_list(elems.glb_idx(), common::from_str<Uint>(elements_node.attribute_value("global_indices")));
247 
248  // Read rank
249  data_reader->read_list(elems.rank(), common::from_str<Uint>(elements_node.attribute_value("ranks")));
250 
251  // Read periodic links elements
252  common::XML::XmlNode periodic_node(elements_node.content->first_node("periodic_links_elements"));
253  if(periodic_node.is_valid())
254  {
255  Handle< common::List<Uint> > periodic_links_elements = elems.create_component< common::List<Uint> >("periodic_links_elements");
256  data_reader->read_list(*periodic_links_elements, common::from_str<Uint>(periodic_node.attribute_value("index")));
257  Handle<common::Link> link = periodic_links_elements->create_component<common::Link>("periodic_link");
258  Handle<Elements> elements_to_link(mesh.access_component_checked(common::URI( periodic_node.attribute_value("periodic_link"), common::URI::Scheme::CPATH) ) );
259  if(is_null(elements_to_link))
260  throw common::FileFormatError(FromHere(), "Invalid periodic link: " + periodic_node.attribute_value("periodic_link"));
261  link->link_to(*elements_to_link);
262  }
263 
264  // Read connectivity cell2face
265  common::XML::XmlNode connectivity_cell2face_node(elements_node.content->first_node("connectivity_cell2face"));
266  if(connectivity_cell2face_node.is_valid())
267  {
268  using namespace common;
269  boost::shared_ptr< Table<Uint> > conn = allocate_component< Table<Uint> >("tmp");
270  data_reader->read_table(*conn, common::from_str<Uint>(connectivity_cell2face_node.attribute_value("connectivity")));
271  elems.connectivity_cell2face() = elems.create_component<ElementConnectivity>("connectivity_cell2face");
272 
273  const Uint rows = conn->size();
274  const Uint cols = conn->row_size()/2;
275 
276  elems.connectivity_cell2face()->set_row_size( cols );
277  elems.connectivity_cell2face()->resize( rows );
278  for (Uint e=0; e<rows; ++e)
279  {
280  for (Uint n=0; n<cols; ++n)
281  {
282  cf3_assert( conn->array()[e][n+cols*0] < m_entities.size() );
283  cf3_assert( is_not_null(m_entities[conn->array()[e][n+cols*0]]) );
284  elems.connectivity_cell2face()->array()[e][n] = Entity(m_entities[conn->array()[e][n+cols*0]],conn->array()[e][n+cols*1]);
285  }
286  }
287  }
288 
289  // Read connectivity face2cell
290  common::XML::XmlNode connectivity_face2cell_node(elements_node.content->first_node("connectivity_face2cell"));
291  if(connectivity_face2cell_node.is_valid())
292  {
293  using namespace common;
294  boost::shared_ptr< Table<Uint> > conn = allocate_component< Table<Uint> >("tmp");
295  data_reader->read_table(*conn, common::from_str<Uint>(connectivity_face2cell_node.attribute_value("connectivity")));
296  elems.connectivity_face2cell() = elems.create_component<FaceCellConnectivity>("connectivity_face2cell");
297  const Uint rows = conn->size();
298  const Uint cols = conn->row_size()/2;
299  elems.connectivity_face2cell()->connectivity().set_row_size( cols );
300  elems.connectivity_face2cell()->connectivity().resize( rows );
301  for (Uint e=0; e<rows; ++e)
302  {
303  for (Uint n=0; n<cols; ++n)
304  {
305  cf3_assert( conn->array()[e][n+cols*0] < m_entities.size() );
306  cf3_assert( is_not_null(m_entities[conn->array()[e][n+cols*0]]) );
307  elems.connectivity_face2cell()->connectivity()[e][n] = Entity(m_entities[conn->array()[e][n+cols*0]],conn->array()[e][n+cols*1]);
308  }
309  }
310  data_reader->read_list (elems.connectivity_face2cell()->is_bdry_face(), common::from_str<Uint>(connectivity_face2cell_node.attribute_value("is_bdry_face")));
311  data_reader->read_table(elems.connectivity_face2cell()->face_number(), common::from_str<Uint>(connectivity_face2cell_node.attribute_value("face_number")));
312  data_reader->read_table(elems.connectivity_face2cell()->cell_rotation(), common::from_str<Uint>(connectivity_face2cell_node.attribute_value("cell_rotation")));
313  data_reader->read_table(elems.connectivity_face2cell()->cell_orientation(), common::from_str<Uint>(connectivity_face2cell_node.attribute_value("cell_orientation")));
314  }
315 
316  // Read connectivity cell2cell
317  common::XML::XmlNode connectivity_cell2cell_node(elements_node.content->first_node("connectivity_cell2cell"));
318  if(connectivity_cell2cell_node.is_valid())
319  {
320  throw common::NotImplemented(FromHere(), "reading connectivity_cell2face is not implemented");
321  }
322  }
323  }
324 }
325 
327 
328 } // cf3mesh
329 } // mesh
330 } // cf3
std::string name(ComponentWrapper &self)
Field & create_field(const std::string &name, const Uint cols)
Create a new field in this group.
Definition: Dictionary.cpp:178
bool check_sanity() const
Definition: Mesh.cpp:460
bool is_null(T ptr)
predicate for comparison to nullptr
Definition: CF.hpp:151
Safe pointer to an object. This is the supported method for referring to components.
Definition: Handle.hpp:39
Dictionary & create_discontinuous_space(const std::string &space_name, const std::string &space_lib_name, const std::vector< Handle< Entities > > &entities)
Definition: Mesh.cpp:316
Helper class to create the Builder and place it in the factory.
Definition: Builder.hpp:212
void initialize_nodes(const Uint nb_nodes, const Uint dimension)
will among others set the coordinate dimension for the nodes
Definition: Mesh.cpp:127
Dictionary & create_continuous_space(const std::string &space_name, const std::string &space_lib_name, const std::vector< Handle< Entities > > &entities)
Definition: Mesh.cpp:269
bool is_valid() const
Definition: XmlNode.cpp:102
std::string path() const
Definition: URI.cpp:253
#define cf3_assert(a)
Definition: Assertions.hpp:93
Region & create_region(const std::string &name)
Definition: Region.cpp:50
common::List< Uint > & rank()
Return the rank of every field row.
Definition: Dictionary.hpp:90
Common_API bool from_str< bool >(const std::string &str)
boost::shared_ptr< common::BinaryDataReader > data_reader
Definition: Reader.hpp:58
Elements & create_elements(const std::string &element_type_name, Dictionary &geometry)
Definition: Region.cpp:57
void update_structures()
Definition: Mesh.cpp:147
const std::string & name() const
Access the name of the component.
Definition: Component.hpp:146
const Field & coordinates() const
Definition: Dictionary.cpp:481
common::List< Uint > & rank()
Definition: Entities.hpp:71
rapidxml::xml_node< char > * content
Pointer to the underlying XML implementation.
Definition: XmlNode.hpp:50
virtual void do_read_mesh_into(const common::URI &path, Mesh &mesh)
Definition: Reader.cpp:60
Reader(const std::string &name)
constructor
Definition: Reader.cpp:46
Conversions from and to std::string.
virtual std::vector< std::string > get_extensions()
Definition: Reader.cpp:53
Real e()
Definition of the Unit charge [C].
Definition: Consts.hpp:30
common::Libraries & libraries() const
Definition: Core.cpp:176
void read_elements(const common::XML::XmlNode &region_node, Region &region, Dictionary &geometry, Mesh &mesh)
Definition: Reader.cpp:233
Handle< Component > access_component(const URI &path) const
Definition: Component.cpp:487
Common_API std::string to_str(const T &v)
Converts to std::string.
void fix_node_ranks()
Correct ranks of nodes to be unique in all pid's.
Handle< Mesh > m_mesh
Definition: MeshReader.hpp:103
Uint size() const
Definition: Table.hpp:127
std::vector< Handle< Entities > > m_entities
Definition: Reader.hpp:59
common::List< Uint > & glb_idx()
Mutable access to the list of nodes.
Definition: Entities.hpp:66
common::ComponentBuilder< cf3mesh::Reader, MeshReader, LibCF3Mesh > aCF3MeshReader_Builder
Definition: Reader.cpp:44
void remove_duplicate_elements_and_nodes()
Add another mesh to this mesh.
Handle< Component > get_child(const std::string &name)
Definition: Component.cpp:441
Class to adapt the mesh.
Definition: MeshAdaptor.hpp:45
Top-level namespace for coolfluid.
Definition: Action.cpp:18
common::List< Uint > & glb_idx()
Return the global index of every field row.
Definition: Dictionary.hpp:84
Handle< ElementConnectivity > & connectivity_cell2face()
Definition: Entities.hpp:119
void read_mesh_part(const common::XML::XmlNode &topology_node, const common::XML::XmlNode &dictionaries_node, Mesh &mesh, const Uint rank)
Definition: Reader.cpp:114
void finish()
Apply the changes the mesh adaptor for changes and fix inconsistent state.
Component holding a 2 dimensional array of a templated type.
Definition: Table.hpp:45
void raise_mesh_loaded()
Definition: Mesh.cpp:479
void update_statistics()
Definition: Mesh.cpp:203
void rename(const std::string &name)
Rename the component.
Definition: Component.cpp:215
Low storage struct to uniquely identify one element.
Definition: Entities.hpp:141
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
Handle< Library > autoload_library_with_namespace(const std::string &libnamespace)
Definition: Libraries.cpp:105
std::string attribute_value(const std::string &name) const
Definition: XmlNode.cpp:75
Region & topology() const
Definition: Mesh.hpp:51
static Core & instance()
Definition: Core.cpp:37
void read_topology(const common::XML::XmlNode &region_node, Region &region, Dictionary &geometry)
Definition: Reader.cpp:214
Handle< Component > handle()
Get a handle to the component.
Definition: Component.hpp:179
Handle< FaceCellConnectivity > & connectivity_face2cell()
Definition: Entities.hpp:120
Dictionary & geometry_fields() const
Definition: Mesh.cpp:339
static Comm & instance()
Return a reference to the current PE.
Definition: Comm.cpp:44
Handle< Component > create_component(const std::string &name, const std::string &builder)
Build a (sub)component of this component using the extended type_name of the component.
Definition: Component.cpp:568
void combine_mesh(const Mesh &other_mesh)
Add another mesh to this mesh.
bool is_not_null(T ptr)
predicate for comparison to nullptr
Definition: CF.hpp:147
boost::shared_ptr< XmlDoc > parse_file(const URI &file)
Handle< Component > access_component_checked(const URI &path)
Definition: Component.cpp:550
#define FromHere()
Send comments to:
COOLFluiD Web Admin