Flow123d  release_3.0.0-1263-g7cf53c1
output_msh.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file output_msh.cc
15  * @brief The functions for outputs to GMSH files.
16  */
17 
18 #include "output_msh.hh"
19 #include "output_mesh.hh"
20 #include "output_element.hh"
21 #include "mesh/mesh.h"
23 #include "input/factory.hh"
24 #include "tools/unit_si.hh"
25 
26 
28 
29 
30 using namespace Input::Type;
31 
32 
33 /**
34  * Auxiliary implementation of ElementDataCacheBase that performs output of single zero data for the fields that are
35  * off for current time frame.
36  */
38 public:
39 
40  DummyOutputData(std::string field_name_in, unsigned int n_comp_in)
41  {
42  this->field_input_name_ = field_name_in;
43  this->n_comp_ = n_comp_in;
44  this->n_values_ = 1;
45  }
46 
47  virtual ~DummyOutputData() override
48  {}
49 
50  void print_ascii(ostream &out_stream, unsigned int) override
51  {
52  for(unsigned int i=0; i< n_comp_;i++) out_stream << 0 << " ";
53  }
54 
55  void print_ascii_all(ostream &out_stream) override
56  {
57  for(unsigned int i=0; i< n_comp_;i++) out_stream << 0 << " ";
58  }
59 
60  void print_binary_all(ostream &, bool) override
61  {
62  ASSERT(false).error("Not implemented.");
63  }
64 
65  void print_yaml_subarray(ostream &, unsigned int, unsigned int , unsigned int) override
66  {}
67 
68  void get_min_max_range(double &, double &) override
69  {}
70 
71  void read_ascii_data(Tokenizer &, unsigned int, unsigned int ) override
72  {}
73 
74  void read_binary_data(std::istream &, unsigned int, unsigned int) override
75  {}
76 
77  std::shared_ptr< ElementDataCacheBase > gather(Distribution *, LongIdx *) override
78  {
79  return std::make_shared<DummyOutputData>(this->field_input_name_, this->n_comp_);
80  }
81 
82  std::shared_ptr< ElementDataCacheBase > element_node_cache_fixed_size(std::vector<unsigned int> &) override
83  {
84  return std::make_shared<DummyOutputData>(this->field_input_name_, this->n_comp_);
85  }
86 
87  std::shared_ptr< ElementDataCacheBase > element_node_cache_optimize_size(std::vector<unsigned int> &) override
88  {
89  return std::make_shared<DummyOutputData>(this->field_input_name_, this->n_comp_);
90  }
91 
92  std::shared_ptr< ElementDataCacheBase > compute_node_data(std::vector<unsigned int> &, unsigned int ) override
93  {
94  return std::make_shared<DummyOutputData>(this->field_input_name_, this->n_comp_);
95  }
96 
97 };
98 
99 
100 
101 
102 
103 
104 
106  return Record("gmsh", "Parameters of gmsh output format.")
107  // It is derived from abstract class
109  .close();
110 }
111 
112 const int OutputMSH::registrar = Input::register_class< OutputMSH >("gmsh") +
114 
115 
117 {
118  this->enable_refinement_ = false;
119  this->header_written = false;
120 
122 
123 
124 }
125 
127 {
128  this->write_tail();
129 }
130 
131 
132 
133 
135 {
136  ofstream &file = this->_base_file;
137 
138  // Write simple header
139  file << "$MeshFormat" << endl;
140  file << "2" << " 0 " << sizeof(double) << endl;
141  file << "$EndMeshFormat" << endl;
142 }
143 
145 {
146  ofstream &file = this->_base_file;
147 
148  // Write information about nodes
149  file << "$Nodes" << endl;
150  file << this->nodes_->n_values() << endl;
151  auto &id_node_vec = *( this->node_ids_->get_component_data(0).get() );
152  for(unsigned int i_node=0; i_node < id_node_vec.size(); ++i_node) {
153  file << id_node_vec[i_node] << " ";
154  this->nodes_->print_ascii(file, i_node);
155  file << endl;
156  }
157  file << "$EndNodes" << endl;
158 }
159 
161 {
162  ofstream &file = this->_base_file;
163  const static unsigned int gmsh_simplex_types_[4] = {0, 1, 2, 4};
164  auto &id_elem_vec = *( this->elem_ids_->get_component_data(0).get() );
165  auto &id_node_vec = *( this->node_ids_->get_component_data(0).get() );
166  auto &connectivity_vec = *( this->connectivity_->get_component_data(0).get() );
167  auto &offsets_vec = *( this->offsets_->get_component_data(0).get() );
168  auto &regions_vec = *( this->region_ids_->get_component_data(0).get() );
169  auto &partition_vec = *( this->partitions_->get_component_data(0).get() );
170 
171  unsigned int n_nodes, i_node=0;
172 
173  // Write information about elements
174  file << "$Elements" << endl;
175  file << this->offsets_->n_values() << endl;
177  for(unsigned int i_elm=0; i_elm < id_elem_vec.size(); ++i_elm) {
178  n_nodes = (i_elm==0) ? (offsets_vec[0]) : (offsets_vec[i_elm]-offsets_vec[i_elm-1]);
179  // element_id element_type 3_other_tags material region partition
180  file << id_elem_vec[i_elm]
181  << " " << gmsh_simplex_types_[ n_nodes-1 ]
182  << " 3 " << regions_vec[i_elm] << " " << regions_vec[i_elm] << " " << partition_vec[i_elm];
183 
184  for(unsigned int i=0; i<n_nodes; i++, i_node++) {
185  file << " " << id_node_vec[connectivity_vec[i_node]];
186  }
187  file << endl;
188  }
189  file << "$EndElements" << endl;
190 }
191 
192 
193 void OutputMSH::write_msh_ascii_data(std::shared_ptr<ElementDataCache<unsigned int>> id_cache, OutputDataPtr output_data, bool discont)
194 {
195  ofstream &file = this->_base_file;
196  auto &id_vec = *( id_cache->get_component_data(0).get() );
197 
198  if (discont) { // corner data
199  auto &offsets_vec = *( this->offsets_->get_component_data(0).get() );
200  unsigned int n_nodes, i_corner=0;
201  for(unsigned int i=0; i < id_vec.size(); ++i) {
202  n_nodes = (i==0) ? (offsets_vec[0]) : (offsets_vec[i]-offsets_vec[i-1]);
203  file << id_vec[i] << " " << n_nodes << " ";
204  for (unsigned int j=0; j<n_nodes; j++)
205  output_data->print_ascii(file, i_corner++);
206  file << std::endl;
207  }
208  } else { // element / node data
209  for(unsigned int i=0; i < output_data->n_values(); ++i) {
210  file << id_vec[i] << " ";
211  output_data->print_ascii(file, i);
212  file << std::endl;
213  }
214 
215  }
216 }
217 
218 
220 {
221  ofstream &file = this->_base_file;
222  double time_fixed = isfinite(this->time)?this->time:0;
223  time_fixed /= UnitSI().s().convert_unit_from(this->unit_string_);
224 
225  file << "$NodeData" << endl;
226 
227  file << "1" << endl; // one string tag
228  file << "\"" << output_data->field_input_name() <<"\"" << endl;
229 
230  file << "1" << endl; // one real tag
231  file << time_fixed << endl; // first real tag = time
232 
233  file << "3" << endl; // 3 integer tags
234  file << this->current_step << endl; // step number (start = 0)
235  file << output_data->n_comp() << endl; // number of components
236  file << output_data->n_values() << endl; // number of values
237 
238  this->write_msh_ascii_data(this->node_ids_, output_data);
239 
240  file << "$EndNodeData" << endl;
241 }
242 
243 
245 {
246  ofstream &file = this->_base_file;
247  double time_fixed = isfinite(this->time)?this->time:0;
248 
249  file << "$ElementNodeData" << endl;
250 
251  file << "1" << endl; // one string tag
252  file << "\"" << output_data->field_input_name() <<"\"" << endl;
253 
254  file << "1" << endl; // one real tag
255  file << time_fixed << endl; // first real tag = time
256 
257  file << "3" << endl; // 3 integer tags
258  file << this->current_step << endl; // step number (start = 0)
259  file << output_data->n_comp() << endl; // number of components
260  file << this->offsets_->n_values() << endl; // number of values
261 
262  this->write_msh_ascii_data(this->elem_ids_, output_data, true);
263 
264  file << "$EndElementNodeData" << endl;
265 }
266 
268 {
269  ofstream &file = this->_base_file;
270  double time_fixed = isfinite(this->time)?this->time:0;
271 
272  file << "$ElementData" << endl;
273 
274  file << "1" << endl; // one string tag
275  file << "\"" << output_data->field_input_name() <<"\"" << endl;
276 
277  file << "1" << endl; // one real tag
278  file << time_fixed << endl; // first real tag = time
279 
280  file << "3" << endl; // 3 integer tags
281  file << this->current_step << endl; // step number (start = 0)
282  file << output_data->n_comp() << endl; // number of components
283  file << output_data->n_values() << endl; // number of values
284 
285  this->write_msh_ascii_data(this->elem_ids_, output_data);
286 
287  file << "$EndElementData" << endl;
288 }
289 
291 {
292  LogOut() << __func__ << ": Writing output file " << this->_base_filename << " ... ";
293 
294  this->write_msh_header();
295 
296  this->write_msh_geometry();
297 
298  this->write_msh_topology();
299 
300  LogOut() << "O.K.";
301 
302  return 1;
303 }
304 
306 {
307  /* Output of serial format is implemented only in the first process */
308  if (this->rank_ != 0) {
309  return 0;
310  }
311 
312  // Write header with mesh, when it hasn't been written to output file yet
313  if(this->header_written == false) {
314  this->fix_main_file_extension(".msh");
315  try {
316  this->_base_filename.open_stream( this->_base_file );
317  this->set_stream_precision(this->_base_file);
318  } INPUT_CATCH(FilePath::ExcFileOpen, FilePath::EI_Address_String, input_record_)
319 
320  this->write_head();
321  this->header_written = true;
322  }
323 
324  LogOut() << __func__ << ": Writing output file " << this->_base_filename << " ... ";
325 
326 
327  auto &node_data_list = this->output_data_vec_[NODE_DATA];
328  for(auto data_it = node_data_list.begin(); data_it != node_data_list.end(); ++data_it) {
329  write_node_data(*data_it);
330  }
331  auto &corner_data_list = this->output_data_vec_[CORNER_DATA];
332  for(auto data_it = corner_data_list.begin(); data_it != corner_data_list.end(); ++data_it) {
333  write_corner_data(*data_it);
334  }
335  auto &elem_data_list = this->output_data_vec_[ELEM_DATA];
336  for(auto data_it = elem_data_list.begin(); data_it != elem_data_list.end(); ++data_it) {
337  write_elem_data(*data_it);
338  }
339 
340  // Flush stream to be sure everything is in the file now
341  this->_base_file.flush();
342 
343  LogOut() << "O.K.";
344 
345  return 1;
346 }
347 
348 
349 
351 {
352  return 1;
353 }
354 
355 
356 
358 {
360  for (auto type_idx : space_types) {
361  auto &dummy_data_list = dummy_data_list_[type_idx];
362  auto &data_list = this->output_data_vec_[type_idx];
363 
364  // Collect all output fields
365  if (dummy_data_list.size() == 0)
366  for(auto out_ptr : data_list)
367  dummy_data_list.push_back( std::make_shared<DummyOutputData>(out_ptr->field_input_name(), out_ptr->n_comp()));
368 
369  auto data_it = data_list.begin();
370  for(auto dummy_it = dummy_data_list.begin(); dummy_it != dummy_data_list.end(); ++dummy_it) {
371  if ( data_it == data_list.end() ) {
372  data_list.push_back( *dummy_it );
373  } else if ((*dummy_it)->field_input_name() == (*data_it)->field_input_name()) {
374  ++data_it;
375  } else {
376  data_list.push_back( *dummy_it );
377  }
378  }
379  }
380 }
381 
382 
383 
384 void OutputMSH::set_output_data_caches(std::shared_ptr<OutputMeshBase> mesh_ptr) {
386 
387  mesh_ptr->get_master_mesh()->create_id_caches();
388  this->node_ids_ = mesh_ptr->get_master_mesh()->node_ids_;
389  this->elem_ids_ = mesh_ptr->get_master_mesh()->elem_ids_;
390  this->region_ids_ = mesh_ptr->get_master_mesh()->region_ids_;
391  this->partitions_ = mesh_ptr->get_master_mesh()->partitions_;
392 }
393 
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
Definition: long_idx.hh:22
Classes for auxiliary output mesh.
std::vector< std::vector< OutputDataPtr > > dummy_data_list_
Definition: output_msh.hh:93
virtual void set_output_data_caches(std::shared_ptr< OutputMeshBase > mesh_ptr)
Definition: output_time.cc:130
void print_ascii_all(ostream &out_stream) override
Definition: output_msh.cc:55
double time
Definition: output_time.hh:278
void write_msh_header(void)
This function write header of GMSH (.msh) file format.
Definition: output_msh.cc:134
static const Input::Type::Record & get_input_type()
The definition of input record for gmsh file format.
Definition: output_msh.cc:105
Input::Record input_record_
Definition: output_time.hh:288
OutputMSH()
The constructor of this class. We open the output file in first call of write_data.
Definition: output_msh.cc:116
void fix_main_file_extension(std::string extension)
Definition: output_time.cc:150
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:598
DummyOutputData(std::string field_name_in, unsigned int n_comp_in)
Definition: output_msh.cc:40
std::shared_ptr< ElementDataCache< unsigned int > > connectivity_
Vector maps the nodes to their coordinates in vector nodes_.
Definition: output_time.hh:328
void write_msh_ascii_data(std::shared_ptr< ElementDataCache< unsigned int >> id_cache, OutputDataPtr output_data, bool discont=false)
This function writes ascii data to GMSH (.msh) output file.
Definition: output_msh.cc:193
std::shared_ptr< ElementDataCache< unsigned int > > offsets_
Vector of offsets of node indices of elements. Maps elements to their nodes in connectivity_.
Definition: output_time.hh:330
static const int registrar
Registrar of class to factory.
Definition: output_msh.hh:85
void write_msh_geometry(void)
This function writes geometry (position of nodes) to GMSH (.msh) file format.
Definition: output_msh.cc:144
FilePath _base_filename
Definition: output_time.hh:298
double convert_unit_from(std::string actual_unit) const
Convert and check user-defined unit.
Definition: unit_si.cc:217
Abstract linear system class.
Definition: balance.hh:37
void write_corner_data(OutputDataPtr output_data)
writes ElementNode data ascii GMSH (.msh) output file.
Definition: output_msh.cc:244
#define INPUT_CATCH(ExceptionType, AddressEITag, input_accessor)
Definition: accessors.hh:64
int write_tail(void)
This method should write tail of GMSH (.msh) file format.
Definition: output_msh.cc:350
static Input::Type::Abstract & get_input_format_type()
The specification of output file format.
Definition: output_time.cc:64
void read_ascii_data(Tokenizer &, unsigned int, unsigned int) override
Definition: output_msh.cc:71
std::shared_ptr< ElementDataCacheBase > OutputDataPtr
Definition: output_time.hh:122
void read_binary_data(std::istream &, unsigned int, unsigned int) override
Definition: output_msh.cc:74
std::shared_ptr< ElementDataCache< double > > nodes_
Vector of node coordinates. [spacedim x n_nodes].
Definition: output_time.hh:326
std::shared_ptr< ElementDataCacheBase > compute_node_data(std::vector< unsigned int > &, unsigned int) override
Definition: output_msh.cc:92
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
std::shared_ptr< ElementDataCache< unsigned int > > node_ids_
Vector gets ids of nodes.
Definition: output_msh.hh:151
std::shared_ptr< ElementDataCacheBase > element_node_cache_optimize_size(std::vector< unsigned int > &) override
Definition: output_msh.cc:87
#define LogOut()
Macro defining &#39;log&#39; record of log.
Definition: logger.hh:249
std::shared_ptr< ElementDataCache< int > > partitions_
Vector gets partitions of elements.
Definition: output_msh.hh:157
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
void write_node_data(OutputDataPtr output_data)
This function write all data on nodes to output file. This function is used for static and dynamic da...
Definition: output_msh.cc:219
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:196
void open_stream(Stream &stream) const
Definition: file_path.cc:211
void add_dummy_fields() override
Complete information about dummy fields that are not in output_data_list_.
Definition: output_msh.cc:357
std::shared_ptr< ElementDataCacheBase > element_node_cache_fixed_size(std::vector< unsigned int > &) override
Definition: output_msh.cc:82
int current_step
Definition: output_time.hh:273
void write_msh_topology(void)
This function writes topology (connection of nodes) to the GMSH (.msh) file format.
Definition: output_msh.cc:160
UnitSI & s(int exp=1)
Definition: unit_si.cc:76
void print_binary_all(ostream &, bool) override
Definition: output_msh.cc:60
static const unsigned int N_DISCRETE_SPACES
Definition: output_time.hh:103
bool header_written
Definition: output_msh.hh:87
void set_stream_precision(std::ofstream &stream)
Definition: output_time.cc:99
string unit_string_
String representation of time unit.
Definition: output_time.hh:323
~OutputMSH()
The destructor of this class.
Definition: output_msh.cc:126
ofstream _base_file
Definition: output_time.hh:293
void write_elem_data(OutputDataPtr output_data)
This function write all data on elements to output file. This function is used for static and dynamic...
Definition: output_msh.cc:267
void print_yaml_subarray(ostream &, unsigned int, unsigned int, unsigned int) override
Definition: output_msh.cc:65
void set_output_data_caches(std::shared_ptr< OutputMeshBase > mesh_ptr) override
Definition: output_msh.cc:384
virtual ~DummyOutputData() override
Definition: output_msh.cc:47
void get_min_max_range(double &, double &) override
Definition: output_msh.cc:68
void print_ascii(ostream &out_stream, unsigned int) override
Definition: output_msh.cc:50
int write_data(void)
This method writes data to GMSH (.msh) file format for current time.
Definition: output_msh.cc:305
Class OutputElement and its iterator OutputElementIterator on the output mesh.
OutputDataFieldVec output_data_vec_[N_DISCRETE_SPACES]
Definition: output_time.hh:268
Record type proxy class.
Definition: type_record.hh:182
bool enable_refinement_
Auxiliary flag for refinement enabling, due to gmsh format.
Definition: output_time.hh:317
std::shared_ptr< ElementDataCacheBase > gather(Distribution *, LongIdx *) override
Definition: output_msh.cc:77
std::shared_ptr< ElementDataCache< unsigned int > > elem_ids_
Vector gets ids of elements.
Definition: output_msh.hh:153
Class for representation SI units of Fields.
Definition: unit_si.hh:40
int write_head(void)
This method writes head of GMSH (.msh) file format.
Definition: output_msh.cc:290
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:180
std::shared_ptr< ElementDataCache< unsigned int > > region_ids_
Vector gets ids of regions.
Definition: output_msh.hh:155