LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
Loading...
Searching...
No Matches
eigen_fusion_adapter.h
1
9
10#ifndef INCGa4e6283ee2844d93bc9772c830f33b2d
11#define INCGa4e6283ee2844d93bc9772c830f33b2d
12#include <lf/base/base.h>
13
14#include <Eigen/Eigen>
15#include <boost/fusion/include/adapt_struct.hpp>
16#include <boost/fusion/iterator.hpp>
17#include <boost/fusion/support/category_of.hpp>
18#include <boost/fusion/support/iterator_base.hpp>
19#include <boost/fusion/support/tag_of.hpp>
20#include <boost/fusion/support/tag_of_fwd.hpp>
21
22// BOOST Fusion Adaption for Eigen fixed size matrices:
24// The following allows us to use Eigen matrices directly with boost spirit to
25// read tuples of double values into fixed size eigen matrices (see
26// gmsh_reader.cpp for example usage)
27
29namespace Eigen {
30template <class MATRIX>
31struct FusionMatrixTag;
32
33template <class MATRIX>
34struct FusionIteratorTag;
35
36template <class STRUCT, int POS>
37struct FusionIterator
38 : boost::fusion::iterator_base<FusionIterator<STRUCT, POS>> {
39 static_assert(STRUCT::SizeAtCompileTime != Eigen::Dynamic,
40 "Dynamic matrices are not yet supported.");
41 static_assert(POS >= 0 & POS <= STRUCT::SizeAtCompileTime,
42 "POS has wrong value.");
43 using struct_type = STRUCT;
44 using index = boost::mpl::int_<POS>;
45 using category = boost::fusion::random_access_traversal_tag;
46
47 explicit FusionIterator(STRUCT& str) : struct_(str) {}
48 STRUCT& struct_; // NOLINT
49};
50} // namespace Eigen
51
52namespace boost::fusion::traits {
53template <class STRUCT, int POS>
54struct tag_of<Eigen::FusionIterator<STRUCT, POS>> {
55 using type = Eigen::FusionIteratorTag<STRUCT>;
56};
57
58template <class T, int ROWS, int COLS, int OPTIONS, int MAX_ROWS, int MAX_COLS>
59struct tag_of<Eigen::Matrix<T, ROWS, COLS, OPTIONS, MAX_ROWS, MAX_COLS>> {
60 using type = Eigen::FusionMatrixTag<
61 Eigen::Matrix<T, ROWS, COLS, OPTIONS, MAX_ROWS, MAX_COLS>>;
62};
63} // namespace boost::fusion::traits
64
65namespace boost::fusion::extension {
66template <class MATRIX>
67struct value_of_impl<Eigen::FusionIteratorTag<MATRIX>> {
68 template <class ITERATOR>
69 struct apply;
70 template <class STRUCT, int N>
71 struct apply<Eigen::FusionIterator<STRUCT, N>> {
72 using type = typename STRUCT::Scalar;
73 };
74};
75
76template <class MATRIX>
77struct deref_impl<Eigen::FusionIteratorTag<MATRIX>> {
78 template <class ITERATOR>
79 struct apply;
80
81 template <class STRUCT, int N>
82 struct apply<Eigen::FusionIterator<STRUCT, N>> {
83 using type =
84 typename mpl::if_<is_const<STRUCT>, const typename STRUCT::Scalar&,
85 typename STRUCT::Scalar&>::type;
86 static type call(Eigen::FusionIterator<STRUCT, N> const& it) {
87 return it.struct_(N);
88 }
89 };
90};
91
92template <class MATRIX>
93struct next_impl<Eigen::FusionIteratorTag<MATRIX>> {
94 template <class ITERATOR>
95 struct apply {
96 using struct_type = typename ITERATOR::struct_type;
97 using index = typename ITERATOR::index;
98 using type = Eigen::FusionIterator<struct_type, index::value + 1>;
99
100 static type call(ITERATOR const& i) { return type(i.struct_); }
101 };
102};
103
104template <class MATRIX>
105struct prior_impl<Eigen::FusionIteratorTag<MATRIX>> {
106 template <class ITERATOR>
107 struct apply {
108 using struct_type = typename ITERATOR::struct_type;
109 using index = typename ITERATOR::index;
110 using type = Eigen::FusionIterator<struct_type, index::value - 1>;
111
112 static type call(ITERATOR const& i) { return type(i.struct_); }
113 };
114};
115
116template <class MATRIX>
117struct advance_impl<Eigen::FusionIteratorTag<MATRIX>> {
118 template <class ITERATOR, class N>
119 struct apply {
120 using struct_type = typename ITERATOR::struct_type;
121 using index = typename ITERATOR::index;
122 using type = Eigen::FusionIterator<struct_type, index::value + N::value>;
123
124 static type call(ITERATOR const& i) { return type(i.struct_); }
125 };
126};
127
128template <class MATRIX>
129struct distance_impl<Eigen::FusionIteratorTag<MATRIX>> {
130 template <class FIRST, class LAST>
131 struct apply : mpl::minus<typename LAST::index, typename FIRST::index> {
132 using self = apply<FIRST, LAST>;
133
134 static typename self::type call(FIRST const& /*first*/,
135 LAST const& /*last*/) {
136 return typename self::type();
137 }
138 };
139};
140
141template <class MATRIX>
142struct equal_to_impl<Eigen::FusionIteratorTag<MATRIX>> {
143 template <class IT1, class IT2>
144 struct apply : mpl::equal_to<typename IT1::index, typename IT2::index> {};
145};
146
147template <class MATRIX>
148struct begin_impl<Eigen::FusionMatrixTag<MATRIX>> {
149 template <class SEQUENCE>
150 struct apply {
151 using type = Eigen::FusionIterator<SEQUENCE, 0>;
152
153 static type call(SEQUENCE& seq) { return type(seq); }
154 };
155};
156
157template <class MATRIX>
158struct end_impl<Eigen::FusionMatrixTag<MATRIX>> {
159 template <class SEQUENCE>
160 struct apply {
161 using type = Eigen::FusionIterator<SEQUENCE, MATRIX::SizeAtCompileTime>;
162 static type call(SEQUENCE& seq) { return type(seq); }
163 };
164};
165
166template <class MATRIX>
167struct at_impl<Eigen::FusionMatrixTag<MATRIX>> {
168 template <class SEQUENCE, class KEY>
169 struct apply;
170 template <class SEQUENCE, int N>
171 struct apply<SEQUENCE, mpl::int_<N>> {
172 using type =
173 typename mpl::if_<is_const<SEQUENCE>, const typename MATRIX::Scalar&,
174 typename MATRIX::Scalar&>::type;
175
176 static type call(SEQUENCE& seq) { return seq(N); }
177 };
178};
179
180template <class MATRIX>
181struct value_at_impl<Eigen::FusionMatrixTag<MATRIX>> {
182 template <typename Sequence, typename N>
183 struct apply;
184
185 template <class SEQUENCE, int N>
186 struct apply<SEQUENCE, mpl::int_<N>> {
187 using type = typename MATRIX::Scalar;
188 };
189};
190
191template <class MATRIX>
192struct size_impl<Eigen::FusionMatrixTag<MATRIX>> {
193 template <class SEQUENCE>
194 struct apply : mpl::int_<MATRIX::SizeAtCompileTime> {};
195};
196
197template <class MATRIX>
198struct category_of_impl<Eigen::FusionMatrixTag<MATRIX>> {
199 template <class SEQUENCE>
200 struct apply {
201 struct type : random_access_traversal_tag {};
202 };
203};
204
205template <class MATRIX>
206struct is_sequence_impl<Eigen::FusionMatrixTag<MATRIX>> {
207 template <class T>
208 struct apply : mpl::true_ {};
209};
210
211template <class MATRIX>
212struct is_view_impl<Eigen::FusionMatrixTag<MATRIX>> {
213 template <class SEQ>
214 struct apply : boost::mpl::false_ {};
215};
216} // namespace boost::fusion::extension
218#endif // INCGa4e6283ee2844d93bc9772c830f33b2d