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 #include <iomanip>
9 
10 #include <boost/date_time/gregorian/gregorian.hpp> //include all types plus i/o
11 #include <boost/progress.hpp>
12 
14 #include "common/Foreach.hpp"
15 #include "common/Log.hpp"
16 #include "common/Builder.hpp"
18 #include "common/OptionList.hpp"
19 #include "common/PropertyList.hpp"
21 
22 #include "mesh/neu/Writer.hpp"
23 #include "mesh/Mesh.hpp"
24 #include "mesh/Dictionary.hpp"
25 #include "mesh/Field.hpp"
26 #include "mesh/Region.hpp"
27 #include "mesh/Elements.hpp"
29 #include "mesh/ElementData.hpp"
30 #include "mesh/MeshMetadata.hpp"
31 #include "mesh/Connectivity.hpp"
32 
34 
35 namespace cf3 {
36 namespace mesh {
37 namespace neu {
38 
39 using namespace cf3::common;
40 
42 
43 common::ComponentBuilder < mesh::neu::Writer,
44  mesh::MeshWriter,
45  mesh::neu::LibNeu>
47 
49 
50 Writer::Writer( const std::string& name )
51 : MeshWriter(name),
52  Shared()
53 {
54 
55 }
56 
58 
59 std::vector<std::string> Writer::get_extensions()
60 {
61  std::vector<std::string> extensions;
62  extensions.push_back(".neu");
63  return extensions;
64 }
65 
67 
69 {
70  // if the file is present open it
71  boost::filesystem::fstream file;
72  boost::filesystem::path path(m_file_path.path());
73  CFinfo << "Opening file " << path.string() << CFendl;
74  file.open(path,std::ios_base::out);
75  if (!file) // didn't open so throw exception
76  {
77  throw boost::filesystem::filesystem_error( path.string() + " failed to open",
78  boost::system::error_code() );
79  }
80  m_fileBasename = boost::filesystem::basename(path);
81 
82  // must be in correct order!
83  write_headerData(file, *m_mesh);
84  write_coordinates(file, *m_mesh);
85  write_connectivity(file, *m_mesh);
86  write_groups(file, *m_mesh);
87 
88  try
89  {
90  write_boundaries(file, *m_mesh);
91  }
92  catch( ... )
93  {
94  }
95 
96  file.close();
97 }
98 
100 
101 void Writer::write_headerData(std::fstream& file, const Mesh& mesh)
102 {
103  // get the day of today
104  boost::gregorian::date date = boost::gregorian::from_simple_string(mesh.metadata().properties().value_str("date"));
105 
106  Uint group_counter(0);
107  Uint element_counter(0);
108  Uint bc_counter(0);
109 
110  const Uint node_counter = mesh.geometry_fields().size();
111 
112 
113  boost_foreach(const Region& group, find_components_recursively_with_filter<Region>(mesh,m_region_filter))
114  {
115  bool isGroupBC(false);
116  boost_foreach(const Elements& elementregion, find_components_recursively<Elements>(group))
117  {
118  bool isElementBC(false);
119  Uint dimensionality = elementregion.element_type().dimensionality();
120  if (dimensionality < mesh.dimensionality()) // is bc
121  {
122  isElementBC = true;
123  isGroupBC = true;
124  }
125  if (!isElementBC)
126  element_counter += elementregion.geometry_space().connectivity().size();
127  }
128  if (!isGroupBC)
129  {
130  group_counter++;
131  }
132  else
133  {
134  bc_counter++;
135  }
136  }
137 
138 
139  file.setf(std::ios::right);
140  //CFinfo << "group_counter = " << group_counter << CFendl;
141  //CFinfo << "element_counter = " << element_counter << CFendl;
142  //CFinfo << "node_counter = " << node_counter << CFendl;
143  file << " CONTROL INFO 2.3.16\n";
144  file << "** GAMBIT NEUTRAL FILE\n";
145  file << m_fileBasename << "\n";
146  file << "PROGRAM: Gambit VERSION: 2.3.16\n";
147  file << std::setw(4) << std::string(date.month().as_long_string()).substr(0,3) << " " << int(date.year()) << "\n";
148  file << std::setw(10) << "NUMNP" << std::setw(10) << "NELEM" << std::setw(10) << "NGRPS"
149  << std::setw(10) << "NBSETS" << std::setw(10) << "NDFCD" << std::setw(10) << "NDFVL" << std::endl;
150  file << std::setw(10) << node_counter << std::setw(10) << element_counter << std::setw(10) << group_counter
151  << std::setw(10) << bc_counter << std::setw(10) << mesh.dimension() << std::setw(10) << mesh.dimension() << std::endl;
152  file << "ENDOFSECTION" << std::endl ;
153 }
154 
156 
157 void Writer::write_coordinates(std::fstream& file, const Mesh& mesh)
158 {
159  // set precision for Real
160  Uint prec = file.precision();
161  file.precision(11);
162 
163 
164  file << " NODAL COORDINATES 2.3.16" << std::endl;
165  file.setf(std::ios::fixed);
166  Uint node_number = 0;
168  {
169  ++node_number;
170  file << std::setw(10) << node_number;
171  for (Uint d=0; d<mesh.dimension(); ++d)
172  file << std::setw(20) << std::scientific << row[d];
173  file << std::endl;
174  }
175  file << "ENDOFSECTION" << std::endl;
176  // restore precision
177  file.precision(prec);
178 }
179 
181 
182 void Writer::write_connectivity(std::fstream& file, const Mesh& mesh)
183 {
184  file << " ELEMENTS/CELLS 2.3.16" << std::endl;
185 
186  // global element number
187  Uint elm_number=0;
188 
189  // loop over all element regions
190  Uint node_idx=0;
191  boost_foreach(const Elements& elementregion, find_components_recursively<Elements>(mesh.topology()))
192  {
193  bool isBC = false;
194  Uint dimensionality = elementregion.element_type().dimensionality();
195  if (dimensionality < mesh.dimensionality()) // is bc
196  {
197  isBC = true;
198  }
199  if (!isBC)
200  {
201  //CFinfo << "elements from region: " << elementregion->uri().string() << CFendl;
202  // information of this region with one unique element type
203  Uint elm_type;
204  Uint nb_nodes;
205  elm_type = m_CFelement_to_neuElement[elementregion.element_type().shape()];
206  nb_nodes = elementregion.element_type().nb_nodes();
207  m_global_start_idx[Handle<Elements const>(elementregion.handle<Component>())]=elm_number;
208 
209  // write the nodes for each element of this region
210  boost_foreach(const Connectivity::ConstRow& cf_element , elementregion.geometry_space().connectivity().array())
211  {
212  file << std::setw(8) << ++elm_number << std::setw(3) << elm_type << std::setw(3) << nb_nodes << " ";
213  std::vector<Uint> neu_element(nb_nodes);
214 
215  // fill the neu_element (connectivity)
216  for (Uint j=0; j<nb_nodes; ++j)
217  {
218  // index within a neu element (because of different node numbering)
219  Uint neu_idx = m_nodes_cf_to_neu[elm_type][j];
220  // put the global element number inside the row
221  neu_element[neu_idx] = node_idx+cf_element[j]+1;
222  }
223 
224  Uint eol_counter=0;
225  boost_foreach(Uint neu_node, neu_element)
226  {
227  if (eol_counter == 8)
228  {
229  file << std::endl << std::setw(15) << " ";
230  eol_counter = 0;
231  }
232  file << std::setw(8) << neu_node;
233  ++eol_counter;
234  }
235  file << std::endl;
236  }
237  }
238  }
239  file << "ENDOFSECTION" << std::endl;
240 }
241 
243 
244 void Writer::write_groups(std::fstream& file, const Mesh& mesh)
245 {
246  Uint group_counter(0);
247 
248  boost_foreach(const Region& group, find_components_recursively_with_filter<Region>(mesh,m_region_filter))
249  {
250  bool isBC(false);
251  boost_foreach(const Elements& elementregion, find_components_recursively <Elements>(group))
252  {
253  Uint dimensionality = elementregion.element_type().dimensionality();
254  if (dimensionality < mesh.dimensionality()) // is bc
255  {
256  isBC = true;
257  }
258  }
259  if (!isBC)
260  {
261  Uint element_counter(0);
262  boost_foreach(const Elements& elementregion, find_components_recursively<Elements>(group))
263  {
264  element_counter += elementregion.geometry_space().connectivity().size();
265  }
266  file << " ELEMENT GROUP 2.3.16\n";
267  file << "GROUP:" << std::setw(11) << ++group_counter << " ELEMENTS:" << std::setw(11) << element_counter << " MATERIAL:" << std::setw(11) << 2 << " NFLAGS:" << std::setw(11) << 1 << std::endl;
268  file << std::setw(32) << group.name() << std::endl << std::setw(8) << 0 << std::endl;
269  Uint line_counter=0;
270  boost_foreach(const Elements& elementregion, find_components_recursively <Elements>(group))
271  {
272  Uint elm_global_start_idx = m_global_start_idx[Handle<Elements const>(elementregion.handle<Component>())]+1;
273  Uint elm_global_end_idx = elementregion.geometry_space().connectivity().size() + elm_global_start_idx;
274 
275  for (Uint elm=elm_global_start_idx; elm<elm_global_end_idx; elm++, line_counter++)
276  {
277  if (line_counter == 10)
278  {
279  file << std::endl;
280  line_counter = 0;
281  }
282  file << std::setw(8) << elm;
283  }
284  }
285  file << std::endl;
286  file << "ENDOFSECTION" << std::endl;
287  }
288  }
289 }
290 
292 
293 void Writer::write_boundaries(std::fstream& file, const Mesh& mesh)
294 {
295  // Add node connectivity data at the mesh level
296  Handle<NodeConnectivity> node_connectivity = create_component<NodeConnectivity>("node_connectivity");
297  node_connectivity->initialize(find_components_recursively_with_filter<Elements>(*Handle<Mesh const>(mesh.handle<Component>()), IsElementsVolume()));
298 
299  std::map<Handle< Elements const >,boost::shared_ptr< FaceConnectivity > > element_2_face_connecitivity;
300  boost_foreach(const Elements& elementregion, find_components_recursively_with_filter<Elements>(mesh,IsElementsSurface()))
301  {
302  element_2_face_connecitivity[Handle<Elements const>(elementregion.handle<Component>())] = allocate_component<FaceConnectivity>("face_connectivity");
303  element_2_face_connecitivity[Handle<Elements const>(elementregion.handle<Component>())]->initialize(elementregion,*node_connectivity);
304  }
305 
306  // Find total number of boundary elements and store all bc groups
307  Uint total_nbElements=0;
308  std::set<Handle< Region const > > bc_regions;
309  boost_foreach(const Elements& elementregion, find_components_recursively_with_filter<Elements>(mesh,IsElementsSurface()))
310  {
311  bc_regions.insert(Handle<Region const>(elementregion.parent()));
312  total_nbElements += elementregion.geometry_space().connectivity().size();
313  }
314 
315  if (total_nbElements > 0)
316  {
318  boost::progress_display progress(total_nbElements,std::cout,"writing boundary conditions\n");
319 
320  boost_foreach(Handle< Region const > group, bc_regions) // For each boundary condition
321  {
322  file << " BOUNDARY CONDITIONS 2.3.16\n";
323  file << std::setw(32) << group->name() << std::setw(8) << 1 << std::setw(8) << group->recursive_elements_count(m_enable_overlap) << std::setw(8) << 0 << std::setw(8) << 6 << std::endl;
324 
325  boost_foreach(const Elements& elementregion, find_components_recursively<Elements>(*group)) // for each element type in this BC
326  {
327  const Connectivity& table = elementregion.geometry_space().connectivity();
328  const FaceConnectivity& face_connectivity = *element_2_face_connecitivity[Handle<Elements const>(elementregion.handle<Component>())];
329 
330  const Uint nb_elems = table.size();
331  const Uint nb_faces = elementregion.element_type().nb_faces();
332  for(Uint elem = 0; elem != nb_elems; ++elem)
333  {
334  for(Uint face = 0; face != nb_faces; ++face)
335  {
336  if(face_connectivity.has_adjacent_element(elem, face))
337  {
338  FaceConnectivity::ElementReferenceT connected = face_connectivity.adjacent_element(elem, face);
339 
340  Handle<Elements const> connected_region = Handle<Elements const>(face_connectivity.node_connectivity().entities()[connected.first]);
341  Uint connected_region_start_idx = m_global_start_idx[connected_region];
342 
343  Uint elm_local_idx = connected.second;
344  Uint elm_global_idx = connected_region_start_idx + elm_local_idx;
345  Uint neu_elm_type = m_CFelement_to_neuElement[connected_region->element_type().shape()];
346  Uint neu_elm_face_idx = m_faces_cf_to_neu[neu_elm_type][face_connectivity.adjacent_face(elem, face)];
347 
348  file << std::setw(10) << elm_global_idx+1 << std::setw(5) << neu_elm_type << std::setw(5) << neu_elm_face_idx << std::endl;
349  ++progress;
350  }
351  else
352  {
353  std::stringstream error_msg;
354  error_msg << "\nFace " << face << " of element " << elem
355  << " of " << elementregion.uri().string() << " has no neighbour." << std::endl;
356  error_msg << "nb_elems = " << nb_elems << std::endl;
357  error_msg << "nb_faces per elem = " << nb_faces << std::endl;
358  error_msg << "elem coordinates:\n";
359  for( Uint n=0; n<elementregion.element_type().nb_nodes(); ++n)
360  {
361  error_msg << elementregion.geometry_space().connectivity()[elem][n] << ": ";
362  error_msg << elementregion.geometry_space().get_coordinates(elem).row(n) << std::endl;
363  }
364  boost_foreach( Uint n, elementregion.element_type().faces().nodes_range(face) )
365  {
366  error_msg << "node " << elementregion.geometry_space().connectivity()[elem][n] << " face coord: " << elementregion.geometry_space().get_coordinates(elem).row(n) << std::endl;
367  error_msg << " connected elems: \n";
368  boost_foreach( const NodeConnectivity::ElementReferenceT element, node_connectivity->node_element_range( elementregion.geometry_space().connectivity()[elem][n] ) )
369  {
370  const Entities& nc_entities = *node_connectivity->entities()[element.first];
371  error_msg << " " << nc_entities.uri() << "[" << element.second << "] ";
372  error_msg << " ( ";
373  boost_foreach ( Uint elem_n, nc_entities.geometry_space().connectivity()[element.second] )
374  {
375  error_msg << elem_n << " ";
376  }
377  error_msg << ")" << std::endl;
378  }
379 
380  }
381  error_msg << "It could be that faces are oriented in the wrong way!!!" << std::endl;
382  throw ValueNotFound (FromHere(), error_msg.str());
383  }
384  }
385  }
386  }
387 
388  file << "ENDOFSECTION" << std::endl;
389  }
390  }
391 }
392 
394 
395 
396 } // neu
397 } // mesh
398 } // cf3
virtual void write()
Definition: Writer.cpp:68
#define CFinfo
these are always defined
Definition: Log.hpp:104
NodeConnectivity::ElementReferenceT ElementReferenceT
Uniquely refer an element by its Elements and local element index.
std::string name(ComponentWrapper &self)
Writer(const std::string &name)
constructor
Definition: Writer.cpp:50
void write_headerData(std::fstream &file, const Mesh &mesh)
Definition: Writer.cpp:101
std::vector< std::vector< Uint > > m_nodes_cf_to_neu
Definition: Shared.hpp:48
Safe pointer to an object. This is the supported method for referring to components.
Definition: Handle.hpp:39
ArrayT & array()
Definition: Table.hpp:92
Space & geometry_space() const
Definition: Entities.hpp:94
bool m_enable_overlap
If true, writing of overlap will be enabled.
Definition: MeshWriter.hpp:93
const EntitiesT & entities() const
Access to the raw data.
MeshMetadata & metadata()
Definition: Mesh.hpp:74
Handle< Mesh const > m_mesh
Handle to configured mesh.
Definition: MeshWriter.hpp:89
std::string path() const
Definition: URI.cpp:253
ElementType & element_type() const
return the elementType
Definition: Entities.cpp:116
URI uri() const
Construct the full path.
Definition: Component.cpp:248
Uint nb_faces() const
Definition: ElementType.hpp:67
#define boost_foreach
lowercase version of BOOST_FOREACH
Definition: Foreach.hpp:16
const std::string & name() const
Access the name of the component.
Definition: Component.hpp:146
const Field & coordinates() const
Definition: Dictionary.cpp:481
RegionFilter m_region_filter
Filters regions.
Definition: MeshWriter.hpp:87
std::map< GeoShape::Type, Uint > m_CFelement_to_neuElement
Definition: Shared.hpp:44
common::URI m_file_path
File path to be configured.
Definition: MeshWriter.hpp:86
#define CFendl
Definition: Log.hpp:109
Conversions from and to std::string.
virtual const FaceConnectivity & faces() const =0
void write_boundaries(std::fstream &file, const Mesh &mesh)
Definition: Writer.cpp:293
Uint size() const
Definition: Table.hpp:127
Uint dimension() const
Definition: Mesh.hpp:86
Uint dimensionality() const
Definition: ElementType.hpp:79
PropertyList & properties()
Definition: Component.cpp:842
std::vector< std::vector< Uint > > m_faces_cf_to_neu
Definition: Shared.hpp:46
Handle< Component > parent() const
Definition: Component.cpp:256
ElementReferenceT adjacent_element(const Uint element, const Uint face) const
Get the element that is adjacent to the given face of the given element.
GeoShape::Type shape() const
Definition: ElementType.hpp:64
void write_connectivity(std::fstream &file, const Mesh &mesh)
Definition: Writer.cpp:182
std::string value_str(const std::string &pname) const
std::pair< Uint, Uint > ElementReferenceT
Uniquely refer an element by its index into the list of entities and it's local element index...
TableConstRow< ValueT >::type ConstRow
the const type of a row in the internal structure of the table
Definition: Table.hpp:59
Top-level namespace for coolfluid.
Definition: Action.cpp:18
std::map< Handle< Elements const >, Uint > m_global_start_idx
implementation detail, raw pointers are safe as keys
Definition: Writer.hpp:64
const NodeConnectivity & node_connectivity() const
RealMatrix get_coordinates(const Uint elem_idx) const
Lookup element coordinates.
Definition: Space.cpp:179
virtual std::vector< std::string > get_extensions()
Definition: Writer.cpp:59
void write_groups(std::fstream &file, const Mesh &mesh)
Definition: Writer.cpp:244
static boost::proto::terminal< ExpressionGroupTag >::type group
Use group(expr1, expr2, ..., exprN) to evaluate a group of expressions.
std::string m_fileBasename
Definition: Writer.hpp:66
Uint dimensionality() const
Definition: Mesh.hpp:88
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
Uint nb_nodes() const
Definition: ElementType.hpp:73
RangeT nodes_range(const Uint face) const
Iterator range over the nodes of the given face.
Region & topology() const
Definition: Mesh.hpp:51
Handle< Component > handle()
Get a handle to the component.
Definition: Component.hpp:179
common::ComponentBuilder< mesh::neu::Writer, mesh::MeshWriter, mesh::neu::LibNeu > aneuWriter_Builder
Definition: Writer.cpp:46
Uint adjacent_face(const Uint element, const Uint face) const
Get the face that is adjacent to the given face of the given element.
Dictionary & geometry_fields() const
Definition: Mesh.cpp:339
Base class for defining CF components.
Definition: Component.hpp:82
void write_coordinates(std::fstream &file, const Mesh &mesh)
Definition: Writer.cpp:157
Uint size() const
Number of rows of contained fields.
Definition: Dictionary.cpp:99
Most basic kernel library.
Definition: Action.cpp:19
std::string string() const
Definition: URI.cpp:258
bool has_adjacent_element(const Uint element, const Uint face) const
True if the given face of the given element has an adjacent element.
Connectivity & connectivity()
connectivity table to dictionary entries
Definition: Space.hpp:110
#define FromHere()
Send comments to:
COOLFluiD Web Admin