9#ifndef GRIDFORMAT_TRAITS_DEAL_II_HPP_
10#define GRIDFORMAT_TRAITS_DEAL_II_HPP_
18#include <deal.II/grid/tria.h>
19#include <deal.II/distributed/tria.h>
20#include <deal.II/distributed/fully_distributed_tria.h>
22#include <gridformat/common/exceptions.hpp>
23#include <gridformat/common/filtered_range.hpp>
25#include <gridformat/grid/cell_type.hpp>
26#include <gridformat/grid/traits.hpp>
34template<
int dim,
int space_dim>
using Tria = dealii::Triangulation<dim, space_dim>;
35template<
int dim,
int space_dim>
using DTria = dealii::parallel::distributed::Triangulation<dim, space_dim>;
36template<
int dim,
int space_dim>
using FDTria = dealii::parallel::fullydistributed::Triangulation<dim, space_dim>;
38template<
typename T>
struct IsTriangulation :
public std::false_type {};
39template<
typename T>
struct IsParallelTriangulation :
public std::false_type {};
41template<
int d,
int sd>
struct IsTriangulation<Tria<d, sd>> :
public std::true_type {};
42template<
int d,
int sd>
struct IsTriangulation<DTria<d, sd>> :
public std::true_type {};
43template<
int d,
int sd>
struct IsTriangulation<FDTria<d, sd>> :
public std::true_type {};
44template<
int d,
int sd>
struct IsParallelTriangulation<DTria<d, sd>> :
public std::true_type {};
45template<
int d,
int sd>
struct IsParallelTriangulation<FDTria<d, sd>> :
public std::true_type {};
47template<
typename T>
inline constexpr bool is_triangulation = IsTriangulation<T>::value;
48template<
typename T>
inline constexpr bool is_parallel_triangulation = IsParallelTriangulation<T>::value;
62template<
typename Iterator>
63class ForwardIteratorWrapper
64:
public ForwardIteratorFacade<ForwardIteratorWrapper<Iterator>,
65 typename Iterator::value_type,
66 decltype(*(std::declval<std::add_const_t<Iterator>>())),
67 typename Iterator::pointer,
68 typename Iterator::difference_type> {
69 using Reference =
decltype(*(std::declval<std::add_const_t<Iterator>>()));
72 ForwardIteratorWrapper() =
default;
73 ForwardIteratorWrapper(Iterator it) : _it{it} {}
81 friend bool operator==(
const ForwardIteratorWrapper& self,
const ForwardIteratorWrapper<I>& other) {
82 return self._it == other._get_it();
86 friend bool operator!=(
const ForwardIteratorWrapper& self,
const ForwardIteratorWrapper<I>& other) {
87 return self._it != other._get_it();
90 const Iterator& _get_it()
const {
95 friend IteratorAccess;
97 Reference _dereference()
const {
return *_it; }
98 bool _is_equal(
const ForwardIteratorWrapper& other) {
return _it == other._it; }
99 void _increment() { ++_it; }
105ForwardIteratorWrapper(It&& it) -> ForwardIteratorWrapper<std::remove_cvref_t<It>>;
107template<
typename T>
requires(is_triangulation<T>)
108using Cell =
typename T::active_cell_iterator::AccessorType;
110template<
typename T>
requires(is_triangulation<T>)
111using Point =
typename T::active_vertex_iterator::AccessorType;
113const std::vector<int>& cell_corners_in_gridformat_order(
unsigned int cell_dimension,
114 unsigned int number_of_cell_corners) {
115 if (cell_dimension == 0) {
116 assert(number_of_cell_corners == 1);
117 static const std::vector<int> corners{0};
119 }
else if (cell_dimension == 1) {
120 assert(number_of_cell_corners == 2);
121 static const std::vector<int> corners{0, 1};
123 }
else if (cell_dimension == 2) {
124 if (number_of_cell_corners == 3) {
125 static const std::vector<int> corners{0, 1, 2};
127 }
else if (number_of_cell_corners == 4) {
128 static const std::vector<int> corners{0, 1, 3, 2};
131 }
else if (cell_dimension == 3) {
132 if (number_of_cell_corners == 4) {
133 static const std::vector<int> corners{0, 1, 2, 3};
135 }
else if (number_of_cell_corners == 8) {
136 static const std::vector<int> corners{0, 1, 3, 2, 4, 5, 7, 6};
141 throw NotImplemented(
142 "deal.ii cell corner indices for cell of dimension " + std::to_string(cell_dimension) +
143 " and " + std::to_string(number_of_cell_corners) +
" corners"
146 static const std::vector<int> v{};
156template<
typename T>
requires(DealII::is_triangulation<T>)
158 static std::ranges::range
decltype(
auto) get(
const T& grid) {
159 return std::ranges::subrange(
160 DealII::ForwardIteratorWrapper{grid.begin_active_vertex()},
161 DealII::ForwardIteratorWrapper{grid.end_vertex()}
166template<
typename T>
requires(DealII::is_triangulation<T>)
168 static std::ranges::range
auto get(
const T& grid) {
169 if constexpr (DealII::is_parallel_triangulation<T>)
170 return Ranges::filter_by(
171 [] (
const auto& cell) {
return cell.is_locally_owned(); },
172 std::ranges::subrange(
173 DealII::ForwardIteratorWrapper{grid.begin_active()},
174 DealII::ForwardIteratorWrapper{grid.end()}
178 return std::ranges::subrange(
179 DealII::ForwardIteratorWrapper{grid.begin_active()},
180 DealII::ForwardIteratorWrapper{grid.end()}
185template<
typename T>
requires(DealII::is_triangulation<T>)
186struct CellType<T, DealII::Cell<T>> {
187 static GridFormat::CellType get(
const T&,
const DealII::Cell<T>& cell) {
188 using CT = GridFormat::CellType;
189 static constexpr std::array cubes{CT::vertex, CT::segment, CT::quadrilateral, CT::hexahedron};
190 static constexpr std::array simplices{CT::vertex, CT::segment, CT::triangle, CT::tetrahedron};
191 const auto& ref_cell = cell.reference_cell();
192 if (ref_cell.is_hyper_cube())
193 return cubes[ref_cell.get_dimension()];
194 else if (ref_cell.is_simplex())
195 return simplices[ref_cell.get_dimension()];
196 throw NotImplemented(
"CellType only implemented for hypercubes & simplices");
200template<
typename T>
requires(DealII::is_triangulation<T>)
201struct CellPoints<T, DealII::Cell<T>> {
202 static std::ranges::range
decltype(
auto) get(
const T&,
const DealII::Cell<T>& cell) {
203 return DealII::cell_corners_in_gridformat_order(cell.reference_cell().get_dimension(), cell.n_vertices())
204 | std::views::transform([&] (
int i) {
return *cell.vertex_iterator(i); });
208template<
typename T>
requires(DealII::is_triangulation<T>)
209struct PointId<T, DealII::Point<T>> {
210 static auto get(
const T&,
const DealII::Point<T>& point) {
211 return point.index();
215template<
typename T>
requires(DealII::is_triangulation<T>)
216struct PointCoordinates<T, DealII::Point<T>> {
217 static std::ranges::range
decltype(
auto) get(
const T&,
const DealII::Point<T>& point) {
218 static_assert(T::dimension >= 1 && T::dimension <= 3);
219 const auto& center = point.center();
220 if constexpr (T::dimension == 1)
221 return std::array{center[0]};
222 else if constexpr (T::dimension == 2)
223 return std::array{center[0], center[1]};
224 else if constexpr (T::dimension == 3)
225 return std::array{center[0], center[1], center[2]};
229template<
typename T>
requires(DealII::is_triangulation<T>)
230struct NumberOfPoints<T> {
231 static std::integral
auto get(
const T& grid) {
232 return grid.n_used_vertices();
236template<
typename T>
requires(DealII::is_triangulation<T>)
237struct NumberOfCells<T> {
238 static std::integral
auto get(
const T& grid) {
239 if constexpr (DealII::is_parallel_triangulation<T>)
240 return grid.n_locally_owned_active_cells();
242 return grid.n_active_cells();
246template<
typename T>
requires(DealII::is_triangulation<T>)
247struct NumberOfCellPoints<T, DealII::Cell<T>> {
248 static std::integral
auto get(
const T&,
const DealII::Cell<T>& cell) {
249 return cell.n_vertices();