Flow123d  release_3.0.0-1264-g45bfb2a
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/bih_tree.hh"
28 #include "mesh/long_idx.hh"
29 #include "mesh/mesh.h"
30 #include "mesh/accessors.hh"
31 
32 #include "config.h"
33 #include <zlib.h>
34 
35 
36 /*******************************************************************
37  * Helper methods
38  */
39 template<typename T>
40 T read_binary_value(std::istream &data_stream)
41 {
42  T val;
43  data_stream.read(reinterpret_cast<char *>(&val), sizeof(val));
44  return val;
45 }
46 
47 
48 uint64_t read_header_type(DataType data_header_type, std::istream &data_stream)
49 {
50  if (data_header_type == DataType::uint64)
51  return read_binary_value<uint64_t>(data_stream);
52  else if (data_header_type == DataType::uint32)
53  return (uint64_t)read_binary_value<unsigned int>(data_stream);
54  else {
55  ASSERT(false).error("Unsupported header_type!\n"); //should not happen
56  return 0;
57  }
58 }
59 
60 
61 /*******************************************************************
62  * implementation of VtkMeshReader
63  */
64 const double VtkMeshReader::point_tolerance = 1E-10;
65 
66 
68 : BaseMeshReader(file_name),
69  time_step_(0.0)
70 {
71  data_section_name_ = "DataArray";
72  has_compatible_mesh_ = false;
74 }
75 
76 
77 
78 VtkMeshReader::VtkMeshReader(const FilePath &file_name, std::shared_ptr<ElementDataFieldMap> element_data_values, double time_step)
79 : BaseMeshReader(file_name, element_data_values),
80  time_step_(time_step)
81 {
82  data_section_name_ = "DataArray";
83  has_compatible_mesh_ = false;
85 }
86 
87 
88 
90 {
91  delete data_stream_;
92 }
93 
94 
95 
96 void VtkMeshReader::read_base_vtk_attributes(pugi::xml_node vtk_node, unsigned int &n_nodes, unsigned int &n_elements)
97 {
98  try {
99  // header type of appended data
100  header_type_ = this->get_data_type( vtk_node.attribute("header_type").as_string() );
101  } catch(ExcWrongType &e) {
102  e << EI_SectionTypeName("base parameter header_type");
103  }
104  // data format
106  data_format_ = DataFormat::ascii;
107  } else {
109  // Allowable values of header type are only 'UInt64' or 'UInt32'
110  THROW( ExcWrongType() << EI_ErrMessage("Forbidden") << EI_SectionTypeName("base parameter header_type")
111  << EI_VTKFile(tok_.f_name()));
112  }
113  std::string compressor = vtk_node.attribute("compressor").as_string();
114  if (compressor == "vtkZLibDataCompressor")
115  data_format_ = DataFormat::binary_zlib;
116  else
117  data_format_ = DataFormat::binary_uncompressed;
118  }
119  // size of node and element vectors
120  pugi::xml_node piece_node = vtk_node.child("UnstructuredGrid").child("Piece");
121  n_nodes = piece_node.attribute("NumberOfPoints").as_uint();
122  n_elements = piece_node.attribute("NumberOfCells").as_uint();
123 }
124 
125 
126 
128  Tokenizer::Position appended_pos;
129 
130  {
131  // find line by tokenizer
132  tok_.set_position( Tokenizer::Position() );
133  if (! tok_.skip_to("AppendedData"))
134  THROW(ExcMissingTag() << EI_TagType("tag") << EI_TagName("AppendedData") << EI_VTKFile(tok_.f_name()) );
135  else {
136  appended_pos = tok_.get_position();
137  }
138  }
139 
140  // find exact position of appended data (starts with '_')
141  char c;
142  data_stream_->seekg(appended_pos.file_position_);
143  do {
144  data_stream_->get(c);
145  } while (c!='_');
146  appended_pos.file_position_ = data_stream_->tellg();
147  appended_pos.line_counter_++;
148  delete data_stream_; // close stream
149 
150  // reopen stream in binary mode
151  data_stream_ = new std::ifstream( tok_.f_name(), std::ios_base::in | std::ios_base::binary );
152 
153  return appended_pos;
154 }
155 
156 
157 BaseMeshReader::MeshDataHeader VtkMeshReader::create_header(pugi::xml_node node, unsigned int n_entities, Tokenizer::Position pos,
159 {
160  MeshDataHeader header;
161  header.field_name = node.attribute("Name").as_string();
162  header.time = this->time_step_;
163  try {
164  header.type = this->get_data_type( node.attribute("type").as_string() );
165  } catch(ExcWrongType &e) {
166  e << EI_SectionTypeName("DataArray " + header.field_name);
167  }
168  header.discretization = disc;
169  if (disc == OutputTime::DiscreteSpace::NATIVE_DATA) {
170  header.n_components = node.attribute("n_dofs_per_element").as_uint();
171  header.dof_handler_hash = node.attribute("dof_handler_hash").as_uint();
172  } else {
173  header.n_components = node.attribute("NumberOfComponents").as_uint(1);
174  }
175  header.n_entities = n_entities;
176  std::string format = node.attribute("format").as_string();
177  if (format=="appended") {
178  if (data_format_ == DataFormat::ascii)
179  THROW(ExcInvalidFormat() << EI_FieldName(header.field_name) << EI_ExpectedFormat("ascii") << EI_VTKFile(tok_.f_name()) );
180  std::streampos file_pos = pos.file_position_;
181  file_pos += node.attribute("offset").as_uint();
182  header.position = Tokenizer::Position( file_pos, pos.line_counter_, pos.line_position_ );
183  } else if (format=="ascii") {
184  if (data_format_ != DataFormat::ascii)
185  THROW(ExcInvalidFormat() << EI_FieldName(header.field_name) << EI_ExpectedFormat("appended") << EI_VTKFile(tok_.f_name()) );
186 
187  tok_.set_position( Tokenizer::Position() );
188  bool is_point = (header.field_name=="");
189  std::string found_str = (is_point) ? "<Points>" : "Name=\"" + header.field_name + "\"";
190  if (! tok_.skip_to(found_str))
191  THROW(ExcMissingTag() << EI_TagType("DataArray tag") << EI_TagName(header.field_name) << EI_VTKFile(tok_.f_name()) );
192  else {
193  if (is_point) tok_.skip_to("DataArray");
194  header.position = tok_.get_position();
195  }
196  } else {
197  THROW(ExcUnknownFormat() << EI_FieldName(header.field_name) << EI_VTKFile(tok_.f_name()) );
198  }
199 
200  return header;
201 }
202 
203 
205 {
206  pugi::xml_document doc;
207  doc.load_file( tok_.f_name().c_str() );
208  unsigned int n_nodes, n_elements;
209  this->read_base_vtk_attributes( doc.child("VTKFile"), n_nodes, n_elements );
210 
211  // open ifstream for find position
212  data_stream_ = new std::ifstream( tok_.f_name() );
213 
214  // data of appended tag
215  Tokenizer::Position appended_pos;
217  // no AppendedData tag
218  } else {
219  appended_pos = get_appended_position();
220  }
221 
222  pugi::xml_node node = doc.child("VTKFile").child("UnstructuredGrid").child("Piece");
223 
224  header_table_.clear();
225 
226  // create headers of Points and Cells DataArrays
227  auto points_header = create_header( node.child("Points").child("DataArray"), n_nodes, appended_pos,
228  OutputTime::DiscreteSpace::MESH_DEFINITION );
229  points_header.field_name = "Points";
230  header_table_.insert( std::pair<std::string, MeshDataHeader>("Points", points_header) );
231  auto con_header = create_header( node.child("Cells").find_child_by_attribute("DataArray", "Name", "connectivity"),
232  n_elements, appended_pos, OutputTime::DiscreteSpace::MESH_DEFINITION );
233  header_table_.insert( std::pair<std::string, MeshDataHeader>("connectivity", con_header) );
234  auto offsets_header = create_header( node.child("Cells").find_child_by_attribute("DataArray", "Name", "offsets"),
235  n_elements, appended_pos, OutputTime::DiscreteSpace::MESH_DEFINITION );
236  header_table_.insert( std::pair<std::string, MeshDataHeader>("offsets", offsets_header) );
237  auto types_header = create_header( node.child("Cells").find_child_by_attribute("DataArray", "Name", "types"), n_elements,
238  appended_pos, OutputTime::DiscreteSpace::MESH_DEFINITION );
239  header_table_.insert( std::pair<std::string, MeshDataHeader>("types", types_header) );
240 
241  pugi::xml_node point_node = node.child("PointData");
242  for (pugi::xml_node subnode = point_node.child("DataArray"); subnode; subnode = subnode.next_sibling("DataArray")) {
243  auto header = create_header( subnode, n_nodes, appended_pos, OutputTime::DiscreteSpace::NODE_DATA );
244  header_table_.insert( std::pair<std::string, MeshDataHeader>(header.field_name, header) );
245  }
246 
247  pugi::xml_node cell_node = node.child("CellData");
248  for (pugi::xml_node subnode = cell_node.child("DataArray"); subnode; subnode = subnode.next_sibling("DataArray")) {
249  auto header = create_header( subnode, n_elements, appended_pos, OutputTime::DiscreteSpace::ELEM_DATA );
250  header_table_.insert( std::pair<std::string, MeshDataHeader>(header.field_name, header) );
251  }
252 
253  pugi::xml_node native_node = node.child("Flow123dData");
254  for (pugi::xml_node subnode = native_node.child("DataArray"); subnode; subnode = subnode.next_sibling("DataArray")) {
255  auto header = create_header( subnode, n_elements, appended_pos, OutputTime::DiscreteSpace::NATIVE_DATA );
256  header_table_.insert( std::pair<std::string, MeshDataHeader>(header.field_name, header) );
257  }
258 }
259 
260 
262 {
263  unsigned int count = header_table_.count(header_query.field_name);
264 
265  if (count == 0) {
266  // no data found
267  THROW( ExcFieldNameNotFound() << EI_FieldName(header_query.field_name) << EI_MeshFile(tok_.f_name()));
268  } else if (count == 1) {
269  HeaderTable::iterator table_it = header_table_.find(header_query.field_name);
270 
271  // check discretization
272  if (header_query.discretization != table_it->second.discretization) {
273  if (header_query.discretization != OutputTime::DiscreteSpace::UNDEFINED && header_query.discretization != OutputTime::DiscreteSpace::NATIVE_DATA) {
274  WarningOut().fmt(
275  "Invalid value of 'input_discretization' for field '{}', time: {}.\nCorrect discretization type will be used.\n",
276  header_query.field_name, header_query.time);
277  }
278  header_query.discretization = table_it->second.discretization;
279  }
280 
281  if (header_query.discretization == OutputTime::DiscreteSpace::NATIVE_DATA)
282  if (header_query.dof_handler_hash != table_it->second.dof_handler_hash) {
283  THROW(ExcInvalidDofHandler() << EI_FieldName(header_query.field_name) << EI_VTKFile(tok_.f_name()) );
284  }
285  actual_header_ = table_it->second;
286  } else {
287  /*HeaderTable::iterator table_it;
288  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) {
289  if (header_query.discretization != table_it->second.discretization) {
290  header_query.dof_handler_hash = table_it->second.dof_handler_hash;
291  actual_header_ = table_it->second;
292  }
293  }*/
294  THROW( ExcMissingFieldDiscretization() << EI_FieldName(header_query.field_name) << EI_Time(header_query.time) << EI_MeshFile(tok_.f_name()));
295  }
296 
297  return actual_header_;
298 }
299 
300 
301 
302 DataType VtkMeshReader::get_data_type(std::string type_str) {
303  // names of types in DataArray section
304  static const std::map<std::string, DataType> types = {
305  {"Int8", DataType::int8},
306  {"UInt8", DataType::uint8},
307  {"Int16", DataType::int16},
308  {"UInt16", DataType::uint16},
309  {"Int32", DataType::int32},
310  {"UInt32", DataType::uint32},
311  {"Int64", DataType::int64},
312  {"UInt64", DataType::uint64},
313  {"Float32", DataType::float32},
314  {"Float64", DataType::float64},
315  {"", DataType::undefined}
316  };
317 
319  if (it != types.end()) {
320  return it->second;
321  } else {
322  THROW( ExcWrongType() << EI_ErrMessage("Unknown") << EI_VTKFile(tok_.f_name()));
323  return DataType::uint32;
324  }
325 
326 }
327 
328 
329 
331 {
332  static const std::vector<unsigned int> sizes = { 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 0 };
333 
334  return sizes[data_type];
335 }
336 
337 
338 
339 void VtkMeshReader::read_element_data(ElementDataCacheBase &data_cache, MeshDataHeader actual_header, unsigned int n_components,
340  bool boundary_domain) {
341 
342  ASSERT(!boundary_domain).error("Reading VTK data of boundary elements is not supported yet!\n");
343 
344  switch (data_format_) {
345  case DataFormat::ascii: {
346  parse_ascii_data( data_cache, n_components, actual_header.n_entities, actual_header.position, boundary_domain );
347  break;
348  }
349  case DataFormat::binary_uncompressed: {
350  ASSERT_PTR(data_stream_).error();
351  parse_binary_data( data_cache, n_components, actual_header.n_entities, actual_header.position, boundary_domain);
352  break;
353  }
354  case DataFormat::binary_zlib: {
355  ASSERT_PTR(data_stream_).error();
356  parse_compressed_data( data_cache, n_components, actual_header.n_entities, actual_header.position, boundary_domain);
357  break;
358  }
359  default: {
360  ASSERT(false).error(); // should not happen
361  break;
362  }
363  }
364 
365  LogOut().fmt("time: {}; {} entities of field {} read.\n",
366  actual_header.time, n_read_, actual_header.field_name);
367 }
368 
369 
370 void VtkMeshReader::parse_ascii_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities,
371  Tokenizer::Position pos, bool boundary_domain)
372 {
373  n_read_ = 0;
374 
375  tok_.set_position( pos );
376  try {
377  tok_.next_line();
378  for (unsigned int i_row = 0; i_row < n_entities; ++i_row) {
379  data_cache.read_ascii_data(tok_, n_components, get_element_vector(boundary_domain)[i_row]);
380  n_read_++;
381  }
382  } catch (boost::bad_lexical_cast &) {
383  THROW(ExcWrongFormat() << EI_Type("DataArray tag") << EI_TokenizerMsg(tok_.position_msg())
384  << EI_MeshFile(tok_.f_name()) );
385  }
386 }
387 
388 
389 void VtkMeshReader::parse_binary_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities,
390  Tokenizer::Position pos, bool boundary_domain)
391 {
392  n_read_ = 0;
393 
394  data_stream_->seekg(pos.file_position_);
396 
397  for (unsigned int i_row = 0; i_row < n_entities; ++i_row) {
398  data_cache.read_binary_data(*data_stream_, n_components, get_element_vector(boundary_domain)[i_row]);
399  n_read_++;
400  }
401 }
402 
403 
404 void VtkMeshReader::parse_compressed_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities,
405  Tokenizer::Position pos, bool boundary_domain)
406 {
407  data_stream_->seekg(pos.file_position_);
408  uint64_t n_blocks = read_header_type(header_type_, *data_stream_);
409  uint64_t u_size = read_header_type(header_type_, *data_stream_);
410  uint64_t p_size = read_header_type(header_type_, *data_stream_);
411 
412  std::vector<uint64_t> block_sizes;
413  block_sizes.reserve(n_blocks);
414  for (uint64_t i = 0; i < n_blocks; ++i) {
415  block_sizes.push_back( read_header_type(header_type_, *data_stream_) );
416  }
417 
418  stringstream decompressed_data;
419  uint64_t decompressed_data_size = 0;
420  for (uint64_t i = 0; i < n_blocks; ++i) {
421  uint64_t decompressed_block_size = (i==n_blocks-1 && p_size>0) ? p_size : u_size;
422  uint64_t compressed_block_size = block_sizes[i];
423 
424  std::vector<char> data_block(compressed_block_size);
425  data_stream_->read(&data_block[0], compressed_block_size);
426 
427  std::vector<char> buffer(decompressed_block_size);
428 
429  // set zlib object
430  z_stream strm;
431  strm.zalloc = 0;
432  strm.zfree = 0;
433  strm.next_in = (Bytef *)(&data_block[0]);
434  strm.avail_in = compressed_block_size;
435  strm.next_out = (Bytef *)(&buffer[0]);
436  strm.avail_out = decompressed_block_size;
437 
438  // decompression of data
439  inflateInit(&strm);
440  inflate(&strm, Z_NO_FLUSH);
441  inflateEnd(&strm);
442 
443  // store decompressed data to stream
444  decompressed_data << std::string(buffer.begin(), buffer.end());
445  decompressed_data_size += decompressed_block_size;
446  }
447 
448  n_read_ = 0;
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  uint found_i_node = Mesh::undef_idx;
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  ElementAccessor<3> ele = mesh.element_accessor( *it );
487  for (i_node=0; i_node<ele->n_nodes(); i_node++)
488  {
489  if ( compare_points(ele.node(i_node)->point(), point) ) {
490  i_elm_node = ele.node_accessor(i_node).idx();
491  if (found_i_node == Mesh::undef_idx) 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 == Mesh::undef_idx) {
500  THROW( ExcIncompatibleMesh() << EI_ErrMessage("no node found in GMSH file") << EI_VTKFile(tok_.f_name()));
501  }
502  node_ids[i] = 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_accessor(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] = (LongIdx)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  // ASSERT(0).error("Not implemented!");
565 }
566 
567 
570 
571  ElementDataFieldMap::iterator it=element_data_values_->find("Points");
572  ASSERT(it != element_data_values_->end()).error("Missing cache of Points section. Did you call create_node_element_caches()?\n");
573 
574  // create nodes of mesh
575  std::vector<double> &vect = *( dynamic_cast<ElementDataCache<double> &>(*(it->second)).get_component_data(0).get() );
576  unsigned int n_nodes = vect.size()/3;
577  mesh->init_node_vector( n_nodes );
578  arma::vec3 point;
579  for (unsigned int i=0, ivec=0; i<n_nodes; ++i) {
580  point(0)=vect[ivec]; ++ivec;
581  point(1)=vect[ivec]; ++ivec;
582  point(2)=vect[ivec]; ++ivec;
583  mesh->add_node(i, point);
584  }
585 
586  bulk_elements_id_.clear();
587 }
588 
589 
591  // read offset section in VTK file
592  ElementDataFieldMap::iterator offset_it=element_data_values_->find("offsets");
593  ASSERT(offset_it != element_data_values_->end()).error("Missing cache of offsets section. Did you call create_node_element_caches()?\n");
594  std::vector<unsigned int> &offsets_vec = *( dynamic_cast<ElementDataCache<unsigned int> &>(*(offset_it->second)).get_component_data(0).get() );
595 
596  // read connectivity data section
597  ElementDataFieldMap::iterator conn_it=element_data_values_->find("connectivity");
598  ASSERT(conn_it != element_data_values_->end()).error("Missing cache of offsets section. Did you call create_node_element_caches()?\n");
599  std::vector<unsigned int> &connectivity_vec = *( dynamic_cast<ElementDataCache<unsigned int> &>(*(conn_it->second)).get_component_data(0).get() );
600 
601  // iterate trough connectivity data, create bulk elements
602  // fill bulk_elements_id_ vector
603  bulk_elements_id_.clear();
604  bulk_elements_id_.resize(offsets_vec.size());
605  mesh->init_element_vector(offsets_vec.size());
606  unsigned int i_con = 0, last_offset=0, dim;
607  vector<unsigned int> node_list;
608  for (unsigned int i=0; i<offsets_vec.size(); ++i) { // iterate trough offset - one value for every element
609  dim = offsets_vec[i] - last_offset - 1; // dimension of vtk element
610  for ( ; i_con<offsets_vec[i]; ++i_con ) { // iterate trough all nodes of any element
611  node_list.push_back( connectivity_vec[i_con] );
612  }
613  mesh->add_element(i, dim, dim, 0, node_list); // TODO need to set region_id (3rd parameter, now is created from dim)
614  bulk_elements_id_[i] = (LongIdx)i;
615  node_list.clear();
616  last_offset = offsets_vec[i];
617  }
618 
619  mesh->create_boundary_elements();
620 }
621 
622 
624  ElementDataFieldMap::iterator it=element_data_values_->find("Points");
625  if ( it != element_data_values_->end() ) {
626  // prevents repeat call of read_nodes
627  return;
628  }
629 
630  ASSERT( !has_compatible_mesh_ ).error();
631 
632  has_compatible_mesh_ = true;
633 
634  // read Points data section
635  HeaderQuery header_params("Points", 0.0, OutputTime::DiscreteSpace::MESH_DEFINITION);
636  auto point_header = this->find_header(header_params);
637  bulk_elements_id_.resize(point_header.n_entities);
638  for (unsigned int i=0; i<bulk_elements_id_.size(); ++i) bulk_elements_id_[i]=i;
639  this->get_element_data<double>(point_header.n_entities, point_header.n_components, false, 0 );
640 
641  // read offset data section
642  HeaderQuery offsets_params("offsets", 0.0, OutputTime::DiscreteSpace::MESH_DEFINITION);
643  auto offset_header = this->find_header(offsets_params);
644  for (unsigned int i=bulk_elements_id_.size(); i<offset_header.n_entities; ++i) bulk_elements_id_.push_back(i);
645  std::vector<unsigned int> &offsets_vec = *( this->get_element_data<unsigned int>(offset_header.n_entities, offset_header.n_components, false, 0 ) );
646 
647  // read connectivity data section
648  HeaderQuery con_params("connectivity", 0.0, OutputTime::DiscreteSpace::MESH_DEFINITION);
649  auto & con_header = this->find_header(con_params);
650  con_header.n_entities = offsets_vec[offsets_vec.size()-1];
651  for (unsigned int i=bulk_elements_id_.size(); i<con_header.n_entities; ++i) bulk_elements_id_.push_back(i);
652  this->get_element_data<unsigned int>(con_header.n_entities, con_header.n_components, false, 0 );
653 
654  has_compatible_mesh_ = false;
655  bulk_elements_id_.clear();
656 }
657 
658 
659 
660 // explicit instantiation of template methods
661 template unsigned int read_binary_value<unsigned int>(std::istream &data_stream);
662 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:128
void parse_compressed_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities, Tokenizer::Position pos, bool boundary_domain)
Uncompress and parse binary compressed data to data cache.
DataType type
Type of data (used only for VTK reader)
HeaderTable header_table_
Table with data of DataArray headers.
unsigned int uint
NodeAccessor< 3 > node_accessor(unsigned int ni) const
Definition: accessors.hh:202
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:1019
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:962
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.
static const unsigned int undef_idx
Definition: mesh.h:102
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.
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
#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:739
std::size_t dof_handler_hash
Hash of DOF handler object.
unsigned int dim() const
Definition: elements.h:123
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:944
void create_boundary_elements()
Create boundary elements from data of temporary structure, this method MUST be call after read mesh f...
Definition: mesh.cc:1161
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 parse_binary_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities, Tokenizer::Position pos, bool boundary_domain)
Parse binary data to data cache.
void read_elements(Mesh *mesh)
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:336
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:361
#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:970
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:1030
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:198