| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de> | ||
| 2 | // SPDX-License-Identifier: MIT | ||
| 3 | /*! | ||
| 4 | * \file | ||
| 5 | * \ingroup VTK | ||
| 6 | * \copydoc GridFormat::PVTRReader | ||
| 7 | */ | ||
| 8 | #ifndef GRIDFORMAT_VTK_PVTR_READER_HPP_ | ||
| 9 | #define GRIDFORMAT_VTK_PVTR_READER_HPP_ | ||
| 10 | |||
| 11 | #include <algorithm> | ||
| 12 | #include <unordered_map> | ||
| 13 | #include <vector> | ||
| 14 | #include <ranges> | ||
| 15 | #include <array> | ||
| 16 | |||
| 17 | #include <gridformat/vtk/vtr_reader.hpp> | ||
| 18 | #include <gridformat/vtk/pxml_reader.hpp> | ||
| 19 | |||
| 20 | namespace GridFormat { | ||
| 21 | |||
| 22 | /*! | ||
| 23 | * \ingroup VTK | ||
| 24 | * \brief Reader for .pvtr file format | ||
| 25 | * \copydetails VTK::PXMLStructuredGridReader | ||
| 26 | */ | ||
| 27 | class PVTRReader : public VTK::PXMLStructuredGridReader<VTRReader> { | ||
| 28 | using ParentType = VTK::PXMLStructuredGridReader<VTRReader>; | ||
| 29 | using IndexInterval = std::array<std::size_t, 2>; | ||
| 30 | |||
| 31 | public: | ||
| 32 | 1 | PVTRReader() | |
| 33 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | : ParentType("PRectilinearGrid") |
| 34 | 1 | {} | |
| 35 | |||
| 36 | 50 | explicit PVTRReader(const NullCommunicator&) | |
| 37 |
2/4✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
|
100 | : ParentType("PRectilinearGrid") |
| 38 | 50 | {} | |
| 39 | |||
| 40 | template<Concepts::Communicator C> | ||
| 41 | 84 | explicit PVTRReader(const C& comm) | |
| 42 |
2/4✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 84 times.
✗ Branch 6 not taken.
|
168 | : ParentType("PRectilinearGrid", comm) |
| 43 | 84 | {} | |
| 44 | |||
| 45 | private: | ||
| 46 | 2 | std::string _name() const override { | |
| 47 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
4 | return "PVTRReader"; |
| 48 | } | ||
| 49 | |||
| 50 | 9 | std::vector<double> _ordinates(unsigned int i) const override { | |
| 51 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
|
9 | if (this->_num_process_pieces() == 0) |
| 52 | ✗ | return {}; | |
| 53 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
|
9 | if (this->_num_process_pieces() == 1) |
| 54 |
1/2✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 | return this->_readers().front().ordinates(i); |
| 55 | |||
| 56 | 3 | std::unordered_map<std::size_t, IndexInterval> piece_to_interval; | |
| 57 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | std::ranges::for_each(this->_readers(), [&, reader_idx=0] (const GridReader& reader) mutable { |
| 58 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | auto interval = _to_interval(reader.location(), i); |
| 59 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | const bool should_insert = std::ranges::none_of( |
| 60 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | piece_to_interval | std::views::values, |
| 61 | 3 | [&] (const auto& inserted_interval) { | |
| 62 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
|
3 | if (_is_same(inserted_interval, interval)) |
| 63 | 2 | return true; | |
| 64 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | else if (_overlap(inserted_interval, interval)) |
| 65 | ✗ | throw IOError("Cannot determine ordinates for pieces with overlapping intervals"); | |
| 66 | 1 | return false; | |
| 67 | } | ||
| 68 | ); | ||
| 69 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
|
6 | if (should_insert) |
| 70 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | piece_to_interval.emplace(std::make_pair(reader_idx, std::move(interval))); |
| 71 | 6 | reader_idx++; | |
| 72 | 6 | }); | |
| 73 | |||
| 74 | |||
| 75 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | std::vector<unsigned int> sorted_piece_indices(piece_to_interval.size()); |
| 76 |
2/4✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
3 | std::ranges::copy(std::views::iota(std::size_t{0}, sorted_piece_indices.size()), sorted_piece_indices.begin()); |
| 77 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | std::ranges::sort(sorted_piece_indices, [&] (unsigned int a, unsigned int b) { |
| 78 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | return piece_to_interval.at(a)[0] < piece_to_interval.at(b)[0]; |
| 79 | }); | ||
| 80 | |||
| 81 | 3 | std::vector<double> result; | |
| 82 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | std::ranges::for_each(sorted_piece_indices, [&] (unsigned int piece_idx) { |
| 83 |
2/4✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
|
4 | auto piece_ordinates = this->_readers().at(piece_idx).ordinates(i); |
| 84 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
|
4 | if (result.size() > 0) |
| 85 | 1 | result.pop_back(); // avoid duplicate points at overlaps | |
| 86 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | result.reserve(result.size() + piece_ordinates.size()); |
| 87 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
|
4 | std::ranges::move(std::move(piece_ordinates), std::back_inserter(result)); |
| 88 | 4 | }); | |
| 89 | 3 | return result; | |
| 90 | 3 | } | |
| 91 | |||
| 92 | 3 | bool _is_same(const IndexInterval& a, const IndexInterval& b) const { | |
| 93 | 3 | return std::ranges::equal(a, b); | |
| 94 | } | ||
| 95 | |||
| 96 | 1 | bool _overlap(const IndexInterval& a, const IndexInterval& b) const { | |
| 97 |
3/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
1 | return (a[0] < b[0] && a[1] > b[0]) || (b[0] < a[0] && b[1] > a[0]); |
| 98 | } | ||
| 99 | |||
| 100 | 6 | IndexInterval _to_interval(const typename ParentType::PieceLocation& loc, unsigned int i) const { | |
| 101 | 6 | return {loc.lower_left.at(i), loc.upper_right.at(i)}; | |
| 102 | } | ||
| 103 | }; | ||
| 104 | |||
| 105 | } // namespace GridFormat | ||
| 106 | |||
| 107 | #endif // GRIDFORMAT_VTK_PVTR_READER_HPP_ | ||
| 108 |