Flow123d  release_2.2.0-914-gf1a3a4f
msh_vtkreader.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 msh_vtkreader.cc
15  * @brief
16  * @author dalibor
17  */
18 
19 
20 #include <iostream>
21 #include <vector>
22 #include "boost/lexical_cast.hpp"
23 
24 #include "msh_vtkreader.hh"
25 #include "system/system.hh"
26 #include "mesh/bih_tree.hh"
27 
28 #include "config.h"
29 #include <zlib.h>
30 
31 
32 /*******************************************************************
33  * Helper methods
34  */
35 template<typename T>
36 T read_binary_value(std::istream &data_stream)
37 {
38  T val;
39  data_stream.read(reinterpret_cast<char *>(&val), sizeof(val));
40  return val;
41 }
42 
43 
44 uint64_t read_header_type(DataType data_header_type, std::istream &data_stream)
45 {
46  if (data_header_type == DataType::uint64)
47  return read_binary_value<uint64_t>(data_stream);
48  else if (data_header_type == DataType::uint32)
49  return (uint64_t)read_binary_value<unsigned int>(data_stream);
50  else {
51  ASSERT(false).error("Unsupported header_type!\n"); //should not happen
52  return 0;
53  }
54 }
55 
56 
57 /*******************************************************************
58  * implementation of VtkMeshReader
59  */
60 const double VtkMeshReader::point_tolerance = 1E-10;
61 
62 
64 : BaseMeshReader(file_name),
65  time_step_(0.0)
66 {
67  data_section_name_ = "DataArray";
68  has_compatible_mesh_ = false;
70 }
71 
72 
73 
74 VtkMeshReader::VtkMeshReader(const FilePath &file_name, std::shared_ptr<ElementDataFieldMap> element_data_values, double time_step)
75 : BaseMeshReader(file_name, element_data_values),
76  time_step_(time_step)
77 {
78  data_section_name_ = "DataArray";
79  has_compatible_mesh_ = false;
81 }
82 
83 
84 
86 {
87  delete data_stream_;
88 }
89 
90 
91 
92 void VtkMeshReader::read_base_vtk_attributes(pugi::xml_node vtk_node, unsigned int &n_nodes, unsigned int &n_elements)
93 {
94  try {
95  // header type of appended data
96  header_type_ = this->get_data_type( vtk_node.attribute("header_type").as_string() );
97  } catch(ExcWrongType &e) {
98  e << EI_SectionTypeName("base parameter header_type");
99  }
100  // data format
102  data_format_ = DataFormat::ascii;
103  } else {
105  // Allowable values of header type are only 'UInt64' or 'UInt32'
106  THROW( ExcWrongType() << EI_ErrMessage("Forbidden") << EI_SectionTypeName("base parameter header_type")
107  << EI_VTKFile(tok_.f_name()));
108  }
109  std::string compressor = vtk_node.attribute("compressor").as_string();
110  if (compressor == "vtkZLibDataCompressor")
111  data_format_ = DataFormat::binary_zlib;
112  else
113  data_format_ = DataFormat::binary_uncompressed;
114  }
115  // size of node and element vectors
116  pugi::xml_node piece_node = vtk_node.child("UnstructuredGrid").child("Piece");
117  n_nodes = piece_node.attribute("NumberOfPoints").as_uint();
118  n_elements = piece_node.attribute("NumberOfCells").as_uint();
119 }
120 
121 
122 
124  Tokenizer::Position appended_pos;
125 
126  {
127  // find line by tokenizer
128  tok_.set_position( Tokenizer::Position() );
129  if (! tok_.skip_to("AppendedData"))
130  THROW(ExcMissingTag() << EI_TagType("tag") << EI_TagName("AppendedData") << EI_VTKFile(tok_.f_name()) );
131  else {
132  appended_pos = tok_.get_position();
133  }
134  }
135 
136  // find exact position of appended data (starts with '_')
137  char c;
138  data_stream_->seekg(appended_pos.file_position_);
139  do {
140  data_stream_->get(c);
141  } while (c!='_');
142  appended_pos.file_position_ = data_stream_->tellg();
143  appended_pos.line_counter_++;
144  delete data_stream_; // close stream
145 
146  // reopen stream in binary mode
147  data_stream_ = new std::ifstream( tok_.f_name(), std::ios_base::in | std::ios_base::binary );
148 
149  return appended_pos;
150 }
151 
152 
153 BaseMeshReader::MeshDataHeader VtkMeshReader::create_header(pugi::xml_node node, unsigned int n_entities, Tokenizer::Position pos,
155 {
156  MeshDataHeader header;
157  header.field_name = node.attribute("Name").as_string();
158  header.time = this->time_step_;
159  try {
160  header.type = this->get_data_type( node.attribute("type").as_string() );
161  } catch(ExcWrongType &e) {
162  e << EI_SectionTypeName("DataArray " + header.field_name);
163  }
164  header.discretization = disc;
165  if (disc == OutputTime::DiscreteSpace::NATIVE_DATA) {
166  header.n_components = node.attribute("n_dofs_per_element").as_uint();
167  header.dof_handler_hash = node.attribute("dof_handler_hash").as_uint();
168  } else {
169  header.n_components = node.attribute("NumberOfComponents").as_uint(1);
170  }
171  header.n_entities = n_entities;
172  std::string format = node.attribute("format").as_string();
173  if (format=="appended") {
174  if (data_format_ == DataFormat::ascii)
175  THROW(ExcInvalidFormat() << EI_FieldName(header.field_name) << EI_ExpectedFormat("ascii") << EI_VTKFile(tok_.f_name()) );
176  std::streampos file_pos = pos.file_position_;
177  file_pos += node.attribute("offset").as_uint();
178  header.position = Tokenizer::Position( file_pos, pos.line_counter_, pos.line_position_ );
179  } else if (format=="ascii") {
180  if (data_format_ != DataFormat::ascii)
181  THROW(ExcInvalidFormat() << EI_FieldName(header.field_name) << EI_ExpectedFormat("appended") << EI_VTKFile(tok_.f_name()) );
182 
183  tok_.set_position( Tokenizer::Position() );
184  bool is_point = (header.field_name=="");
185  std::string found_str = (is_point) ? "<Points>" : "Name=\"" + header.field_name + "\"";
186  if (! tok_.skip_to(found_str))
187  THROW(ExcMissingTag() << EI_TagType("DataArray tag") << EI_TagName(header.field_name) << EI_VTKFile(tok_.f_name()) );
188  else {
189  if (is_point) tok_.skip_to("DataArray");
190  header.position = tok_.get_position();
191  }
192  } else {
193  THROW(ExcUnknownFormat() << EI_FieldName(header.field_name) << EI_VTKFile(tok_.f_name()) );
194  }
195 
196  return header;
197 }
198 
199 
201 {
202  pugi::xml_document doc;
203  doc.load_file( tok_.f_name().c_str() );
204  unsigned int n_nodes, n_elements;
205  this->read_base_vtk_attributes( doc.child("VTKFile"), n_nodes, n_elements );
206 
207  // open ifstream for find position
208  data_stream_ = new std::ifstream( tok_.f_name() );
209 
210  // data of appended tag
211  Tokenizer::Position appended_pos;
213  // no AppendedData tag
214  } else {
215  appended_pos = get_appended_position();
216  }
217 
218  pugi::xml_node node = doc.child("VTKFile").child("UnstructuredGrid").child("Piece");
219 
220  header_table_.clear();
221 
222  // create headers of Points and Cells DataArrays
223  auto points_header = create_header( node.child("Points").child("DataArray"), n_nodes, appended_pos,
224  OutputTime::DiscreteSpace::MESH_DEFINITION );
225  points_header.field_name = "Points";
226  header_table_.insert( std::pair<std::string, MeshDataHeader>("Points", points_header) );
227  auto con_header = create_header( node.child("Cells").find_child_by_attribute("DataArray", "Name", "connectivity"),
228  n_elements, appended_pos, OutputTime::DiscreteSpace::MESH_DEFINITION );
229  header_table_.insert( std::pair<std::string, MeshDataHeader>("connectivity", con_header) );
230  auto offsets_header = create_header( node.child("Cells").find_child_by_attribute("DataArray", "Name", "offsets"),
231  n_elements, appended_pos, OutputTime::DiscreteSpace::MESH_DEFINITION );
232  header_table_.insert( std::pair<std::string, MeshDataHeader>("offsets", offsets_header) );
233  auto types_header = create_header( node.child("Cells").find_child_by_attribute("DataArray", "Name", "types"), n_elements,
234  appended_pos, OutputTime::DiscreteSpace::MESH_DEFINITION );
235  header_table_.insert( std::pair<std::string, MeshDataHeader>("types", types_header) );
236 
237  pugi::xml_node point_node = node.child("PointData");
238  for (pugi::xml_node subnode = point_node.child("DataArray"); subnode; subnode = subnode.next_sibling("DataArray")) {
239  auto header = create_header( subnode, n_nodes, appended_pos, OutputTime::DiscreteSpace::NODE_DATA );
240  header_table_.insert( std::pair<std::string, MeshDataHeader>(header.field_name, header) );
241  }
242 
243  pugi::xml_node cell_node = node.child("CellData");
244  for (pugi::xml_node subnode = cell_node.child("DataArray"); subnode; subnode = subnode.next_sibling("DataArray")) {
245  auto header = create_header( subnode, n_elements, appended_pos, OutputTime::DiscreteSpace::ELEM_DATA );
246  header_table_.insert( std::pair<std::string, MeshDataHeader>(header.field_name, header) );
247  }
248 
249  pugi::xml_node native_node = node.child("Flow123dData");
250  for (pugi::xml_node subnode = native_node.child("DataArray"); subnode; subnode = subnode.next_sibling("DataArray")) {
251  auto header = create_header( subnode, n_elements, appended_pos, OutputTime::DiscreteSpace::NATIVE_DATA );
252  header_table_.insert( std::pair<std::string, MeshDataHeader>(header.field_name, header) );
253  }
254 }
255 
256 
258 {
259  unsigned int count = header_table_.count(header_query.field_name);
260 
261  if (count == 0) {
262  // no data found
263  THROW( ExcFieldNameNotFound() << EI_FieldName(header_query.field_name) << EI_MeshFile(tok_.f_name()));
264  } else if (count == 1) {
265  HeaderTable::iterator table_it = header_table_.find(header_query.field_name);
266 
267  // check discretization
268  if (header_query.discretization != table_it->second.discretization) {
269  if (header_query.discretization != OutputTime::DiscreteSpace::UNDEFINED) {
270  WarningOut().fmt(
271  "Invalid value of 'input_discretization' for field '{}', time: {}.\nCorrect discretization type will be used.\n",
272  header_query.field_name, header_query.time);
273  }
274  header_query.discretization = table_it->second.discretization;
275  }
276 
277  if (header_query.discretization == OutputTime::DiscreteSpace::NATIVE_DATA)
278  if (header_query.dof_handler_hash != table_it->second.dof_handler_hash) {
279  THROW(ExcInvalidDofHandler() << EI_FieldName(header_query.field_name) << EI_VTKFile(tok_.f_name()) );
280  }
281  actual_header_ = table_it->second;
282  } else {
283  HeaderTable::iterator table_it;
284  for (table_it=header_table_.equal_range(header_query.field_name).first; table_it!=header_table_.equal_range(header_query.field_name).second; ++table_it) {
285  if (header_query.discretization != table_it->second.discretization) {
286  header_query.dof_handler_hash = table_it->second.dof_handler_hash;
287  actual_header_ = table_it->second;
288  }
289  }
290  THROW( ExcMissingFieldDiscretization() << EI_FieldName(header_query.field_name) << EI_Time(header_query.time) << EI_MeshFile(tok_.f_name()));
291  }
292 
293  return actual_header_;
294 }
295 
296 
297 
298 DataType VtkMeshReader::get_data_type(std::string type_str) {
299  // names of types in DataArray section
300  static const std::map<std::string, DataType> types = {
301  {"Int8", DataType::int8},
302  {"UInt8", DataType::uint8},
303  {"Int16", DataType::int16},
304  {"UInt16", DataType::uint16},
305  {"Int32", DataType::int32},
306  {"UInt32", DataType::uint32},
307  {"Int64", DataType::int64},
308  {"UInt64", DataType::uint64},
309  {"Float32", DataType::float32},
310  {"Float64", DataType::float64},
311  {"", DataType::undefined}
312  };
313 
315  if (it != types.end()) {
316  return it->second;
317  } else {
318  THROW( ExcWrongType() << EI_ErrMessage("Unknown") << EI_VTKFile(tok_.f_name()));
319  return DataType::uint32;
320  }
321 
322 }
323 
324 
325 
327 {
328  static const std::vector<unsigned int> sizes = { 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 0 };
329 
330  return sizes[data_type];
331 }
332 
333 
334 
335 void VtkMeshReader::read_element_data(ElementDataCacheBase &data_cache, MeshDataHeader actual_header, unsigned int n_components,
336  bool boundary_domain) {
337 
338  ASSERT(!boundary_domain).error("Reading VTK data of boundary elements is not supported yet!\n");
339 
340  switch (data_format_) {
341  case DataFormat::ascii: {
342  parse_ascii_data( data_cache, n_components, actual_header.n_entities, actual_header.position, boundary_domain );
343  break;
344  }
345  case DataFormat::binary_uncompressed: {
346  ASSERT_PTR(data_stream_).error();
347  parse_binary_data( data_cache, n_components, actual_header.n_entities, actual_header.position, boundary_domain,
348  actual_header.type );
349  break;
350  }
351  case DataFormat::binary_zlib: {
352  ASSERT_PTR(data_stream_).error();
353  parse_compressed_data( data_cache, n_components, actual_header.n_entities, actual_header.position, boundary_domain,
354  actual_header.type);
355  break;
356  }
357  default: {
358  ASSERT(false).error(); // should not happen
359  break;
360  }
361  }
362 
363  LogOut().fmt("time: {}; {} entities of field {} read.\n",
364  actual_header.time, n_read_, actual_header.field_name);
365 }
366 
367 
368 void VtkMeshReader::parse_ascii_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities,
369  Tokenizer::Position pos, bool boundary_domain)
370 {
371  n_read_ = 0;
372 
373  tok_.set_position( pos );
374  try {
375  tok_.next_line();
376  for (unsigned int i_row = 0; i_row < n_entities; ++i_row) {
377  data_cache.read_ascii_data(tok_, n_components, get_element_vector(boundary_domain)[i_row]);
378  n_read_++;
379  }
380  } catch (boost::bad_lexical_cast &) {
381  THROW(ExcWrongFormat() << EI_Type("DataArray tag") << EI_TokenizerMsg(tok_.position_msg())
382  << EI_MeshFile(tok_.f_name()) );
383  }
384 }
385 
386 
387 void VtkMeshReader::parse_binary_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities,
388  Tokenizer::Position pos, bool boundary_domain, DataType value_type)
389 {
390  n_read_ = 0;
391 
392  data_stream_->seekg(pos.file_position_);
393  uint64_t data_size = read_header_type(header_type_, *data_stream_) / type_value_size(value_type);
394 
395  for (unsigned int i_row = 0; i_row < n_entities; ++i_row) {
396  data_cache.read_binary_data(*data_stream_, n_components, get_element_vector(boundary_domain)[i_row]);
397  n_read_++;
398  }
399 }
400 
401 
402 void VtkMeshReader::parse_compressed_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities,
403  Tokenizer::Position pos, bool boundary_domain, DataType value_type)
404 {
405  data_stream_->seekg(pos.file_position_);
406  uint64_t n_blocks = read_header_type(header_type_, *data_stream_);
407  uint64_t u_size = read_header_type(header_type_, *data_stream_);
408  uint64_t p_size = read_header_type(header_type_, *data_stream_);
409 
410  std::vector<uint64_t> block_sizes;
411  block_sizes.reserve(n_blocks);
412  for (uint64_t i = 0; i < n_blocks; ++i) {
413  block_sizes.push_back( read_header_type(header_type_, *data_stream_) );
414  }
415 
416  stringstream decompressed_data;
417  uint64_t decompressed_data_size = 0;
418  for (uint64_t i = 0; i < n_blocks; ++i) {
419  uint64_t decompressed_block_size = (i==n_blocks-1 && p_size>0) ? p_size : u_size;
420  uint64_t compressed_block_size = block_sizes[i];
421 
422  std::vector<char> data_block(compressed_block_size);
423  data_stream_->read(&data_block[0], compressed_block_size);
424 
425  std::vector<char> buffer(decompressed_block_size);
426 
427  // set zlib object
428  z_stream strm;
429  strm.zalloc = 0;
430  strm.zfree = 0;
431  strm.next_in = (Bytef *)(&data_block[0]);
432  strm.avail_in = compressed_block_size;
433  strm.next_out = (Bytef *)(&buffer[0]);
434  strm.avail_out = decompressed_block_size;
435 
436  // decompression of data
437  inflateInit(&strm);
438  inflate(&strm, Z_NO_FLUSH);
439  inflateEnd(&strm);
440 
441  // store decompressed data to stream
442  decompressed_data << std::string(buffer.begin(), buffer.end());
443  decompressed_data_size += decompressed_block_size;
444  }
445 
446  n_read_ = 0;
447 
448  uint64_t data_size = decompressed_data_size / type_value_size(value_type);
449 
450  for (unsigned int i_row = 0; i_row < n_entities; ++i_row) {
451  data_cache.read_binary_data(decompressed_data, n_components, get_element_vector(boundary_domain)[i_row]);
452  n_read_++;
453  }
454 }
455 
456 
458 {
460  std::vector<unsigned int> node_ids; // allow mapping ids of nodes from VTK mesh to GMSH
461  std::vector<unsigned int> offsets_vec; // value of offset section in VTK file
462 
463  bulk_elements_id_.clear();
464 
465  {
466  // read points data section, find corresponding nodes in GMSH trough BIH tree
467  // points in data section and nodes in GMSH must be in ratio 1:1
468  // store orders (mapping between VTK and GMSH file) into node_ids vector
469  std::vector<unsigned int> searched_elements; // for BIH tree
470  unsigned int i_node, i_elm_node;
471  const BIHTree &bih_tree=mesh.get_bih_tree();
472 
473  ElementDataFieldMap::iterator field_it=element_data_values_->find("Points");
474  ASSERT(field_it != element_data_values_->end()).error("Missing cache of Points section. Did you call create_node_element_caches()?\n");
475 
476  // create nodes of mesh
477  std::vector<double> &node_vec = *( dynamic_cast<ElementDataCache<double> &>(*(field_it->second)).get_component_data(0).get() );
478  unsigned int n_nodes = node_vec.size() / 3;
479  node_ids.resize(n_nodes);
480  for (unsigned int i=0; i<n_nodes; ++i) {
481  arma::vec3 point = { node_vec[3*i], node_vec[3*i+1], node_vec[3*i+2] };
482  int found_i_node = -1;
483  bih_tree.find_point(point, searched_elements);
484 
485  for (std::vector<unsigned int>::iterator it = searched_elements.begin(); it!=searched_elements.end(); it++) {
486  ElementFullIter ele = mesh.element( *it );
487  FOR_ELEMENT_NODES(ele, i_node)
488  {
489  if ( compare_points(ele->node[i_node]->point(), point) ) {
490  i_elm_node = mesh.node_vector.index(ele->node[i_node]);
491  if (found_i_node == -1) found_i_node = i_elm_node;
492  else if (found_i_node != i_elm_node) {
493  THROW( ExcIncompatibleMesh() << EI_ErrMessage("duplicate nodes found in GMSH file")
494  << EI_VTKFile(tok_.f_name()));
495  }
496  }
497  }
498  }
499  if (found_i_node == -1) {
500  THROW( ExcIncompatibleMesh() << EI_ErrMessage("no node found in GMSH file") << EI_VTKFile(tok_.f_name()));
501  }
502  node_ids[i] = (unsigned int)found_i_node;
503  searched_elements.clear();
504  }
505 
506  }
507 
508  {
509  ElementDataFieldMap::iterator field_it=element_data_values_->find("offsets");
510  ASSERT(field_it != element_data_values_->end()).error("Missing cache of offsets section. Did you call create_node_element_caches()?\n");
511 
512  offsets_vec = *( dynamic_cast<ElementDataCache<unsigned int> &>(*(field_it->second)).get_component_data(0).get() );
513  }
514 
515  {
516  // read connectivity data section, find corresponding elements in GMSH
517  // cells in data section and elements in GMSH must be in ratio 1:1
518  // store orders (mapping between VTK and GMSH file) into bulk_elements_id_ vector
519  ElementDataFieldMap::iterator field_it=element_data_values_->find("connectivity");
520  ASSERT(field_it != element_data_values_->end()).error("Missing cache of connectivity section. Did you call create_node_element_caches()?\n");
521 
522  std::vector<unsigned int> &connectivity_vec = *( dynamic_cast<ElementDataCache<unsigned int> &>(*(field_it->second)).get_component_data(0).get() );
523  vector<unsigned int> node_list;
524  vector<unsigned int> candidate_list; // returned by intersect_element_lists
525  vector<unsigned int> result_list; // list of elements with same dimension as vtk element
526  bulk_elements_id_.clear();
527  bulk_elements_id_.resize(offsets_vec.size());
528  // iterate trough connectivity data, to each VTK cell must exist only one GMSH element
529  // fill bulk_elements_id_ vector
530  unsigned int i_con = 0, last_offset=0, dim;
531  for (unsigned int i=0; i<offsets_vec.size(); ++i) { // iterate trough offset - one value for every element
532  dim = offsets_vec[i] - last_offset - 1; // dimension of vtk element
533  for ( ; i_con<offsets_vec[i]; ++i_con ) { // iterate trough all nodes of any element
534  node_list.push_back( node_ids[connectivity_vec[i_con]] );
535  }
536  mesh.intersect_element_lists(node_list, candidate_list);
537  for (auto i_elm : candidate_list) {
538  if ( mesh.element( i_elm )->dim() == dim ) result_list.push_back(i_elm);
539  }
540  if (result_list.size() != 1) {
541  THROW( ExcIncompatibleMesh() << EI_ErrMessage("intersect_element_lists must produce one element")
542  << EI_VTKFile(tok_.f_name()));
543  }
544  bulk_elements_id_[i] = (IdxInt)result_list[0];
545  node_list.clear();
546  result_list.clear();
547  last_offset = offsets_vec[i];
548  }
549  }
550 
551  has_compatible_mesh_ = true;
552 }
553 
554 
556  return fabs(p1[0]-p2[0]) < point_tolerance
557  && fabs(p1[1]-p2[1]) < point_tolerance
558  && fabs(p1[2]-p2[2]) < point_tolerance;
559 }
560 
561 
563  // will be implemented later
564 }
565 
566 
569 
570  ElementDataFieldMap::iterator it=element_data_values_->find("Points");
571  ASSERT(it != element_data_values_->end()).error("Missing cache of Points section. Did you call create_node_element_caches()?\n");
572 
573  // create nodes of mesh
574  std::vector<double> &vect = *( dynamic_cast<ElementDataCache<double> &>(*(it->second)).get_component_data(0).get() );
575  unsigned int n_nodes = vect.size()/3;
576  mesh->reserve_node_size(n_nodes);
578  for (unsigned int i=0, ivec=0; i<n_nodes; ++i) {
579  point(0)=vect[ivec]; ++ivec;
580  point(1)=vect[ivec]; ++ivec;
581  point(2)=vect[ivec]; ++ivec;
582  mesh->add_node(i, point);
583  }
584 
585  bulk_elements_id_.clear();
586 }
587 
588 
590  // read offset section in VTK file
591  ElementDataFieldMap::iterator offset_it=element_data_values_->find("offsets");
592  ASSERT(offset_it != element_data_values_->end()).error("Missing cache of offsets section. Did you call create_node_element_caches()?\n");
593  std::vector<unsigned int> &offsets_vec = *( dynamic_cast<ElementDataCache<unsigned int> &>(*(offset_it->second)).get_component_data(0).get() );
594 
595  // read connectivity data section
596  ElementDataFieldMap::iterator conn_it=element_data_values_->find("connectivity");
597  ASSERT(conn_it != element_data_values_->end()).error("Missing cache of offsets section. Did you call create_node_element_caches()?\n");
598  std::vector<unsigned int> &connectivity_vec = *( dynamic_cast<ElementDataCache<unsigned int> &>(*(conn_it->second)).get_component_data(0).get() );
599 
600  // iterate trough connectivity data, create bulk elements
601  // fill bulk_elements_id_ vector
602  bulk_elements_id_.clear();
603  bulk_elements_id_.resize(offsets_vec.size());
604  unsigned int i_con = 0, last_offset=0, dim;
605  vector<unsigned int> node_list;
606  for (unsigned int i=0; i<offsets_vec.size(); ++i) { // iterate trough offset - one value for every element
607  dim = offsets_vec[i] - last_offset - 1; // dimension of vtk element
608  for ( ; i_con<offsets_vec[i]; ++i_con ) { // iterate trough all nodes of any element
609  node_list.push_back( connectivity_vec[i_con] );
610  }
611  mesh->add_element(i, dim, dim, 0, node_list); // TODO need to set region_id (3rd parameter, now is created from dim)
612  bulk_elements_id_[i] = (IdxInt)i;
613  node_list.clear();
614  last_offset = offsets_vec[i];
615  }
616 }
617 
618 
620  ElementDataFieldMap::iterator it=element_data_values_->find("Points");
621  if ( it != element_data_values_->end() ) {
622  // prevents repeat call of read_nodes
623  return;
624  }
625 
626  ASSERT( !has_compatible_mesh_ ).error();
627 
628  has_compatible_mesh_ = true;
629 
630  // read Points data section
631  HeaderQuery header_params("Points", 0.0, OutputTime::DiscreteSpace::MESH_DEFINITION);
632  auto point_header = this->find_header(header_params);
633  bulk_elements_id_.resize(point_header.n_entities);
634  for (unsigned int i=0; i<bulk_elements_id_.size(); ++i) bulk_elements_id_[i]=i;
635  this->get_element_data<double>(point_header.n_entities, point_header.n_components, false, 0 );
636 
637  // read offset data section
638  HeaderQuery offsets_params("offsets", 0.0, OutputTime::DiscreteSpace::MESH_DEFINITION);
639  auto offset_header = this->find_header(offsets_params);
640  for (unsigned int i=bulk_elements_id_.size(); i<offset_header.n_entities; ++i) bulk_elements_id_.push_back(i);
641  std::vector<unsigned int> &offsets_vec = *( this->get_element_data<unsigned int>(offset_header.n_entities, offset_header.n_components, false, 0 ) );
642 
643  // read connectivity data section
644  HeaderQuery con_params("connectivity", 0.0, OutputTime::DiscreteSpace::MESH_DEFINITION);
645  auto & con_header = this->find_header(con_params);
646  con_header.n_entities = offsets_vec[offsets_vec.size()-1];
647  for (unsigned int i=bulk_elements_id_.size(); i<con_header.n_entities; ++i) bulk_elements_id_.push_back(i);
648  this->get_element_data<unsigned int>(con_header.n_entities, con_header.n_components, false, 0 );
649 
650  has_compatible_mesh_ = false;
651  bulk_elements_id_.clear();
652 }
653 
654 
655 
656 // explicit instantiation of template methods
657 template unsigned int read_binary_value<unsigned int>(std::istream &data_stream);
658 template uint64_t read_binary_value<uint64_t>(std::istream &data_stream);
MeshDataHeader create_header(pugi::xml_node node, unsigned int n_entities, Tokenizer::Position pos, OutputTime::DiscreteSpace disc)
Helper method that create DataArray header of given xml node (used from make_header_table) ...
void make_header_table() override
Reads table of DataArray headers through pugixml interface.
bool compare_points(arma::vec3 &p1, arma::vec3 &p2)
double time_step_
time of VTK file (getting only during initialization from PVD reader)
int IdxInt
Define integers that are indices into large arrays (elements, nodes, dofs etc.)
Definition: mesh.h:85
#define FOR_ELEMENT_NODES(i, j)
Definition: elements.h:156
DataType type
Type of data (used only for VTK reader)
HeaderTable header_table_
Table with data of DataArray headers.
void read_nodes(Mesh *mesh)
static const double point_tolerance
Tolerance during comparison point data with GMSH nodes.
DataFormat data_format_
variants of data format (ascii, appended, compressed appended)
template unsigned int read_binary_value< unsigned int >(std::istream &data_stream)
void add_node(unsigned int node_id, arma::vec3 coords)
Add new node of given id and coordinates to mesh.
Definition: mesh.cc:767
VtkMeshReader(const FilePath &file_name)
template uint64_t read_binary_value< uint64_t >(std::istream &data_stream)
std::shared_ptr< ElementDataFieldMap > element_data_values_
Cache with last read element data.
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3141
std::string field_name
Name of field.
void read_base_vtk_attributes(pugi::xml_node vtk_node, unsigned int &n_nodes, unsigned int &n_elements)
Set base attributes of VTK and get count of nodes and elements.
Definition: mesh.h:99
DataType get_data_type(std::string type_str)
Get DataType by value of string.
std::string data_section_name_
Store name of field data section specify for type of mesh file.
void parse_compressed_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities, Tokenizer::Position pos, bool boundary_domain, DataType value_type)
Uncompress and parse binary compressed data to data cache.
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:346
#define LogOut()
Macro defining &#39;log&#39; record of log.
Definition: logger.hh:249
std::size_t dof_handler_hash
Hash of DOF handler object.
unsigned int n_entities
Number of rows.
uint64_t read_header_type(DataType data_header_type, std::istream &data_stream)
MeshDataHeader & find_header(HeaderQuery &header_query) override
void read_physical_names(Mesh *mesh) override
std::istream * data_stream_
input stream allow read appended data, used only if this tag exists
void check_compatible_mesh(Mesh &mesh) override
virtual void read_ascii_data(Tokenizer &tok, unsigned int n_components, unsigned int i_row)=0
Class for O(log N) lookup for intersections with a set of bounding boxes.
Definition: bih_tree.hh:36
unsigned int index(const T *pointer) const
Definition: sys_vector.hh:373
virtual ~VtkMeshReader()
Destructor.
OutputTime::DiscreteSpace discretization
Flag marks input discretization of data of VTK file.
DataType header_type_
header type of VTK file (only for appended data)
std::string field_name
Name of field.
const BIHTree & get_bih_tree()
Getter for BIH. Creates and compute BIH at first call.
Definition: mesh.cc:752
unsigned int n_read_
store count of read entities
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
void read_elements(Mesh *mesh)
void parse_binary_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities, Tokenizer::Position pos, bool boundary_domain, DataType value_type)
Parse binary data to data cache.
Tokenizer::Position position
Position of data in mesh file.
void find_point(const Space< 3 >::Point &point, std::vector< unsigned int > &result_list, bool full_list=false) const
Definition: bih_tree.cc:265
OutputTime::DiscreteSpace discretization
Flag determinate type of discrete of Field (typically is used for native data of VTK) ...
double time
Time of field data (used only for GMSH reader)
vector< IdxInt > bulk_elements_id_
void create_node_element_caches()
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:335
T read_binary_value(std::istream &data_stream)
void read_element_data(ElementDataCacheBase &data_cache, MeshDataHeader actual_header, unsigned int n_components, bool boundary_domain) override
unsigned int n_components
Number of values on one row.
double time
Time of field data (used only for GMSH and PVD reader)
ComponentDataPtr get_component_data(unsigned int component_idx)
Return vector of element data for get component.
MeshDataHeader actual_header_
Header of actual loaded data.
void intersect_element_lists(vector< unsigned int > const &nodes_list, vector< unsigned int > &intersection_element_list)
Definition: mesh.cc:308
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:246
void add_element(unsigned int elm_id, unsigned int dim, unsigned int region_id, unsigned int partition_id, std::vector< unsigned int > node_ids)
Add new element of given id to mesh.
Definition: mesh.cc:773
DataType
Types of VTK data (value &#39;undefined&#39; for empty value)
Tokenizer tok_
Tokenizer used for reading ASCII file format.
virtual void read_binary_data(std::istream &data_stream, unsigned int n_components, unsigned int i_row)=0
unsigned int type_value_size(DataType data_type)
Return size of value of data_type.
std::size_t dof_handler_hash
Hash of DOF handler object (only for native data of VTK file)
void reserve_node_size(unsigned int n_nodes)
Reserve size of node vector.
Definition: mesh.h:175
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
Tokenizer::Position get_appended_position()
Get position of AppendedData tag in VTK file.
std::vector< int > const & get_element_vector(bool boundary_domain)
NodeVector node_vector
Vector of nodes of the mesh.
Definition: mesh.h:258
ElementVector element
Vector of elements of the mesh.
Definition: mesh.h:260
void parse_ascii_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities, Tokenizer::Position pos, bool boundary_domain)
Parse ascii data to data cache.