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