dune-vtk 2.12
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
12
13#include "utility/errors.hh"
14#include "utility/filesystem.hh"
15#include "utility/string.hh"
16
17namespace Dune::Vtk {
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::Vtk::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>
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::Vtk::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::Vtk::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");
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 });
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::Vtk::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
359{
360 VTK_ASSERT(numberOfCells_ > 0);
361 unsigned int components = dataArray_[id].components;
362
363 Sections sec = NO_SECTION;
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>
378{
379 VTK_ASSERT(numberOfCells_ > 0);
380 unsigned int components = dataArray_[id].components;
381
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
394{
395 VTK_ASSERT(numberOfPoints_ > 0);
396 unsigned int components = dataArray_[id].components;
397
398 Sections sec = NO_SECTION;
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>
413{
414 VTK_ASSERT(numberOfPoints_ > 0);
415 unsigned int components = dataArray_[id].components;
416
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
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 = NO_SECTION;
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>
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
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
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>
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) {
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 ([[maybe_unused]] T* buffer,
562 [[maybe_unused]] unsigned char* buffer_in,
563 [[maybe_unused]] std::uint64_t bs,
564 [[maybe_unused]] std::uint64_t cbs,
565 [[maybe_unused]] IStream& input)
566{
567#if HAVE_VTK_ZLIB
568 uLongf uncompressed_space = uLongf(bs);
569 uLongf compressed_space = uLongf(cbs);
570
571 Bytef* compressed_buffer = reinterpret_cast<Bytef*>(buffer_in);
572 Bytef* uncompressed_buffer = reinterpret_cast<Bytef*>(buffer);
573
574 input.read((char*)(compressed_buffer), compressed_space);
575 VTK_ASSERT(uLongf(input.gcount()) == compressed_space);
576
577 if (uncompress(uncompressed_buffer, &uncompressed_space, compressed_buffer, compressed_space) != Z_OK) {
578 std::cerr << "Zlib error while uncompressing data.\n";
579 std::abort();
580 }
581 VTK_ASSERT(uLongf(bs) == uncompressed_space);
582#else
583 std::cerr << "ZLib Compression not supported. Provide the ZLIB package to CMake." << std::endl;
584 std::abort();
585#endif
586}
587
588template <class T, class IStream>
589void read_compressed_lz4 (T* /* buffer */, unsigned char* /* buffer_in */,
590 std::uint64_t /* bs */, std::uint64_t /* cbs */, IStream& /* input */)
591{
592#if HAVE_VTK_LZ4
593 std::cerr << "LZ4 Compression not yet implemented" << std::endl;
594 std::abort();
595#else
596 std::cerr << "LZ4 Compression not supported. Provide the LZ4 package to CMake." << std::endl;
597 std::abort();
598#endif
599}
600
601template <class T, class IStream>
602void read_compressed_lzma (T* /* buffer */, unsigned char* /* buffer_in */,
603 std::uint64_t /* bs */, std::uint64_t /* cbs */, IStream& /* input */)
604{
605#if HAVE_VTK_LZMA
606 std::cerr << "LZMA Compression not yet implemented" << std::endl;
607 std::abort();
608#else
609 std::cerr << "LZMA Compression not supported. Provide the LZMA package to CMake." << std::endl;
610 std::abort();
611#endif
612}
613
614}
615// @}
616
617
618template <class Grid, class Creator, class Field>
619 template <class FloatType, class HeaderType>
620void VtkReader<Grid,Creator,Field>::readAppended (std::ifstream& input, std::vector<FloatType>& values, HeaderType offset)
621{
622 input.seekg(offset0_ + offset);
623
624 HeaderType size = 0;
625
626 HeaderType num_blocks = 0;
627 HeaderType block_size = 0;
628 HeaderType last_block_size = 0;
629 std::vector<HeaderType> cbs; // compressed block sizes
630
631 // read total size / block-size(s)
632 if (compressor_ != Vtk::CompressorTypes::NONE) {
633 input.read((char*)&num_blocks, sizeof(HeaderType));
634 input.read((char*)&block_size, sizeof(HeaderType));
635 input.read((char*)&last_block_size, sizeof(HeaderType));
636
637 VTK_ASSERT(block_size % sizeof(FloatType) == 0);
638
639 // total size of the uncompressed data
640 size = block_size * (num_blocks-1) + last_block_size;
641
642 // size of the compressed blocks
643 cbs.resize(num_blocks);
644 input.read((char*)cbs.data(), num_blocks*sizeof(HeaderType));
645 } else {
646 input.read((char*)&size, sizeof(HeaderType));
647 }
648 VTK_ASSERT(size > 0 && (size % sizeof(FloatType)) == 0);
649 values.resize(size / sizeof(FloatType));
650
651 if (compressor_ != Vtk::CompressorTypes::NONE) {
652 // upper bound for compressed block-size
653 HeaderType compressed_block_size = block_size + (block_size + 999)/1000 + 12;
654 // number of values in the full blocks
655 std::size_t num_values = block_size / sizeof(FloatType);
656
657 std::vector<unsigned char> buffer_in(compressed_block_size);
658 for (std::size_t i = 0; i < std::size_t(num_blocks); ++i) {
659 HeaderType bs = i < std::size_t(num_blocks-1) ? block_size : last_block_size;
660
661 switch (compressor_) {
663 read_compressed_zlib(values.data() + i*num_values, buffer_in.data(), bs, cbs[i], input);
664 break;
666 read_compressed_lz4(values.data() + i*num_values, buffer_in.data(), bs, cbs[i], input);
667 break;
669 read_compressed_lzma(values.data() + i*num_values, buffer_in.data(), bs, cbs[i], input);
670 break;
671 default:
672 VTK_ASSERT_MSG(false, "Unsupported Compressor type.");
673 break;
674 }
675 }
676 } else {
677 input.read((char*)(values.data()), size);
679 }
680}
681
682
683template <class Grid, class Creator, class Field>
685{
686 VTK_ASSERT(vec_points.size() == numberOfPoints_);
687 VTK_ASSERT(vec_types.size() == numberOfCells_);
688 VTK_ASSERT(vec_offsets.size() == numberOfCells_);
689
690 if (!vec_points.empty())
691 creator_->insertVertices(vec_points, vec_point_ids);
692 if (!vec_types.empty())
693 creator_->insertElements(vec_types, vec_offsets, vec_connectivity);
694 if (insertPieces)
695 creator_->insertPieces(pieces_);
696}
697
698
699// Convert section into string
700template <class Grid, class Creator, class Field>
702{
703 switch (s) {
704 case VTK_FILE:
705 return "VTKFile";
706 case UNSTRUCTURED_GRID:
707 return "UnstructuredGrid";
708 case PIECE:
709 return "Piece";
710 case POINT_DATA:
711 return "PointData";
712 case CELL_DATA:
713 return "CellData";
714 case POINTS:
715 return "Points";
716 case CELLS:
717 return "Cells";
718 case APPENDED_DATA:
719 return "AppendedData";
720 case PD_DATA_ARRAY:
721 case CD_DATA_ARRAY:
722 case POINTS_DATA_ARRAY:
723 case CELLS_DATA_ARRAY:
724 return "DataArray";
725 default:
726 return "Unknown";
727 }
728}
729
730
731// Assume input already read the line <AppendedData ...>
732template <class Grid, class Creator, class Field>
733std::uint64_t VtkReader<Grid,Creator,Field>::findAppendedDataPosition (std::ifstream& input) const
734{
735 char c = 0;
736 while (input.get(c) && std::isblank(c)) { /*do nothing*/ }
737
738 std::uint64_t offset = input.tellg();
739 if (c != '_')
740 --offset; // if char is not '_', assume it is part of the data.
741
742 return offset;
743}
744
745
746template <class Grid, class Creator, class Field>
747std::map<std::string, std::string> VtkReader<Grid,Creator,Field>::parseXml (std::string const& line, bool& closed)
748{
749 closed = false;
751
752 Sections sec = NO_SECTION;
753 bool escape = false;
754
755 std::string name = "";
756 std::string value = "";
757 for (auto c : line) {
758 switch (sec) {
759 case NO_SECTION:
760 if (std::isalpha(c) || c == '_') {
761 name.clear();
762 sec = XML_NAME;
763 name.push_back(c);
764 } else if (c == '/') {
765 closed = true;
766 }
767 break;
768 case XML_NAME:
769 if (std::isalpha(c) || c == '_')
770 name.push_back(c);
771 else
772 sec = (c == '=' ? XML_NAME_ASSIGN : NO_SECTION);
773 break;
774 case XML_NAME_ASSIGN:
775 value.clear();
776 escape = false;
777 VTK_ASSERT_MSG( c == '"', "Format error!" );
778 sec = XML_VALUE;
779 break;
780 case XML_VALUE:
781 if (c == '"' && !escape) {
782 attr[name] = value;
783 sec = NO_SECTION;
784 } else if (c == '\\' && !escape) {
785 escape = true;
786 } else {
787 value.push_back(c);
788 escape = false;
789 }
790 break;
791 default:
792 VTK_ASSERT_MSG(false, "Format error!");
793 }
794 }
795
796 return attr;
797}
798
799
800template <class Grid, class Creator, class Field>
801void VtkReader<Grid,Creator,Field>::clear ()
802{
803 vec_points.clear();
804 vec_point_ids.clear();
805 vec_types.clear();
806 vec_offsets.clear();
807 vec_connectivity.clear();
808 dataArray_.clear();
809 pieces_.clear();
810
811 numberOfCells_ = 0;
812 numberOfPoints_ = 0;
813 offset0_ = 0;
814 read_ = false;
815}
816
817} // end namespace Dune::Vtk
#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:16
std::string & ltrim(std::string &str)
trim a string from the left
Definition string.hh:28
std::string & trim(std::string &str)
trim a string from both sides
Definition string.hh:50
Sections skipRestOfDataArray(IStream &input, Sections section, Sections parent_section)
Definition vtkreader.impl.hh:342
Vtk::DataTypes dataTypeOf()
Definition types.hh:78
std::string to_lower(std::string input)
convert all characters in a string to upper case
Definition string.hh:20
Sections readDataArray(IStream &input, std::vector< T > &values, std::size_t max_size, Sections section, Sections parent_section)
Definition vtkreader.impl.hh:316
DataTypes
Definition types.hh:51
bool exists(Path const &p)
Test whether the path is a valid (existing and accessible) file / directory.
Definition filesystem.cc:133
const char * name()
int id()
int size() const
void clear()
bool empty() const
#define DUNE_THROW(E,...)
Definition errors.hh:12
Definition filesystem.hh:13
Path extension() const
Returns the file extension path component.
Definition filesystem.cc:76
std::string string() const
Return the path as string.
Definition filesystem.cc:26
File-Reader for Vtk unstructured .vtu files.
Definition vtkreader.hh:37
typename GridCreator::GlobalCoordinate GlobalCoordinate
Type of global world coordinates.
Definition vtkreader.hh:66
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 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
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 fillGridCreator(bool insertPieces=true)
Definition vtkreader.impl.hh:684
Definition vtkreader.hh:346
T abort(T... args)
T begin(T... args)
T clear(T... args)
T copy(T... args)
T data(T... args)
T end(T... args)
T endl(T... args)
T gcount(T... args)
T get(T... args)
T getline(T... args)
T is_open(T... args)
T push_back(T... args)
T read(T... args)
T reserve(T... args)
T resize(T... args)
T seekg(T... args)
T size(T... args)
T stod(T... args)
T stoul(T... args)
T tellg(T... args)