COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
Writer.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/Log.hpp"
16 #include "common/PE/Comm.hpp"
17 #include "common/Builder.hpp"
20 
21 #include "common/XML/XmlDoc.hpp"
23 
24 #include "mesh/cf3mesh/Writer.hpp"
25 #include "mesh/GeoShape.hpp"
26 #include "mesh/Mesh.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"
32 #include "mesh/Tags.hpp"
34 
36 
38 
39 namespace cf3 {
40 namespace mesh {
41 namespace cf3mesh {
42 
44 
46 
48 
49 namespace detail
50 {
51  // Recursively write all region nodes starting at the given parent component
52  void write_regions(common::XML::XmlNode& node, const common::Component& parent, common::BinaryDataWriter& writer, const std::string& root_path)
53  {
54  BOOST_FOREACH(const Region& region, common::find_components<Region>(parent))
55  {
56  common::XML::XmlNode region_node = node.add_node("region");
57  region_node.set_attribute("name", region.name());
58  write_regions(region_node, region, writer, root_path);
59  BOOST_FOREACH(const Entities& elements, common::find_components<Entities>(region))
60  {
61  common::XML::XmlNode elements_node = region_node.add_node("elements");
62  elements_node.set_attribute("idx", common::to_str(elements.entities_idx()));
63  elements_node.set_attribute("name", elements.name());
64  elements_node.set_attribute("element_type", elements.element_type().derived_type_name());
65  elements_node.set_attribute("global_indices", common::to_str(writer.append_data(elements.glb_idx())));
66  elements_node.set_attribute("ranks", common::to_str(writer.append_data(elements.rank())));
67 
68  if( is_not_null(elements.connectivity_cell2face()) )
69  {
70  using namespace common;
71  common::XML::XmlNode connectivity_cell2face = elements_node.add_node("connectivity_cell2face");
72  const Uint rows = elements.connectivity_cell2face()->size();
73  const Uint cols = elements.connectivity_cell2face()->row_size();
74  boost::shared_ptr< Table<Uint> > conn = allocate_component< Table<Uint> >("tmp");
75  conn->set_row_size( 2*cols );
76  conn->resize( rows );
77  for (Uint e=0; e<rows; ++e)
78  {
79  for (Uint n=0; n<cols; ++n)
80  {
81  conn->array()[e][n+cols*0] = elements.connectivity_cell2face()->array()[e][n].comp_idx();
82  conn->array()[e][n+cols*1] = elements.connectivity_cell2face()->array()[e][n].idx;
83  }
84  }
85  connectivity_cell2face.set_attribute("connectivity", to_str(writer.append_data(*conn)));
86  }
87  if( is_not_null(elements.connectivity_face2cell()) )
88  {
89  using namespace common;
90  common::XML::XmlNode connectivity_face2cell = elements_node.add_node("connectivity_face2cell");
91  const Uint rows = elements.connectivity_face2cell()->size();
92  const Uint cols = elements.connectivity_face2cell()->connectivity().row_size();
93  boost::shared_ptr< Table<Uint> > conn = allocate_component< Table<Uint> >("tmp");
94  conn->set_row_size( 2*cols );
95  conn->resize( rows );
96  for (Uint e=0; e<rows; ++e)
97  {
98  for (Uint n=0; n<cols; ++n)
99  {
100  conn->array()[e][n+cols*0] = elements.connectivity_face2cell()->connectivity()[e][n].comp_idx();
101  conn->array()[e][n+cols*1] = elements.connectivity_face2cell()->connectivity()[e][n].idx;
102  }
103  }
104  connectivity_face2cell.set_attribute("connectivity", to_str(writer.append_data(*conn)));
105  connectivity_face2cell.set_attribute("is_bdry_face", to_str(writer.append_data(elements.connectivity_face2cell()->is_bdry_face())));
106  connectivity_face2cell.set_attribute("face_number", to_str(writer.append_data(elements.connectivity_face2cell()->face_number())));
107  connectivity_face2cell.set_attribute("cell_rotation", to_str(writer.append_data(elements.connectivity_face2cell()->cell_rotation())));
108  connectivity_face2cell.set_attribute("cell_orientation", to_str(writer.append_data(elements.connectivity_face2cell()->cell_orientation())));
109  }
110  if( is_not_null(elements.connectivity_cell2cell()) )
111  {
112  using namespace common;
113  common::XML::XmlNode connectivity_cell2cell = elements_node.add_node("connectivity_cell2cell");
114  const Uint rows = elements.connectivity_cell2cell()->size();
115  const Uint cols = elements.connectivity_cell2cell()->row_size();
116  boost::shared_ptr< Table<Uint> > conn = allocate_component< Table<Uint> >("tmp");
117  conn->set_row_size( 2*cols );
118  conn->resize( rows );
119  for (Uint e=0; e<rows; ++e)
120  {
121  for (Uint n=0; n<cols; ++n)
122  {
123  conn->array()[e][n+cols*0] = elements.connectivity_cell2cell()->array()[e][n].comp_idx();
124  conn->array()[e][n+cols*1] = elements.connectivity_cell2cell()->array()[e][n].idx;
125  }
126  }
127  connectivity_cell2cell.set_attribute("connectivity", to_str(writer.append_data(*conn)));
128  }
129 
130  Handle< common::List<Uint> const > periodic_links_elements(elements.get_child("periodic_links_elements"));
131  if(is_not_null(periodic_links_elements))
132  {
133  common::XML::XmlNode periodic_node = elements_node.add_node("periodic_links_elements");
134  periodic_node.set_attribute("index", common::to_str(writer.append_data(*periodic_links_elements)));
135  Handle< common::Link const > periodic_link(periodic_links_elements->get_child("periodic_link"));
136  cf3_always_assert(is_not_null(periodic_link));
137  cf3_always_assert(is_not_null(periodic_link->follow()));
138  periodic_node.set_attribute("periodic_link", boost::replace_first_copy(periodic_link->follow()->uri().path(), root_path, ""));
139  }
140  }
141  }
142  }
143 
144  // Write a field node into the given XmlNode
146  {
147  common::XML::XmlNode field_node = node.add_node("field");
148  field_node.set_attribute("name", field.name());
149  field_node.set_attribute("description", field.descriptor().description());
150  field_node.set_attribute("table_idx", common::to_str(writer.append_data(field)));
151  BOOST_FOREACH(const std::string& tag, field.get_tags())
152  {
153  field_node.add_node("tag").set_attribute("name", tag);
154  }
155  }
156 } // namespace detail
157 
158 Writer::Writer( const std::string& name )
159 : MeshWriter(name)
160 {
161 
162 }
163 
165 
166 std::vector<std::string> Writer::get_extensions()
167 {
168  std::vector<std::string> extensions;
169  extensions.push_back(".cf3mesh");
170  return extensions;
171 }
172 
174 
176 {
178  const Mesh& mesh = *m_mesh;
179  const std::string mesh_path = mesh.uri().path() + "/";
180 
181  // Writer for the arrays
182  boost::shared_ptr<common::BinaryDataWriter> data_writer = common::allocate_component<common::BinaryDataWriter>("DataWriter");
183  const common::URI binfile = m_file_path.base_path() / (m_file_path.base_name() + ".cfbinxml");
184  data_writer->options().set("file", binfile);
185 
186  common::XML::XmlDoc xml_doc("1.0", "ISO-8859-1");
187  common::XML::XmlNode mesh_node = xml_doc.add_node("mesh");
188  mesh_node.set_attribute("version", "1");
189  mesh_node.set_attribute("binary_file", binfile.path());
190  mesh_node.set_attribute("nb_procs", common::to_str(comm.size()));
191 
192  // Write the dictionaries
193  common::XML::XmlNode dictionaries_node = mesh_node.add_node("dictionaries");
194  BOOST_FOREACH(const Dictionary& dictionary, common::find_components<Dictionary>(mesh))
195  {
196  if(dictionary.spaces().empty())
197  {
198  CFwarn << "Dictionary " << dictionary.name() << " with no spaces will not be written" << CFendl;
199  continue;
200  }
201 
202  common::XML::XmlNode dict_node = dictionaries_node.add_node("dictionary");
203  dict_node.set_attribute("name", dictionary.name());
204  dict_node.set_attribute("continuous", common::to_str(dictionary.continuous()));
205  std::string space_lib_name;
206  BOOST_FOREACH(const Field& field, common::find_components<Field>(dictionary))
207  {
208  detail::write_field(dict_node, field, *data_writer);
209  }
210  dict_node.set_attribute("global_indices", common::to_str(data_writer->append_data(dictionary.glb_idx())));
211  dict_node.set_attribute("ranks", common::to_str(data_writer->append_data(dictionary.rank())));
212  BOOST_FOREACH(const Handle< Entities >& entities, dictionary.entities_range())
213  {
214  common::XML::XmlNode entities_node = dict_node.add_node("entities");
215  std::string entities_path = entities->uri().path();
216  boost::erase_first(entities_path, mesh_path);
217  entities_node.set_attribute("path", entities_path);
218  entities_node.set_attribute("table_idx", common::to_str(data_writer->append_data(entities->space(dictionary).connectivity())));
219 
220  if(space_lib_name.empty())
221  {
222  std::string sf_name = entities->space(dictionary).shape_function().derived_type_name();
223  std::vector<std::string> name_parts;
224  boost::split(name_parts, sf_name, boost::is_any_of("."));
225  space_lib_name = name_parts.front();
226  for(Uint i = 1; i != name_parts.size()-1; ++i)
227  space_lib_name += "." + name_parts[i];
228  }
229  }
230 
231  dict_node.set_attribute("space_lib_name", space_lib_name);
232 
233  // Add periodic data if needed
234  if(dictionary.has_tag(mesh::Tags::geometry()))
235  {
236  Handle< common::List<Uint> const > periodic_links_nodes(dictionary.get_child("periodic_links_nodes"));
237  Handle< common::List<bool> const > periodic_links_active(dictionary.get_child("periodic_links_active"));
238  if(is_not_null(periodic_links_nodes) && is_not_null(periodic_links_active))
239  {
240  dict_node.set_attribute("periodic_links_nodes", common::to_str(data_writer->append_data(*periodic_links_nodes)));
241  dict_node.set_attribute("periodic_links_active", common::to_str(data_writer->append_data(*periodic_links_active)));
242  }
243  }
244  }
245 
246  // Topology and geometry connectivity
247  common::XML::XmlNode topology_node = mesh_node.add_node("topology");
248  detail::write_regions(topology_node, mesh.topology(), *data_writer, mesh.uri().path() + "/");
249 
250  if(comm.rank() == 0)
251  {
253  }
254 }
255 
257 
258 } // cf3mesh
259 } // mesh
260 } // cf3
Writer(const std::string &name)
constructor
Definition: Writer.cpp:158
std::string name(ComponentWrapper &self)
XmlNode add_node(const std::string &name, const std::string &value=std::string()) const
Definition: XmlNode.cpp:38
void to_file(const XmlNode &node, const URI &file)
virtual std::vector< std::string > get_extensions()
Definition: Writer.cpp:166
URI base_path() const
Definition: URI.cpp:199
const std::vector< Handle< Entities > > & entities_range() const
Definition: Dictionary.cpp:353
Safe pointer to an object. This is the supported method for referring to components.
Definition: Handle.hpp:39
Helper class to create the Builder and place it in the factory.
Definition: Builder.hpp:212
virtual std::string derived_type_name() const =0
Handle< Mesh const > m_mesh
Handle to configured mesh.
Definition: MeshWriter.hpp:89
std::string path() const
Definition: URI.cpp:253
std::string base_name() const
Filename without extension.
Definition: URI.cpp:300
ElementType & element_type() const
return the elementType
Definition: Entities.cpp:116
URI uri() const
Construct the full path.
Definition: Component.cpp:248
common::List< Uint > & rank()
Return the rank of every field row.
Definition: Dictionary.hpp:90
void write_field(common::XML::XmlNode node, const mesh::Field &field, common::BinaryDataWriter &writer)
Definition: Writer.cpp:145
const std::string & name() const
Access the name of the component.
Definition: Component.hpp:146
common::List< Uint > & rank()
Definition: Entities.hpp:71
common::URI m_file_path
File path to be configured.
Definition: MeshWriter.hpp:86
#define CFendl
Definition: Log.hpp:109
Uint append_data(const Table< T > &table)
Append a new data block containing data from the supplied table. An index into the current file is re...
Uint rank() const
Return rank, additionally, if is_init==0.
Definition: Comm.cpp:135
Conversions from and to std::string.
Real e()
Definition of the Unit charge [C].
Definition: Consts.hpp:30
const std::vector< Handle< Space > > & spaces() const
Definition: Dictionary.cpp:360
Common_API std::string to_str(const T &v)
Converts to std::string.
Uint size() const
Return the number of processes, or 1 if is_init==0.
Definition: Comm.cpp:145
#define cf3_always_assert(a)
Definition: Assertions.hpp:81
common::List< Uint > & glb_idx()
Mutable access to the list of nodes.
Definition: Entities.hpp:66
virtual void write()
Definition: Writer.cpp:175
Handle< ElementConnectivity > & connectivity_cell2cell()
Definition: Entities.hpp:121
void set_attribute(const std::string &name, const std::string &value)
Definition: XmlNode.cpp:54
Handle< Component > get_child(const std::string &name)
Definition: Component.cpp:441
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
#define CFwarn
Definition: Log.hpp:106
Handle< ElementConnectivity > & connectivity_cell2face()
Definition: Entities.hpp:119
std::vector< std::string > get_tags() const
std::string description() const
Get the string description for all the variables.
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
bool has_tag(const std::string &tag) const
Uint entities_idx() const
Definition: Entities.hpp:98
common::ComponentBuilder< cf3mesh::Writer, MeshWriter, LibCF3Mesh > aCF3MeshWriter_Builder
Definition: Writer.cpp:45
void write_regions(common::XML::XmlNode &node, const common::Component &parent, common::BinaryDataWriter &writer, const std::string &root_path)
Definition: Writer.cpp:52
Region & topology() const
Definition: Mesh.hpp:51
bool continuous() const
Definition: Dictionary.hpp:135
math::VariablesDescriptor & descriptor() const
Definition: Field.hpp:127
Handle< FaceCellConnectivity > & connectivity_face2cell()
Definition: Entities.hpp:120
static Comm & instance()
Return a reference to the current PE.
Definition: Comm.cpp:44
Base class for defining CF components.
Definition: Component.hpp:82
Component for writing binary data collected into a single file.
bool is_not_null(T ptr)
predicate for comparison to nullptr
Definition: CF.hpp:147
Send comments to:
COOLFluiD Web Admin