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 PredefinedTraits | ||
6 | * \brief Traits specializations for <a href="https://gitlab.dune-project.org/core/dune-grid">dune grid views</a> | ||
7 | */ | ||
8 | #ifndef GRIDFORMAT_TRAITS_DUNE_HPP_ | ||
9 | #define GRIDFORMAT_TRAITS_DUNE_HPP_ | ||
10 | |||
11 | #include <ranges> | ||
12 | #include <cassert> | ||
13 | #include <algorithm> | ||
14 | #include <tuple> | ||
15 | // dune seems to not explicitly include this but uses std::int64_t. | ||
16 | // With gcc-13 this leads to an error, maybe before gcc-13 the header | ||
17 | // was included by some other standard library header... | ||
18 | #include <cstdint> | ||
19 | |||
20 | #ifdef GRIDFORMAT_IGNORE_DUNE_WARNINGS | ||
21 | #pragma GCC diagnostic push | ||
22 | #pragma GCC diagnostic ignored "-Wold-style-cast" | ||
23 | #pragma GCC diagnostic ignored "-Wuseless-cast" | ||
24 | #pragma GCC diagnostic ignored "-Warray-bounds" | ||
25 | #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" | ||
26 | #pragma GCC diagnostic ignored "-Wnull-dereference" | ||
27 | #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" | ||
28 | #endif // GRIDFORMAT_IGNORE_DUNE_WARNINGS | ||
29 | #include <dune/common/fmatrix.hh> | ||
30 | #include <dune/common/fvector.hh> | ||
31 | #include <dune/geometry/type.hh> | ||
32 | #include <dune/grid/common/gridview.hh> | ||
33 | #include <dune/grid/common/gridenums.hh> | ||
34 | #include <dune/grid/common/gridfactory.hh> | ||
35 | #include <dune/grid/yaspgrid.hh> | ||
36 | #ifdef GRIDFORMAT_IGNORE_DUNE_WARNINGS | ||
37 | #pragma GCC diagnostic pop | ||
38 | #endif // GRIDFORMAT_IGNORE_DUNE_WARNINGS | ||
39 | |||
40 | #include <gridformat/common/ranges.hpp> | ||
41 | #include <gridformat/common/exceptions.hpp> | ||
42 | #include <gridformat/common/type_traits.hpp> | ||
43 | |||
44 | #include <gridformat/grid/cell_type.hpp> | ||
45 | #include <gridformat/grid/traits.hpp> | ||
46 | |||
47 | namespace GridFormat::Traits { | ||
48 | |||
49 | template<typename T, int R, int C> | ||
50 | struct StaticSize<Dune::FieldMatrix<T, R, C>> { | ||
51 | static constexpr std::size_t value = R; | ||
52 | }; | ||
53 | |||
54 | #ifndef DOXYGEN | ||
55 | namespace DuneDetail { | ||
56 | |||
57 | 1144 | inline int map_corner_index(const Dune::GeometryType& gt, int i) { | |
58 |
2/2✓ Branch 1 taken 568 times.
✓ Branch 2 taken 576 times.
|
1144 | if (gt.isQuadrilateral()) { |
59 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 568 times.
|
568 | assert(i < 4); |
60 | static constexpr int map[4] = {0, 1, 3, 2}; | ||
61 | 568 | return map[i]; | |
62 | } | ||
63 |
1/2✓ Branch 1 taken 576 times.
✗ Branch 2 not taken.
|
576 | if (gt.isHexahedron()) { |
64 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 576 times.
|
576 | assert(i < 8); |
65 | static constexpr int map[8] = {0, 1, 3, 2, 4, 5, 7, 6}; | ||
66 | 576 | return map[i]; | |
67 | } | ||
68 | ✗ | return i; | |
69 | } | ||
70 | |||
71 | 257 | inline constexpr GridFormat::CellType cell_type(const Dune::GeometryType& gt) { | |
72 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 257 times.
|
257 | if (gt.isVertex()) return GridFormat::CellType::vertex; |
73 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 257 times.
|
257 | if (gt.isLine()) return GridFormat::CellType::segment; |
74 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 257 times.
|
257 | if (gt.isTriangle()) return GridFormat::CellType::triangle; |
75 |
2/2✓ Branch 1 taken 233 times.
✓ Branch 2 taken 24 times.
|
257 | if (gt.isQuadrilateral()) return GridFormat::CellType::quadrilateral; |
76 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
|
24 | if (gt.isTetrahedron()) return GridFormat::CellType::tetrahedron; |
77 |
1/2✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
|
24 | if (gt.isHexahedron()) return GridFormat::CellType::hexahedron; |
78 | ✗ | throw NotImplemented("Unknown Dune::GeometryType"); | |
79 | } | ||
80 | |||
81 | template<typename GridView> | ||
82 | using Element = typename GridView::template Codim<0>::Entity; | ||
83 | |||
84 | template<typename GridView> | ||
85 | using Vertex = typename GridView::template Codim<GridView::dimension>::Entity; | ||
86 | |||
87 | } // namespace DuneDetail | ||
88 | #endif // DOXYGEN | ||
89 | |||
90 | |||
91 | template<typename Traits> | ||
92 | struct Points<Dune::GridView<Traits>> { | ||
93 | 652 | static decltype(auto) get(const Dune::GridView<Traits>& grid_view) { | |
94 | using GV = Dune::GridView<Traits>; | ||
95 | static constexpr int vertex_codim = GV::dimension; | ||
96 | return std::ranges::subrange( | ||
97 |
1/2✓ Branch 1 taken 428 times.
✗ Branch 2 not taken.
|
654 | grid_view.template begin<vertex_codim, Dune::InteriorBorder_Partition>(), |
98 |
1/2✓ Branch 1 taken 428 times.
✗ Branch 2 not taken.
|
1304 | grid_view.template end<vertex_codim, Dune::InteriorBorder_Partition>() |
99 |
1/2✓ Branch 1 taken 428 times.
✗ Branch 2 not taken.
|
1304 | ); |
100 | } | ||
101 | }; | ||
102 | |||
103 | template<typename Traits> | ||
104 | struct Cells<Dune::GridView<Traits>> { | ||
105 | 2352 | static decltype(auto) get(const Dune::GridView<Traits>& grid_view) { | |
106 | return std::ranges::subrange( | ||
107 |
1/2✓ Branch 1 taken 1713 times.
✗ Branch 2 not taken.
|
2534 | grid_view.template begin<0, Dune::Interior_Partition>(), |
108 |
1/2✓ Branch 1 taken 1713 times.
✗ Branch 2 not taken.
|
4704 | grid_view.template end<0, Dune::Interior_Partition>() |
109 |
1/2✓ Branch 1 taken 1713 times.
✗ Branch 2 not taken.
|
4704 | ); |
110 | } | ||
111 | }; | ||
112 | |||
113 | template<typename Traits> | ||
114 | struct NumberOfPoints<Dune::GridView<Traits>> { | ||
115 | 786 | static auto get(const Dune::GridView<Traits>& grid_view) { | |
116 | static constexpr int point_codim = Dune::GridView<Traits>::dimension; | ||
117 |
2/2✓ Branch 2 taken 111 times.
✓ Branch 3 taken 372 times.
|
786 | if (grid_view.comm().size() == 1) |
118 | 222 | return static_cast<std::size_t>(grid_view.size(point_codim)); | |
119 | return static_cast<std::size_t>( | ||
120 |
2/4✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 372 times.
✗ Branch 5 not taken.
|
564 | Ranges::size(Points<Dune::GridView<Traits>>::get(grid_view)) |
121 | 564 | ); | |
122 | } | ||
123 | }; | ||
124 | |||
125 | template<typename Traits> | ||
126 | struct NumberOfCells<Dune::GridView<Traits>> { | ||
127 | 2992 | static auto get(const Dune::GridView<Traits>& grid_view) { | |
128 |
2/2✓ Branch 2 taken 881 times.
✓ Branch 3 taken 1038 times.
|
2992 | if (grid_view.comm().size() == 1) |
129 | 1762 | return static_cast<std::size_t>(grid_view.size(0)); | |
130 | return static_cast<std::size_t>( | ||
131 |
2/4✓ Branch 1 taken 1038 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1038 times.
✗ Branch 5 not taken.
|
1230 | Ranges::size(Cells<Dune::GridView<Traits>>::get(grid_view)) |
132 | 1230 | ); | |
133 | } | ||
134 | }; | ||
135 | |||
136 | template<typename Traits> | ||
137 | struct NumberOfCellPoints<Dune::GridView<Traits>, DuneDetail::Element<Dune::GridView<Traits>>> { | ||
138 | 396 | static auto get(const Dune::GridView<Traits>&, | |
139 | const DuneDetail::Element<Dune::GridView<Traits>>& cell) { | ||
140 | 396 | return cell.subEntities(Dune::GridView<Traits>::dimension); | |
141 | } | ||
142 | }; | ||
143 | |||
144 | template<typename Traits> | ||
145 | struct CellPoints<Dune::GridView<Traits>, DuneDetail::Element<Dune::GridView<Traits>>> { | ||
146 | 1436 | static decltype(auto) get(const Dune::GridView<Traits>&, | |
147 | const DuneDetail::Element<Dune::GridView<Traits>>& element) { | ||
148 | static constexpr int dim = Dune::GridView<Traits>::dimension; | ||
149 |
4/8✓ Branch 1 taken 818 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 818 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 818 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 818 times.
✗ Branch 11 not taken.
|
3616 | return std::views::iota(unsigned{0}, element.subEntities(dim)) | std::views::transform([&] (int i) { |
150 |
4/8✓ Branch 1 taken 976 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 976 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 168 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 168 times.
✗ Branch 13 not taken.
|
2288 | return element.template subEntity<dim>(DuneDetail::map_corner_index(element.type(), i)); |
151 | 2872 | }); | |
152 | } | ||
153 | }; | ||
154 | |||
155 | template<typename Traits> | ||
156 | struct CellType<Dune::GridView<Traits>, DuneDetail::Element<Dune::GridView<Traits>>> { | ||
157 | 414 | static decltype(auto) get(const Dune::GridView<Traits>&, | |
158 | const DuneDetail::Element<Dune::GridView<Traits>>& element) { | ||
159 |
2/4✓ Branch 1 taken 257 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 257 times.
✗ Branch 5 not taken.
|
414 | return DuneDetail::cell_type(element.type()); |
160 | } | ||
161 | }; | ||
162 | |||
163 | template<typename Traits> | ||
164 | struct PointCoordinates<Dune::GridView<Traits>, DuneDetail::Vertex<Dune::GridView<Traits>>> { | ||
165 | 504 | static decltype(auto) get(const Dune::GridView<Traits>&, | |
166 | const DuneDetail::Vertex<Dune::GridView<Traits>>& vertex) { | ||
167 |
2/4✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 324 times.
✗ Branch 5 not taken.
|
504 | return vertex.geometry().center(); |
168 | } | ||
169 | }; | ||
170 | |||
171 | template<typename Traits> | ||
172 | struct PointId<Dune::GridView<Traits>, DuneDetail::Vertex<Dune::GridView<Traits>>> { | ||
173 | 1216 | static decltype(auto) get(const Dune::GridView<Traits>& grid_view, | |
174 | const DuneDetail::Vertex<Dune::GridView<Traits>>& vertex) { | ||
175 | 1216 | return grid_view.indexSet().index(vertex); | |
176 | } | ||
177 | }; | ||
178 | |||
179 | |||
180 | #ifndef DOXYGEN | ||
181 | namespace DuneDetail { | ||
182 | |||
183 | template<typename T> | ||
184 | struct IsDuneYaspGrid : public std::false_type {}; | ||
185 | |||
186 | template<int dim, typename Coords> | ||
187 | struct IsDuneYaspGrid<Dune::YaspGrid<dim, Coords>> : public std::true_type { | ||
188 | static constexpr bool uses_tp_coords = std::same_as< | ||
189 | Coords, | ||
190 | Dune::TensorProductCoordinates<typename Coords::ctype, dim> | ||
191 | >; | ||
192 | }; | ||
193 | |||
194 | template<typename GridView> | ||
195 | inline constexpr bool is_yasp_grid_view = IsDuneYaspGrid<typename GridView::Grid>::value; | ||
196 | |||
197 | template<typename GridView> requires(is_yasp_grid_view<GridView>) | ||
198 | inline constexpr bool uses_tensor_product_coords = IsDuneYaspGrid<typename GridView::Grid>::uses_tp_coords; | ||
199 | |||
200 | template<typename ctype, int dim> | ||
201 | 190 | auto spacing_in(int direction, const Dune::EquidistantCoordinates<ctype, dim>& coords) { | |
202 | 190 | return coords.meshsize(direction, 0); | |
203 | } | ||
204 | template<typename ctype, int dim> | ||
205 | 10 | auto spacing_in(int direction, const Dune::EquidistantOffsetCoordinates<ctype, dim>& coords) { | |
206 | 10 | return coords.meshsize(direction, 0); | |
207 | } | ||
208 | |||
209 | } // namespace DuneDetail | ||
210 | #endif // DOXYGEN | ||
211 | |||
212 | |||
213 | // Register YaspGrid as structured grid | ||
214 | template<typename Traits> requires(DuneDetail::is_yasp_grid_view<Dune::GridView<Traits>>) | ||
215 | struct Extents<Dune::GridView<Traits>> { | ||
216 | 208 | static auto get(const Dune::GridView<Traits>& grid_view) { | |
217 |
4/8✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 120 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 120 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 120 times.
✗ Branch 11 not taken.
|
208 | const auto level = std::ranges::begin(Cells<Dune::GridView<Traits>>::get(grid_view))->level(); |
218 |
2/4✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 76 times.
✗ Branch 5 not taken.
|
208 | const auto& grid_level = *grid_view.grid().begin(level); |
219 | 208 | const auto& interior_grid = grid_level.interior[0]; | |
220 | 208 | const auto& gc = *interior_grid.dataBegin(); | |
221 | |||
222 | static constexpr int dim = Traits::Grid::dimension; | ||
223 | std::array<std::size_t, dim> result; | ||
224 |
2/2✓ Branch 0 taken 284 times.
✓ Branch 1 taken 120 times.
|
712 | for (int i = 0; i < Traits::Grid::dimension; ++i) |
225 |
1/2✓ Branch 1 taken 152 times.
✗ Branch 2 not taken.
|
504 | result[i] = gc.max(i) - gc.min(i) + 1; |
226 | 208 | return result; | |
227 | } | ||
228 | }; | ||
229 | |||
230 | template<typename Traits, typename Entity> requires(DuneDetail::is_yasp_grid_view<Dune::GridView<Traits>>) | ||
231 | struct Location<Dune::GridView<Traits>, Entity> { | ||
232 | 12384 | static auto get(const Dune::GridView<Traits>& grid_view, const Entity& entity) { | |
233 |
3/6✓ Branch 1 taken 6192 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6192 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6192 times.
✗ Branch 8 not taken.
|
12384 | auto const& grid_level = *grid_view.grid().begin(entity.level()); |
234 | 12384 | auto const& interior = grid_level.interior[0]; | |
235 | 12384 | auto const& extent_bounds = *interior.dataBegin(); | |
236 | |||
237 |
1/2✓ Branch 3 taken 6192 times.
✗ Branch 4 not taken.
|
12384 | auto result = entity.impl().transformingsubiterator().coord(); |
238 |
2/2✓ Branch 0 taken 17659 times.
✓ Branch 1 taken 6192 times.
|
47702 | for (int i = 0; i < Dune::GridView<Traits>::dimension; ++i) |
239 | 35318 | result[i] -= extent_bounds.min(i); | |
240 | 12384 | return result; | |
241 | } | ||
242 | }; | ||
243 | |||
244 | template<typename Traits> requires(DuneDetail::is_yasp_grid_view<Dune::GridView<Traits>>) | ||
245 | struct Origin<Dune::GridView<Traits>> { | ||
246 | 40 | static auto get(const Dune::GridView<Traits>& grid_view) { | |
247 |
4/8✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
|
40 | const auto level = std::ranges::begin(Cells<Dune::GridView<Traits>>::get(grid_view))->level(); |
248 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
40 | auto const& grid_level = *grid_view.grid().begin(level); |
249 | 40 | auto const& interior = grid_level.interior[0]; | |
250 | 40 | auto const& extent_bounds = *interior.dataBegin(); | |
251 | |||
252 | std::array<typename Traits::Grid::ctype, Traits::Grid::dimension> result; | ||
253 |
2/2✓ Branch 0 taken 50 times.
✓ Branch 1 taken 20 times.
|
140 | for (int i = 0; i < Traits::Grid::dimension; ++i) |
254 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
100 | result[i] = grid_level.coords.coordinate(i, extent_bounds.min(i)); |
255 | 40 | return result; | |
256 | } | ||
257 | }; | ||
258 | |||
259 | template<typename Traits> | ||
260 | requires(DuneDetail::is_yasp_grid_view<Dune::GridView<Traits>> and | ||
261 | !DuneDetail::uses_tensor_product_coords<Dune::GridView<Traits>>) // spacing not uniquely defined for tpcoords | ||
262 | struct Spacing<Dune::GridView<Traits>> { | ||
263 | 44 | static auto get(const Dune::GridView<Traits>& grid_view) { | |
264 |
4/8✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
|
44 | const auto level = std::ranges::begin(Cells<Dune::GridView<Traits>>::get(grid_view))->level(); |
265 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
44 | auto const& grid_level = *grid_view.grid().begin(level); |
266 | |||
267 | std::array<typename Traits::Grid::ctype, Traits::Grid::dimension> result; | ||
268 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
|
154 | for (int i = 0; i < Traits::Grid::dimension; ++i) |
269 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
110 | result[i] = DuneDetail::spacing_in(i, grid_level.coords); |
270 | 44 | return result; | |
271 | } | ||
272 | }; | ||
273 | |||
274 | template<typename Traits> requires(DuneDetail::is_yasp_grid_view<Dune::GridView<Traits>>) | ||
275 | struct Ordinates<Dune::GridView<Traits>> { | ||
276 | 37 | static auto get(const Dune::GridView<Traits>& grid_view, int direction) { | |
277 |
4/8✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 32 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 32 times.
✗ Branch 11 not taken.
|
37 | const auto level = std::ranges::begin(Cells<Dune::GridView<Traits>>::get(grid_view))->level(); |
278 | 37 | auto const& grid_level = *grid_view.grid().begin(level); | |
279 | 37 | auto const& interior = grid_level.interior[0]; | |
280 | 37 | auto const& extent_bounds = *interior.dataBegin(); | |
281 | |||
282 | 37 | const auto num_point_ordinates = extent_bounds.max(direction) - extent_bounds.min(direction) + 2; | |
283 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
37 | std::vector<typename Traits::Grid::ctype> ordinates(num_point_ordinates); |
284 |
2/2✓ Branch 0 taken 144 times.
✓ Branch 1 taken 32 times.
|
196 | for (int i = 0; i < num_point_ordinates; ++i) |
285 | 159 | ordinates[i] = grid_level.coords.coordinate(direction, extent_bounds.min(direction) + i); | |
286 | 37 | return ordinates; | |
287 | } | ||
288 | }; | ||
289 | |||
290 | } // namespace GridFormat::Traits | ||
291 | |||
292 | |||
293 | // Higher-order output is only available with dune-localfunctions | ||
294 | #if GRIDFORMAT_HAVE_DUNE_LOCALFUNCTIONS | ||
295 | |||
296 | #include <algorithm> | ||
297 | #include <iterator> | ||
298 | #include <utility> | ||
299 | #include <ranges> | ||
300 | #include <cassert> | ||
301 | #include <type_traits> | ||
302 | #include <unordered_map> | ||
303 | #include <map> | ||
304 | |||
305 | #ifdef GRIDFORMAT_IGNORE_DUNE_WARNINGS | ||
306 | #pragma GCC diagnostic push | ||
307 | #pragma GCC diagnostic ignored "-Wold-style-cast" | ||
308 | #pragma GCC diagnostic ignored "-Wtype-limits" | ||
309 | #endif // GRIDFORMAT_IGNORE_DUNE_WARNINGS | ||
310 | #include <dune/geometry/referenceelements.hh> | ||
311 | #include <dune/grid/common/mcmgmapper.hh> | ||
312 | #include <dune/localfunctions/lagrange/equidistantpoints.hh> | ||
313 | #ifdef GRIDFORMAT_IGNORE_DUNE_WARNINGS | ||
314 | #pragma GCC diagnostic pop | ||
315 | #endif // GRIDFORMAT_IGNORE_DUNE_WARNINGS | ||
316 | |||
317 | #include <gridformat/common/reserved_vector.hpp> | ||
318 | #include <gridformat/common/type_traits.hpp> | ||
319 | #include <gridformat/common/precision.hpp> | ||
320 | #include <gridformat/common/concepts.hpp> | ||
321 | #include <gridformat/common/field.hpp> | ||
322 | #include <gridformat/grid.hpp> | ||
323 | |||
324 | |||
325 | namespace GridFormat { | ||
326 | |||
327 | // create this alias s.t. we can explicitly | ||
328 | // address the original Dune namespace | ||
329 | namespace DUNE = Dune; | ||
330 | |||
331 | namespace Dune { | ||
332 | |||
333 | #ifndef DOXYGEN | ||
334 | namespace LagrangeDetail { | ||
335 | |||
336 | 2508 | inline int dune_to_gfmt_sub_entity(const DUNE::GeometryType& gt, int i, int codim) { | |
337 |
2/2✓ Branch 1 taken 92 times.
✓ Branch 2 taken 2416 times.
|
2508 | if (gt.isTriangle()) { |
338 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 48 times.
|
92 | if (codim == 1) { |
339 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
|
44 | assert(i < 3); |
340 | static constexpr int map[3] = {0, 2, 1}; | ||
341 | 44 | return map[i]; | |
342 | } | ||
343 | } | ||
344 |
2/2✓ Branch 1 taken 588 times.
✓ Branch 2 taken 1876 times.
|
2464 | if (gt.isQuadrilateral()) { |
345 |
2/2✓ Branch 0 taken 252 times.
✓ Branch 1 taken 336 times.
|
588 | if (codim == 2) { |
346 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 252 times.
|
252 | assert(i < 4); |
347 | static constexpr int map[4] = {0, 1, 3, 2}; | ||
348 | 252 | return map[i]; | |
349 | } | ||
350 |
2/2✓ Branch 0 taken 300 times.
✓ Branch 1 taken 36 times.
|
336 | if (codim == 1) { |
351 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
|
300 | assert(i < 4); |
352 | static constexpr int map[4] = {3, 1, 0, 2}; | ||
353 | 300 | return map[i]; | |
354 | } | ||
355 | } | ||
356 |
2/2✓ Branch 1 taken 252 times.
✓ Branch 2 taken 1660 times.
|
1912 | if (gt.isTetrahedron()) { |
357 |
2/2✓ Branch 0 taken 160 times.
✓ Branch 1 taken 92 times.
|
252 | if (codim == 2) { |
358 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
|
160 | assert(i < 6); |
359 | static constexpr int map[6] = {0, 2, 1, 3, 4, 5}; | ||
360 | 160 | return map[i]; | |
361 | } | ||
362 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 68 times.
|
92 | if (codim == 1) { |
363 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | assert(i < 4); |
364 | static constexpr int map[4] = {3, 0, 2, 1}; | ||
365 | 24 | return map[i]; | |
366 | } | ||
367 | } | ||
368 |
2/2✓ Branch 1 taken 1576 times.
✓ Branch 2 taken 152 times.
|
1728 | if (gt.isHexahedron()) { |
369 |
2/2✓ Branch 0 taken 236 times.
✓ Branch 1 taken 1340 times.
|
1576 | if (codim == 3) { |
370 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 236 times.
|
236 | assert(i < 8); |
371 | static constexpr int map[8] = {0, 1, 3, 2, 4, 5, 7, 6}; | ||
372 | 236 | return map[i]; | |
373 | } | ||
374 |
2/2✓ Branch 0 taken 808 times.
✓ Branch 1 taken 532 times.
|
1340 | if (codim == 2) { |
375 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 808 times.
|
808 | assert(i < 12); |
376 | static constexpr int map[12] = {8, 9, 11, 10, 3, 1, 0, 2, 7, 5, 4, 6}; | ||
377 | 808 | return map[i]; | |
378 | } | ||
379 | } | ||
380 | 684 | return i; | |
381 | } | ||
382 | |||
383 | 1818 | inline constexpr GridFormat::CellType cell_type(const DUNE::GeometryType& gt) { | |
384 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1818 times.
|
1818 | if (gt.isLine()) return GridFormat::CellType::lagrange_segment; |
385 |
2/2✓ Branch 1 taken 438 times.
✓ Branch 2 taken 1380 times.
|
1818 | if (gt.isTriangle()) return GridFormat::CellType::lagrange_triangle; |
386 |
2/2✓ Branch 1 taken 318 times.
✓ Branch 2 taken 1062 times.
|
1380 | if (gt.isQuadrilateral()) return GridFormat::CellType::lagrange_quadrilateral; |
387 |
2/2✓ Branch 1 taken 1026 times.
✓ Branch 2 taken 36 times.
|
1062 | if (gt.isTetrahedron()) return GridFormat::CellType::lagrange_tetrahedron; |
388 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 | if (gt.isHexahedron()) return GridFormat::CellType::lagrange_hexahedron; |
389 | ✗ | throw NotImplemented("Unsupported Dune::GeometryType"); | |
390 | } | ||
391 | |||
392 | // Exposes the lagrange points of a geometry in gridformat ordering | ||
393 | template<typename GridView> | ||
394 | class LocalPoints { | ||
395 | // reserve space for third-order hexahedra | ||
396 | static constexpr std::size_t reserved_size = 64; | ||
397 | |||
398 | public: | ||
399 | using PointSet = DUNE::EquidistantPointSet<typename GridView::ctype, GridView::dimension>; | ||
400 | using Point = typename PointSet::LagrangePoint; | ||
401 | |||
402 | 60 | explicit LocalPoints(unsigned int order) | |
403 | 60 | : _points(order) | |
404 | 60 | {} | |
405 | |||
406 | 60 | void build(const DUNE::GeometryType& geo_type) { | |
407 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
|
60 | if (geo_type.dim() != GridView::dimension) |
408 | ✗ | throw ValueError("Dimension of given geometry does not match the grid"); | |
409 | 60 | _points.build(geo_type); | |
410 | 60 | _setup_sorted_indices(geo_type); | |
411 | 60 | } | |
412 | |||
413 | 6672 | std::size_t size() const { | |
414 | 6672 | return _points.size(); | |
415 | } | ||
416 | |||
417 | const Point& at(std::size_t i) const { | ||
418 | return _points[_sorted_indices.at(i)]; | ||
419 | } | ||
420 | |||
421 | 6372 | std::ranges::range auto get() const { | |
422 |
2/4✓ Branch 1 taken 3336 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3336 times.
✗ Branch 5 not taken.
|
44272 | return _sorted_indices | std::views::transform([&] (unsigned int i) { |
423 | 34428 | return _points[i]; | |
424 | 12744 | }); | |
425 | } | ||
426 | |||
427 | private: | ||
428 | 60 | void _setup_sorted_indices(const DUNE::GeometryType& geo_type) { | |
429 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
60 | std::ranges::copy( |
430 |
1/2✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
|
60 | std::views::iota(unsigned{0}, static_cast<unsigned int>(_points.size())), |
431 | 60 | std::back_inserter(_sorted_indices) | |
432 | ); | ||
433 | 1574 | std::ranges::sort(_sorted_indices, [&] (unsigned int i1, unsigned int i2) { | |
434 | 1810 | const auto& key1 = _points[i1].localKey(); | |
435 | 1810 | const auto& key2 = _points[i2].localKey(); | |
436 | using LagrangeDetail::dune_to_gfmt_sub_entity; | ||
437 |
8/8✓ Branch 2 taken 322 times.
✓ Branch 3 taken 170 times.
✓ Branch 6 taken 46 times.
✓ Branch 7 taken 26 times.
✓ Branch 10 taken 788 times.
✓ Branch 11 taken 310 times.
✓ Branch 14 taken 98 times.
✓ Branch 15 taken 50 times.
|
1810 | if (key1.codim() == key2.codim()) { |
438 | 1254 | const auto mapped1 = dune_to_gfmt_sub_entity(geo_type, key1.subEntity(), key1.codim()); | |
439 | 1254 | const auto mapped2 = dune_to_gfmt_sub_entity(geo_type, key2.subEntity(), key2.codim()); | |
440 |
8/8✓ Branch 0 taken 42 times.
✓ Branch 1 taken 280 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 40 times.
✓ Branch 8 taken 96 times.
✓ Branch 9 taken 692 times.
✓ Branch 12 taken 14 times.
✓ Branch 13 taken 84 times.
|
1254 | return mapped1 == mapped2 ? key1.index() < key2.index() : mapped1 < mapped2; |
441 | } | ||
442 | 556 | return _points[i1].localKey().codim() > _points[i2].localKey().codim(); | |
443 | }); | ||
444 | 60 | } | |
445 | |||
446 | PointSet _points; | ||
447 | ReservedVector<unsigned int, reserved_size> _sorted_indices; | ||
448 | }; | ||
449 | |||
450 | class PointMapper { | ||
451 | public: | ||
452 | template<typename GridView> | ||
453 | 60 | explicit PointMapper(const GridView& grid_view) { | |
454 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
60 | _codim_to_global_indices.resize(GridView::dimension + 1); |
455 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 36 times.
|
264 | for (int codim = 0; codim < GridView::dimension + 1; ++codim) |
456 |
2/4✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 120 times.
✗ Branch 6 not taken.
|
204 | _codim_to_global_indices[codim].resize(grid_view.size(codim)); |
457 | 60 | } | |
458 | |||
459 | struct Key { | ||
460 | unsigned int codim; | ||
461 | std::size_t global_index; | ||
462 | unsigned int sub_index; | ||
463 | }; | ||
464 | |||
465 | 34428 | bool contains(const Key& key) const { | |
466 | 34428 | const auto& entity_dofs = _codim_to_global_indices[key.codim][key.global_index]; | |
467 |
2/2✓ Branch 1 taken 11562 times.
✓ Branch 2 taken 22866 times.
|
34428 | if (entity_dofs.size() <= key.sub_index) |
468 | 11562 | return false; | |
469 | 22866 | return entity_dofs[key.sub_index] != -1; | |
470 | } | ||
471 | |||
472 | 11562 | void insert(const Key& key, std::size_t index) { | |
473 | 11562 | auto& entity_dofs = _codim_to_global_indices[key.codim][key.global_index]; | |
474 |
1/2✓ Branch 1 taken 11562 times.
✗ Branch 2 not taken.
|
11562 | if (entity_dofs.size() < key.sub_index + 1) |
475 |
1/2✓ Branch 1 taken 11562 times.
✗ Branch 2 not taken.
|
11562 | entity_dofs.resize(key.sub_index + 1, -1); |
476 | 11562 | entity_dofs[key.sub_index] = static_cast<std::int64_t>(index); | |
477 | 11562 | } | |
478 | |||
479 | 22866 | std::size_t get(const Key& key) const { | |
480 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 22866 times.
|
22866 | assert(_codim_to_global_indices[key.codim][key.global_index].size() > key.sub_index); |
481 | 22866 | auto index = _codim_to_global_indices[key.codim][key.global_index][key.sub_index]; | |
482 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22866 times.
|
22866 | assert(index != -1); |
483 | 22866 | return static_cast<std::size_t>(index); | |
484 | } | ||
485 | |||
486 | void clear() { | ||
487 | _codim_to_global_indices.clear(); | ||
488 | } | ||
489 | |||
490 | private: | ||
491 | std::vector< // codim | ||
492 | std::vector< // entity index | ||
493 | ReservedVector<std::int64_t, 20> // sub-entity index to global indices | ||
494 | > | ||
495 | > _codim_to_global_indices; | ||
496 | }; | ||
497 | |||
498 | } // namespace LagrangeDetail | ||
499 | #endif // DOXYGEN | ||
500 | |||
501 | |||
502 | /*! | ||
503 | * \ingroup PredefinedTraits | ||
504 | * \brief Exposes a `Dune::GridView` as a grid composed of lagrange cells with the given order. | ||
505 | * Can be used to conveniently write `Dune::Functions` into grid files. | ||
506 | * \note This is only available if dune-localfunctions is found on the system. | ||
507 | */ | ||
508 | template<typename GV> | ||
509 | class LagrangePolynomialGrid { | ||
510 | using Element = typename GV::Grid::template Codim<0>::Entity; | ||
511 | using ElementGeometry = typename Element::Geometry; | ||
512 | using GlobalCoordinate = typename ElementGeometry::GlobalCoordinate; | ||
513 | using LocalCoordinate = typename ElementGeometry::LocalCoordinate; | ||
514 | |||
515 | using LocalPoints = LagrangeDetail::LocalPoints<GV>; | ||
516 | using Mapper = DUNE::MultipleCodimMultipleGeomTypeMapper<GV>; | ||
517 | static constexpr int dim = GV::dimension; | ||
518 | |||
519 | template<typename Coord> | ||
520 | struct P { | ||
521 | std::size_t index; | ||
522 | Coord coordinates; | ||
523 | }; | ||
524 | |||
525 | using _GlobalPoint = P<GlobalCoordinate>; | ||
526 | using _LocalPoint = P<LocalCoordinate>; | ||
527 | |||
528 | public: | ||
529 | using GridView = GV; | ||
530 | using Position = GlobalCoordinate; | ||
531 | using Cell = Element; | ||
532 | using Point = _GlobalPoint; | ||
533 | using LocalPoint = _LocalPoint; | ||
534 | |||
535 | 36 | explicit LagrangePolynomialGrid(const GridView& grid_view, unsigned int order = 1) | |
536 | 36 | : _grid_view{grid_view} | |
537 | 36 | , _order{order} { | |
538 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
36 | if (order < 1) |
539 | ✗ | throw InvalidState("Order must be >= 1"); | |
540 |
1/2✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
|
36 | update(grid_view); |
541 | 36 | } | |
542 | |||
543 | 60 | void update(const GridView& grid_view) { | |
544 | 60 | clear(); | |
545 | 60 | _grid_view = grid_view; | |
546 | 60 | _make_codim_mappers(); | |
547 | 60 | _update_local_points(); | |
548 | 60 | _update_mesh(); | |
549 | 60 | } | |
550 | |||
551 | 84 | void clear() { | |
552 | 84 | _codim_to_mapper.clear(); | |
553 | 84 | _local_points.clear(); | |
554 | 84 | _points.clear(); | |
555 | 84 | _cells.clear(); | |
556 | 84 | } | |
557 | |||
558 | 2238 | std::size_t number_of_cells() const { | |
559 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1446 times.
|
2238 | return _cells.empty() ? 0 : Traits::NumberOfCells<GridView>::get(_grid_view); |
560 | } | ||
561 | |||
562 | 2238 | std::size_t number_of_points() const { | |
563 | 2238 | return _points.size(); | |
564 | } | ||
565 | |||
566 | 6672 | std::size_t number_of_points(const Element& element) const { | |
567 |
2/4✓ Branch 1 taken 3636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3636 times.
✗ Branch 5 not taken.
|
6672 | return _local_points.at(element.type()).size(); |
568 | } | ||
569 | |||
570 | 432 | std::ranges::range auto cells() const { | |
571 | 432 | return Traits::Cells<GridView>::get(_grid_view); | |
572 | } | ||
573 | |||
574 | 108 | std::ranges::range auto points() const { | |
575 |
1/2✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
|
108 | return std::views::iota(std::size_t{0}, _points.size()) |
576 |
2/4✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
|
15189 | | std::views::transform([&] (std::size_t idx) { |
577 | 19821 | return Point{idx, _points[idx]}; | |
578 | 216 | }); | |
579 | } | ||
580 | |||
581 | 16380 | std::ranges::range auto points(const Element& e) const { | |
582 | 16380 | const auto& corners = _cells[_codim_to_mapper[0].index(e)]; | |
583 |
1/2✓ Branch 2 taken 8790 times.
✗ Branch 3 not taken.
|
16380 | return std::views::iota(std::size_t{0}, corners.size()) |
584 |
2/4✓ Branch 1 taken 8790 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8790 times.
✗ Branch 5 not taken.
|
127960 | | std::views::transform([&] (std::size_t i) { |
585 | return Point{ | ||
586 | 90420 | .index = corners[i], | |
587 | 90420 | .coordinates = _points[corners[i]] | |
588 | 180840 | }; | |
589 | 32760 | }); | |
590 | } | ||
591 | |||
592 | const GridView& grid_view() const { | ||
593 | return _grid_view; | ||
594 | } | ||
595 | |||
596 | private: | ||
597 | 60 | void _update_local_points() { | |
598 |
4/6✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✓ Branch 11 taken 36 times.
✓ Branch 12 taken 36 times.
|
120 | for (const auto& gt : _grid_view.indexSet().types(0)) { |
599 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
60 | _local_points.emplace(gt, _order); |
600 |
2/4✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
|
60 | _local_points.at(gt).build(gt); |
601 | } | ||
602 | 60 | } | |
603 | |||
604 | 60 | void _make_codim_mappers() { | |
605 | 60 | _codim_to_mapper.reserve(dim + 1); | |
606 |
2/4✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
|
60 | _codim_to_mapper.emplace_back(Mapper{_grid_view, DUNE::mcmgLayout(DUNE::Codim<0>{})}); |
607 | if constexpr (int(GridView::dimension) >= 1) | ||
608 |
2/4✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
|
60 | _codim_to_mapper.emplace_back(Mapper{_grid_view, DUNE::mcmgLayout(DUNE::Codim<1>{})}); |
609 | if constexpr (int(GridView::dimension) >= 2) | ||
610 |
2/4✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
|
60 | _codim_to_mapper.emplace_back(Mapper{_grid_view, DUNE::mcmgLayout(DUNE::Codim<2>{})}); |
611 | if constexpr (int(GridView::dimension) == 3) | ||
612 |
2/4✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
|
24 | _codim_to_mapper.emplace_back(Mapper{_grid_view, DUNE::mcmgLayout(DUNE::Codim<3>{})}); |
613 | 60 | } | |
614 | |||
615 | 60 | void _update_mesh() { | |
616 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
60 | LagrangeDetail::PointMapper point_mapper{_grid_view}; |
617 | 60 | std::size_t dof_index = 0; | |
618 |
2/4✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
|
60 | _cells.resize(_grid_view.size(0)); |
619 |
10/16✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 36 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2928 times.
✓ Branch 11 taken 408 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 3360 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 408 times.
✓ Branch 17 taken 2964 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 2928 times.
✓ Branch 20 taken 12 times.
|
12864 | for (const auto& element : Traits::Cells<GridView>::get(_grid_view)) { |
620 |
3/6✓ Branch 1 taken 3336 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3336 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3336 times.
✗ Branch 8 not taken.
|
6372 | const auto& local_points = _local_points.at(element.type()).get(); |
621 |
1/2✓ Branch 1 taken 3336 times.
✗ Branch 2 not taken.
|
6372 | const auto& element_geometry = element.geometry(); |
622 |
1/2✓ Branch 2 taken 3336 times.
✗ Branch 3 not taken.
|
6372 | const auto element_index = _codim_to_mapper[0].index(element); |
623 |
2/4✓ Branch 2 taken 3336 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3336 times.
✗ Branch 6 not taken.
|
6372 | _cells[element_index].reserve(local_points.size()); |
624 |
5/8✓ Branch 1 taken 3336 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3336 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 34428 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 34428 times.
✓ Branch 12 taken 3336 times.
|
78700 | for (const auto& local_point : local_points) { |
625 | 65956 | const auto& localKey = local_point.localKey(); | |
626 | 197868 | const typename LagrangeDetail::PointMapper::Key key{ | |
627 | 65956 | .codim = localKey.codim(), | |
628 |
1/2✓ Branch 4 taken 34428 times.
✗ Branch 5 not taken.
|
131912 | .global_index = _codim_to_mapper[localKey.codim()].subIndex( |
629 | 65956 | element, localKey.subEntity(), localKey.codim() | |
630 | ), | ||
631 | 65956 | .sub_index = localKey.index() | |
632 | }; | ||
633 |
3/4✓ Branch 1 taken 34428 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11562 times.
✓ Branch 4 taken 22866 times.
|
65956 | if (!point_mapper.contains(key)) { |
634 |
1/2✓ Branch 1 taken 11562 times.
✗ Branch 2 not taken.
|
21472 | point_mapper.insert(key, dof_index); |
635 |
1/2✓ Branch 2 taken 11562 times.
✗ Branch 3 not taken.
|
21472 | _cells[element_index].push_back(dof_index); |
636 |
2/4✓ Branch 2 taken 11562 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 11562 times.
✗ Branch 6 not taken.
|
21472 | _points.push_back(element_geometry.global(local_point.point())); |
637 | 21472 | dof_index++; | |
638 | } else { | ||
639 |
2/4✓ Branch 2 taken 22866 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 22866 times.
✗ Branch 6 not taken.
|
44484 | _cells[element_index].push_back(point_mapper.get(key)); |
640 | } | ||
641 | } | ||
642 | } | ||
643 | 60 | } | |
644 | |||
645 | GridView _grid_view; | ||
646 | unsigned int _order; | ||
647 | std::vector<Mapper> _codim_to_mapper; | ||
648 | std::map<DUNE::GeometryType, LocalPoints> _local_points; | ||
649 | std::vector<GlobalCoordinate> _points; | ||
650 | std::vector<std::vector<std::size_t>> _cells; | ||
651 | }; | ||
652 | |||
653 | namespace Traits { | ||
654 | |||
655 | template<typename GV> | ||
656 | struct GridView { | ||
657 | using type = GV; | ||
658 | static const auto& get(const GV& gv) { | ||
659 | return gv; | ||
660 | } | ||
661 | }; | ||
662 | |||
663 | template<typename GV> | ||
664 | struct GridView<LagrangePolynomialGrid<GV>> { | ||
665 | using type = GV; | ||
666 | static const auto& get(const LagrangePolynomialGrid<GV>& grid) { | ||
667 | return grid.grid_view(); | ||
668 | } | ||
669 | }; | ||
670 | |||
671 | } // namespace Traits | ||
672 | } // namespace Dune | ||
673 | |||
674 | |||
675 | namespace Traits { | ||
676 | |||
677 | template<typename GridView> | ||
678 | struct Points<Dune::LagrangePolynomialGrid<GridView>> { | ||
679 | 108 | static auto get(const Dune::LagrangePolynomialGrid<GridView>& mesh) { | |
680 | 108 | return mesh.points(); | |
681 | } | ||
682 | }; | ||
683 | |||
684 | template<typename GridView> | ||
685 | struct Cells<Dune::LagrangePolynomialGrid<GridView>> { | ||
686 | 432 | static auto get(const Dune::LagrangePolynomialGrid<GridView>& mesh) { | |
687 | 432 | return mesh.cells(); | |
688 | } | ||
689 | }; | ||
690 | |||
691 | template<typename GridView> | ||
692 | struct NumberOfPoints<Dune::LagrangePolynomialGrid<GridView>> { | ||
693 | 2106 | static auto get(const Dune::LagrangePolynomialGrid<GridView>& mesh) { | |
694 | 2106 | return mesh.number_of_points(); | |
695 | } | ||
696 | }; | ||
697 | |||
698 | template<typename GridView> | ||
699 | struct NumberOfCells<Dune::LagrangePolynomialGrid<GridView>> { | ||
700 | 2166 | static auto get(const Dune::LagrangePolynomialGrid<GridView>& mesh) { | |
701 | 2166 | return mesh.number_of_cells(); | |
702 | } | ||
703 | }; | ||
704 | |||
705 | template<typename GridView> | ||
706 | struct NumberOfCellPoints<Dune::LagrangePolynomialGrid<GridView>, | ||
707 | typename Dune::LagrangePolynomialGrid<GridView>::Cell> { | ||
708 | 6672 | static auto get(const Dune::LagrangePolynomialGrid<GridView>& mesh, | |
709 | const typename Dune::LagrangePolynomialGrid<GridView>::Cell& cell) { | ||
710 | 6672 | return mesh.number_of_points(cell); | |
711 | } | ||
712 | }; | ||
713 | |||
714 | template<typename GridView> | ||
715 | struct CellPoints<Dune::LagrangePolynomialGrid<GridView>, | ||
716 | typename Dune::LagrangePolynomialGrid<GridView>::Cell> { | ||
717 | 3336 | static auto get(const Dune::LagrangePolynomialGrid<GridView>& mesh, | |
718 | const typename Dune::LagrangePolynomialGrid<GridView>::Cell& cell) { | ||
719 | 3336 | return mesh.points(cell); | |
720 | } | ||
721 | }; | ||
722 | |||
723 | template<typename GridView> | ||
724 | struct CellType<Dune::LagrangePolynomialGrid<GridView>, | ||
725 | typename Dune::LagrangePolynomialGrid<GridView>::Cell> { | ||
726 | 3336 | static auto get(const Dune::LagrangePolynomialGrid<GridView>&, | |
727 | const typename Dune::LagrangePolynomialGrid<GridView>::Cell& cell) { | ||
728 |
2/4✓ Branch 1 taken 1818 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1818 times.
✗ Branch 5 not taken.
|
3336 | return Dune::LagrangeDetail::cell_type(cell.type()); |
729 | } | ||
730 | }; | ||
731 | |||
732 | template<typename GridView> | ||
733 | struct PointCoordinates<Dune::LagrangePolynomialGrid<GridView>, | ||
734 | typename Dune::LagrangePolynomialGrid<GridView>::Point> { | ||
735 | 11562 | static const auto& get(const Dune::LagrangePolynomialGrid<GridView>&, | |
736 | const typename Dune::LagrangePolynomialGrid<GridView>::Point& point) { | ||
737 | 11562 | return point.coordinates; | |
738 | } | ||
739 | }; | ||
740 | |||
741 | template<typename GridView> | ||
742 | struct PointId<Dune::LagrangePolynomialGrid<GridView>, | ||
743 | typename Dune::LagrangePolynomialGrid<GridView>::Point> { | ||
744 | 57552 | static auto get(const Dune::LagrangePolynomialGrid<GridView>&, | |
745 | const typename Dune::LagrangePolynomialGrid<GridView>::Point& point) { | ||
746 | 57552 | return point.index; | |
747 | } | ||
748 | }; | ||
749 | |||
750 | } // namespace Traits | ||
751 | |||
752 | |||
753 | namespace Dune { | ||
754 | namespace Concepts { | ||
755 | |||
756 | template<typename T, typename GridView> | ||
757 | concept Function = requires(const T& f, const typename GridView::template Codim<0>::Entity& element) { | ||
758 | { localFunction(f) }; | ||
759 | { localFunction(f).bind(element) }; | ||
760 | { localFunction(f)(element.geometry().center()) }; | ||
761 | }; | ||
762 | |||
763 | } // namespace Concepts | ||
764 | |||
765 | #ifndef DOXYGEN | ||
766 | namespace FunctionDetail { | ||
767 | |||
768 | template<typename Function, typename GridView> | ||
769 | using RangeType = std::invoke_result_t< | ||
770 | typename std::remove_cvref_t<Function>::LocalFunction, | ||
771 | typename GridView::template Codim<0>::Entity::Geometry::LocalCoordinate | ||
772 | >; | ||
773 | |||
774 | template<typename Function, typename GridView> | ||
775 | using RangeScalar = FieldScalar<RangeType<Function, GridView>>; | ||
776 | |||
777 | } // FunctionDetail | ||
778 | #endif // DOXYGEN | ||
779 | |||
780 | /*! | ||
781 | * \ingroup PredefinedTraits | ||
782 | * \brief Implements the field interface for a Dune::Function defined on a (wrapped) Dune::GridView. | ||
783 | * \note Takes ownership of the given function if constructed with an rvalue reference, otherwise it | ||
784 | * stores a reference. | ||
785 | */ | ||
786 | template<typename _Function, typename Grid, GridFormat::Concepts::Scalar T> | ||
787 | requires(Concepts::Function<_Function, typename Dune::Traits::GridView<Grid>::type>) | ||
788 | class FunctionField : public GridFormat::Field { | ||
789 | using Function = std::remove_cvref_t<_Function>; | ||
790 | using GridView = typename Dune::Traits::GridView<Grid>::type; | ||
791 | using Element = typename GridView::template Codim<0>::Entity; | ||
792 | using ElementGeometry = typename Element::Geometry; | ||
793 | |||
794 | static constexpr bool is_higher_order = std::is_same_v<Grid, LagrangePolynomialGrid<GridView>>; | ||
795 | |||
796 | public: | ||
797 | template<typename F> | ||
798 | requires(std::is_same_v<std::remove_cvref_t<F>, Function>) | ||
799 | 336 | explicit FunctionField(F&& function, | |
800 | const Grid& grid, | ||
801 | const Precision<T>& = {}, | ||
802 | bool cellwise_constant = false) | ||
803 | 672 | : _function{std::forward<F>(function)} | |
804 | 336 | , _grid{grid} | |
805 | 336 | , _cellwise_constant{cellwise_constant} { | |
806 | if constexpr (requires { function.basis(); }) { | ||
807 | static_assert(std::is_same_v<typename Function::Basis::GridView, GridView>); | ||
808 | if (&function.basis().gridView().grid() != &Dune::Traits::GridView<Grid>::get(_grid).grid()) | ||
809 | throw ValueError("Function and mesh do not use the same underlying grid"); | ||
810 | } | ||
811 | 336 | } | |
812 | |||
813 | private: | ||
814 | 3888 | MDLayout _layout() const override { | |
815 | return MDLayout{{ | ||
816 |
3/4✓ Branch 0 taken 918 times.
✓ Branch 1 taken 1026 times.
✓ Branch 3 taken 918 times.
✗ Branch 4 not taken.
|
3888 | _cellwise_constant ? GridFormat::Traits::NumberOfCells<Grid>::get(_grid) |
817 |
1/2✓ Branch 1 taken 1026 times.
✗ Branch 2 not taken.
|
2052 | : GridFormat::Traits::NumberOfPoints<Grid>::get(_grid) |
818 |
3/6✓ Branch 1 taken 1944 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1944 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1944 times.
✗ Branch 8 not taken.
|
3888 | }}.template with_sub_layout_from<FunctionDetail::RangeType<Function, GridView>>(); |
819 | } | ||
820 | |||
821 | 1332 | DynamicPrecision _precision() const override { | |
822 | 1332 | return {Precision<T>{}}; | |
823 | } | ||
824 | |||
825 | 336 | Serialization _serialized() const override { | |
826 |
1/2✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
|
336 | const auto layout = _layout(); |
827 |
1/2✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
|
336 | const auto num_entries = layout.number_of_entries(); |
828 |
4/6✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 96 times.
✓ Branch 4 taken 72 times.
✓ Branch 6 taken 96 times.
✗ Branch 7 not taken.
|
336 | const auto num_entries_per_value = layout.dimension() == 1 ? 1 : layout.number_of_entries(1); |
829 | |||
830 |
1/2✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
|
336 | Serialization result(num_entries*sizeof(T)); |
831 |
1/2✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
|
336 | auto out_data = result.template as_span_of<T>(); |
832 | |||
833 | using GridFormat::Traits::Cells; | ||
834 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 84 times.
|
336 | if (_cellwise_constant) { |
835 | 168 | std::size_t count = 0; | |
836 |
1/2✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
|
168 | auto local_function = localFunction(_function); |
837 |
12/17✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 84 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5856 times.
✓ Branch 11 taken 1152 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3636 times.
✓ Branch 14 taken 3396 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3348 times.
✓ Branch 17 taken 2964 times.
✓ Branch 18 taken 2928 times.
✓ Branch 19 taken 2940 times.
✓ Branch 20 taken 12 times.
|
26808 | for (const auto& element : Cells<Grid>::get(_grid)) { |
838 |
1/2✓ Branch 1 taken 6972 times.
✗ Branch 2 not taken.
|
13944 | local_function.bind(element); |
839 |
1/2✓ Branch 1 taken 6972 times.
✗ Branch 2 not taken.
|
13944 | const auto& elem_geo = element.geometry(); |
840 |
2/4✓ Branch 1 taken 6972 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6972 times.
✗ Branch 5 not taken.
|
13944 | const auto& local_pos = elem_geo.local(elem_geo.center()); |
841 | 13944 | std::size_t offset = (count++)*num_entries_per_value; | |
842 |
3/6✓ Branch 1 taken 6972 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3636 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 708 times.
✗ Branch 8 not taken.
|
13944 | _copy_values(local_function(local_pos), out_data, offset); |
843 | } | ||
844 | 48 | } else { | |
845 |
1/2✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
|
168 | _fill_point_values(out_data, num_entries_per_value); |
846 | } | ||
847 | |||
848 | 336 | return result; | |
849 | 336 | } | |
850 | |||
851 | void _fill_point_values(std::span<T> out_data, std::size_t num_entries_per_value) const | ||
852 | requires(!is_higher_order) { | ||
853 | using GridFormat::Traits::Cells; | ||
854 | using GridFormat::Traits::CellPoints; | ||
855 | using GridFormat::Traits::PointCoordinates; | ||
856 | using GridFormat::Traits::PointId; | ||
857 | using GridFormat::Traits::NumberOfPoints; | ||
858 | |||
859 | auto local_function = localFunction(_function); | ||
860 | auto point_id_to_running_idx = make_point_id_map(_grid); | ||
861 | std::vector<bool> handled(NumberOfPoints<Grid>::get(_grid), false); | ||
862 | |||
863 | std::ranges::for_each(Cells<Grid>::get(_grid), [&] <typename C> (const C& element) { | ||
864 | const auto& element_geometry = element.geometry(); | ||
865 | local_function.bind(element); | ||
866 | std::ranges::for_each(CellPoints<Grid, Element>::get(_grid, element), [&] <typename P> (const P& point) { | ||
867 | const auto point_id = PointId<Grid, P>::get(_grid, point); | ||
868 | const auto running_idx = point_id_to_running_idx.at(point_id); | ||
869 | if (!handled[running_idx]) { | ||
870 | const auto local_pos = element_geometry.local(PointCoordinates<Grid, P>::get(_grid, point)); | ||
871 | std::size_t offset = running_idx*num_entries_per_value; | ||
872 | _copy_values(local_function(local_pos), out_data, offset); | ||
873 | } | ||
874 | handled[running_idx] = true; | ||
875 | }); | ||
876 | }); | ||
877 | } | ||
878 | |||
879 | 168 | void _fill_point_values(std::span<T> out_data, std::size_t num_entries_per_value) const | |
880 | requires(is_higher_order) { | ||
881 | using GridFormat::Traits::Cells; | ||
882 | using GridFormat::Traits::CellPoints; | ||
883 |
1/2✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
|
168 | auto local_function = localFunction(_function); |
884 |
1/2✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
|
168 | std::vector<bool> handled(_grid.number_of_points(), false); |
885 |
2/4✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
|
8256 | std::ranges::for_each(Cells<Grid>::get(_grid), [&] <typename C> (const C& element) { |
886 |
16/32✓ Branch 1 taken 318 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 336 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 738 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1026 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 18 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 18 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 18 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 36 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 36 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 36 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 438 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 438 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 438 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 1026 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 1026 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 1026 times.
✗ Branch 47 not taken.
|
6972 | const auto& element_geometry = element.geometry(); |
887 |
16/32✓ Branch 1 taken 318 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 336 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 738 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1026 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 18 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 18 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 18 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 36 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 36 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 36 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 438 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 438 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 438 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 1026 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 1026 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 1026 times.
✗ Branch 47 not taken.
|
6972 | local_function.bind(element); |
888 |
32/64✓ Branch 1 taken 318 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 318 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 336 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 336 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 738 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 738 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1026 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1026 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 18 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 18 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 18 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 18 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 18 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 18 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 36 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 36 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 36 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 36 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 36 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 36 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 438 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 438 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 438 times.
✗ Branch 68 not taken.
✓ Branch 70 taken 438 times.
✗ Branch 71 not taken.
✓ Branch 73 taken 438 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 438 times.
✗ Branch 77 not taken.
✓ Branch 79 taken 1026 times.
✗ Branch 80 not taken.
✓ Branch 82 taken 1026 times.
✗ Branch 83 not taken.
✓ Branch 85 taken 1026 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 1026 times.
✗ Branch 89 not taken.
✓ Branch 91 taken 1026 times.
✗ Branch 92 not taken.
✓ Branch 94 taken 1026 times.
✗ Branch 95 not taken.
|
150484 | std::ranges::for_each(_grid.points(element), [&] <typename P> (const P& point) { |
889 |
48/64✓ Branch 1 taken 3074 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1769 times.
✓ Branch 5 taken 1305 times.
✓ Branch 8 taken 4088 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2353 times.
✓ Branch 12 taken 1735 times.
✓ Branch 15 taken 5674 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 2773 times.
✓ Branch 19 taken 2901 times.
✓ Branch 22 taken 11628 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 3016 times.
✓ Branch 26 taken 8612 times.
✓ Branch 29 taken 174 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 117 times.
✓ Branch 33 taken 57 times.
✓ Branch 36 taken 174 times.
✗ Branch 37 not taken.
✓ Branch 39 taken 117 times.
✓ Branch 40 taken 57 times.
✓ Branch 43 taken 174 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 117 times.
✓ Branch 47 taken 57 times.
✓ Branch 50 taken 1188 times.
✗ Branch 51 not taken.
✓ Branch 53 taken 701 times.
✓ Branch 54 taken 487 times.
✓ Branch 57 taken 1188 times.
✗ Branch 58 not taken.
✓ Branch 60 taken 701 times.
✓ Branch 61 taken 487 times.
✓ Branch 64 taken 1188 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 701 times.
✓ Branch 68 taken 487 times.
✓ Branch 71 taken 2774 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 1121 times.
✓ Branch 75 taken 1653 times.
✓ Branch 78 taken 2774 times.
✗ Branch 79 not taken.
✓ Branch 81 taken 1121 times.
✓ Branch 82 taken 1653 times.
✓ Branch 85 taken 2774 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 1121 times.
✓ Branch 89 taken 1653 times.
✓ Branch 92 taken 11628 times.
✗ Branch 93 not taken.
✓ Branch 95 taken 3016 times.
✓ Branch 96 taken 8612 times.
✓ Branch 99 taken 11628 times.
✗ Branch 100 not taken.
✓ Branch 102 taken 3016 times.
✓ Branch 103 taken 8612 times.
✓ Branch 106 taken 11628 times.
✗ Branch 107 not taken.
✓ Branch 109 taken 3016 times.
✓ Branch 110 taken 8612 times.
|
71756 | if (!handled[point.index]) { |
890 |
16/32✓ Branch 1 taken 1769 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2353 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2773 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3016 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 117 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 117 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 117 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 701 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 701 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 701 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 1121 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 1121 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 1121 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 3016 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 3016 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 3016 times.
✗ Branch 47 not taken.
|
24776 | const auto local_pos = element_geometry.local(point.coordinates); |
891 | 24776 | std::size_t offset = point.index*num_entries_per_value; | |
892 |
27/52✓ Branch 1 taken 1769 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2353 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1652 times.
✓ Branch 9 taken 1121 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1652 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3016 times.
✓ Branch 14 taken 1652 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 117 times.
✗ Branch 18 not taken.
✓ Branch 21 taken 117 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 117 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 117 times.
✗ Branch 28 not taken.
✓ Branch 30 taken 117 times.
✗ Branch 31 not taken.
✓ Branch 33 taken 701 times.
✗ Branch 34 not taken.
✓ Branch 37 taken 701 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 701 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 701 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 701 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 1121 times.
✗ Branch 50 not taken.
✓ Branch 53 taken 1121 times.
✗ Branch 54 not taken.
✓ Branch 56 taken 1121 times.
✗ Branch 57 not taken.
✓ Branch 59 taken 1121 times.
✗ Branch 60 not taken.
✓ Branch 62 taken 1121 times.
✗ Branch 63 not taken.
✓ Branch 65 taken 3016 times.
✗ Branch 66 not taken.
✓ Branch 69 taken 3016 times.
✗ Branch 70 not taken.
✓ Branch 72 taken 3016 times.
✗ Branch 73 not taken.
✓ Branch 75 taken 3016 times.
✗ Branch 76 not taken.
✓ Branch 78 taken 3016 times.
✗ Branch 79 not taken.
|
24776 | _copy_values(local_function(local_pos), out_data, offset); |
893 | } | ||
894 |
16/32✓ Branch 1 taken 3074 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 4088 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 5674 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 11628 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 174 times.
✗ Branch 18 not taken.
✓ Branch 21 taken 174 times.
✗ Branch 22 not taken.
✓ Branch 25 taken 174 times.
✗ Branch 26 not taken.
✓ Branch 29 taken 1188 times.
✗ Branch 30 not taken.
✓ Branch 33 taken 1188 times.
✗ Branch 34 not taken.
✓ Branch 37 taken 1188 times.
✗ Branch 38 not taken.
✓ Branch 41 taken 2774 times.
✗ Branch 42 not taken.
✓ Branch 45 taken 2774 times.
✗ Branch 46 not taken.
✓ Branch 49 taken 2774 times.
✗ Branch 50 not taken.
✓ Branch 53 taken 11628 times.
✗ Branch 54 not taken.
✓ Branch 57 taken 11628 times.
✗ Branch 58 not taken.
✓ Branch 61 taken 11628 times.
✗ Branch 62 not taken.
|
71756 | handled[point.index] = true; |
895 | }); | ||
896 | 5856 | }); | |
897 | 168 | } | |
898 | |||
899 | template<std::ranges::range R> | ||
900 | 76958 | void _copy_values(R&& range, std::span<T> out, std::size_t& offset) const { | |
901 |
1/2✓ Branch 1 taken 38479 times.
✗ Branch 2 not taken.
|
278664 | std::ranges::for_each(range, [&] (const auto& entry) { |
902 | 100853 | _copy_values(entry, out, offset); | |
903 | }); | ||
904 | 76958 | } | |
905 | |||
906 | template<GridFormat::Concepts::Scalar S> | ||
907 | 188244 | void _copy_values(const S value, std::span<T> out, std::size_t& offset) const { | |
908 | 188244 | out[offset++] = static_cast<T>(value); | |
909 | 188244 | } | |
910 | |||
911 | _Function _function; | ||
912 | const Grid& _grid; | ||
913 | bool _cellwise_constant; | ||
914 | }; | ||
915 | |||
916 | |||
917 | template<typename F, typename G, typename T = FunctionDetail::RangeScalar<F, typename Traits::GridView<G>::type>> | ||
918 | requires(std::is_lvalue_reference_v<F>) | ||
919 | FunctionField(F&&, const G&, const Precision<T>& = {}, bool = false) -> FunctionField< | ||
920 | std::add_lvalue_reference_t<std::add_const_t<std::remove_reference_t<F>>>, G, T | ||
921 | >; | ||
922 | |||
923 | template<typename F, typename G, typename T = FunctionDetail::RangeScalar<F, typename Traits::GridView<G>::type>> | ||
924 | requires(!std::is_lvalue_reference_v<F>) | ||
925 | FunctionField(F&&, const G&, const Precision<T>& = {}, bool = false) -> FunctionField<std::remove_cvref_t<F>, G, T>; | ||
926 | |||
927 | |||
928 | #ifndef DOXYGEN | ||
929 | template<typename T> struct IsLagrangeGrid : public std::false_type {}; | ||
930 | template<typename GV> struct IsLagrangeGrid<LagrangePolynomialGrid<GV>> : public std::true_type {}; | ||
931 | |||
932 | namespace FunctionDetail { | ||
933 | template<typename F, typename W, typename T> | ||
934 | 336 | void set_function(F&& f, W& w, const std::string& name, const Precision<T>& prec, bool is_cellwise) { | |
935 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 84 times.
|
336 | if (is_cellwise) |
936 |
1/2✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
|
168 | w.set_cell_field(name, FunctionField{std::forward<F>(f), w.grid(), prec, true}); |
937 | else | ||
938 |
1/2✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
|
168 | w.set_point_field(name, FunctionField{std::forward<F>(f), w.grid(), prec, false}); |
939 | 336 | } | |
940 | |||
941 | template<typename F, typename W> | ||
942 | 288 | void set_function(F&& f, W& w, const std::string& name, bool is_cellwise) { | |
943 | using GV = Dune::Traits::GridView<typename W::Grid>::type; | ||
944 | using T = RangeScalar<F, GV>; | ||
945 |
1/2✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
|
288 | set_function(std::forward<F>(f), w, name, Precision<T>{}, is_cellwise); |
946 | 288 | } | |
947 | } // namespace FunctionDetail | ||
948 | #endif //DOXYGEN | ||
949 | |||
950 | /*! | ||
951 | * \ingroup PredefinedTraits | ||
952 | * \brief Insert the given Dune::Function to the writer as point field. | ||
953 | * \note This requires the Writer to have been constructed with a LagrangePolynomialGrid. | ||
954 | */ | ||
955 | template<typename Function, typename Writer> | ||
956 | 144 | void set_point_function(Function&& f, Writer& writer, const std::string& name) { | |
957 | 144 | FunctionDetail::set_function(std::forward<Function>(f), writer, name, false); | |
958 | 144 | } | |
959 | |||
960 | /*! | ||
961 | * \ingroup PredefinedTraits | ||
962 | * \brief Insert the given Dune::Function to the writer as point field with the given precision. | ||
963 | * \note This requires the Writer to have been constructed with a LagrangePolynomialGrid. | ||
964 | */ | ||
965 | template<typename Function, typename Writer, GridFormat::Concepts::Scalar T> | ||
966 | 24 | void set_point_function(Function&& f, Writer& writer, const std::string& name, const Precision<T>& prec) { | |
967 | 24 | FunctionDetail::set_function(std::forward<Function>(f), writer, name, prec, false); | |
968 | 24 | } | |
969 | |||
970 | /*! | ||
971 | * \ingroup PredefinedTraits | ||
972 | * \brief Insert the given Dune::Function to the writer as cell field. | ||
973 | * \note This requires the Writer to have been constructed with a LagrangePolynomialGrid. | ||
974 | */ | ||
975 | template<typename Writer, typename Function> | ||
976 | 144 | void set_cell_function(Function&& f, Writer& writer, const std::string& name) { | |
977 | 144 | FunctionDetail::set_function(std::forward<Function>(f), writer, name, true); | |
978 | 144 | } | |
979 | |||
980 | /*! | ||
981 | * \ingroup PredefinedTraits | ||
982 | * \brief Insert the given Dune::Function to the writer as cell field with the given precision. | ||
983 | * \note This requires the Writer to have been constructed with a LagrangePolynomialGrid. | ||
984 | */ | ||
985 | template<typename Writer, typename Function, GridFormat::Concepts::Scalar T> | ||
986 | 24 | void set_cell_function(Function&& f, Writer& writer, const std::string& name, const Precision<T>& prec) { | |
987 | 24 | FunctionDetail::set_function(std::forward<Function>(f), writer, name, prec, true); | |
988 | 24 | } | |
989 | |||
990 | } // namespace Dune | ||
991 | } // namespace GridFormat | ||
992 | |||
993 | #else // GRIDFORMAT_HAVE_DUNE_LOCALFUNCTIONS | ||
994 | |||
995 | #ifndef DOXYGEN | ||
996 | namespace GridFormat::Dune { | ||
997 | |||
998 | template<typename... T> | ||
999 | class LagrangePolynomialGrid { | ||
1000 | template<typename... Ts> struct False { static constexpr bool value = false; }; | ||
1001 | public: | ||
1002 | template<typename... Args> | ||
1003 | LagrangePolynomialGrid(Args&&... args) { | ||
1004 | static_assert(False<Args...>::value, "Dune-localfunctions required for higher-order output"); | ||
1005 | } | ||
1006 | }; | ||
1007 | |||
1008 | } // namespace GridFormat::Dune | ||
1009 | #endif // DOXYGEN | ||
1010 | |||
1011 | #endif // GRIDFORMAT_HAVE_DUNE_LOCALFUNCTIONS | ||
1012 | |||
1013 | namespace GridFormat::Dune { | ||
1014 | |||
1015 | 12 | inline constexpr ::Dune::GeometryType to_dune_geometry_type(const CellType& ct) { | |
1016 | namespace DGT = ::Dune::GeometryTypes; | ||
1017 |
1/15✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
12 | switch (ct) { |
1018 | ✗ | case CellType::vertex: return DGT::vertex; | |
1019 | ✗ | case CellType::segment: return DGT::line; | |
1020 | ✗ | case CellType::triangle: return DGT::triangle; | |
1021 | 12 | case CellType::pixel: return DGT::quadrilateral; | |
1022 | ✗ | case CellType::quadrilateral: return DGT::quadrilateral; | |
1023 | ✗ | case CellType::tetrahedron: return DGT::tetrahedron; | |
1024 | ✗ | case CellType::hexahedron: return DGT::hexahedron; | |
1025 | ✗ | case CellType::voxel: return DGT::hexahedron; | |
1026 | ✗ | case CellType::polygon: throw NotImplemented("No conversion from polygon to Dune::GeometryType"); | |
1027 | ✗ | case CellType::lagrange_segment: throw NotImplemented("Cannot map higher-order cells to Dune::GeometryType"); | |
1028 | ✗ | case CellType::lagrange_triangle: throw NotImplemented("Cannot map higher-order cells to Dune::GeometryType"); | |
1029 | ✗ | case CellType::lagrange_quadrilateral: throw NotImplemented("Cannot map higher-order cells to Dune::GeometryType"); | |
1030 | ✗ | case CellType::lagrange_tetrahedron: throw NotImplemented("Cannot map higher-order cells to Dune::GeometryType"); | |
1031 | ✗ | case CellType::lagrange_hexahedron: throw NotImplemented("Cannot map higher-order cells to Dune::GeometryType"); | |
1032 | ✗ | default: throw NotImplemented("Unknown cell type."); | |
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | template<std::integral TargetType, std::integral T> | ||
1037 | 12 | auto to_dune(const CellType& ct, const std::vector<T>& corners) { | |
1038 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | auto gt = to_dune_geometry_type(ct); |
1039 |
1/2✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 | std::vector<TargetType> reordered(corners.size()); |
1040 | |||
1041 | // voxels/pixels map to hexes/quads, but reordering has to be skipped | ||
1042 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
12 | if (ct != CellType::pixel && ct != CellType::voxel) { |
1043 | ✗ | std::ranges::copy( | |
1044 | ✗ | std::views::iota(std::size_t{0}, corners.size()) | |
1045 | ✗ | | std::views::transform([&] (std::size_t i) { | |
1046 | ✗ | return corners[GridFormat::Traits::DuneDetail::map_corner_index(gt, i)]; | |
1047 | }), | ||
1048 | reordered.begin() | ||
1049 | ); | ||
1050 | ✗ | } else { | |
1051 |
1/2✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 | std::ranges::copy(corners, reordered.begin()); |
1052 | } | ||
1053 | |||
1054 | 24 | return std::make_tuple(std::move(gt), std::move(reordered)); | |
1055 | 12 | } | |
1056 | |||
1057 | /*! | ||
1058 | * \ingroup PredefinedTraits | ||
1059 | * \brief Adapter around a Dune::GridFactory to be compatible with GridFormat::Concepts::GridFactory. | ||
1060 | * Can be used to export a grid from a reader directly into a Dune::GridFactory. For instance: | ||
1061 | * \code{.cpp} | ||
1062 | * GridFormat::Reader reader; reader.open(filename); | ||
1063 | * Dune::GridFactory<DuneGrid> factory; | ||
1064 | * { | ||
1065 | * GridFormat::Dune::GridFactoryAdapter adapter{factory}; | ||
1066 | * reader.export_grid(adapter); | ||
1067 | * } | ||
1068 | * // ... use dune grid factory | ||
1069 | * \endcode | ||
1070 | */ | ||
1071 | template<typename Grid> | ||
1072 | class GridFactoryAdapter { | ||
1073 | public: | ||
1074 | static constexpr int space_dim = Grid::dimensionworld; | ||
1075 | using ctype = typename Grid::ctype; | ||
1076 | using DuneFactory = ::Dune::GridFactory<Grid>; | ||
1077 | |||
1078 | 1 | GridFactoryAdapter(DuneFactory& factory) | |
1079 | 1 | : _factory{factory} | |
1080 | 1 | {} | |
1081 | |||
1082 | template<std::size_t _space_dim> | ||
1083 | 20 | void insert_point(const std::array<ctype, _space_dim>& point) { | |
1084 | 20 | ::Dune::FieldVector<ctype, space_dim> p; | |
1085 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
|
20 | std::copy_n(point.begin(), space_dim, p.begin()); |
1086 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | _factory.insertVertex(p); |
1087 | 20 | } | |
1088 | |||
1089 | 12 | void insert_cell(const CellType& ct, const std::vector<std::size_t>& corners) { | |
1090 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | const auto [dune_gt, dune_corners] = to_dune<unsigned int>(ct, corners); |
1091 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | _factory.insertElement(dune_gt, dune_corners); |
1092 | 12 | } | |
1093 | |||
1094 | private: | ||
1095 | DuneFactory& _factory; | ||
1096 | }; | ||
1097 | |||
1098 | } // namespace GridFormat::Dune | ||
1099 | |||
1100 | #endif // GRIDFORMAT_TRAITS_DUNE_HPP_ | ||
1101 |