| 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 | * \brief Helper function for writing parallel VTK files | ||
| 7 | */ | ||
| 8 | #ifndef GRIDFORMAT_VTK_PARALLEL_HPP_ | ||
| 9 | #define GRIDFORMAT_VTK_PARALLEL_HPP_ | ||
| 10 | |||
| 11 | #include <array> | ||
| 12 | #include <vector> | ||
| 13 | #include <string> | ||
| 14 | #include <utility> | ||
| 15 | #include <concepts> | ||
| 16 | #include <algorithm> | ||
| 17 | #include <iterator> | ||
| 18 | #include <numeric> | ||
| 19 | #include <tuple> | ||
| 20 | #include <cmath> | ||
| 21 | |||
| 22 | #include <gridformat/common/math.hpp> | ||
| 23 | #include <gridformat/common/exceptions.hpp> | ||
| 24 | #include <gridformat/common/concepts.hpp> | ||
| 25 | #include <gridformat/common/ranges.hpp> | ||
| 26 | #include <gridformat/common/field.hpp> | ||
| 27 | #include <gridformat/grid/grid.hpp> | ||
| 28 | |||
| 29 | #include <gridformat/parallel/communication.hpp> | ||
| 30 | #include <gridformat/parallel/helpers.hpp> | ||
| 31 | |||
| 32 | #include <gridformat/xml/element.hpp> | ||
| 33 | #include <gridformat/vtk/attributes.hpp> | ||
| 34 | |||
| 35 | namespace GridFormat::PVTK { | ||
| 36 | |||
| 37 | //! Return the piece filename (w/o extension) for the given rank | ||
| 38 | 12740 | std::string piece_basefilename(const std::string& par_filename, int rank) { | |
| 39 |
1/2✓ Branch 2 taken 12740 times.
✗ Branch 3 not taken.
|
12740 | const std::string base_name = par_filename.substr(0, par_filename.find_last_of(".")); |
| 40 |
2/4✓ Branch 2 taken 12740 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 12740 times.
✗ Branch 6 not taken.
|
25480 | return base_name + "-" + std::to_string(rank); |
| 41 | 12740 | } | |
| 42 | |||
| 43 | //! Helper to add a PDataArray child to an xml element | ||
| 44 | template<typename Encoder, typename DataFormat> | ||
| 45 | class PDataArrayHelper { | ||
| 46 | public: | ||
| 47 | 8480 | PDataArrayHelper(const Encoder& e, | |
| 48 | const DataFormat& df, | ||
| 49 | XMLElement& element) | ||
| 50 | 8480 | : _encoder(e) | |
| 51 | 8480 | , _data_format(df) | |
| 52 | 8480 | , _element(element) | |
| 53 | 8480 | {} | |
| 54 | |||
| 55 | 46968 | void add(const std::string& name, const Field& field) { | |
| 56 | // vtk always uses 3d, this assumes that the field | ||
| 57 | // is transformed accordingly in the piece writers | ||
| 58 | static constexpr std::size_t vtk_space_dim = 3; | ||
| 59 |
1/2✓ Branch 1 taken 23484 times.
✗ Branch 2 not taken.
|
46968 | const auto layout = field.layout(); |
| 60 |
2/4✓ Branch 1 taken 23484 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23484 times.
✗ Branch 5 not taken.
|
46968 | std::size_t ncomps = std::pow(vtk_space_dim, field.layout().dimension() - 1); |
| 61 | |||
| 62 | // leave higher-dimensional vectors untouched | ||
| 63 |
8/10✓ Branch 1 taken 23484 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7910 times.
✓ Branch 4 taken 15574 times.
✓ Branch 6 taken 7910 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 144 times.
✓ Branch 9 taken 7766 times.
✓ Branch 10 taken 144 times.
✓ Branch 11 taken 23340 times.
|
46968 | if (layout.dimension() == 2 && layout.extent(1) > vtk_space_dim) |
| 64 |
1/2✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
|
288 | ncomps = layout.extent(1); |
| 65 | |||
| 66 |
2/4✓ Branch 1 taken 23484 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23484 times.
✗ Branch 5 not taken.
|
93936 | XMLElement& arr = _element.add_child("PDataArray"); |
| 67 |
2/4✓ Branch 1 taken 23484 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23484 times.
✗ Branch 5 not taken.
|
93936 | arr.set_attribute("Name", name); |
| 68 |
4/8✓ Branch 1 taken 23484 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23484 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 23484 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 23484 times.
✗ Branch 11 not taken.
|
140904 | arr.set_attribute("type", VTK::attribute_name(field.precision())); |
| 69 |
3/6✓ Branch 1 taken 23484 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23484 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 23484 times.
✗ Branch 8 not taken.
|
140904 | arr.set_attribute("format", VTK::data_format_name(_encoder, _data_format)); |
| 70 |
2/4✓ Branch 1 taken 23484 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23484 times.
✗ Branch 5 not taken.
|
93936 | arr.set_attribute("NumberOfComponents", ncomps); |
| 71 | 46968 | } | |
| 72 | |||
| 73 | private: | ||
| 74 | const Encoder& _encoder; | ||
| 75 | const DataFormat& _data_format; | ||
| 76 | XMLElement& _element; | ||
| 77 | }; | ||
| 78 | |||
| 79 | template<std::size_t dim> | ||
| 80 | class StructuredGridMapper { | ||
| 81 | public: | ||
| 82 | using Location = std::array<std::size_t, dim>; | ||
| 83 | |||
| 84 | 4220 | explicit StructuredGridMapper(std::vector<Location>&& map) | |
| 85 | 4220 | : _map{std::move(map)} | |
| 86 | 4220 | {} | |
| 87 | |||
| 88 | 35092 | const auto& location(std::integral auto rank) const { | |
| 89 | 35092 | return _map[rank]; | |
| 90 | } | ||
| 91 | |||
| 92 | 35092 | std::ranges::view auto ranks_below(const Location& loc, unsigned direction) const { | |
| 93 | return std::views::filter( | ||
| 94 |
1/2✓ Branch 1 taken 17718 times.
✗ Branch 2 not taken.
|
35092 | std::views::iota(std::size_t{0}, _map.size()), |
| 95 | 128124 | [&, loc=loc, direction=direction] (const std::size_t rank) { | |
| 96 | 58660 | const auto& rank_loc = _map[rank]; | |
| 97 |
4/4✓ Branch 0 taken 15862 times.
✓ Branch 1 taken 5110 times.
✓ Branch 2 taken 110744 times.
✓ Branch 3 taken 23140 times.
|
154856 | for (unsigned dir = 0; dir < dim; ++dir) |
| 98 |
12/12✓ Branch 0 taken 9064 times.
✓ Branch 1 taken 6798 times.
✓ Branch 4 taken 3954 times.
✓ Branch 5 taken 5110 times.
✓ Branch 6 taken 3954 times.
✓ Branch 7 taken 11908 times.
✓ Branch 8 taken 79340 times.
✓ Branch 9 taken 31404 times.
✓ Branch 12 taken 26456 times.
✓ Branch 13 taken 52884 times.
✓ Branch 14 taken 26456 times.
✓ Branch 15 taken 84288 times.
|
126606 | if (dir != direction && rank_loc[dir] != loc[dir]) { |
| 99 | 30410 | return false; | |
| 100 | } | ||
| 101 | 28250 | return rank_loc[direction] < loc[direction]; | |
| 102 | } | ||
| 103 |
1/2✓ Branch 1 taken 17718 times.
✗ Branch 2 not taken.
|
70184 | ); |
| 104 | } | ||
| 105 | |||
| 106 | private: | ||
| 107 | std::vector<Location> _map; | ||
| 108 | }; | ||
| 109 | |||
| 110 | //! Helper for finding the locations of the sub-grids | ||
| 111 | //! associated with each rank in structured parallel grids | ||
| 112 | template<typename T, std::size_t dim> | ||
| 113 | class StructuredGridMapperHelper { | ||
| 114 | public: | ||
| 115 | using Origin = std::array<T, dim>; | ||
| 116 | using Basis = std::array<Origin, dim>; | ||
| 117 | |||
| 118 | 4220 | explicit StructuredGridMapperHelper(std::integral auto ranks, | |
| 119 | const Basis& basis, | ||
| 120 | T default_epsilon = 1e-6) | ||
| 121 | 4220 | : _basis(basis) | |
| 122 |
1/2✓ Branch 1 taken 2152 times.
✗ Branch 2 not taken.
|
8440 | , _origins(ranks) |
| 123 |
1/2✓ Branch 1 taken 2152 times.
✗ Branch 2 not taken.
|
8440 | , _set(ranks, false) |
| 124 | 4220 | , _default_epsilon{default_epsilon} { | |
| 125 |
1/2✓ Branch 1 taken 2152 times.
✗ Branch 2 not taken.
|
4220 | std::ranges::fill(_reverse, false); |
| 126 | 4220 | } | |
| 127 | |||
| 128 | 5712 | void reverse(int direction) { | |
| 129 | 5712 | _reverse[direction] = !_reverse[direction]; | |
| 130 | 5712 | } | |
| 131 | |||
| 132 | 12588 | void set_origin_for(int rank, Origin origin) { | |
| 133 |
2/4✓ Branch 1 taken 6380 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6380 times.
|
12588 | if (_set[rank]) |
| 134 | ✗ | throw ValueError("Origin for given rank already set"); | |
| 135 | 12588 | _origins[rank] = std::move(origin); | |
| 136 |
1/2✓ Branch 1 taken 6380 times.
✗ Branch 2 not taken.
|
12588 | _set[rank] = true; |
| 137 | 12588 | } | |
| 138 | |||
| 139 | 4220 | auto make_mapper() const { | |
| 140 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2152 times.
|
4220 | if (_origins.empty()) |
| 141 | ✗ | throw InvalidState("No origins have been set"); | |
| 142 | |||
| 143 |
1/2✓ Branch 2 taken 2152 times.
✗ Branch 3 not taken.
|
4220 | std::vector<std::array<std::size_t, dim>> map(_origins.size()); |
| 144 |
2/2✓ Branch 1 taken 5956 times.
✓ Branch 2 taken 2152 times.
|
15964 | for (unsigned dir = 0; dir < dim; ++dir) { |
| 145 |
1/2✓ Branch 1 taken 5956 times.
✗ Branch 2 not taken.
|
11744 | auto ordinates = _get_ordinates(dir); |
| 146 |
1/2✓ Branch 1 taken 5956 times.
✗ Branch 2 not taken.
|
11744 | const auto eps = _epsilon(ordinates); |
| 147 |
1/2✓ Branch 2 taken 5956 times.
✗ Branch 3 not taken.
|
11744 | _sort_ordinates(ordinates, eps, _reverse[dir]); |
| 148 | |||
| 149 |
2/2✓ Branch 1 taken 3190 times.
✓ Branch 2 taken 2766 times.
|
11744 | if (ordinates.size() > 1) { |
| 150 |
2/2✓ Branch 1 taken 10532 times.
✓ Branch 2 taken 3190 times.
|
27178 | for (unsigned rank = 0; rank < _origins.size(); ++rank) { |
| 151 |
1/2✓ Branch 2 taken 10532 times.
✗ Branch 3 not taken.
|
20884 | const auto rank_origin_ordinate = _get_ordinate(_origins[rank], dir); |
| 152 |
1/2✓ Branch 1 taken 10532 times.
✗ Branch 2 not taken.
|
36412 | auto it = std::ranges::find_if(ordinates, [&] (const T o) { |
| 153 | using std::abs; | ||
| 154 | 15798 | return abs(o - rank_origin_ordinate) < eps; | |
| 155 | }); | ||
| 156 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 10532 times.
|
20884 | if (it == ordinates.end()) |
| 157 | ✗ | throw InvalidState("Could not determine rank ordinate"); | |
| 158 | 41768 | map[rank][dir] = std::distance(ordinates.begin(), it); | |
| 159 | } | ||
| 160 | } else { | ||
| 161 |
2/2✓ Branch 1 taken 7186 times.
✓ Branch 2 taken 2766 times.
|
19658 | for (unsigned rank = 0; rank < _origins.size(); ++rank) |
| 162 | 14208 | map[rank][dir] = 0; | |
| 163 | } | ||
| 164 | } | ||
| 165 | 8440 | return StructuredGridMapper<dim>{std::move(map)}; | |
| 166 | 4220 | } | |
| 167 | |||
| 168 | 4220 | Origin compute_origin() const { | |
| 169 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2152 times.
|
4220 | if (_origins.empty()) |
| 170 | ✗ | throw InvalidState("No origins have been set"); | |
| 171 | |||
| 172 | Origin result; | ||
| 173 |
2/2✓ Branch 0 taken 5956 times.
✓ Branch 1 taken 2152 times.
|
15964 | for (unsigned dir = 0; dir < dim; ++dir) { |
| 174 |
1/2✓ Branch 1 taken 5956 times.
✗ Branch 2 not taken.
|
11744 | auto ordinates = _get_ordinates(dir); |
| 175 |
1/2✓ Branch 2 taken 5956 times.
✗ Branch 3 not taken.
|
11744 | _sort_ordinates(ordinates, _reverse[dir]); |
| 176 | 11744 | result[dir] = ordinates[0]; | |
| 177 | } | ||
| 178 | 4220 | return result; | |
| 179 | } | ||
| 180 | |||
| 181 | private: | ||
| 182 | 23488 | auto _get_ordinates(unsigned int axis) const { | |
| 183 | 23488 | std::vector<T> result; | |
| 184 |
1/2✓ Branch 2 taken 11912 times.
✗ Branch 3 not taken.
|
23488 | result.reserve(_origins.size()); |
| 185 |
2/4✓ Branch 1 taken 11912 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11912 times.
✗ Branch 5 not taken.
|
46976 | std::ranges::copy( |
| 186 |
1/2✓ Branch 1 taken 11912 times.
✗ Branch 2 not taken.
|
58236 | std::views::transform(_origins, [&] (const Origin& o) { |
| 187 | 35436 | return _get_ordinate(o, axis); | |
| 188 | }), | ||
| 189 | std::back_inserter(result) | ||
| 190 | ); | ||
| 191 | 23488 | return result; | |
| 192 | ✗ | } | |
| 193 | |||
| 194 | 91068 | auto _get_ordinate(const Origin& o, unsigned int axis) const { | |
| 195 | 91068 | return dot_product(o, _basis[axis]); | |
| 196 | } | ||
| 197 | |||
| 198 | 11744 | void _sort_ordinates(std::vector<T>& ordinates, bool reverse) const { | |
| 199 |
1/2✓ Branch 1 taken 5956 times.
✗ Branch 2 not taken.
|
11744 | if (ordinates.size() > 1) |
| 200 |
2/4✓ Branch 1 taken 5956 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5956 times.
✗ Branch 5 not taken.
|
11744 | _sort_ordinates(ordinates, _epsilon(ordinates), reverse); |
| 201 | 11744 | } | |
| 202 | |||
| 203 | 23488 | void _sort_ordinates(std::vector<T>& ordinates, const T& eps, bool reverse) const { | |
| 204 |
1/2✓ Branch 1 taken 11912 times.
✗ Branch 2 not taken.
|
23488 | if (ordinates.size() > 1) { |
| 205 |
3/6✓ Branch 1 taken 11912 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11912 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 11912 times.
✗ Branch 8 not taken.
|
46660 | auto [it, _] = Ranges::sort_and_unique(ordinates, {}, [&] (T a, T b) { |
| 206 | using std::abs; | ||
| 207 | 23524 | return abs(a - b) < eps; | |
| 208 | }); | ||
| 209 |
1/2✓ Branch 4 taken 11912 times.
✗ Branch 5 not taken.
|
23488 | ordinates.erase(it, ordinates.end()); |
| 210 |
2/2✓ Branch 0 taken 5712 times.
✓ Branch 1 taken 6200 times.
|
23488 | if (reverse) |
| 211 |
1/2✓ Branch 1 taken 5712 times.
✗ Branch 2 not taken.
|
11424 | std::ranges::reverse(ordinates); |
| 212 | } | ||
| 213 | 23488 | } | |
| 214 | |||
| 215 | 23488 | T _epsilon(const std::vector<T>& ordinates) const { | |
| 216 |
1/2✓ Branch 1 taken 11912 times.
✗ Branch 2 not taken.
|
23488 | const auto max = *std::ranges::max_element(ordinates); |
| 217 |
1/2✓ Branch 1 taken 11912 times.
✗ Branch 2 not taken.
|
23488 | const auto min = *std::ranges::min_element(ordinates); |
| 218 | 23488 | const auto size = max - min; | |
| 219 | |||
| 220 |
2/2✓ Branch 0 taken 6380 times.
✓ Branch 1 taken 5532 times.
|
23488 | if (size > _default_epsilon) { |
| 221 |
1/2✓ Branch 2 taken 6380 times.
✗ Branch 3 not taken.
|
12588 | std::vector<T> dx; dx.reserve(ordinates.size()); |
| 222 |
2/4✓ Branch 1 taken 6380 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 6380 times.
✗ Branch 7 not taken.
|
12588 | std::adjacent_difference(ordinates.begin(), ordinates.end(), std::back_inserter(dx)); |
| 223 |
1/2✓ Branch 1 taken 6380 times.
✗ Branch 2 not taken.
|
33652 | std::ranges::for_each(dx, [] (auto& v) { v = std::abs(v); }); |
| 224 |
1/2✓ Branch 1 taken 6380 times.
✗ Branch 2 not taken.
|
12588 | std::ranges::sort(dx); |
| 225 |
1/2✓ Branch 5 taken 16912 times.
✗ Branch 6 not taken.
|
33472 | for (T _dx : dx) |
| 226 |
2/2✓ Branch 0 taken 6380 times.
✓ Branch 1 taken 10532 times.
|
33472 | if (_dx > 1e-8*size) |
| 227 | 12588 | return _dx*0.1; | |
| 228 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6380 times.
|
12588 | } |
| 229 | |||
| 230 | 10900 | return _default_epsilon; | |
| 231 | } | ||
| 232 | |||
| 233 | const Basis& _basis; | ||
| 234 | std::vector<Origin> _origins; | ||
| 235 | std::vector<bool> _set; | ||
| 236 | std::array<bool, dim> _reverse; | ||
| 237 | T _default_epsilon; | ||
| 238 | }; | ||
| 239 | |||
| 240 | |||
| 241 | template<typename Communicator> | ||
| 242 | class StructuredParallelGridHelper { | ||
| 243 | public: | ||
| 244 | 6380 | StructuredParallelGridHelper(const Communicator& comm, int root_rank = 0) | |
| 245 | 6380 | : _comm{comm} | |
| 246 | 6380 | , _root_rank{root_rank} | |
| 247 | 6380 | {} | |
| 248 | |||
| 249 | template<Concepts::Scalar CT, | ||
| 250 | std::size_t dim, | ||
| 251 | Concepts::StaticallySizedMDRange<2> B = std::array<std::array<CT, dim>, dim>> | ||
| 252 | 12588 | auto compute_extents_and_origin(const std::vector<CT>& all_origins, | |
| 253 | const std::vector<std::size_t>& all_extents, | ||
| 254 | const std::array<bool, dim>& is_negative_axis, | ||
| 255 | const B& basis = GridDetail::standard_basis<CT, dim>()) const { | ||
| 256 |
1/2✓ Branch 1 taken 6380 times.
✗ Branch 2 not taken.
|
12588 | const auto num_ranks = Parallel::size(_comm); |
| 257 |
1/2✓ Branch 1 taken 6380 times.
✗ Branch 2 not taken.
|
25176 | std::vector<std::array<std::size_t, dim>> pieces_begin(num_ranks); |
| 258 |
1/2✓ Branch 1 taken 6380 times.
✗ Branch 2 not taken.
|
12588 | std::vector<std::array<std::size_t, dim>> pieces_end(num_ranks); |
| 259 | std::array<std::size_t, dim> whole_extent; | ||
| 260 | std::array<CT, dim> origin; | ||
| 261 | |||
| 262 |
3/4✓ Branch 1 taken 6380 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2152 times.
✓ Branch 4 taken 4228 times.
|
12588 | if (Parallel::rank(_comm) == _root_rank) { |
| 263 |
3/6✓ Branch 1 taken 2152 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2152 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2152 times.
✗ Branch 8 not taken.
|
21594 | const auto default_epsilon = 1e-6*std::ranges::max(all_origins | std::views::transform([] (CT v) { |
| 264 | using std::abs; | ||
| 265 | 17718 | return abs(v); | |
| 266 | })); | ||
| 267 |
1/2✓ Branch 1 taken 2152 times.
✗ Branch 2 not taken.
|
4220 | const auto mapper_helper = _make_mapper_helper(basis, all_origins, is_negative_axis, default_epsilon); |
| 268 |
1/2✓ Branch 1 taken 2152 times.
✗ Branch 2 not taken.
|
4220 | const auto rank_mapper = mapper_helper.make_mapper(); |
| 269 |
1/2✓ Branch 1 taken 2152 times.
✗ Branch 2 not taken.
|
4220 | origin = mapper_helper.compute_origin(); |
| 270 | |||
| 271 |
2/2✓ Branch 0 taken 5956 times.
✓ Branch 1 taken 2152 times.
|
15964 | for (unsigned dir = 0; dir < dim; ++dir) { |
| 272 |
2/2✓ Branch 0 taken 17718 times.
✓ Branch 1 taken 5956 times.
|
46836 | for (int rank = 0; rank < num_ranks; ++rank) { |
| 273 |
1/2✓ Branch 2 taken 17718 times.
✗ Branch 3 not taken.
|
35092 | auto ranks_below = rank_mapper.ranks_below(rank_mapper.location(rank), dir); |
| 274 |
3/6✓ Branch 1 taken 17718 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 17718 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 17718 times.
✗ Branch 8 not taken.
|
35092 | const std::size_t offset = std::accumulate( |
| 275 | std::ranges::begin(ranks_below), | ||
| 276 | std::ranges::end(ranks_below), | ||
| 277 | std::size_t{0}, | ||
| 278 | 5266 | [&] (const std::size_t current, int r) { | |
| 279 |
2/4✓ Branch 1 taken 1133 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4133 times.
✗ Branch 5 not taken.
|
5266 | return current + Parallel::access_gathered<dim>(all_extents, _comm, {dir, r}); |
| 280 | } | ||
| 281 | ); | ||
| 282 | 35092 | pieces_begin[rank][dir] = offset; | |
| 283 |
1/2✓ Branch 1 taken 17718 times.
✗ Branch 2 not taken.
|
35092 | pieces_end[rank][dir] = offset + Parallel::access_gathered<dim>(all_extents, _comm, {dir, rank}); |
| 284 | } | ||
| 285 | |||
| 286 |
1/2✓ Branch 3 taken 5956 times.
✗ Branch 4 not taken.
|
23488 | whole_extent[dir] = (*std::max_element( |
| 287 | pieces_end.begin(), pieces_end.end(), | ||
| 288 | 11762 | [&] (const auto& a1, const auto& a2) { return a1[dir] < a2[dir]; } | |
| 289 | 11744 | ))[dir]; | |
| 290 | } | ||
| 291 | 4220 | } | |
| 292 | |||
| 293 | return std::make_tuple( | ||
| 294 | 12588 | std::move(pieces_begin), | |
| 295 | 12588 | std::move(pieces_end), | |
| 296 | 12588 | std::move(whole_extent), | |
| 297 | 12588 | std::move(origin) | |
| 298 | 25176 | ); | |
| 299 | 12588 | } | |
| 300 | |||
| 301 | private: | ||
| 302 | template<Concepts::StaticallySizedMDRange<2> Basis, Concepts::Scalar CT, std::size_t dim> | ||
| 303 | 4220 | auto _make_mapper_helper(const Basis& basis, | |
| 304 | const std::vector<CT>& all_origins, | ||
| 305 | const std::array<bool, dim>& is_negative_axis, | ||
| 306 | CT default_eps) const { | ||
| 307 | 4220 | StructuredGridMapperHelper<CT, dim> helper(Parallel::size(_comm), basis, default_eps); | |
| 308 |
2/4✓ Branch 1 taken 2152 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2152 times.
✗ Branch 5 not taken.
|
16636 | std::ranges::for_each(Parallel::ranks(_comm), [&] (int rank) { |
| 309 | 6380 | helper.set_origin_for(rank, Parallel::access_gathered<dim>(all_origins, _comm, rank)); | |
| 310 | }); | ||
| 311 | |||
| 312 |
2/2✓ Branch 0 taken 5956 times.
✓ Branch 1 taken 2152 times.
|
15964 | for (unsigned dir = 0; dir < dim; ++dir) |
| 313 |
2/2✓ Branch 1 taken 2856 times.
✓ Branch 2 taken 3100 times.
|
11744 | if (is_negative_axis[dir]) |
| 314 | 5712 | helper.reverse(dir); | |
| 315 | |||
| 316 | 4220 | return helper; | |
| 317 | ✗ | } | |
| 318 | |||
| 319 | const Communicator& _comm; | ||
| 320 | int _root_rank; | ||
| 321 | }; | ||
| 322 | |||
| 323 | } // namespace GridFormat::PVTK | ||
| 324 | |||
| 325 | #endif // GRIDFORMAT_VTK_PARALLEL_HPP_ | ||
| 326 |