Flow123d  release_1.8.2-1603-g0109a2b
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 <limits.h>
20 #include "mesh/mesh.h"
21 #include "output_data_base.hh"
22 #include "input/factory.hh"
24 
25 
27 
28 
29 using namespace Input::Type;
30 
31 const Record & OutputVTK::get_input_type() {
32  return Record("vtk", "Parameters of vtk output format.")
33  // It is derived from abstract class
35  .declare_key("variant", OutputVTK::get_input_type_variant(), Default("\"ascii\""),
36  "Variant of output stream file format.")
37  // The parallel or serial variant
38  .declare_key("parallel", Bool(), Default("false"),
39  "Parallel or serial version of file format.")
40  // Type of compression
41  .declare_key("compression", OutputVTK::get_input_type_compression(), Default("\"none\""),
42  "Compression used in output stream file format.")
43  .close();
44 }
45 
46 
48  return Selection("VTK variant (ascii or binary)")
50  "ASCII variant of VTK file format")
52  "Binary variant of VTK file format (not supported yet)")
53  .close();
54 }
55 
56 
58  return Selection("Type of compression of VTK file format")
60  "Data in VTK file format are not compressed")
62  "Data in VTK file format are compressed using zlib (not supported yet)")
63  .close();
64 }
65 
66 
67 const int OutputVTK::registrar = Input::register_class< OutputVTK, const Input::Record & >("vtk") +
69 
70 
72 {
73  this->fix_main_file_extension(".pvd");
74 
75  if(this->rank == 0) {
76  this->_base_file.open(this->_base_filename.c_str());
77  INPUT_CHECK( this->_base_file.is_open() , "Can not open output file: %s\n", this->_base_filename.c_str() );
78  xprintf(MsgLog, "Writing flow output file: %s ... \n", this->_base_filename.c_str());
79  }
80 
81  this->make_subdirectory();
82  this->write_head();
83 }
84 
85 
86 
88 {}
89 
90 
91 
93 {
94  this->write_tail();
95 }
96 
97 
98 
99 
101 {
102  OLD_ASSERT(_mesh != nullptr, "Null mesh.\n");
103 
104  /* It's possible now to do output to the file only in the first process */
105  if(this->rank != 0) {
106  /* TODO: do something, when support for Parallel VTK is added */
107  return 0;
108  }
109 
110  ostringstream ss;
111  ss << main_output_basename_ << "-"
112  << std::setw(6) << std::setfill('0') << this->current_step
113  << ".vtu";
114 
115 
116  std::string frame_file_name = ss.str();
117  std::string frame_file_path = main_output_dir_ + "/" + main_output_basename_ + "/" + frame_file_name;
118 
119  _data_file.open(frame_file_path);
120  if(_data_file.is_open() == false) {
121  xprintf(Err, "Could not write output to the file: %s\n", frame_file_path.c_str());
122  return 0;
123  } else {
124  /* Set up data file */
125 
126  xprintf(MsgLog, "%s: Writing output file %s ... ",
127  __func__, this->_base_filename.c_str());
128 
129 
130  /* Set floating point precision to max */
131  this->_base_file.precision(std::numeric_limits<double>::digits10);
132 
133  /* Strip out relative path and add "base/" string */
134  std::string relative_frame_file = main_output_basename_ + "/" + frame_file_name;
135  this->_base_file << scientific << "<DataSet timestep=\"" << (isfinite(this->time)?this->time:0)
136  << "\" group=\"\" part=\"0\" file=\"" << relative_frame_file <<"\"/>" << endl;
137 
138  xprintf(MsgLog, "O.K.\n");
139 
140  xprintf(MsgLog, "%s: Writing output (frame %d) file %s ... ", __func__,
141  this->current_step, relative_frame_file.c_str());
142 
143  this->write_vtk_vtu();
144 
145  /* Close stream for file of current frame */
146  _data_file.close();
147  //delete data_file;
148  //this->_data_file = NULL;
149 
150  xprintf(MsgLog, "O.K.\n");
151  }
152 
153  return 1;
154 }
155 
156 
157 
158 
160 {
161  string main_file="./" + this->_base_filename; // guarantee that find_last_of succeeds
162  OLD_ASSERT( main_file.substr( main_file.size() - 4) == ".pvd" , "none");
163  unsigned int last_sep_pos=main_file.find_last_of(DIR_DELIMITER);
164  main_output_dir_=main_file.substr(2, last_sep_pos-2);
165  main_output_basename_=main_file.substr(last_sep_pos+1);
166  main_output_basename_=main_output_basename_.substr(0, main_output_basename_.size() - 4); // 5 = ".pvd".size() +1
167 
169  fp.create_output_dir();
170 }
171 
172 
173 
174 
176 {
177  ofstream &file = this->_data_file;
178 
179  file << "<?xml version=\"1.0\"?>" << endl;
180  // TODO: test endianess of platform (this would be important, when raw
181  // data will be saved to the VTK file)
182  file << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
183  file << "<UnstructuredGrid>" << endl;
184 }
185 
187 {
188  Mesh *mesh = this->_mesh;
189  ofstream &file = this->_data_file;
190 
191  int tmp;
192 
193  /* Write Points begin*/
194  file << "<Points>" << endl;
195  /* Write DataArray begin */
196  file << "<DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">" << endl;
197  /* Write own coordinates */
198  tmp = 0;
199  /* Set floating point precision */
200  file.precision(std::numeric_limits<double>::digits10);
201  FOR_NODES(mesh, node) {
202  node->aux = tmp; /* store index in the auxiliary variable */
203 
204  file << scientific << node->getX() << " ";
205  file << scientific << node->getY() << " ";
206  file << scientific << node->getZ() << " ";
207 
208  tmp++;
209  }
210  /* Write DataArray end */
211  file << endl << "</DataArray>" << endl;
212  /* Write Points end*/
213  file << "</Points>" << endl;
214 }
215 
217 {
218  Mesh *mesh = this->_mesh;
219  ofstream &file = this->_data_file;
220 
221  Node* node;
222  //ElementIter ele;
223  unsigned int li;
224  int tmp;
225 
226  /* Write Cells begin*/
227  file << "<Cells>" << endl;
228  /* Write DataArray begin */
229  file << "<DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">" << endl;
230  /* Write own coordinates */
231  FOR_ELEMENTS(mesh, ele) {
232  FOR_ELEMENT_NODES(ele, li) {
233  node = ele->node[li];
234  file << node->aux << " "; /* Write connectivity */
235  }
236  }
237  /* Write DataArray end */
238  file << endl << "</DataArray>" << endl;
239 
240  /* Write DataArray begin */
241  file << "<DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">" << endl;
242  /* Write number of nodes for each element */
243  tmp = 0;
244  FOR_ELEMENTS(mesh, ele) {
245  switch(ele->dim()) {
246  case 1:
247  tmp += VTK_LINE_SIZE;
248  break;
249  case 2:
250  tmp += VTK_TRIANGLE_SIZE;
251  break;
252  case 3:
253  tmp += VTK_TETRA_SIZE;
254  break;
255  }
256  file << tmp << " ";
257  }
258  /* Write DataArray end */
259  file << endl << "</DataArray>" << endl;
260 
261  /* Write DataArray begin */
262  file << "<DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">" << endl;
263  /* Write type of nodes for each element */
264  FOR_ELEMENTS(mesh, ele) {
265  switch(ele->dim()) {
266  case 1:
267  file << (int)VTK_LINE << " ";
268  break;
269  case 2:
270  file << (int)VTK_TRIANGLE << " ";
271  break;
272  case 3:
273  file << (int)VTK_TETRA << " ";
274  break;
275  }
276  }
277  /* Write DataArray end */
278  file << endl << "</DataArray>" << endl;
279 
280  /* Write Cells end*/
281  file << "</Cells>" << endl;
282 }
283 
285 {
286  Mesh *mesh = this->_mesh;
287  ofstream &file = this->_data_file;
288 
289  NodeIter node;
290  unsigned int li;
291 
292  /* Write Points begin*/
293  file << "<Points>" << endl;
294  /* Write DataArray begin */
295  file << "<DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">" << endl;
296  /* Set floating point precision */
297  file.precision(std::numeric_limits<double>::digits10);
298  FOR_ELEMENTS(mesh, ele) {
299  FOR_ELEMENT_NODES(ele, li) {
300  node = ele->node[li];
301 
302  file << scientific << node->getX() << " ";
303  file << scientific << node->getY() << " ";
304  file << scientific << node->getZ() << " ";
305  }
306  }
307  /* Write DataArray end */
308  file << endl << "</DataArray>" << endl;
309  /* Write Points end*/
310  file << "</Points>" << endl;
311 }
312 
314 {
315  Mesh *mesh = this->_mesh;
316  ofstream &file = this->_data_file;
317 
318  //Node* node;
319  //ElementIter ele;
320  unsigned int li, tmp;
321 
322  /* Write Cells begin*/
323  file << "<Cells>" << endl;
324  /* Write DataArray begin */
325  file << "<DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">" << endl;
326  /* Write own coordinates */
327  tmp = 0;
328  FOR_ELEMENTS(mesh, ele) {
329  FOR_ELEMENT_NODES(ele, li) {
330  file << tmp << " "; /* Write connectivity */
331  tmp++;
332  }
333  }
334  /* Write DataArray end */
335  file << endl << "</DataArray>" << endl;
336 
337  /* Write DataArray begin */
338  file << "<DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">" << endl;
339  /* Write number of nodes for each element */
340  tmp = 0;
341  FOR_ELEMENTS(mesh, ele) {
342  switch(ele->dim()) {
343  case 1:
344  tmp += VTK_LINE_SIZE;
345  break;
346  case 2:
347  tmp += VTK_TRIANGLE_SIZE;
348  break;
349  case 3:
350  tmp += VTK_TETRA_SIZE;
351  break;
352  }
353  file << tmp << " ";
354  }
355  /* Write DataArray end */
356  file << endl << "</DataArray>" << endl;
357 
358  /* Write DataArray begin */
359  file << "<DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">" << endl;
360  /* Write type of nodes for each element */
361  FOR_ELEMENTS(mesh, ele) {
362  switch(ele->dim()) {
363  case 1:
364  file << (int)VTK_LINE << " ";
365  break;
366  case 2:
367  file << (int)VTK_TRIANGLE << " ";
368  break;
369  case 3:
370  file << (int)VTK_TETRA << " ";
371  break;
372  }
373  }
374  /* Write DataArray end */
375  file << endl << "</DataArray>" << endl;
376 
377  /* Write Cells end*/
378  file << "</Cells>" << endl;
379 }
380 
381 
382 
383 
385 {
386  ofstream &file = this->_data_file;
387 
388  for(OutputDataPtr data : output_data_vec)
389  {
390  file << "<DataArray type=\"Float64\" "
391  << "Name=\"" << data->output_field_name <<"\" ";
392  if (data->n_elem_ > 1)
393  {
394  file
395  << "NumberOfComponents=\"" << data->n_elem_ << "\" ";
396  }
397  file << "format=\"ascii\">"
398  << endl;
399 
400  /* Set precision to max */
401  file.precision(std::numeric_limits<double>::digits10);
402 
403  data->print_all(file);
404 
405  file << "\n</DataArray>" << endl;
406  }
407 }
408 
409 
410 
411 
413  OutputDataFieldVec &output_data_vec)
414 {
415  if (output_data_vec.empty()) return;
416 
417  file << "Scalars=\"";
418  for(OutputDataPtr data : output_data_vec )
419  if (data->n_elem_ == OutputDataBase::N_SCALAR) file << data->output_field_name << ",";
420  file << "\" ";
421 
422  file << "Vectors=\"";
423  for(OutputDataPtr data : output_data_vec )
424  if (data->n_elem_ == OutputDataBase::N_VECTOR) file << data->output_field_name << ",";
425  file << "\" ";
426 
427  file << "Tensors=\"";
428  for(OutputDataPtr data : output_data_vec )
429  if (data->n_elem_ == OutputDataBase::N_TENSOR) file << data->output_field_name << ",";
430  file << "\"";
431 }
432 
433 
435 {
436  ofstream &file = this->_data_file;
437 
438  // merge node and corner data
439  OutputDataFieldVec node_corner_data(output_data_vec_[NODE_DATA]);
440  node_corner_data.insert(node_corner_data.end(),
442 
443  if( ! node_corner_data.empty() ) {
444  /* Write <PointData begin */
445  file << "<PointData ";
446  write_vtk_data_names(file, node_corner_data);
447  file << ">" << endl;
448 
449  /* Write data on nodes */
450  this->write_vtk_data_ascii(output_data_vec_[NODE_DATA]);
451 
452  /* Write data in corners of elements */
454 
455  /* Write PointData end */
456  file << "</PointData>" << endl;
457  }
458 }
459 
460 
462 {
463  ofstream &file = this->_data_file;
464 
465  auto &data_map = this->output_data_vec_[ELEM_DATA];
466  if (data_map.empty()) return;
467 
468  /* Write CellData begin */
469  file << "<CellData ";
470  write_vtk_data_names(file, data_map);
471  file << ">" << endl;
472 
473  /* Write own data */
474  this->write_vtk_data_ascii(data_map);
475 
476  /* Write PointData end */
477  file << "</CellData>" << endl;
478 }
479 
480 
482 {
483  ofstream &file = this->_data_file;
484 
485  file << "</UnstructuredGrid>" << endl;
486  file << "</VTKFile>" << endl;
487 }
488 
489 
491 {
492  ofstream &file = this->_data_file;
493  Mesh *mesh = this->_mesh;
494 
495  /* Write header */
496  this->write_vtk_vtu_head();
497 
498  /* When there is no discontinuous data, then write classical vtu */
499  if ( this->output_data_vec_[CORNER_DATA].empty() )
500  {
501  /* Write Piece begin */
502  file << "<Piece NumberOfPoints=\"" << mesh->n_nodes() << "\" NumberOfCells=\"" << mesh->n_elements() <<"\">" << endl;
503 
504  /* Write VTK Geometry */
505  this->write_vtk_geometry();
506 
507  /* Write VTK Topology */
508  this->write_vtk_topology();
509 
510  /* Write VTK scalar and vector data on nodes to the file */
511  this->write_vtk_node_data();
512 
513  /* Write VTK data on elements */
514  this->write_vtk_element_data();
515 
516  /* Write Piece end */
517  file << "</Piece>" << endl;
518 
519  } else {
520  /* Write Piece begin */
521  file << "<Piece NumberOfPoints=\"" << mesh->n_corners() << "\" NumberOfCells=\"" << mesh->n_elements() <<"\">" << endl;
522 
523  /* Write VTK Geometry */
525 
526  /* Write VTK Topology */
528 
529  /* Write VTK scalar and vector data on nodes to the file */
530  this->write_vtk_node_data();
531 
532  /* Write VTK data on elements */
533  this->write_vtk_element_data();
534 
535  /* Write Piece end */
536  file << "</Piece>" << endl;
537  }
538 
539  /* Write tail */
540  this->write_vtk_vtu_tail();
541 }
542 
543 
544 
546 {
547  /* It's possible now to do output to the file only in the first process */
548  if(this->rank != 0) {
549  /* TODO: do something, when support for Parallel VTK is added */
550  return 0;
551  }
552 
553  xprintf(MsgLog, "%s: Writing output file (head) %s ... ", __func__,
554  this->_base_filename.c_str() );
555 
556  this->_base_file << "<?xml version=\"1.0\"?>" << endl;
557  this->_base_file << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
558  this->_base_file << "<Collection>" << endl;
559 
560  xprintf(MsgLog, "O.K.\n");
561 
562  return 1;
563 }
564 
565 
567 {
568  /* It's possible now to do output to the file only in the first process */
569  if(this->rank != 0) {
570  /* TODO: do something, when support for Parallel VTK is added */
571  return 0;
572  }
573 
574  xprintf(MsgLog, "%s: Writing output file (tail) %s ... ", __func__,
575  this->_base_filename.c_str() );
576 
577  this->_base_file << "</Collection>" << endl;
578  this->_base_file << "</VTKFile>" << endl;
579 
580  xprintf(MsgLog, "O.K.\n");
581 
582  return 1;
583 }
584 
585 
586 
587 
double time
Definition: output_time.hh:200
Mesh * _mesh
Definition: output_time.hh:232
void write_vtk_discont_topology(void)
Write topology (connection of nodes) to the VTK file (.vtu)
Definition: output_vtk.cc:313
#define FOR_ELEMENT_NODES(i, j)
Definition: elements.h:139
static Input::Type::Abstract & get_input_format_type()
The specification of output file format.
Definition: output_time.cc:55
void fix_main_file_extension(std::string extension)
Definition: output_time.cc:103
double getY() const
Definition: nodes.hh:59
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:578
void make_subdirectory()
Definition: output_vtk.cc:159
Definition: nodes.hh:32
static const Input::Type::Record & get_input_type()
The definition of input record for vtk file format.
Definition: output_vtk.cc:31
void create_output_dir()
Definition: file_path.cc:140
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:490
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:50
#define FOR_ELEMENTS(_mesh_, __i)
Definition: mesh.h:408
Class for declaration of the input of type Bool.
Definition: type_base.hh:429
static const int registrar
Registrar of class to factory.
Definition: output_vtk.hh:136
Definition: mesh.h:99
#define INPUT_CHECK(i,...)
Debugging macros.
Definition: global_defs.h:51
void write_vtk_geometry(void)
Write geometry (position of nodes) to the VTK file (.vtu)
Definition: output_vtk.cc:186
string main_output_basename_
Definition: output_vtk.hh:217
int write_head(void)
This function writes header of VTK (.pvd) file format.
Definition: output_vtk.cc:545
string main_output_dir_
Definition: output_vtk.hh:219
void write_vtk_element_data(void)
Write data on elements to the VTK file (.vtu)
Definition: output_vtk.cc:461
Definition: system.hh:59
void write_vtk_discont_geometry(void)
Write geometry (position of nodes) to the VTK file (.vtu)
Definition: output_vtk.cc:284
double getZ() const
Definition: nodes.hh:61
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:193
#define OLD_ASSERT(...)
Definition: global_defs.h:128
int write_data(void)
This function write data to VTK (.pvd) file format for curent time.
Definition: output_vtk.cc:100
unsigned int n_elements() const
Definition: mesh.h:142
ofstream _data_file
Definition: output_vtk.hh:210
static const Input::Type::Selection & get_input_type_compression()
The definition of input record for selection of compression type.
Definition: output_vtk.cc:57
int current_step
Definition: output_time.hh:195
Selection & add_value(const int value, const std::string &key, const std::string &description="")
Adds one new value with name given by key to the Selection.
Accessor to the data with type Type::Record.
Definition: accessors.hh:277
#define xprintf(...)
Definition: system.hh:87
double getX() const
Definition: nodes.hh:57
void write_vtk_vtu_tail(void)
Write tail of VTK file (.vtu)
Definition: output_vtk.cc:481
This class is used for output data to VTK file format.
Definition: output_vtk.hh:33
unsigned int n_corners()
Definition: mesh.cc:182
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:459
int write_tail(void)
This function writes tail of VTK (.pvd) file format.
Definition: output_vtk.cc:566
int aux
Definition: nodes.hh:93
const Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:271
ofstream _base_file
Definition: output_time.hh:222
The class for outputting data during time.
Definition: output_time.hh:42
~OutputVTK()
The destructor of this class. It writes tail of the file too.
Definition: output_vtk.cc:92
#define FOR_NODES(_mesh_, i)
Definition: mesh.h:62
string _base_filename
Definition: output_time.hh:227
Dedicated class for storing path to input and output files.
Definition: file_path.hh:42
void write_vtk_data_ascii(OutputDataFieldVec &output_data_map)
Definition: output_vtk.cc:384
OutputVTK()
The constructor of this class. The head of file is written, when constructor is called.
Definition: output_vtk.cc:87
const Selection & close() const
Close the Selection, no more values can be added.
void write_vtk_node_data(void)
Write data on nodes to the VTK file (.vtu)
Definition: output_vtk.cc:434
#define DIR_DELIMITER
Definition: system.hh:44
OutputDataFieldVec output_data_vec_[N_DISCRETE_SPACES]
Definition: output_time.hh:190
Definition: system.hh:59
unsigned int n_nodes() const
Definition: mesh.h:138
std::shared_ptr< OutputDataBase > OutputDataPtr
Definition: output_time.hh:183
Record type proxy class.
Definition: type_record.hh:171
void write_vtk_vtu_head(void)
Write header of VTK file (.vtu)
Definition: output_vtk.cc:175
Template for classes storing finite set of named values.
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:246
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:47
void write_vtk_topology(void)
Write topology (connection of nodes) to the VTK file (.vtu)
Definition: output_vtk.cc:216
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:412