AMDiS 2.11-git
The Adaptive Multi-Dimensional Simulation Toolbox
 
Loading...
Searching...
No Matches
RangeType.hpp
1#pragma once
2
3#include <type_traits>
4#include <utility>
5
6#include <dune/common/fvector.hh>
7#include <dune/common/tuplevector.hh>
8#include <dune/common/typetraits.hh>
9#include <dune/common/typetree/childaccess.hh>
10#include <dune/common/typetree/nodeconcepts.hh>
11
12#include <amdis/common/Index.hpp>
13#include <amdis/common/TypeTraits.hpp>
14#include <amdis/typetree/NodeTags.hpp>
15
16namespace Dune
17{
18 template <class... T>
19 struct FieldTraits<TupleVector<T...>>
20 {
21 using field_type = std::common_type_t<typename FieldTraits<T>::field_type...>;
22 using real_type = std::common_type_t<typename FieldTraits<T>::real_type...>;
23 };
24}
25
26namespace AMDiS
27{
28 namespace Impl
29 {
30 template <class Node, class R, class NodeTag, class Default>
31 struct RangeTypeImpl
32 {
33 using type = Default;
34 static type create(Node const& node)
35 {
36 type range{};
37 return range;
38 }
39 };
40
41 template <class Node, class R, class NodeTag>
42 struct RangeTypeImpl<Node,R,NodeTag,void>
43 {
44 static_assert( Dune::AlwaysFalse<NodeTag>::value, "Unknown node-type for range definition" );
45 };
46 }
47
48
49 template <class Node, class R = double, class Default = void>
50 using RangeType = Impl::RangeTypeImpl<Node, R, AMDiS::NodeTag_t<Node>, Default>;
51
54
64 template <class Node, class R = double, class Default = void>
65 using RangeType_t =
66 typename Impl::RangeTypeImpl<Node, R, AMDiS::NodeTag_t<Node>, Default>::type;
67
68
69 namespace Impl
70 {
71 // Leaf node
72 template <class Node, class R>
73 struct RangeTypeImpl<Node, R, AMDiS::LeafNodeTag, void>
74 {
75 using LocalBasis = typename Node::FiniteElement::Traits::LocalBasisType;
76 using T = typename LocalBasis::Traits::RangeType;
77 using type = remove_cvref_t<decltype(std::declval<R>() * std::declval<T>())>;
78 static type create(Node const& node)
79 {
80 return type(0);
81 }
82 };
83
84 // Power node
85 template <class Node, class R>
86 struct RangeTypeImpl<Node, R, AMDiS::PowerNodeTag, void>
87 {
88 using ChildNode = Dune::TypeTree::Child<Node,0>;
89
90 template <bool childIsLeaf, class ChildRangeType>
91 struct FlatType {
92 using type = Dune::FieldVector<ChildRangeType, int(Node::degree())>;
93 };
94
95 template <class T>
96 struct FlatType<true, Dune::FieldVector<T,1>> {
97 using type = Dune::FieldVector<T, int(Node::degree())>;
98 };
99
100 using type = typename FlatType<Dune::TypeTree::Concept::LeafTreeNode<ChildNode>, RangeType_t<ChildNode,R>>::type;
101 static type create(Node const& node)
102 {
103 return Dune::unpackIntegerSequence([&](auto... indices) {
104 return type{RangeType<ChildNode,R>::create(node.child(indices))...};
105 }, std::make_index_sequence<std::size_t(Node::degree())>());
106 }
107 };
108
109 // Power node
110 template <class Node, class R>
111 struct RangeTypeImpl<Node, R, AMDiS::DynamicPowerNodeTag, void>
112 {
113 using ChildNode = Dune::TypeTree::Child<Node,0>;
114
115 template <bool childIsLeaf, class ChildRangeType>
116 struct FlatType {
117 using type = Dune::DynamicVector<ChildRangeType>;
118 };
119
120 template <class T>
121 struct FlatType<true, Dune::FieldVector<T,1>> {
122 using type = Dune::DynamicVector<T>;
123 };
124
125 using type = typename FlatType<Dune::TypeTree::Concept::LeafTreeNode<ChildNode>, RangeType_t<ChildNode,R>>::type;
126 static type create(Node const& node)
127 {
128 type vector(node.degree());
129 for (std::size_t i = 0; i < std::size_t(node.degree()); ++i)
130 vector[i] = RangeType<ChildNode,R>::create(node.child(i));
131 return vector;
132 }
133 };
134
135 // Composite node
136 template <class Node, class R>
137 struct RangeTypeImpl<Node, R, AMDiS::CompositeNodeTag, void>
138 {
139 template <std::size_t J>
140 using ChildNode = Dune::TypeTree::Child<Node,J>;
141 template <std::size_t J>
142 using ChildRange = RangeType<ChildNode<J>,R>;
143
144 template <class Idx> struct RangeTypeGenerator;
145 template <std::size_t... I>
146 struct RangeTypeGenerator<Indices<I...>>
147 {
148 using type = Dune::TupleVector<typename ChildRange<I>::type...>;
149 };
150
151 using type = typename RangeTypeGenerator<std::make_index_sequence<std::size_t(Node::degree())>>::type;
152 static type create(Node const& node)
153 {
154 return Dune::unpackIntegerSequence([&](auto... indices) {
155 return type{ChildRange<decltype(indices)::value>::create(node.child(indices))...};
156 }, std::make_index_sequence<std::size_t(Node::degree())>());
157 }
158 };
159
160 } // end namespace Impl
161
162} // end namespace AMDiS