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 |