Flow123d  release_3.0.0-973-g92f55e826
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);
VtkMeshReader::header_table_
HeaderTable header_table_
Table with data of DataArray headers.
Definition: msh_vtkreader.hh:194
BaseMeshReader::actual_header_
MeshDataHeader actual_header_
Header of actual loaded data.
Definition: msh_basereader.hh:263
BaseMeshReader::tok_
Tokenizer tok_
Tokenizer used for reading ASCII file format.
Definition: msh_basereader.hh:256
VtkMeshReader::create_node_element_caches
void create_node_element_caches()
Definition: msh_vtkreader.cc:627
VtkMeshReader::make_header_table
void make_header_table() override
Reads table of DataArray headers through pugixml interface.
Definition: msh_vtkreader.cc:205
VtkMeshReader::~VtkMeshReader
virtual ~VtkMeshReader()
Destructor.
Definition: msh_vtkreader.cc:90
bih_tree.hh
Mesh::init_element_vector
void init_element_vector(unsigned int size)
Initialize element_vec_, set size and reset counters of boundary and bulk elements.
Definition: mesh.cc:1082
uint8
@ uint8
Definition: msh_basereader.hh:46
Mesh::create_boundary_elements
void create_boundary_elements()
Create boundary elements from data of temporary structure, this method MUST be call after read mesh f...
Definition: mesh.cc:1218
ElementDataCache
Definition: element_data_cache.hh:44
ElementDataCache::get_component_data
ComponentDataPtr get_component_data(unsigned int component_idx)
Return vector of element data for get component.
Definition: element_data_cache.cc:68
ASSERT
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:346
undefined
@ undefined
Definition: msh_basereader.hh:46
LongIdx
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
Definition: long_idx.hh:22
Element::dim
unsigned int dim() const
Definition: elements.h:124
uint64
@ uint64
Definition: msh_basereader.hh:46
FilePath
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
BIHTree
Class for O(log N) lookup for intersections with a set of bounding boxes.
Definition: bih_tree.hh:38
THROW
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
BaseMeshReader::MeshDataHeader::type
DataType type
Type of data (used only for VTK reader)
Definition: msh_basereader.hh:137
std::vector< unsigned int >
ElementAccessor< 3 >
system.hh
VtkMeshReader::get_appended_position
Tokenizer::Position get_appended_position()
Get position of AppendedData tag in VTK file.
Definition: msh_vtkreader.cc:128
BaseMeshReader::HeaderQuery::dof_handler_hash
std::size_t dof_handler_hash
Hash of DOF handler object.
Definition: msh_basereader.hh:140
arma::vec3
Definition: doxy_dummy_defs.hh:17
ElementAccessor::node
const Node * node(unsigned int ni) const
Definition: accessors.hh:145
BaseMeshReader::MeshDataHeader::n_components
unsigned int n_components
Number of values on one row.
Definition: msh_basereader.hh:129
VtkMeshReader::create_header
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)
Definition: msh_vtkreader.cc:158
fmt::format
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3141
read_binary_value< uint64_t >
template uint64_t read_binary_value< uint64_t >(std::istream &data_stream)
BaseMeshReader::get_element_vector
const std::vector< int > & get_element_vector(bool boundary_domain)
Definition: msh_basereader.cc:80
BaseMeshReader::element_data_values_
std::shared_ptr< ElementDataFieldMap > element_data_values_
Cache with last read element data.
Definition: msh_basereader.hh:253
Mesh::intersect_element_lists
void intersect_element_lists(vector< unsigned int > const &nodes_list, vector< unsigned int > &intersection_element_list)
Definition: mesh.cc:427
VtkMeshReader::parse_binary_data
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.
Definition: msh_vtkreader.cc:392
int8
@ int8
Definition: msh_basereader.hh:46
BaseMeshReader::MeshDataHeader::discretization
OutputTime::DiscreteSpace discretization
Flag marks input discretization of data of VTK file.
Definition: msh_basereader.hh:139
VtkMeshReader::parse_compressed_data
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.
Definition: msh_vtkreader.cc:407
BaseMeshReader::HeaderQuery::field_name
std::string field_name
Name of field.
Definition: msh_basereader.hh:135
BaseMeshReader
Definition: msh_basereader.hh:58
accessors.hh
LogOut
#define LogOut()
Macro defining 'log' record of log.
Definition: logger.hh:249
BIHTree::find_point
void find_point(const Space< 3 >::Point &point, std::vector< unsigned int > &result_list, bool full_list=false) const
Definition: bih_tree.cc:287
Mesh::get_bih_tree
const BIHTree & get_bih_tree()
Getter for BIH. Creates and compute BIH at first call.
Definition: mesh.cc:1007
int32
@ int32
Definition: msh_basereader.hh:46
read_binary_value< unsigned int >
template unsigned int read_binary_value< unsigned int >(std::istream &data_stream)
BaseMeshReader::MeshDataHeader::field_name
std::string field_name
Name of field.
Definition: msh_basereader.hh:121
uint16
@ uint16
Definition: msh_basereader.hh:46
int16
@ int16
Definition: msh_basereader.hh:46
Node::point
arma::vec3 & point()
Definition: nodes.hh:67
ElementDataCacheBase
Definition: element_data_cache_base.hh:33
VtkMeshReader::type_value_size
unsigned int type_value_size(DataType data_type)
Return size of value of data_type.
Definition: msh_vtkreader.cc:331
mesh.h
VtkMeshReader::find_header
MeshDataHeader & find_header(HeaderQuery &header_query) override
Definition: msh_vtkreader.cc:262
std::map
Definition: doxy_dummy_defs.hh:11
Mesh::add_element
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:1033
BaseMeshReader::MeshDataHeader::dof_handler_hash
std::size_t dof_handler_hash
Hash of DOF handler object (only for native data of VTK file)
Definition: msh_basereader.hh:141
VtkMeshReader::read_element_data
void read_element_data(ElementDataCacheBase &data_cache, MeshDataHeader actual_header, unsigned int n_components, bool boundary_domain) override
Definition: msh_vtkreader.cc:340
Input::Type
Definition: balance.hh:38
VtkMeshReader::read_nodes
void read_nodes(Mesh *mesh)
Definition: msh_vtkreader.cc:572
VtkMeshReader::data_format_
DataFormat data_format_
variants of data format (ascii, appended, compressed appended)
Definition: msh_vtkreader.hh:191
BaseMeshReader::MeshDataHeader
Definition: msh_basereader.hh:100
ElementAccessor::node_accessor
NodeAccessor< 3 > node_accessor(unsigned int ni) const
Definition: accessors.hh:149
int64
@ int64
Definition: msh_basereader.hh:46
VtkMeshReader::point_tolerance
static const double point_tolerance
Tolerance during comparison point data with GMSH nodes.
Definition: msh_vtkreader.hh:185
uint32
@ uint32
Definition: msh_basereader.hh:46
ElementDataCacheBase::read_ascii_data
virtual void read_ascii_data(Tokenizer &tok, unsigned int n_components, unsigned int i_row)=0
Mesh
Definition: mesh.h:80
VtkMeshReader::VtkMeshReader
VtkMeshReader(const FilePath &file_name)
Definition: msh_vtkreader.cc:68
VtkMeshReader::parse_ascii_data
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.
Definition: msh_vtkreader.cc:373
Mesh::init_node_vector
void init_node_vector(unsigned int size)
Initialize node_vec_, set size.
Definition: mesh.cc:1093
VtkMeshReader::read_base_vtk_attributes
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: msh_vtkreader.cc:97
BaseMeshReader::HeaderQuery::discretization
OutputTime::DiscreteSpace discretization
Flag determinate type of discrete of Field (typically is used for native data of VTK)
Definition: msh_basereader.hh:139
WarningOut
#define WarningOut()
Macro defining 'warning' record of log.
Definition: logger.hh:246
BaseMeshReader::MeshDataHeader::position
Tokenizer::Position position
Position of data in mesh file.
Definition: msh_basereader.hh:135
side_impl.hh
read_header_type
uint64_t read_header_type(DataType data_header_type, std::istream &data_stream)
Definition: msh_vtkreader.cc:49
ElementDataCacheBase::read_binary_data
virtual void read_binary_data(std::istream &data_stream, unsigned int n_components, unsigned int i_row)=0
msh_vtkreader.hh
float64
@ float64
Definition: msh_basereader.hh:46
Mesh::add_node
void add_node(unsigned int node_id, arma::vec3 coords)
Add new node of given id and coordinates to mesh.
Definition: mesh.cc:1025
OutputTime::DiscreteSpace
DiscreteSpace
Definition: output_time.hh:104
long_idx.hh
read_binary_value
T read_binary_value(std::istream &data_stream)
Definition: msh_vtkreader.cc:41
BaseMeshReader::MeshDataHeader::n_entities
unsigned int n_entities
Number of rows.
Definition: msh_basereader.hh:131
BaseMeshReader::data_section_name_
std::string data_section_name_
Store name of field data section specify for type of mesh file.
Definition: msh_basereader.hh:250
BaseMeshReader::MeshDataHeader::time
double time
Time of field data (used only for GMSH reader)
Definition: msh_basereader.hh:125
ASSERT_PTR
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:335
VtkMeshReader::compare_points
bool compare_points(const arma::vec3 &p1, const arma::vec3 &p2)
Definition: msh_vtkreader.cc:560
Mesh::element_accessor
virtual ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
Definition: mesh.cc:802
BaseMeshReader::HeaderQuery::time
double time
Time of field data (used only for GMSH and PVD reader)
Definition: msh_basereader.hh:138
VtkMeshReader::time_step_
double time_step_
time of VTK file (getting only during initialization from PVD reader)
Definition: msh_vtkreader.hh:203
VtkMeshReader::header_type_
DataType header_type_
header type of VTK file (only for appended data)
Definition: msh_vtkreader.hh:188
BaseMeshReader::has_compatible_mesh_
bool has_compatible_mesh_
Definition: msh_basereader.hh:247
VtkMeshReader::get_data_type
DataType get_data_type(std::string type_str)
Get DataType by value of string.
Definition: msh_vtkreader.cc:303
float32
@ float32
Definition: msh_basereader.hh:46
BaseMeshReader::HeaderQuery
Definition: msh_basereader.hh:132
VtkMeshReader::read_physical_names
void read_physical_names(Mesh *mesh) override
Definition: msh_vtkreader.cc:567
VtkMeshReader::data_stream_
std::istream * data_stream_
input stream allow read appended data, used only if this tag exists
Definition: msh_vtkreader.hh:197
VtkMeshReader::n_read_
unsigned int n_read_
store count of read entities
Definition: msh_vtkreader.hh:200
BaseMeshReader::bulk_elements_id_
vector< LongIdx > bulk_elements_id_
Definition: msh_basereader.hh:260
Element::n_nodes
unsigned int n_nodes() const
Definition: elements.h:129
DataType
DataType
Types of VTK data (value 'undefined' for empty value)
Definition: msh_basereader.hh:45
VtkMeshReader::check_compatible_mesh
void check_compatible_mesh(Mesh &mesh) override
Definition: msh_vtkreader.cc:462
VtkMeshReader::read_elements
void read_elements(Mesh *mesh)
Definition: msh_vtkreader.cc:594