dune-vtk 2.8
Loading...
Searching...
No Matches
vtkreader.impl.hh
Go to the documentation of this file.
1#include <fstream>
2#include <iterator>
3#include <sstream>
4#include <string>
5
6#if HAVE_VTK_ZLIB
7#include <zlib.h>
8#endif
9
10#include <dune/common/classname.hh>
11#include <dune/common/version.hh>
12
13#include "utility/errors.hh"
14#include "utility/filesystem.hh"
15#include "utility/string.hh"
16
17namespace Dune {
18
19template <class Grid, class Creator, class Field>
20void VtkReader<Grid,Creator,Field>::read (std::string const& filename, bool fillCreator)
21{
22 // check whether file exists!
23 if (!Vtk::exists(filename))
24 DUNE_THROW(IOError, "File " << filename << " does not exist!");
25
26 std::ifstream input(filename, std::ios_base::in | std::ios_base::binary);
27 VTK_ASSERT(input.is_open());
28
29 std::string ext = Vtk::Path(filename).extension().string();
30 if (ext == ".vtu") {
31 readSerialFileFromStream(input, fillCreator);
32 pieces_.push_back(filename);
33 } else if (ext == ".pvtu") {
34 readParallelFileFromStream(input, comm().rank(), comm().size(), fillCreator);
35 } else {
36 DUNE_THROW(Dune::VtkError, "File has unknown file-extension '" << ext << "'. Allowed are only '.vtu' and '.pvtu'.");
37 }
38 read_ = true;
39}
40
41
42template <class Grid, class Creator, class Field>
43void VtkReader<Grid,Creator,Field>::readSerialFileFromStream (std::ifstream& input, bool fillCreator)
44{
45 clear();
46 compressor_ = Vtk::CompressorTypes::NONE;
48 std::string data_id = "";
49 std::string data_format = "";
51 unsigned int data_components = 0;
52 std::uint64_t data_offset = 0;
53
54 Sections section = NO_SECTION;
55 for (std::string line; std::getline(input, line); ) {
56 Vtk::ltrim(line);
57
58 if (isSection(line, "VTKFile", section)) {
59 bool closed = false;
60 auto attr = parseXml(line, closed);
61
62 if (!attr["type"].empty())
63 VTK_ASSERT_MSG(attr["type"] == "UnstructuredGrid", "VtkReader supports UnstructuredGrid types");
64 if (!attr["byte_order"].empty())
65 VTK_ASSERT_MSG(attr["byte_order"] == "LittleEndian", "LittleEndian byte order supported");
66
67 if (attr["header_type"] == "UInt32")
68 header_type = Vtk::DataTypes::UINT32;
69 else if (attr["header_type"] == "UInt64")
70 header_type = Vtk::DataTypes::UINT64;
71
72 if (attr["compressor"] == "vtkZLibDataCompressor")
73 compressor_ = Vtk::CompressorTypes::ZLIB;
74 else if (attr["compressor"] == "vtkLZ4DataCompressor")
75 compressor_ = Vtk::CompressorTypes::LZ4;
76 else if (attr["compressor"] == "vtkLZMADataCompressor")
77 compressor_ = Vtk::CompressorTypes::LZMA;
78
79 section = VTK_FILE;
80 }
81 else if (isSection(line, "/VTKFile", section, VTK_FILE)) {
82 section = NO_SECTION;
83 break;
84 }
85 else if (isSection(line, "UnstructuredGrid", section, VTK_FILE))
86 section = UNSTRUCTURED_GRID;
87 else if (isSection(line, "/UnstructuredGrid", section, UNSTRUCTURED_GRID))
88 section = VTK_FILE;
89 else if (isSection(line, "Piece", section, UNSTRUCTURED_GRID)) {
90 bool closed = false;
91 auto attr = parseXml(line, closed);
92
93 VTK_ASSERT_MSG(attr.count("NumberOfPoints") > 0 && attr.count("NumberOfCells") > 0,
94 "Number of points or cells in file must be > 0");
95 numberOfPoints_ = std::stoul(attr["NumberOfPoints"]);
96 numberOfCells_ = std::stoul(attr["NumberOfCells"]);
97 section = PIECE;
98 }
99 else if (isSection(line, "/Piece", section, PIECE))
100 section = UNSTRUCTURED_GRID;
101 else if (isSection(line, "PointData", section, PIECE))
102 section = POINT_DATA;
103 else if (isSection(line, "/PointData", section, POINT_DATA))
104 section = PIECE;
105 else if (isSection(line, "CellData", section, PIECE))
106 section = CELL_DATA;
107 else if (isSection(line, "/CellData", section, CELL_DATA))
108 section = PIECE;
109 else if (isSection(line, "Points", section, PIECE))
110 section = POINTS;
111 else if (isSection(line, "/Points", section, POINTS))
112 section = PIECE;
113 else if (isSection(line, "Cells", section, PIECE))
114 section = CELLS;
115 else if (isSection(line, "/Cells", section, CELLS))
116 section = PIECE;
117 else if (line.substr(1,9) == "DataArray") {
118 bool closed = false;
119 auto attr = parseXml(line, closed);
120
121 data_type = Vtk::dataTypeOf(attr["type"]);
122
123 // Use Section.Name as id
124 data_id = toString(section) + "." + attr["Name"];
125
126 if (section == POINTS)
127 // In the Points section must only be one DataArray with id=Points
128 data_id = "Points";
129
130 data_components = 1;
131 if (!attr["NumberOfComponents"].empty())
132 data_components = std::stoul(attr["NumberOfComponents"]);
133
134 // determine FormatType
135 data_format = Vtk::to_lower(attr["format"]);
136 if (data_format == "appended") {
138 } else {
139 format_ = Vtk::FormatTypes::ASCII;
140 }
141
142 // Offset makes sense in appended mode only
143 data_offset = 0;
144 if (!attr["offset"].empty()) {
145 data_offset = std::stoul(attr["offset"]);
146 VTK_ASSERT_MSG(data_format == "appended", "Attribute 'offset' only supported by appended mode");
147 }
148
149 // Store attributes of DataArray
150 dataArray_[data_id] = {attr["Name"], data_type, data_components, data_offset, section};
151
152 // Skip section in appended mode
153 if (data_format == "appended") {
154 if (!closed) {
155 while (std::getline(input, line)) {
156 Vtk::ltrim(line);
157 if (line.substr(1,10) == "/DataArray")
158 break;
159 }
160 }
161 continue;
162 }
163
164 if (section == POINT_DATA)
165 section = PD_DATA_ARRAY;
166 else if (section == POINTS)
167 section = POINTS_DATA_ARRAY;
168 else if (section == CELL_DATA)
169 section = CD_DATA_ARRAY;
170 else if (section == CELLS)
171 section = CELLS_DATA_ARRAY;
172 else
173 DUNE_THROW(Dune::VtkError, "Wrong section for <DataArray>");
174 }
175 else if (line.substr(1,10) == "/DataArray") {
176 if (section == PD_DATA_ARRAY)
177 section = POINT_DATA;
178 else if (section == POINTS_DATA_ARRAY)
179 section = POINTS;
180 else if (section == CD_DATA_ARRAY)
181 section = CELL_DATA;
182 else if (section == CELLS_DATA_ARRAY)
183 section = CELLS;
184 else
185 DUNE_THROW(Dune::VtkError, "Wrong section for </DataArray>");
186 }
187 else if (isSection(line, "AppendedData", section, VTK_FILE)) {
188 bool closed = false;
189 auto attr = parseXml(line, closed);
190 if (!attr["encoding"].empty())
191 VTK_ASSERT_MSG(attr["encoding"] == "raw", "base64 encoding not supported");
192
193 offset0_ = findAppendedDataPosition(input);
194 Vtk::mapDataTypes<std::is_floating_point, std::is_integral>(dataArray_["Points"].type, header_type,
195 [&](auto f, auto h) {
196 this->readPointsAppended(f,h,input);
197 this->readCellsAppended(h,input);
198 });
199
200 // read point and cell data
201 for (auto const& d : dataArray_) {
202 if (d.second.section == POINT_DATA) {
203 Vtk::mapDataTypes<std::is_floating_point, std::is_integral>(d.second.type, header_type,
204 [&](auto f, auto h) {
205 this->readPointDataAppended(f,h,input,d.first);
206 });
207 }
208 else if (d.second.section == CELL_DATA) {
209 Vtk::mapDataTypes<std::is_floating_point, std::is_integral>(d.second.type, header_type,
210 [&](auto f, auto h) {
211 this->readCellDataAppended(f,h,input,d.first);
212 });
213 }
214 }
215
216 section = NO_SECTION; // finish reading after appended section
217 break;
218 }
219 else if (isSection(line, "/AppendedData", section, APPENDED_DATA))
220 section = VTK_FILE;
221
222 switch (section) {
223 case PD_DATA_ARRAY:
224 section = readPointData(input, data_id);
225 break;
226 case POINTS_DATA_ARRAY:
227 section = readPoints(input, data_id);
228 break;
229 case CD_DATA_ARRAY:
230 section = readCellData(input, data_id);
231 break;
232 case CELLS_DATA_ARRAY:
233 section = readCells(input, data_id);
234 break;
235 default:
236 break;
237 }
238 }
239
240 if (section != NO_SECTION)
241 DUNE_THROW(Dune::VtkError, "VTK-File is incomplete. It must end with </VTKFile>!");
242
243 if (fillCreator)
244 fillGridCreator();
245}
246
247
248template <class Grid, class Creator, class Field>
249void VtkReader<Grid,Creator,Field>::readParallelFileFromStream (std::ifstream& input, int /* commRank */, int /* commSize */, bool fillCreator)
250{
251 clear();
252
253 [[maybe_unused]] Vtk::DataTypes header_type = Vtk::DataTypes::UINT32;
254 compressor_ = Vtk::CompressorTypes::NONE;
255
256 Sections section = NO_SECTION;
257 for (std::string line; std::getline(input, line); ) {
258 Vtk::ltrim(line);
259
260 if (isSection(line, "VTKFile", section)) {
261 bool closed = false;
262 auto attr = parseXml(line, closed);
263
264 if (!attr["type"].empty())
265 VTK_ASSERT_MSG(attr["type"] == "PUnstructuredGrid", "VtkReader supports PUnstructuredGrid types");
266 if (!attr["version"].empty())
267 VTK_ASSERT_MSG(std::stod(attr["version"]) == 1.0, "File format must be 1.0");
268 if (!attr["byte_order"].empty())
269 VTK_ASSERT_MSG(attr["byte_order"] == "LittleEndian", "LittleEndian byte order supported");
270
271 if (attr["header_type"] == "UInt32")
272 header_type = Vtk::DataTypes::UINT32;
273 else if (attr["header_type"] == "UInt64")
274 header_type = Vtk::DataTypes::UINT64;
275
276 if (attr["compressor"] == "vtkZLibDataCompressor")
277 compressor_ = Vtk::CompressorTypes::ZLIB;
278 else if (attr["compressor"] == "vtkLZ4DataCompressor")
279 compressor_ = Vtk::CompressorTypes::LZ4;
280 else if (attr["compressor"] == "vtkLZMADataCompressor")
281 compressor_ = Vtk::CompressorTypes::LZMA;
282
283 section = VTK_FILE;
284 }
285 else if (isSection(line, "/VTKFile", section, VTK_FILE)) {
286 section = NO_SECTION;
287 break;
288 } else if (isSection(line, "PUnstructuredGrid", section, VTK_FILE))
289 section = UNSTRUCTURED_GRID;
290 else if (isSection(line, "/PUnstructuredGrid", section, UNSTRUCTURED_GRID))
291 section = VTK_FILE;
292 else if (isSection(line, "Piece", section, UNSTRUCTURED_GRID)) {
293 bool closed = false;
294 auto attr = parseXml(line, closed);
295
296 VTK_ASSERT_MSG(attr.count("Source") > 0, "No source files for partitions provided");
297 pieces_.push_back(attr["Source"]);
298 }
299 }
300
301 VTK_ASSERT_MSG(section == NO_SECTION, "VTK-File is incomplete. It must end with </VTKFile>!");
302
303 if (fillCreator)
304 fillGridCreator();
305}
306
307
308// @{ implementation detail
315template <class IStream, class T, class Sections>
316Sections readDataArray (IStream& input, std::vector<T>& values, std::size_t max_size,
317 Sections section, Sections parent_section)
318{
319 values.reserve(max_size < std::size_t(-1) ? max_size : 0);
320 using S = std::conditional_t<(sizeof(T) <= 1), std::uint16_t, T>; // problem when reading chars as ints
321
322 std::size_t idx = 0;
323 for (std::string line; std::getline(input, line);) {
324 Vtk::trim(line);
325 if (line.substr(1,10) == "/DataArray")
326 return parent_section;
327 if (line[0] == '<')
328 break;
329
330 std::istringstream stream(line);
331 S value;
332 for (; stream >> value; idx++)
333 values.push_back(T(value));
334 if (idx >= max_size)
335 break;
336 }
337
338 return section;
339}
340
341template <class IStream, class Sections>
342Sections skipRestOfDataArray (IStream& input, Sections section, Sections parent_section)
343{
344 for (std::string line; std::getline(input, line);) {
345 Vtk::ltrim(line);
346 if (line.substr(1,10) == "/DataArray")
347 return parent_section;
348 }
349
350 return section;
351}
352// @}
353
354
355// Read values stored on the cells with name `name`
356template <class Grid, class Creator, class Field>
357typename VtkReader<Grid,Creator,Field>::Sections
358VtkReader<Grid,Creator,Field>::readCellData (std::ifstream& input, std::string id)
359{
360 VTK_ASSERT(numberOfCells_ > 0);
361 unsigned int components = dataArray_[id].components;
362
363 Sections sec;
364 std::vector<Field>& values = cellData_[id];
365 sec = readDataArray(input, values, components*numberOfCells_, CD_DATA_ARRAY, CELL_DATA);
366 if (sec != CELL_DATA)
367 sec = skipRestOfDataArray(input, CD_DATA_ARRAY, CELL_DATA);
368 VTK_ASSERT(sec == CELL_DATA);
369 VTK_ASSERT(values.size() == components*numberOfCells_);
370
371 return sec;
372}
373
374
375template <class Grid, class Creator, class Field>
376 template <class FloatType, class HeaderType>
377void VtkReader<Grid,Creator,Field>::readCellDataAppended (MetaType<FloatType>, MetaType<HeaderType>, std::ifstream& input, std::string id)
378{
379 VTK_ASSERT(numberOfCells_ > 0);
380 unsigned int components = dataArray_[id].components;
381
382 std::vector<FloatType> values;
383 readAppended(input, values, HeaderType(dataArray_[id].offset));
384 VTK_ASSERT(values.size() == components*numberOfCells_);
385
386 cellData_[id].resize(values.size());
387 std::copy(values.begin(), values.end(), cellData_[id].begin());
388}
389
390
391template <class Grid, class Creator, class Field>
392typename VtkReader<Grid,Creator,Field>::Sections
393VtkReader<Grid,Creator,Field>::readPointData (std::ifstream& input, std::string id)
394{
395 VTK_ASSERT(numberOfPoints_ > 0);
396 unsigned int components = dataArray_[id].components;
397
398 Sections sec;
399 std::vector<Field>& values = pointData_[id];
400 sec = readDataArray(input, values, components*numberOfPoints_, PD_DATA_ARRAY, POINT_DATA);
401 if (sec != POINT_DATA)
402 sec = skipRestOfDataArray(input, PD_DATA_ARRAY, POINT_DATA);
403 VTK_ASSERT(sec == POINT_DATA);
404 VTK_ASSERT(values.size() == components*numberOfPoints_);
405
406 return sec;
407}
408
409
410template <class Grid, class Creator, class Field>
411 template <class FloatType, class HeaderType>
412void VtkReader<Grid,Creator,Field>::readPointDataAppended (MetaType<FloatType>, MetaType<HeaderType>, std::ifstream& input, std::string id)
413{
414 VTK_ASSERT(numberOfPoints_ > 0);
415 unsigned int components = dataArray_[id].components;
416
417 std::vector<FloatType> values;
418 readAppended(input, values, HeaderType(dataArray_[id].offset));
419 VTK_ASSERT(values.size() == components*numberOfPoints_);
420
421 pointData_[id].resize(values.size());
422 std::copy(values.begin(), values.end(), pointData_[id].begin());
423}
424
425
426template <class Grid, class Creator, class Field>
427typename VtkReader<Grid,Creator,Field>::Sections
428VtkReader<Grid,Creator,Field>::readPoints (std::ifstream& input, std::string id)
429{
430 using T = typename GlobalCoordinate::value_type;
431 VTK_ASSERT(numberOfPoints_ > 0);
432 VTK_ASSERT(id == "Points");
433 VTK_ASSERT(dataArray_["Points"].components == 3u);
434
435 Sections sec;
436
437 std::vector<T> point_values;
438 sec = readDataArray(input, point_values, 3*numberOfPoints_, POINTS_DATA_ARRAY, POINTS);
439 if (sec != POINTS)
440 sec = skipRestOfDataArray(input, POINTS_DATA_ARRAY, POINTS);
441 VTK_ASSERT(sec == POINTS);
442 VTK_ASSERT(point_values.size() == 3*numberOfPoints_);
443
444 // extract points from continuous values
445 GlobalCoordinate p;
446 vec_points.reserve(numberOfPoints_);
447 std::size_t idx = 0;
448 for (std::size_t i = 0; i < numberOfPoints_; ++i) {
449 for (std::size_t j = 0; j < p.size(); ++j)
450 p[j] = point_values[idx++];
451 idx += (3u - p.size());
452 vec_points.push_back(p);
453 }
454
455 return sec;
456}
457
458
459template <class Grid, class Creator, class Field>
460 template <class FloatType, class HeaderType>
461void VtkReader<Grid,Creator,Field>::readPointsAppended (MetaType<FloatType>, MetaType<HeaderType>, std::ifstream& input)
462{
463 VTK_ASSERT(numberOfPoints_ > 0);
464 VTK_ASSERT(dataArray_["Points"].components == 3u);
465 std::vector<FloatType> point_values;
466 readAppended(input, point_values, HeaderType(dataArray_["Points"].offset));
467 VTK_ASSERT(point_values.size() == 3*numberOfPoints_);
468
469 // extract points from continuous values
470 GlobalCoordinate p;
471 vec_points.reserve(numberOfPoints_);
472 std::size_t idx = 0;
473 for (std::size_t i = 0; i < numberOfPoints_; ++i) {
474 for (std::size_t j = 0; j < p.size(); ++j)
475 p[j] = FloatType(point_values[idx++]);
476 idx += (3u - p.size());
477 vec_points.push_back(p);
478 }
479}
480
481
482template <class Grid, class Creator, class Field>
483typename VtkReader<Grid,Creator,Field>::Sections
484VtkReader<Grid,Creator,Field>::readCells (std::ifstream& input, std::string id)
485{
486 Sections sec = CELLS_DATA_ARRAY;
487
488 VTK_ASSERT(numberOfCells_ > 0);
489 if (id == "Cells.types") {
490 sec = readDataArray(input, vec_types, numberOfCells_, CELLS_DATA_ARRAY, CELLS);
491 VTK_ASSERT(vec_types.size() == numberOfCells_);
492 } else if (id == "Cells.offsets") {
493 sec = readDataArray(input, vec_offsets, numberOfCells_, CELLS_DATA_ARRAY, CELLS);
494 VTK_ASSERT(vec_offsets.size() == numberOfCells_);
495 } else if (id == "Cells.connectivity") {
496 sec = readDataArray(input, vec_connectivity, std::size_t(-1), CELLS_DATA_ARRAY, CELLS);
497 } else if (id == "Cells.global_point_ids") {
498 sec = readDataArray(input, vec_point_ids, numberOfPoints_, CELLS_DATA_ARRAY, CELLS);
499 VTK_ASSERT(vec_point_ids.size() == numberOfPoints_);
500 }
501
502 return sec;
503}
504
505
506template <class Grid, class Creator, class Field>
507 template <class HeaderType>
508void VtkReader<Grid,Creator,Field>::readCellsAppended (MetaType<HeaderType>, std::ifstream& input)
509{
510 VTK_ASSERT(numberOfCells_ > 0);
511 auto types_data = dataArray_["Cells.types"];
512 auto offsets_data = dataArray_["Cells.offsets"];
513 auto connectivity_data = dataArray_["Cells.connectivity"];
514
515 VTK_ASSERT(types_data.type == Vtk::DataTypes::UINT8);
516 readAppended(input, vec_types, HeaderType(types_data.offset));
517 VTK_ASSERT(vec_types.size() == numberOfCells_);
518
519 if (offsets_data.type == Vtk::DataTypes::INT64)
520 readAppended(input, vec_offsets, HeaderType(offsets_data.offset));
521 else if (offsets_data.type == Vtk::DataTypes::INT32) {
522 std::vector<std::int32_t> offsets;
523 readAppended(input, offsets, HeaderType(offsets_data.offset));
524 vec_offsets.resize(offsets.size());
525 std::copy(offsets.begin(), offsets.end(), vec_offsets.begin());
526 }
527 else { DUNE_THROW(Dune::NotImplemented, "Unsupported DataType in Cell offsets."); }
528 VTK_ASSERT(vec_offsets.size() == numberOfCells_);
529
530 if (connectivity_data.type == Vtk::DataTypes::INT64)
531 readAppended(input, vec_connectivity, HeaderType(connectivity_data.offset));
532 else if (connectivity_data.type == Vtk::DataTypes::INT32) {
533 std::vector<std::int32_t> connectivity;
534 readAppended(input, connectivity, HeaderType(connectivity_data.offset));
535 vec_connectivity.resize(connectivity.size());
536 std::copy(connectivity.begin(), connectivity.end(), vec_connectivity.begin());
537 }
538 else { DUNE_THROW(Dune::NotImplemented, "Unsupported DataType in Cell connectivity."); }
539 VTK_ASSERT(vec_connectivity.size() == std::size_t(vec_offsets.back()));
540
541 if (dataArray_.count("Cells.global_point_ids") > 0) {
542 auto point_id_data = dataArray_["Cells.global_point_ids"];
543 VTK_ASSERT(point_id_data.type == Vtk::DataTypes::UINT64);
544 readAppended(input, vec_point_ids, HeaderType(point_id_data.offset));
545 VTK_ASSERT(vec_point_ids.size() == numberOfPoints_);
546 }
547}
548
549
550// @{ implementation detail
551namespace {
552
560template <class T, class IStream>
561void read_compressed_zlib (T* buffer, unsigned char* buffer_in,
562 std::uint64_t bs, std::uint64_t cbs, IStream& input)
563{
564#if HAVE_VTK_ZLIB
565 uLongf uncompressed_space = uLongf(bs);
566 uLongf compressed_space = uLongf(cbs);
567
568 Bytef* compressed_buffer = reinterpret_cast<Bytef*>(buffer_in);
569 Bytef* uncompressed_buffer = reinterpret_cast<Bytef*>(buffer);
570
571 input.read((char*)(compressed_buffer), compressed_space);
572 VTK_ASSERT(uLongf(input.gcount()) == compressed_space);
573
574 if (uncompress(uncompressed_buffer, &uncompressed_space, compressed_buffer, compressed_space) != Z_OK) {
575 std::cerr << "Zlib error while uncompressing data.\n";
576 std::abort();
577 }
578 VTK_ASSERT(uLongf(bs) == uncompressed_space);
579#else
580 std::cerr << "ZLib Compression not supported. Provide the ZLIB package to CMake." << std::endl;
581 std::abort();
582#endif
583}
584
585template <class T, class IStream>
586void read_compressed_lz4 (T* /* buffer */, unsigned char* /* buffer_in */,
587 std::uint64_t /* bs */, std::uint64_t /* cbs */, IStream& /* input */)
588{
589#if HAVE_VTK_LZ4
590 std::cerr << "LZ4 Compression not yet implemented" << std::endl;
591 std::abort();
592#else
593 std::cerr << "LZ4 Compression not supported. Provide the LZ4 package to CMake." << std::endl;
594 std::abort();
595#endif
596}
597
598template <class T, class IStream>
599void read_compressed_lzma (T* /* buffer */, unsigned char* /* buffer_in */,
600 std::uint64_t /* bs */, std::uint64_t /* cbs */, IStream& /* input */)
601{
602#if HAVE_VTK_LZMA
603 std::cerr << "LZMA Compression not yet implemented" << std::endl;
604 std::abort();
605#else
606 std::cerr << "LZMA Compression not supported. Provide the LZMA package to CMake." << std::endl;
607 std::abort();
608#endif
609}
610
611}
612// @}
613
614
615template <class Grid, class Creator, class Field>
616 template <class FloatType, class HeaderType>
617void VtkReader<Grid,Creator,Field>::readAppended (std::ifstream& input, std::vector<FloatType>& values, HeaderType offset)
618{
619 input.seekg(offset0_ + offset);
620
621 HeaderType size = 0;
622
623 HeaderType num_blocks = 0;
624 HeaderType block_size = 0;
625 HeaderType last_block_size = 0;
626 std::vector<HeaderType> cbs; // compressed block sizes
627
628 // read total size / block-size(s)
629 if (compressor_ != Vtk::CompressorTypes::NONE) {
630 input.read((char*)&num_blocks, sizeof(HeaderType));
631 input.read((char*)&block_size, sizeof(HeaderType));
632 input.read((char*)&last_block_size, sizeof(HeaderType));
633
634 VTK_ASSERT(block_size % sizeof(FloatType) == 0);
635
636 // total size of the uncompressed data
637 size = block_size * (num_blocks-1) + last_block_size;
638
639 // size of the compressed blocks
640 cbs.resize(num_blocks);
641 input.read((char*)cbs.data(), num_blocks*sizeof(HeaderType));
642 } else {
643 input.read((char*)&size, sizeof(HeaderType));
644 }
645 VTK_ASSERT(size > 0 && (size % sizeof(FloatType)) == 0);
646 values.resize(size / sizeof(FloatType));
647
648 if (compressor_ != Vtk::CompressorTypes::NONE) {
649 // upper bound for compressed block-size
650 HeaderType compressed_block_size = block_size + (block_size + 999)/1000 + 12;
651 // number of values in the full blocks
652 std::size_t num_values = block_size / sizeof(FloatType);
653
654 std::vector<unsigned char> buffer_in(compressed_block_size);
655 for (std::size_t i = 0; i < std::size_t(num_blocks); ++i) {
656 HeaderType bs = i < std::size_t(num_blocks-1) ? block_size : last_block_size;
657
658 switch (compressor_) {
660 read_compressed_zlib(values.data() + i*num_values, buffer_in.data(), bs, cbs[i], input);
661 break;
663 read_compressed_lz4(values.data() + i*num_values, buffer_in.data(), bs, cbs[i], input);
664 break;
666 read_compressed_lzma(values.data() + i*num_values, buffer_in.data(), bs, cbs[i], input);
667 break;
668 default:
669 VTK_ASSERT_MSG(false, "Unsupported Compressor type.");
670 break;
671 }
672 }
673 } else {
674 input.read((char*)(values.data()), size);
675 VTK_ASSERT(input.gcount() == std::streamsize(size));
676 }
677}
678
679
680template <class Grid, class Creator, class Field>
682{
683 VTK_ASSERT(vec_points.size() == numberOfPoints_);
684 VTK_ASSERT(vec_types.size() == numberOfCells_);
685 VTK_ASSERT(vec_offsets.size() == numberOfCells_);
686
687 if (!vec_points.empty())
688 creator_->insertVertices(vec_points, vec_point_ids);
689 if (!vec_types.empty())
690 creator_->insertElements(vec_types, vec_offsets, vec_connectivity);
691 if (insertPieces)
692 creator_->insertPieces(pieces_);
693}
694
695
696// Convert section into string
697template <class Grid, class Creator, class Field>
698std::string VtkReader<Grid,Creator,Field>::toString(Sections s) const
699{
700 switch (s) {
701 case VTK_FILE:
702 return "VTKFile";
703 case UNSTRUCTURED_GRID:
704 return "UnstructuredGrid";
705 case PIECE:
706 return "Piece";
707 case POINT_DATA:
708 return "PointData";
709 case CELL_DATA:
710 return "CellData";
711 case POINTS:
712 return "Points";
713 case CELLS:
714 return "Cells";
715 case APPENDED_DATA:
716 return "AppendedData";
717 case PD_DATA_ARRAY:
718 case CD_DATA_ARRAY:
719 case POINTS_DATA_ARRAY:
720 case CELLS_DATA_ARRAY:
721 return "DataArray";
722 default:
723 return "Unknown";
724 }
725}
726
727
728// Assume input already read the line <AppendedData ...>
729template <class Grid, class Creator, class Field>
730std::uint64_t VtkReader<Grid,Creator,Field>::findAppendedDataPosition (std::ifstream& input) const
731{
732 char c;
733 while (input.get(c) && std::isblank(c)) { /*do nothing*/ }
734
735 std::uint64_t offset = input.tellg();
736 if (c != '_')
737 --offset; // if char is not '_', assume it is part of the data.
738
739 return offset;
740}
741
742
743template <class Grid, class Creator, class Field>
744std::map<std::string, std::string> VtkReader<Grid,Creator,Field>::parseXml (std::string const& line, bool& closed)
745{
746 closed = false;
747 std::map<std::string, std::string> attr;
748
749 Sections sec = NO_SECTION;
750 bool escape = false;
751
752 std::string name = "";
753 std::string value = "";
754 for (auto c : line) {
755 switch (sec) {
756 case NO_SECTION:
757 if (std::isalpha(c) || c == '_') {
758 name.clear();
759 sec = XML_NAME;
760 name.push_back(c);
761 } else if (c == '/') {
762 closed = true;
763 }
764 break;
765 case XML_NAME:
766 if (std::isalpha(c) || c == '_')
767 name.push_back(c);
768 else
769 sec = (c == '=' ? XML_NAME_ASSIGN : NO_SECTION);
770 break;
771 case XML_NAME_ASSIGN:
772 value.clear();
773 escape = false;
774 VTK_ASSERT_MSG( c == '"', "Format error!" );
775 sec = XML_VALUE;
776 break;
777 case XML_VALUE:
778 if (c == '"' && !escape) {
779 attr[name] = value;
780 sec = NO_SECTION;
781 } else if (c == '\\' && !escape) {
782 escape = true;
783 } else {
784 value.push_back(c);
785 escape = false;
786 }
787 break;
788 default:
789 VTK_ASSERT_MSG(false, "Format error!");
790 }
791 }
792
793 return attr;
794}
795
796
797template <class Grid, class Creator, class Field>
798void VtkReader<Grid,Creator,Field>::clear ()
799{
800 vec_points.clear();
801 vec_point_ids.clear();
802 vec_types.clear();
803 vec_offsets.clear();
804 vec_connectivity.clear();
805 dataArray_.clear();
806 pieces_.clear();
807
808 numberOfCells_ = 0;
809 numberOfPoints_ = 0;
810 offset0_ = 0;
811 read_ = false;
812}
813
814} // end namespace Dune
Macro for wrapping error checks and throwing exceptions.
#define VTK_ASSERT_MSG(cond, text)
check if condition cond holds; otherwise, throw a VtkError with a message.
Definition: errors.hh:19
#define VTK_ASSERT(cond)
check if condition cond holds; otherwise, throw a VtkError.
Definition: errors.hh:29
Definition: writer.hh:13
Sections skipRestOfDataArray(IStream &input, Sections section, Sections parent_section)
Definition: vtkreader.impl.hh:342
Sections readDataArray(IStream &input, std::vector< T > &values, std::size_t max_size, Sections section, Sections parent_section)
Definition: vtkreader.impl.hh:316
std::string & ltrim(std::string &str)
trim a string from the left
Definition: string.hh:30
std::string & trim(std::string &str)
trim a string from both sides
Definition: string.hh:52
Vtk::DataTypes dataTypeOf()
Definition: types.hh:79
std::string to_lower(std::string input)
convert all characters in a string to upper case
Definition: string.hh:22
DataTypes
Definition: types.hh:52
bool exists(Path const &p)
Test whether the path is a valid (existing and accessible) file / directory.
Definition: filesystem.cc:134
Definition: errors.hh:12
Definition: filesystem.hh:15
Path extension() const
Returns the file extension path component.
Definition: filesystem.cc:77
std::string string() const
Return the path as string.
Definition: filesystem.cc:27
File-Reader for Vtk unstructured .vtu files.
Definition: vtkreader.hh:37
void read(std::string const &filename, bool fillCreator=true)
Read the grid from file with filename into the GridCreator.
Definition: vtkreader.impl.hh:20
void readParallelFileFromStream(std::ifstream &input, int rank, int size, bool create=true)
Read the grid from and input stream, referring to a .pvtu file, into the GridFactory factory_.
Definition: vtkreader.impl.hh:249
void fillGridCreator(bool insertPieces=true)
Definition: vtkreader.impl.hh:681
void readSerialFileFromStream(std::ifstream &input, bool create=true)
Read the grid from an input stream, referring to a .vtu file, into the GridFactory factory_.
Definition: vtkreader.impl.hh:43