Flow123d  jenkins-Flow123d-windows32-release-multijob-51
output_vtk.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2007 Technical University of Liberec. All rights reserved.
4  *
5  * Please make a following refer to Flow123d on your project site if you use the program for any purpose,
6  * especially for academic research:
7  * Flow123d, Research Centre: Advanced Remedial Technologies, Technical University of Liberec, Czech Republic
8  *
9  * This program is free software; you can redistribute it and/or modify it under the terms
10  * of the GNU General Public License version 3 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this program; if not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
18  *
19  *
20  * $Id: output_vtk.cc 2505 2013-09-13 14:52:27Z jiri.hnidek $
21  * $Revision$
22  * $LastChangedBy$
23  * $LastChangedDate$
24  *
25  * @file output_vtk.cc
26  * @brief The functions for outputs to VTK files.
27  *
28  */
29 
30 #include <limits.h>
31 #include <mpi.h>
32 #include <boost/any.hpp>
33 #include <dirent.h>
34 #include <sys/stat.h>
35 #include <errno.h>
36 #include <assert.h>
37 
38 #include "system/xio.h"
39 #include "io/output.h"
40 #include "io/output_vtk.h"
41 #include "mesh/mesh.h"
42 
43 
44 using namespace Input::Type;
45 
47  = Record("vtk", "Parameters of vtk output format.")
48  // It is derived from abstract class
50  .declare_key("variant", input_type_variant, Default("ascii"),
51  "Variant of output stream file format.")
52  // The parallel or serial variant
53  .declare_key("parallel", Bool(), Default("false"),
54  "Parallel or serial version of file format.")
55  .declare_key("compression", input_type_compression, Default("none"),
56  "Compression used in output stream file format.");
57 
58 
60  = Selection("VTK variant (ascii or binary)")
62  "ASCII variant of VTK file format")
64  "Binary variant of VTK file format (not supported yet)");
65 
66 
68  = Selection("Type of compression of VTK file format")
70  "Data in VTK file format are not compressed")
72  "Data in VTK file format are compressed using zlib (not supported yet)");
73 
74 
75 
77 {
78  ofstream &file = this->get_data_file();
79 
80  file << "<?xml version=\"1.0\"?>" << endl;
81  // TODO: test endianess of platform (this would be important, when raw
82  // data will be saved to the VTK file)
83  file << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
84  file << "<UnstructuredGrid>" << endl;
85 }
86 
88 {
89  Mesh *mesh = this->get_mesh();
90  ofstream &file = this->get_data_file();
91 
92  //NodeIter node;
93  int tmp;
94 
95  /* Write Points begin*/
96  file << "<Points>" << endl;
97  /* Write DataArray begin */
98  file << "<DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">" << endl;
99  /* Write own coordinates */
100  tmp = 0;
101  /* Set floating point precision */
102  this->get_data_file().precision(std::numeric_limits<double>::digits10);
103  FOR_NODES(mesh, node) {
104  node->aux = tmp; /* store index in the auxiliary variable */
105 
106  file << scientific << node->getX() << " ";
107  file << scientific << node->getY() << " ";
108  file << scientific << node->getZ() << " ";
109 
110  tmp++;
111  }
112  /* Write DataArray end */
113  file << endl << "</DataArray>" << endl;
114  /* Write Points end*/
115  file << "</Points>" << endl;
116 }
117 
119 {
120  Mesh *mesh = this->get_mesh();
121  ofstream &file = this->get_data_file();
122 
123  Node* node;
124  //ElementIter ele;
125  unsigned int li;
126  int tmp;
127 
128  /* Write Cells begin*/
129  file << "<Cells>" << endl;
130  /* Write DataArray begin */
131  file << "<DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">" << endl;
132  /* Write own coordinates */
133  FOR_ELEMENTS(mesh, ele) {
134  FOR_ELEMENT_NODES(ele, li) {
135  node = ele->node[li];
136  file << node->aux << " "; /* Write connectivity */
137  }
138  }
139  /* Write DataArray end */
140  file << endl << "</DataArray>" << endl;
141 
142  /* Write DataArray begin */
143  file << "<DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">" << endl;
144  /* Write number of nodes for each element */
145  tmp = 0;
146  FOR_ELEMENTS(mesh, ele) {
147  switch(ele->dim()) {
148  case 1:
149  tmp += VTK_LINE_SIZE;
150  break;
151  case 2:
152  tmp += VTK_TRIANGLE_SIZE;
153  break;
154  case 3:
155  tmp += VTK_TETRA_SIZE;
156  break;
157  }
158  file << tmp << " ";
159  }
160  /* Write DataArray end */
161  file << endl << "</DataArray>" << endl;
162 
163  /* Write DataArray begin */
164  file << "<DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">" << endl;
165  /* Write type of nodes for each element */
166  FOR_ELEMENTS(mesh, ele) {
167  switch(ele->dim()) {
168  case 1:
169  file << (int)VTK_LINE << " ";
170  break;
171  case 2:
172  file << (int)VTK_TRIANGLE << " ";
173  break;
174  case 3:
175  file << (int)VTK_TETRA << " ";
176  break;
177  }
178  }
179  /* Write DataArray end */
180  file << endl << "</DataArray>" << endl;
181 
182  /* Write Cells end*/
183  file << "</Cells>" << endl;
184 }
185 
187 {
188  Mesh *mesh = this->get_mesh();
189  ofstream &file = this->get_data_file();
190 
191  NodeIter node;
192  unsigned int li;
193 
194  /* Write Points begin*/
195  file << "<Points>" << endl;
196  /* Write DataArray begin */
197  file << "<DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">" << endl;
198  /* Set floating point precision */
199  this->get_data_file().precision(std::numeric_limits<double>::digits10);
200  FOR_ELEMENTS(mesh, ele) {
201  FOR_ELEMENT_NODES(ele, li) {
202  node = ele->node[li];
203 
204  file << scientific << node->getX() << " ";
205  file << scientific << node->getY() << " ";
206  file << scientific << node->getZ() << " ";
207  }
208  }
209  /* Write DataArray end */
210  file << endl << "</DataArray>" << endl;
211  /* Write Points end*/
212  file << "</Points>" << endl;
213 }
214 
216 {
217  Mesh *mesh = this->get_mesh();
218  ofstream &file = this->get_data_file();
219 
220  //Node* node;
221  //ElementIter ele;
222  unsigned int li, tmp;
223 
224  /* Write Cells begin*/
225  file << "<Cells>" << endl;
226  /* Write DataArray begin */
227  file << "<DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">" << endl;
228  /* Write own coordinates */
229  tmp = 0;
230  FOR_ELEMENTS(mesh, ele) {
231  FOR_ELEMENT_NODES(ele, li) {
232  file << tmp << " "; /* Write connectivity */
233  tmp++;
234  }
235  }
236  /* Write DataArray end */
237  file << endl << "</DataArray>" << endl;
238 
239  /* Write DataArray begin */
240  file << "<DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">" << endl;
241  /* Write number of nodes for each element */
242  tmp = 0;
243  FOR_ELEMENTS(mesh, ele) {
244  switch(ele->dim()) {
245  case 1:
246  tmp += VTK_LINE_SIZE;
247  break;
248  case 2:
249  tmp += VTK_TRIANGLE_SIZE;
250  break;
251  case 3:
252  tmp += VTK_TETRA_SIZE;
253  break;
254  }
255  file << tmp << " ";
256  }
257  /* Write DataArray end */
258  file << endl << "</DataArray>" << endl;
259 
260  /* Write DataArray begin */
261  file << "<DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">" << endl;
262  /* Write type of nodes for each element */
263  FOR_ELEMENTS(mesh, ele) {
264  switch(ele->dim()) {
265  case 1:
266  file << (int)VTK_LINE << " ";
267  break;
268  case 2:
269  file << (int)VTK_TRIANGLE << " ";
270  break;
271  case 3:
272  file << (int)VTK_TETRA << " ";
273  break;
274  }
275  }
276  /* Write DataArray end */
277  file << endl << "</DataArray>" << endl;
278 
279  /* Write Cells end*/
280  file << "</Cells>" << endl;
281 }
282 
283 
284 
285 
287 {
288  ofstream &file = this->get_data_file();
289 
290  for( OutputDataBase* data : vec_output_data)
291  {
292  file << "<DataArray type=\"Float64\" "
293  << "Name=\"" << data->output_field_name <<"\" ";
294  if (data->n_elem_ > 1)
295  {
296  file
297  << "NumberOfComponents=\"" << data->n_elem_ << "\" ";
298  }
299  file << "format=\"ascii\">"
300  << endl;
301 
302  /* Set precision to max */
303  //file.precision(std::numeric_limits<float>::digits10);
304  file.precision(std::numeric_limits<double>::digits10);
305 
306  for(unsigned int i=0; i < data->n_values; i ++) {
307  data->print(file, i);
308  }
309 
310  file << "\n</DataArray>" << endl;
311  }
312 }
313 
314 
315 
316 
317 void OutputVTK::write_vtk_data_names(ofstream &file, vector<OutputDataBase*> &vec_output_data)
318 {
319  file << "Scalars=\"";
320  for( auto &data : vec_output_data)
321  if (data->n_elem_ == OutputDataBase::scalar) file << data->output_field_name << ",";
322  file << "\" ";
323 
324  file << "Vectors=\"";
325  for( auto &data : vec_output_data)
326  if (data->n_elem_ == OutputDataBase::vector) file << data->output_field_name << ",";
327  file << "\" ";
328 
329  file << "Tensors=\"";
330  for( auto &data : vec_output_data)
331  if (data->n_elem_ == OutputDataBase::tensor) file << data->output_field_name << ",";
332  file << "\"";
333 }
334 
335 
337 {
338  ofstream &file = this->get_data_file();
339 
340  // merge node and corner data
341  vector<OutputDataBase*> node_corner_data(this->node_data);
342  node_corner_data.insert(node_corner_data.end(), this->corner_data.begin(), this->corner_data.end());
343 
344  if( ! node_corner_data.empty() ) {
345  /* Write <PointData begin */
346  file << "<PointData ";
347  write_vtk_data_names(file, node_corner_data);
348  file << ">" << endl;
349 
350  /* Write data on nodes */
351  if( ! this->node_data.empty() ) {
352  this->write_vtk_data_ascii(this->node_data);
353  }
354 
355  /* Write data in corners of elements */
356  if( ! this->corner_data.empty() ) {
357  this->write_vtk_data_ascii(this->corner_data);
358  }
359 
360  /* Write PointData end */
361  file << "</PointData>" << endl;
362  }
363 }
364 
365 
367 {
368  ofstream &file = this->get_data_file();
369 
370  if(this->elem_data.empty() != true) {
371  /* Write PointData begin */
372  file << "<CellData ";
373  write_vtk_data_names(file, this->elem_data);
374  file << ">" << endl;
375 
376  /* Write own data */
377  this->write_vtk_data_ascii(this->elem_data);
378 
379  /* Write PointData end */
380  file << "</CellData>" << endl;
381  }
382 }
383 
384 
386 {
387  ofstream &file = this->get_data_file();
388 
389  file << "</UnstructuredGrid>" << endl;
390  file << "</VTKFile>" << endl;
391 }
392 
393 
395 {
396  ofstream &file = this->get_data_file();
397  Mesh *mesh = this->get_mesh();
398 
399  /* Write header */
400  this->write_vtk_vtu_head();
401 
402  /* When there is no discontinuous data, then write classical vtu */
403  if(this->corner_data.empty() == true)
404  {
405  /* Write Piece begin */
406  file << "<Piece NumberOfPoints=\"" << mesh->n_nodes() << "\" NumberOfCells=\"" << mesh->n_elements() <<"\">" << endl;
407 
408  /* Write VTK Geometry */
409  this->write_vtk_geometry();
410 
411  /* Write VTK Topology */
412  this->write_vtk_topology();
413 
414  /* Write VTK scalar and vector data on nodes to the file */
415  this->write_vtk_node_data();
416 
417  /* Write VTK data on elements */
418  this->write_vtk_element_data();
419 
420  /* Write Piece end */
421  file << "</Piece>" << endl;
422 
423  } else {
424  /* Write Piece begin */
425  file << "<Piece NumberOfPoints=\"" << this->get_corner_count() << "\" NumberOfCells=\"" << mesh->n_elements() <<"\">" << endl;
426 
427  /* Write VTK Geometry */
428  this->write_vtk_discont_geometry();
429 
430  /* Write VTK Topology */
431  this->write_vtk_discont_topology();
432 
433  /* Write VTK scalar and vector data on nodes to the file */
434  this->write_vtk_node_data();
435 
436  /* Write VTK data on elements */
437  this->write_vtk_element_data();
438 
439  /* Write Piece end */
440  file << "</Piece>" << endl;
441  }
442 
443  /* Write tail */
444  this->write_vtk_vtu_tail();
445 }
446 
447 
449 {
450  //Mesh *mesh = this->output_time->get_mesh();
451  char base_dir_name[PATH_MAX];
452  char new_dir_name[PATH_MAX];
453  char base_file_name[PATH_MAX];
454  char base[PATH_MAX];
455  char frame_file_name[PATH_MAX];
456  ofstream *data_file = new ofstream;
457  DIR *dir;
458  int i, j, ret;
459  int rank=0;
461 
462  /* It's possible now to do output to the file only in the first process */
463  if(rank!=0) {
464  /* TODO: do something, when support for Parallel VTK is added */
465  return 0;
466  }
467 
468  // Write header with mesh, when it hasn't been written to output file yet
469  if(this->header_written == false) {
470  this->write_head();
471  this->header_written = true;
472  }
473 
474  strncpy(base_dir_name, this->base_filename()->c_str(), PATH_MAX);
475 
476  /* Remove last file name from base_name and find position of last directory
477  * delimiter: '/' */
478  for(j=strlen(base_dir_name)-1; j>0; j--) {
479  if(base_dir_name[j]=='/') {
480  base_dir_name[j]='\0';
481  break;
482  }
483  }
484 
485  strncpy(base_file_name, this->base_filename()->c_str(), PATH_MAX);
486 
487  /* Find, where is the '.' character of .pvd suffix of base_name */
488  for(i=strlen(base_file_name)-1; i>=0; i--) {
489  if(base_file_name[i]=='.') {
490  break;
491  }
492  }
493 
494  /* Create base of pvd file. Example ./output/transport.pvd -> transport */
495  strncpy(base, &base_file_name[j+1], i-j-1);
496  base[i-j-1]='\0';
497 
498  /* New folder for output */
499  sprintf(new_dir_name, "%s/%s", base_dir_name, base);
500 
501  /* Try to open directory */
502  dir = opendir(new_dir_name);
503  if(dir == NULL) {
504  /* Directory doesn't exist. Create new one. */
505  ret = mkdir(new_dir_name, 0777);
506 
507  if(ret != 0) {
508  xprintf(Err, "Couldn't create directory: %s, error: %s\n", new_dir_name, strerror(errno));
509  }
510  } else {
511  closedir(dir);
512  }
513 
514  sprintf(frame_file_name, "%s/%s-%06d.vtu", new_dir_name, base, this->current_step);
515 
516  data_file->open(frame_file_name);
517  if(data_file->is_open() == false) {
518  xprintf(Err, "Could not write output to the file: %s\n", frame_file_name);
519  return 0;
520  } else {
521  /* Set up data file */
522  this->set_data_file(data_file);
523 
524  xprintf(MsgLog, "%s: Writing output file %s ... ", __func__, this->base_filename()->c_str());
525 
526  /* Find first directory delimiter */
527  for(i=strlen(frame_file_name); i>=0; i--) {
528  if(frame_file_name[i]==DIR_DELIMITER) {
529  break;
530  }
531  }
532 
533  /* Set floating point precision to max */
534  this->get_base_file().precision(std::numeric_limits<double>::digits10);
535 
536  /* Strip out relative path and add "base/" string */
537  this->get_base_file() << scientific << "<DataSet timestep=\"" << (isfinite(this->time)?this->time:0) << "\" group=\"\" part=\"0\" file=\"" << base << "/" << &frame_file_name[i+1] <<"\"/>" << endl;
538 
539  xprintf(MsgLog, "O.K.\n");
540 
541  xprintf(MsgLog, "%s: Writing output (frame %d) file %s ... ", __func__,
542  this->current_step, frame_file_name);
543 
544  this->write_vtk_vtu();
545 
546  /* Close stream for file of current frame */
547  data_file->close();
548  delete data_file;
549  this->set_data_file(NULL);
550 
551  xprintf(MsgLog, "O.K.\n");
552  }
553 
554  return 1;
555 }
556 
557 
559 {
560  int rank=0;
562 
563  /* It's possible now to do output to the file only in the first process */
564  if(rank!=0) {
565  /* TODO: do something, when support for Parallel VTK is added */
566  return 0;
567  }
568 
569  xprintf(MsgLog, "%s: Writing output file (head) %s ... ", __func__,
570  this->base_filename()->c_str() );
571 
572  this->get_base_file() << "<?xml version=\"1.0\"?>" << endl;
573  this->get_base_file() << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
574  this->get_base_file() << "<Collection>" << endl;
575 
576  xprintf(MsgLog, "O.K.\n");
577 
578  return 1;
579 }
580 
581 
583 {
584  int rank=0;
586 
587  /* It's possible now to do output to the file only in the first process */
588  if(rank!=0) {
589  /* TODO: do something, when support for Parallel VTK is added */
590  return 0;
591  }
592 
593  xprintf(MsgLog, "%s: Writing output file (tail) %s ... ", __func__,
594  this->base_filename()->c_str() );
595 
596  this->get_base_file() << "</Collection>" << endl;
597  this->get_base_file() << "</VTKFile>" << endl;
598 
599  xprintf(MsgLog, "O.K.\n");
600 
601  return 1;
602 }
603 
604 
606 {
608  this->header_written = false;
609 }
610 
611 
613 {
614  this->write_tail();
615 }
616 
Common parent class for templated OutputData.
static Input::Type::AbstractRecord input_format_type
The specification of output file format.
Definition: output_time.hh:62
void write_vtk_discont_topology(void)
Write topology (connection of nodes) to the VTK file (.vtu)
Definition: output_vtk.cc:215
#define FOR_ELEMENT_NODES(i, j)
Definition: elements.h:150
Header: The functions for all outputs.
double getY() const
Definition: nodes.hh:71
static Input::Type::Selection input_type_variant
The definition of input record for selection of variant of file format.
Definition: output_vtk.h:70
Definition: nodes.hh:44
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:394
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:39
#define FOR_ELEMENTS(_mesh_, __i)
Definition: mesh.h:357
Class for declaration of the input of type Bool.
Definition: type_base.hh:321
???
Definition: mesh.h:108
bool header_written
Definition: output_vtk.h:98
Record & derive_from(AbstractRecord &parent)
Definition: type_record.cc:169
void write_vtk_geometry(void)
Write geometry (position of nodes) to the VTK file (.vtu)
Definition: output_vtk.cc:87
int write_head(void)
This function writes header of VTK (.pvd) file format.
Definition: output_vtk.cc:558
I/O functions with filename storing, able to track current line in opened file. All standard stdio fu...
void write_vtk_element_data(void)
Write data on elements to the VTK file (.vtu)
Definition: output_vtk.cc:366
void write_vtk_data_names(ofstream &file, vector< OutputDataBase * > &output_data)
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:317
Definition: system.hh:72
void write_vtk_discont_geometry(void)
Write geometry (position of nodes) to the VTK file (.vtu)
Definition: output_vtk.cc:186
static Input::Type::Record input_type
The definition of input record for vtk file format.
Definition: output_vtk.h:65
double getZ() const
Definition: nodes.hh:73
void write_vtk_data_ascii(vector< OutputDataBase * > &output_data)
Definition: output_vtk.cc:286
int write_data(void)
This function write data to VTK (.pvd) file format for curent time.
Definition: output_vtk.cc:448
unsigned int n_elements() const
Definition: mesh.h:137
static Input::Type::Selection input_type_compression
The definition of input record for selection of compression type.
Definition: output_vtk.h:75
Selection & add_value(const int value, const std::string &key, const std::string &description="")
Accessor to the data with type Type::Record.
Definition: accessors.hh:308
#define xprintf(...)
Definition: system.hh:100
double getX() const
Definition: nodes.hh:69
void write_vtk_vtu_tail(void)
Write tail of VTK file (.vtu)
Definition: output_vtk.cc:385
int write_tail(void)
This function writes tail of VTK (.pvd) file format.
Definition: output_vtk.cc:582
int aux
Definition: nodes.hh:105
The class for outputing data during time.
Definition: output_time.hh:37
~OutputVTK()
The destructor of this class. It writes tail of the file too.
Definition: output_vtk.cc:612
#define FOR_NODES(_mesh_, i)
Definition: mesh.h:71
OutFileFormat file_format
Definition: output_time.hh:263
#define MPI_Comm_rank
Definition: mpi.h:236
Header: The functions for VTK outputs.
OutputVTK()
The constructor of this class. The head of file is written, when constructor is called.
void write_vtk_node_data(void)
Write data on nodes to the VTK file (.vtu)
Definition: output_vtk.cc:336
#define DIR_DELIMITER
Definition: system.hh:56
#define MPI_COMM_WORLD
Definition: mpi.h:123
Definition: system.hh:72
unsigned int n_nodes() const
Definition: mesh.h:133
Record type proxy class.
Definition: type_record.hh:161
void write_vtk_vtu_head(void)
Write header of VTK file (.vtu)
Definition: output_vtk.cc:76
Template for classes storing finite set of named values.
void write_vtk_topology(void)
Write topology (connection of nodes) to the VTK file (.vtu)
Definition: output_vtk.cc:118
Record & declare_key(const string &key, const KeyType &type, const Default &default_value, const string &description)
Definition: type_record.cc:386