22 #include <pugixml.hpp> 23 #include "boost/lexical_cast.hpp" 43 data_stream.read(reinterpret_cast<char *>(&val),
sizeof(val));
55 ASSERT(
false).error(
"Unsupported header_type!\n");
101 }
catch(ExcWrongType &e) {
102 e << EI_SectionTypeName(
"base parameter header_type");
110 THROW( ExcWrongType() << EI_ErrMessage(
"Forbidden") << EI_SectionTypeName(
"base parameter header_type")
111 << EI_VTKFile(
tok_.f_name()));
113 std::string compressor = vtk_node.attribute(
"compressor").as_string();
114 if (compressor ==
"vtkZLibDataCompressor")
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();
128 Tokenizer::Position appended_pos;
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()) );
136 appended_pos =
tok_.get_position();
147 appended_pos.line_counter_++;
151 data_stream_ =
new std::ifstream(
tok_.f_name(), std::ios_base::in | std::ios_base::binary );
161 header.
field_name = node.attribute(
"Name").as_string();
165 }
catch(ExcWrongType &e) {
166 e << EI_SectionTypeName(
"DataArray " + header.
field_name);
169 if (disc == OutputTime::DiscreteSpace::NATIVE_DATA) {
170 header.
n_components = node.attribute(
"n_dofs_per_element").as_uint();
173 header.
n_components = node.attribute(
"NumberOfComponents").as_uint(1);
176 std::string
format = node.attribute(
"format").as_string();
177 if (format==
"appended") {
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") {
185 THROW(ExcInvalidFormat() << EI_FieldName(header.
field_name) << EI_ExpectedFormat(
"appended") << EI_VTKFile(
tok_.f_name()) );
187 tok_.set_position( Tokenizer::Position() );
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()) );
193 if (is_point)
tok_.skip_to(
"DataArray");
197 THROW(ExcUnknownFormat() << EI_FieldName(header.
field_name) << EI_VTKFile(
tok_.f_name()) );
206 pugi::xml_document doc;
207 doc.load_file(
tok_.f_name().c_str() );
208 unsigned int n_nodes, n_elements;
215 Tokenizer::Position appended_pos;
222 pugi::xml_node node = doc.child(
"VTKFile").child(
"UnstructuredGrid").child(
"Piece");
227 auto points_header =
create_header( node.child(
"Points").child(
"DataArray"), n_nodes, appended_pos,
228 OutputTime::DiscreteSpace::MESH_DEFINITION );
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) );
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) );
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) );
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) );
267 THROW( ExcFieldNameNotFound() << EI_FieldName(header_query.
field_name) << EI_MeshFile(
tok_.f_name()));
268 }
else if (count == 1) {
272 if (header_query.
discretization != table_it->second.discretization) {
273 if (header_query.
discretization != OutputTime::DiscreteSpace::UNDEFINED) {
275 "Invalid value of 'input_discretization' for field '{}', time: {}.\nCorrect discretization type will be used.\n",
281 if (header_query.
discretization == OutputTime::DiscreteSpace::NATIVE_DATA)
283 THROW(ExcInvalidDofHandler() << EI_FieldName(header_query.
field_name) << EI_VTKFile(
tok_.f_name()) );
294 THROW( ExcMissingFieldDiscretization() << EI_FieldName(header_query.
field_name) << EI_Time(header_query.
time) << EI_MeshFile(
tok_.f_name()));
319 if (it != types.end()) {
322 THROW( ExcWrongType() << EI_ErrMessage(
"Unknown") << EI_VTKFile(
tok_.f_name()));
332 static const std::vector<unsigned int> sizes = { 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 0 };
334 return sizes[data_type];
340 bool boundary_domain) {
342 ASSERT(!boundary_domain).error(
"Reading VTK data of boundary elements is not supported yet!\n");
345 case DataFormat::ascii: {
349 case DataFormat::binary_uncompressed: {
354 case DataFormat::binary_zlib: {
365 LogOut().fmt(
"time: {}; {} entities of field {} read.\n",
371 Tokenizer::Position pos)
375 tok_.set_position( pos );
378 for (
unsigned int i_row = 0; i_row < n_entities; ++i_row) {
382 }
catch (boost::bad_lexical_cast &) {
383 THROW(ExcWrongFormat() << EI_Type(
"DataArray tag") << EI_TokenizerMsg(
tok_.position_msg())
384 << EI_MeshFile(
tok_.f_name()) );
390 Tokenizer::Position pos)
397 for (
unsigned int i_row = 0; i_row < n_entities; ++i_row) {
405 Tokenizer::Position pos)
413 block_sizes.reserve(n_blocks);
414 for (uint64_t i = 0; i < n_blocks; ++i) {
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];
425 data_stream_->read(&data_block[0], compressed_block_size);
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;
440 inflate(&strm, Z_NO_FLUSH);
444 decompressed_data << std::string(buffer.begin(), buffer.end());
445 decompressed_data_size += decompressed_block_size;
450 for (
unsigned int i_row = 0; i_row < n_entities; ++i_row) {
467 ASSERT(it !=
element_data_values_->end()).error(
"Missing cache of Points section. Did you call create_node_element_caches()?\n");
471 unsigned int n_nodes = vect.size()/3;
474 for (
unsigned int i=0, ivec=0; i<n_nodes; ++i) {
475 point(0)=vect[ivec]; ++ivec;
476 point(1)=vect[ivec]; ++ivec;
477 point(2)=vect[ivec]; ++ivec;
488 ASSERT(offset_it !=
element_data_values_->end()).error(
"Missing cache of offsets section. Did you call create_node_element_caches()?\n");
493 ASSERT(conn_it !=
element_data_values_->end()).error(
"Missing cache of offsets section. Did you call create_node_element_caches()?\n");
501 unsigned int i_con = 0, last_offset=0, dim;
503 for (
unsigned int i=0; i<offsets_vec.size(); ++i) {
504 dim = offsets_vec[i] - last_offset - 1;
505 for ( ; i_con<offsets_vec[i]; ++i_con ) {
506 node_list.push_back( connectivity_vec[i_con] );
511 last_offset = offsets_vec[i];
530 HeaderQuery header_params(
"Points", 0.0, OutputTime::DiscreteSpace::MESH_DEFINITION);
531 auto point_header = this->
find_header(header_params);
534 this->get_element_data<double>(point_header.n_entities, point_header.n_components,
false, 0 );
537 HeaderQuery offsets_params(
"offsets", 0.0, OutputTime::DiscreteSpace::MESH_DEFINITION);
538 auto offset_header = this->
find_header(offsets_params);
540 std::vector<unsigned int> &offsets_vec = *( this->get_element_data<unsigned int>(offset_header.n_entities, offset_header.n_components,
false, 0 ) );
543 HeaderQuery con_params(
"connectivity", 0.0, OutputTime::DiscreteSpace::MESH_DEFINITION);
545 con_header.n_entities = offsets_vec[offsets_vec.size()-1];
547 this->get_element_data<unsigned int>(con_header.n_entities, con_header.n_components,
false, 0 );
MeshDataHeader create_header(pugi::xml_node node, unsigned int n_entities, Tokenizer::Position pos, OutputTime::DiscreteSpace disc)
Helper method that create DataArray header of given xml node (used from make_header_table) ...
void make_header_table() override
Reads table of DataArray headers through pugixml interface.
void parse_binary_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities, Tokenizer::Position pos)
Parse binary data to data cache.
double time_step_
time of VTK file (getting only during initialization from PVD reader)
HeaderTable header_table_
Table with data of DataArray headers.
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.
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.
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)
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.
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...
#define LogOut()
Macro defining 'log' record of log.
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
virtual void read_ascii_data(Tokenizer &tok, unsigned int n_components, unsigned int i_row)=0
virtual ~VtkMeshReader()
Destructor.
DataType header_type_
header type of VTK file (only for appended data)
void parse_compressed_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities, Tokenizer::Position pos)
Uncompress and parse binary compressed data to data cache.
void create_boundary_elements()
Create boundary elements from data of temporary structure, this method MUST be call after read mesh f...
unsigned int n_read_
store count of read entities
Dedicated class for storing path to input and output files.
void read_elements(Mesh *mesh)
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
void create_node_element_caches()
void parse_ascii_data(ElementDataCacheBase &data_cache, unsigned int n_components, unsigned int n_entities, Tokenizer::Position pos)
Parse ascii data to data cache.
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
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
ComponentDataPtr get_component_data(unsigned int component_idx)
Return vector of element data for get component.
MeshDataHeader actual_header_
Header of actual loaded data.
#define WarningOut()
Macro defining 'warning' record of log.
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.
bool has_compatible_mesh_
DataType
Types of VTK data (value 'undefined' 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.
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Tokenizer::Position get_appended_position()
Get position of AppendedData tag in VTK file.
void init_node_vector(unsigned int size)
Initialize node_vec_, set size.
vector< LongIdx > bulk_elements_id_