| 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 | 280 | inline constexpr GridFormat::CellType cell_type(const Dune::GeometryType& gt) { | |
| 72 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 280 times.
|
280 | if (gt.isVertex()) return GridFormat::CellType::vertex; |
| 73 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 280 times.
|
280 | if (gt.isLine()) return GridFormat::CellType::segment; |
| 74 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 280 times.
|
280 | if (gt.isTriangle()) return GridFormat::CellType::triangle; |
| 75 |
2/2✓ Branch 1 taken 256 times.
✓ Branch 2 taken 24 times.
|
280 | 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 | 2480 | static decltype(auto) get(const Dune::GridView<Traits>& grid_view) { | |
| 106 | return std::ranges::subrange( | ||
| 107 |
1/2✓ Branch 1 taken 1793 times.
✗ Branch 2 not taken.
|
2686 | grid_view.template begin<0, Dune::Interior_Partition>(), |
| 108 |
1/2✓ Branch 1 taken 1793 times.
✗ Branch 2 not taken.
|
4960 | grid_view.template end<0, Dune::Interior_Partition>() |
| 109 |
1/2✓ Branch 1 taken 1793 times.
✗ Branch 2 not taken.
|
4960 | ); |
| 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 | 372 | static auto get(const Dune::GridView<Traits>&, | |
| 139 | const DuneDetail::Element<Dune::GridView<Traits>>& cell) { | ||
| 140 | 372 | 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 | 1460 | 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 830 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 830 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 830 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 830 times.
✗ Branch 11 not taken.
|
3664 | 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 | 2920 | }); | |
| 152 | } | ||
| 153 | }; | ||
| 154 | |||
| 155 | template<typename Traits> | ||
| 156 | struct CellType<Dune::GridView<Traits>, DuneDetail::Element<Dune::GridView<Traits>>> { | ||
| 157 | 460 | static decltype(auto) get(const Dune::GridView<Traits>&, | |
| 158 | const DuneDetail::Element<Dune::GridView<Traits>>& element) { | ||
| 159 |
2/4✓ Branch 1 taken 280 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 280 times.
✗ Branch 5 not taken.
|
460 | 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 | 504 | std::ranges::range auto cells() const { | |
| 571 | 504 | 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 | 504 | static auto get(const Dune::LagrangePolynomialGrid<GridView>& mesh) { | |
| 687 | 504 | 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/16✗ 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.
✗ Branch 15 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::polyline: throw NotImplemented("No conversion from polyline to Dune::GeometryType"); | |
| 1027 | ✗ | case CellType::polygon: throw NotImplemented("No conversion from polygon to Dune::GeometryType"); | |
| 1028 | ✗ | case CellType::lagrange_segment: throw NotImplemented("Cannot map higher-order cells to Dune::GeometryType"); | |
| 1029 | ✗ | case CellType::lagrange_triangle: throw NotImplemented("Cannot map higher-order cells to Dune::GeometryType"); | |
| 1030 | ✗ | case CellType::lagrange_quadrilateral: throw NotImplemented("Cannot map higher-order cells to Dune::GeometryType"); | |
| 1031 | ✗ | case CellType::lagrange_tetrahedron: throw NotImplemented("Cannot map higher-order cells to Dune::GeometryType"); | |
| 1032 | ✗ | case CellType::lagrange_hexahedron: throw NotImplemented("Cannot map higher-order cells to Dune::GeometryType"); | |
| 1033 | ✗ | default: throw NotImplemented("Unknown cell type."); | |
| 1034 | } | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | template<std::integral TargetType, std::integral T> | ||
| 1038 | 12 | auto to_dune(const CellType& ct, const std::vector<T>& corners) { | |
| 1039 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | auto gt = to_dune_geometry_type(ct); |
| 1040 |
1/2✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 | std::vector<TargetType> reordered(corners.size()); |
| 1041 | |||
| 1042 | // voxels/pixels map to hexes/quads, but reordering has to be skipped | ||
| 1043 |
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) { |
| 1044 | ✗ | std::ranges::copy( | |
| 1045 | ✗ | std::views::iota(std::size_t{0}, corners.size()) | |
| 1046 | ✗ | | std::views::transform([&] (std::size_t i) { | |
| 1047 | ✗ | return corners[GridFormat::Traits::DuneDetail::map_corner_index(gt, i)]; | |
| 1048 | }), | ||
| 1049 | reordered.begin() | ||
| 1050 | ); | ||
| 1051 | ✗ | } else { | |
| 1052 |
1/2✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 | std::ranges::copy(corners, reordered.begin()); |
| 1053 | } | ||
| 1054 | |||
| 1055 | 24 | return std::make_tuple(std::move(gt), std::move(reordered)); | |
| 1056 | 12 | } | |
| 1057 | |||
| 1058 | /*! | ||
| 1059 | * \ingroup PredefinedTraits | ||
| 1060 | * \brief Adapter around a Dune::GridFactory to be compatible with GridFormat::Concepts::GridFactory. | ||
| 1061 | * Can be used to export a grid from a reader directly into a Dune::GridFactory. For instance: | ||
| 1062 | * \code{.cpp} | ||
| 1063 | * GridFormat::Reader reader; reader.open(filename); | ||
| 1064 | * Dune::GridFactory<DuneGrid> factory; | ||
| 1065 | * { | ||
| 1066 | * GridFormat::Dune::GridFactoryAdapter adapter{factory}; | ||
| 1067 | * reader.export_grid(adapter); | ||
| 1068 | * } | ||
| 1069 | * // ... use dune grid factory | ||
| 1070 | * \endcode | ||
| 1071 | */ | ||
| 1072 | template<typename Grid> | ||
| 1073 | class GridFactoryAdapter { | ||
| 1074 | public: | ||
| 1075 | static constexpr int space_dim = Grid::dimensionworld; | ||
| 1076 | using ctype = typename Grid::ctype; | ||
| 1077 | using DuneFactory = ::Dune::GridFactory<Grid>; | ||
| 1078 | |||
| 1079 | 1 | GridFactoryAdapter(DuneFactory& factory) | |
| 1080 | 1 | : _factory{factory} | |
| 1081 | 1 | {} | |
| 1082 | |||
| 1083 | template<std::size_t _space_dim> | ||
| 1084 | 20 | void insert_point(const std::array<ctype, _space_dim>& point) { | |
| 1085 | 20 | ::Dune::FieldVector<ctype, space_dim> p; | |
| 1086 |
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()); |
| 1087 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | _factory.insertVertex(p); |
| 1088 | 20 | } | |
| 1089 | |||
| 1090 | 12 | void insert_cell(const CellType& ct, const std::vector<std::size_t>& corners) { | |
| 1091 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | const auto [dune_gt, dune_corners] = to_dune<unsigned int>(ct, corners); |
| 1092 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | _factory.insertElement(dune_gt, dune_corners); |
| 1093 | 12 | } | |
| 1094 | |||
| 1095 | private: | ||
| 1096 | DuneFactory& _factory; | ||
| 1097 | }; | ||
| 1098 | |||
| 1099 | } // namespace GridFormat::Dune | ||
| 1100 | |||
| 1101 | #endif // GRIDFORMAT_TRAITS_DUNE_HPP_ | ||
| 1102 |