Flow123d  last_with_con_2.0.0-663-gd0e2296
output_vtk.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_vtk.cc
15  * @brief The functions for outputs to VTK files.
16  */
17 
18 #include "output_vtk.hh"
19 #include "output_data_base.hh"
20 #include "output_mesh_data.hh"
21 #include "output_mesh.hh"
22 
23 #include <limits.h>
24 #include "input/factory.hh"
26 #include "system/file_path.hh"
27 
29 
30 
31 using namespace Input::Type;
32 
33 const Record & OutputVTK::get_input_type() {
34  return Record("vtk", "Parameters of vtk output format.")
35  // It is derived from abstract class
37  .declare_key("variant", OutputVTK::get_input_type_variant(), Default("\"ascii\""),
38  "Variant of output stream file format.")
39  // The parallel or serial variant
40  //.declare_key("parallel", Bool(), Default("false"),
41  // "Parallel or serial version of file format.")
42  .close();
43 }
44 
45 
47  return Selection("VTK variant (ascii or binary)")
49  "ASCII variant of VTK file format")
51  "Uncompressed appended binary XML VTK format without usage of base64 encoding of appended data.")
53  "Appended binary XML VTK format without usage of base64 encoding of appended data. Compressed with ZLib. (Not supported yet)")
54  .close();
55 }
56 
57 
58 const int OutputVTK::registrar = Input::register_class< OutputVTK >("vtk") +
60 
61 
62 
64 {
65  this->enable_refinement_ = true;
66 }
67 
68 
69 
71 {
72  this->write_tail();
73 }
74 
75 
76 
77 
79 {
80  ASSERT_PTR(output_mesh_).error();
81 
82  /* It's possible now to do output to the file only in the first process */
83  if(this->rank != 0) {
84  /* TODO: do something, when support for Parallel VTK is added */
85  return 0;
86  }
87 
88  if (! this->_base_file.is_open()) {
89  auto format_rec = (Input::Record)(input_record_.val<Input::AbstractRecord>("format"));
90  variant_type_ = format_rec.val<VTKVariant>("variant");
91 
92  this->fix_main_file_extension(".pvd");
93  try {
94  this->_base_filename.open_stream( this->_base_file );
95  } INPUT_CATCH(FilePath::ExcFileOpen, FilePath::EI_Address_String, input_record_)
96 
97  LogOut() << "Writing flow output file: " << this->_base_filename << " ... ";
98 
99  this->make_subdirectory();
100  this->write_head();
101  }
102 
103  ostringstream ss;
104  ss << main_output_basename_ << "-"
105  << std::setw(6) << std::setfill('0') << this->current_step
106  << ".vtu";
107 
108 
109  std::string frame_file_name = ss.str();
110  FilePath frame_file_path({main_output_dir_, main_output_basename_, frame_file_name}, FilePath::output_file);
111 
112  /* Set up data file */
113  try {
114  frame_file_path.open_stream(_data_file);
115  } INPUT_CATCH(FilePath::ExcFileOpen, FilePath::EI_Address_String, input_record_)
116 
117 
118  LogOut() << __func__ << ": Writing output file " << this->_base_filename << " ... ";
119 
120  /* Set floating point precision to max */
121  this->_base_file.precision(std::numeric_limits<double>::digits10);
122 
123  /* Strip out relative path and add "base/" string */
124  std::string relative_frame_file = main_output_basename_ + "/" + frame_file_name;
125  this->_base_file << scientific << "<DataSet timestep=\"" << (isfinite(this->time)?this->time:0)
126  << "\" group=\"\" part=\"0\" file=\"" << relative_frame_file <<"\"/>" << endl;
127 
128  LogOut() << "O.K.";
129 
130  LogOut() << __func__ << ": Writing output (frame " << this->current_step << ") file " << relative_frame_file << " ... ";
131 
132  this->write_vtk_vtu();
133 
134  /* Close stream for file of current frame */
135  _data_file.close();
136  //delete data_file;
137  //this->_data_file = NULL;
138 
139  LogOut() << "O.K.";
140 
141  return 1;
142 }
143 
144 
145 
146 
148 {
149  ASSERT_EQ(this->_base_filename.extension(), ".pvd").error();
152 
153  vector<string> sub_path = { main_output_dir_, main_output_basename_, "__tmp__" };
154  FilePath fp(sub_path, FilePath::output_file);
155  fp.create_output_dir();
156 }
157 
158 
159 
160 
162 {
163  ofstream &file = this->_data_file;
164 
165  file << "<?xml version=\"1.0\"?>" << endl;
166  // TODO: test endianess of platform (this would be important, when raw
167  // data will be saved to the VTK file)
168  file << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
169  file << "<UnstructuredGrid>" << endl;
170 }
171 
172 
173 
175 {
176  auto offsets = output_mesh_->offsets_->data_;
177  unsigned int n_elements = offsets.size();
178 
179  data.resize(n_elements);
180  int n_nodes;
181 
182  n_nodes = offsets[0];
183  switch(n_nodes) {
184  case 2:
185  data[0] = (unsigned int)VTK_LINE;
186  break;
187  case 3:
188  data[0] = (unsigned int)VTK_TRIANGLE;
189  break;
190  case 4:
191  data[0] = (unsigned int)VTK_TETRA;
192  break;
193  }
194 
195  for(unsigned int i=1; i < n_elements; i++)
196  {
197  n_nodes = offsets[i]-offsets[i-1];
198  switch(n_nodes) {
199  case 2:
200  data[i] = (unsigned int)VTK_LINE;
201  break;
202  case 3:
203  data[i] = (unsigned int)VTK_TRIANGLE;
204  break;
205  case 4:
206  data[i] = (unsigned int)VTK_TETRA;
207  break;
208  }
209  }
210 }
211 
212 
213 
215 {
216  // names of types in DataArray section
217  static const std::vector<std::string> types = {
218  "Int8", "UInt8", "Int16", "UInt16", "Int32", "UInt32", "Float32", "Float64" };
219  // formats of DataArray section
220  static const std::vector<std::string> formats = { "ascii", "appended", "appended" };
221 
222  ofstream &file = this->_data_file;
223 
224  file << "<DataArray type=\"" << types[output_data->vtk_type_] << "\" ";
225  // possibly write name
226  if( ! output_data->output_field_name.empty())
227  file << "Name=\"" << output_data->output_field_name <<"\" ";
228  // write number of components
229  if (output_data->n_elem_ > 1)
230  {
231  file
232  << "NumberOfComponents=\"" << output_data->n_elem_ << "\" ";
233  }
234  file << "format=\"" << formats[this->variant_type_] << "\"";
235 
236  if ( this->variant_type_ == VTKVariant::VARIANT_ASCII ) {
237  // ascii output
238  file << ">" << endl;
239  file << std::fixed << std::setprecision(10); // Set precision to max
240  output_data->print_ascii_all(file);
241  file << "\n</DataArray>" << endl;
242  } else {
243  // binary output is stored to appended_data_ stream
244  double range_min, range_max;
245  output_data->get_min_max_range(range_min, range_max);
246  file << " offset=\"" << appended_data_.tellp() << "\" ";
247  file << "RangeMin=\"" << range_min << "\" RangeMax=\"" << range_max << "\"/>" << endl;
248  output_data->print_binary_all( appended_data_ );
249  }
250 
251 }
252 
253 
255 {
256  for(OutputDataPtr data : output_data_vec)
257  write_vtk_data(data);
258 }
259 
260 
261 
262 
264  OutputDataFieldVec &output_data_vec)
265 {
266  if (output_data_vec.empty()) return;
267 
268  file << "Scalars=\"";
269  for(OutputDataPtr data : output_data_vec )
270  if (data->n_elem_ == OutputDataBase::N_SCALAR) file << data->output_field_name << ",";
271  file << "\" ";
272 
273  file << "Vectors=\"";
274  for(OutputDataPtr data : output_data_vec )
275  if (data->n_elem_ == OutputDataBase::N_VECTOR) file << data->output_field_name << ",";
276  file << "\" ";
277 
278  file << "Tensors=\"";
279  for(OutputDataPtr data : output_data_vec )
280  if (data->n_elem_ == OutputDataBase::N_TENSOR) file << data->output_field_name << ",";
281  file << "\"";
282 }
283 
284 
286 {
287  ofstream &file = this->_data_file;
288 
289  // merge node and corner data
290  OutputDataFieldVec node_corner_data(output_data_vec_[NODE_DATA]);
291  node_corner_data.insert(node_corner_data.end(),
293 
294  if( ! node_corner_data.empty() ) {
295  /* Write <PointData begin */
296  file << "<PointData ";
297  write_vtk_data_names(file, node_corner_data);
298  file << ">" << endl;
299 
300  /* Write data on nodes */
301  this->write_vtk_field_data(output_data_vec_[NODE_DATA]);
302 
303  /* Write data in corners of elements */
305 
306  /* Write PointData end */
307  file << "</PointData>" << endl;
308  }
309 }
310 
311 
313 {
314  ofstream &file = this->_data_file;
315 
316  auto &data_map = this->output_data_vec_[ELEM_DATA];
317  if (data_map.empty()) return;
318 
319  /* Write CellData begin */
320  file << "<CellData ";
321  write_vtk_data_names(file, data_map);
322  file << ">" << endl;
323 
324  /* Write own data */
325  this->write_vtk_field_data(data_map);
326 
327  /* Write PointData end */
328  file << "</CellData>" << endl;
329 }
330 
331 
333 {
334  ofstream &file = this->_data_file;
335 
336  file << "</UnstructuredGrid>" << endl;
337  if ( this->variant_type_ != VTKVariant::VARIANT_ASCII ) {
338  // appended data of binary compressed output
339  if ( this->variant_type_ == VTKVariant::VARIANT_BINARY_ZLIB )
340  WarningOut() << "Zlib library is not supported yet. Appended output is not compressed." << endl;
341  file << "<AppendedData encoding=\"raw\">" << endl;
342  // appended data starts with '_' character
343  file << "_" << appended_data_.str() << endl;
344  file << "</AppendedData>" << endl;
345  }
346  file << "</VTKFile>" << endl;
347 }
348 
349 
351 {
352  ofstream &file = this->_data_file;
353 
354  /* Write header */
355  this->write_vtk_vtu_head();
356 
357  /* When there is no discontinuous data, then write classical vtu */
358  if ( this->output_data_vec_[CORNER_DATA].empty() )
359  {
360  /* Write Piece begin */
361  file << "<Piece NumberOfPoints=\"" << output_mesh_->n_nodes()
362  << "\" NumberOfCells=\"" << output_mesh_->n_elements() <<"\">" << endl;
363 
364  /* Write VTK Geometry */
365  file << "<Points>" << endl;
366  write_vtk_data(output_mesh_->nodes_);
367  file << "</Points>" << endl;
368 
369 
370  /* Write VTK Topology */
371  file << "<Cells>" << endl;
372  write_vtk_data(output_mesh_->connectivity_);
373  write_vtk_data(output_mesh_->offsets_);
374  auto types = std::make_shared<MeshData<unsigned int>>("types");
375  fill_element_types_vector(types->data_);
376  write_vtk_data( types );
377  file << "</Cells>" << endl;
378 
379  /* Write VTK scalar and vector data on nodes to the file */
380  this->write_vtk_node_data();
381 
382  /* Write VTK data on elements */
383  this->write_vtk_element_data();
384 
385  /* Write Piece end */
386  file << "</Piece>" << endl;
387 
388  } else {
389  /* Write Piece begin */
390  file << "<Piece NumberOfPoints=\"" << output_mesh_discont_->n_nodes()
391  << "\" NumberOfCells=\"" << output_mesh_->n_elements() <<"\">" << endl;
392 
393  /* Write VTK Geometry */
394  file << "<Points>" << endl;
396  file << "</Points>" << endl;
397 
398  /* Write VTK Topology */
399  file << "<Cells>" << endl;
400  write_vtk_data(output_mesh_discont_->connectivity_);
402  auto types = std::make_shared<MeshData<unsigned int>>("types");
403  fill_element_types_vector(types->data_);
404  write_vtk_data( types );
405  file << "</Cells>" << endl;
406 
407  /* Write VTK scalar and vector data on nodes to the file */
408  this->write_vtk_node_data();
409 
410  /* Write VTK data on elements */
411  this->write_vtk_element_data();
412 
413  /* Write Piece end */
414  file << "</Piece>" << endl;
415  }
416 
417  /* Write tail */
418  this->write_vtk_vtu_tail();
419 }
420 
421 
422 
424 {
425  /* It's possible now to do output to the file only in the first process */
426  if(this->rank != 0) {
427  /* TODO: do something, when support for Parallel VTK is added */
428  return 0;
429  }
430 
431  LogOut() << __func__ << ": Writing output file (head) " << this->_base_filename << " ... ";
432 
433  this->_base_file << "<?xml version=\"1.0\"?>" << endl;
434  this->_base_file << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
435  this->_base_file << "<Collection>" << endl;
436 
437  LogOut() << "O.K.";
438 
439  return 1;
440 }
441 
442 
444 {
445  /* It's possible now to do output to the file only in the first process */
446  if(this->rank != 0) {
447  /* TODO: do something, when support for Parallel VTK is added */
448  return 0;
449  }
450 
451  LogOut() << __func__ << ": Writing output file (tail) " << this->_base_filename << " ... ";
452 
453  this->_base_file << "</Collection>" << endl;
454  this->_base_file << "</VTKFile>" << endl;
455 
456  LogOut() << "O.K.";
457 
458  return 1;
459 }
460 
461 
462 
463 
464 
465 
Classes for auxiliary output mesh.
string stem() const
Definition: file_path.cc:193
double time
Definition: output_time.hh:208
std::shared_ptr< OutputMesh > output_mesh_
Output mesh.
Definition: output_time.hh:248
Input::Record input_record_
Definition: output_time.hh:224
std::shared_ptr< OutputMeshDiscontinuous > output_mesh_discont_
Discontinuous (non-conforming) mesh. Used for CORNER_DATA.
Definition: output_time.hh:250
void fix_main_file_extension(std::string extension)
Definition: output_time.cc:157
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:588
void make_subdirectory()
Definition: output_vtk.cc:147
static const Input::Type::Record & get_input_type()
The definition of input record for vtk file format.
Definition: output_vtk.cc:33
void create_output_dir()
Definition: file_path.cc:176
void write_vtk_field_data(OutputDataFieldVec &output_data_map)
Definition: output_vtk.cc:254
void write_vtk_vtu(void)
This function write all scalar and vector data on nodes and elements to the VTK file (...
Definition: output_vtk.cc:350
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:50
FilePath _base_filename
Definition: output_time.hh:234
void write_vtk_data(OutputDataPtr output_data)
Definition: output_vtk.cc:214
static const int registrar
Registrar of class to factory.
Definition: output_vtk.hh:119
#define INPUT_CATCH(ExceptionType, AddressEITag, input_accessor)
Definition: accessors.hh:57
static Input::Type::Abstract & get_input_format_type()
The specification of output file format.
Definition: output_time.cc:58
void fill_element_types_vector(std::vector< unsigned int > &data)
Fills the given vector with VTK element types indicators.
Definition: output_vtk.cc:174
string main_output_basename_
Basename of main output file (without extension)
Definition: output_vtk.hh:192
int write_head(void)
This function writes header of VTK (.pvd) file format.
Definition: output_vtk.cc:423
string main_output_dir_
Main output file directory.
Definition: output_vtk.hh:195
void write_vtk_element_data(void)
Write data on elements to the VTK file (.vtu)
Definition: output_vtk.cc:312
#define LogOut()
Macro defining &#39;log&#39; record of log.
Definition: logger.hh:237
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:303
VTKVariant
The declaration enumeration used for variant of file VTK format.
Definition: output_vtk.hh:82
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:195
void open_stream(Stream &stream) const
Definition: file_path.cc:211
int write_data(void)
This function write data to VTK (.pvd) file format for curent time.
Definition: output_vtk.cc:78
ofstream _data_file
Definition: output_vtk.hh:179
int current_step
Definition: output_time.hh:203
ostringstream appended_data_
Definition: output_vtk.hh:184
Accessor to the data with type Type::Record.
Definition: accessors.hh:292
const Ret val(const string &key) const
void write_vtk_vtu_tail(void)
Write tail of VTK file (.vtu)
Definition: output_vtk.cc:332
This class is used for output data to VTK file format.
Definition: output_vtk.hh:34
Selection & add_value(const int value, const std::string &key, const std::string &description="", TypeBase::attribute_map attributes=TypeBase::attribute_map())
Adds one new value with name given by key to the Selection.
string parent_path() const
Definition: file_path.cc:183
Record & declare_key(const string &key, std::shared_ptr< TypeBase > type, const Default &default_value, const string &description, TypeBase::attribute_map key_attributes=TypeBase::attribute_map())
Declares a new key of the Record.
Definition: type_record.cc:484
int write_tail(void)
This function writes tail of VTK (.pvd) file format.
Definition: output_vtk.cc:443
ofstream _base_file
Definition: output_time.hh:229
~OutputVTK()
The destructor of this class. It writes tail of the file too.
Definition: output_vtk.cc:70
string extension() const
Definition: file_path.cc:198
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:459
Dedicated class for storing path to input and output files.
Definition: file_path.hh:48
OutputVTK()
The constructor of this class. The head of file is written, when constructor is called.
Definition: output_vtk.cc:63
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:336
const Selection & close() const
Close the Selection, no more values can be added.
VTKVariant variant_type_
Output format (ascii, binary or binary compressed)
Definition: output_vtk.hh:198
void write_vtk_node_data(void)
Write data on nodes to the VTK file (.vtu)
Definition: output_vtk.cc:285
OutputDataFieldVec output_data_vec_[N_DISCRETE_SPACES]
Definition: output_time.hh:198
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:234
std::shared_ptr< OutputDataBase > OutputDataPtr
Definition: output_time.hh:191
Record type proxy class.
Definition: type_record.hh:171
bool enable_refinement_
Auxliary flag for refinement enabling, due to gmsh format.
Definition: output_time.hh:255
void write_vtk_vtu_head(void)
Write header of VTK file (.vtu)
Definition: output_vtk.cc:161
Template for classes storing finite set of named values.
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:180
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual)
Definition: asserts.hh:328
static const Input::Type::Selection & get_input_type_variant()
The definition of input record for selection of variant of file format.
Definition: output_vtk.cc:46
void write_vtk_data_names(ofstream &file, OutputDataFieldVec &output_data_map)
Write names of data sets in output_data vector that have value type equal to type. Output is done into stream file.
Definition: output_vtk.cc:263