LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
Loading...
Searching...
No Matches
mesh_function_unary.h
1
9#ifndef INCGb9b63bcccec548419a52fe0b06ffb3fc
10#define INCGb9b63bcccec548419a52fe0b06ffb3fc
11
12#include <lf/mesh/mesh.h>
13
14namespace lf::mesh::utils {
15
38template <class OP, class MF>
40 public:
41 MeshFunctionUnary(OP op, MF mf) : op_(std::move(op)), mf_(std::move(mf)) {}
42
43 auto operator()(const mesh::Entity& e, const Eigen::MatrixXd& local) const {
44 return op_(mf_(e, local), 0);
45 }
46
47 private:
48 OP op_;
49 MF mf_;
50};
51
52namespace internal {
53struct UnaryOpMinus {
54 // minus in front of a scalar type
55 template <class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
56 auto operator()(const std::vector<U>& u, int /*unused*/) const {
57 const Eigen::Map<const Eigen::Matrix<U, 1, Eigen::Dynamic>> um(u.data(), 1,
58 u.size());
59 std::vector<U> result(u.size());
60 Eigen::Map<Eigen::Matrix<U, 1, Eigen::Dynamic>> rm(result.data(), 1,
61 u.size());
62 rm = -um;
63 return result;
64 }
65
66 // minus in front of a Eigen::Matrix
67 template <class S, int R, int C, int O, int MR, int MC>
68 auto operator()(const std::vector<Eigen::Matrix<S, R, C, O, MR, MC>>& u,
69 int /*unused*/) const {
70 if constexpr (R == 0 || C == 0) { // NOLINT
71 // result vector is empty
72 return u;
73 }
74 if constexpr (R != Eigen::Dynamic && C != Eigen::Dynamic) {
75 // matrix size is known at compile time
76 const Eigen::Map<const Eigen::Matrix<S, 1, Eigen::Dynamic>> um(
77 &u[0](0, 0), 1, u.size() * R * C);
78 std::vector<Eigen::Matrix<S, R, C, O, MR, MC>> result(u.size());
79 Eigen::Map<Eigen::Matrix<S, 1, Eigen::Dynamic>> rm(&result[0](0, 0), 1,
80 u.size() * R * C);
81 rm = -um;
82 return result;
83 } else {
84 // matrix size is dynamic
85 std::vector<Eigen::Matrix<S, R, C, O, MR, MC>> result(u.size());
86 for (int i = 0; i < u.size(); ++i) {
87 result[i] = -u[i];
88 }
89 return result;
90 }
91 }
92
93 // minus in front of a Eigen::Array
94 template <class S, int R, int C, int O, int MR, int MC>
95 auto operator()(const std::vector<Eigen::Array<S, R, C, O, MR, MC>>& u,
96 int /*unused*/) const {
97 if constexpr (R == 0 || C == 0) {
98 // result array is empty
99 return u;
100 }
101 if constexpr (R != Eigen::Dynamic && C != Eigen::Dynamic) {
102 // array size is known at compile time
103 Eigen::Map<const Eigen::Array<S, 1, Eigen::Dynamic>> um(&u[0](0, 0), 1,
104 u.size() * R * C);
105 std::vector<Eigen::Array<S, R, C, O, MR, MC>> result(u.size());
106 Eigen::Map<Eigen::Array<S, 1, Eigen::Dynamic>> rm(&result[0](0, 0), 1,
107 u.size() * R * C);
108 rm = -um;
109 return result;
110 } else {
111 // array size is dynamic
112 std::vector<Eigen::Array<S, R, C, O, MR, MC>> result(u.size());
113 for (int i = 0; i < u.size(); ++i) {
114 result[i] = -u[i];
115 }
116 return result;
117 }
118 }
119
120 // minus in front of any object that supports the unary operator-
121 template <class T>
122 auto operator()(const std::vector<T>& u, long /*unused*/) const {
123 std::vector<T> result(u.size());
124 for (int i = 0; i < u.size(); ++i) {
125 result[i] = -u[i];
126 }
127 return result;
128 }
129};
130
131struct UnaryOpSquaredNorm {
132 // squared norm of a scalar type
133 template <class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
134 auto operator()(const std::vector<U>& u, int /*unused*/) const {
135 const Eigen::Map<const Eigen::Matrix<U, 1, Eigen::Dynamic>> um(u.data(), 1,
136 u.size());
137 std::vector<U> result(u.size());
138 Eigen::Map<Eigen::Matrix<U, 1, Eigen::Dynamic>> rm(result.data(), 1,
139 u.size());
140 rm = um.cwiseAbs2();
141 return result;
142 }
143
144 // squared norm of a eigen matrix
145 template <class S, int R, int C, int O, int MR, int MC>
146 auto operator()(const std::vector<Eigen::Matrix<S, R, C, O, MR, MC>>& u,
147 int /*unused*/) const {
148 std::vector<double> result(u.size());
149 if constexpr (R != Eigen::Dynamic && C != Eigen::Dynamic) { // NOLINT
150 static_assert(
151 R > 0 && C > 0,
152 "squaredNorm only supported for matrices with at least 1 row "
153 "and column");
154 if constexpr (C == 1) { // NOLINT
155 const Eigen::Map<const Eigen::Matrix<S, R, Eigen::Dynamic>> um(
156 &u[0](0, 0), R, u.size());
157 Eigen::Map<Eigen::Matrix<S, 1, Eigen::Dynamic>> rm(result.data(), 1,
158 u.size());
159 rm = um.cwiseAbs2().colwise().sum();
160 } else if constexpr (R == 1) { // NOLINT
161 Eigen::Map<const Eigen::Matrix<S, Eigen::Dynamic, C, Eigen::RowMajor>>
162 um(&u[0](0, 0), u.size(), C);
163 Eigen::Map<Eigen::Matrix<S, Eigen::Dynamic, 1>> rm(result.data(),
164 u.size(), 1);
165 rm = um.cwiseAbs2().rowwise().sum();
166 }
167 } else { // NOLINT
168 for (std::size_t i = 0; i < u.size(); ++i) {
169 result[i] = u[i].squaredNorm();
170 }
171 }
172 return result;
173 }
174};
175
176struct UnaryOpTranspose {
177 // transpose the eigen matrix
178 template <class S, int R, int C, int O, int MR, int MC>
179 auto operator()(const std::vector<Eigen::Matrix<S, R, C, O, MR, MC>>& u,
180 int /*unused*/) const {
181 std::vector<Eigen::Matrix<S, C, R>> result(u.size());
182 for (std::size_t i = 0; i < u.size(); ++i) {
183 result[i] = u[i].transpose();
184 }
185 return result;
186 }
187
188 // transpose the eigen array
189 template <class S, int R, int C, int O, int MR, int MC>
190 auto operator()(const std::vector<Eigen::Array<S, R, C, O, MR, MC>>& u,
191 int /*unused*/) const {
192 std::vector<Eigen::Array<S, C, R>> result(u.size());
193 for (std::size_t i = 0; i < u.size(); ++i) {
194 result[i] = u[i].transpose();
195 }
196 return result;
197 }
198};
199
200struct UnaryOpAdjoint {
201 // adjoint of eigen matrix
202 template <class S, int R, int C, int O, int MR, int MC>
203 auto operator()(const std::vector<Eigen::Matrix<S, R, C, O, MR, MC>>& u,
204 int /*unused*/) const {
205 std::vector<Eigen::Matrix<S, C, R>> result(u.size());
206 for (std::size_t i = 0; i < u.size(); ++i) {
207 result[i] = u[i].adjoint();
208 }
209 return result;
210 }
211};
212
213struct UnaryOpConjugate {
214 // conjugate of scalar type
215 template <base::Scalar U>
216 auto operator()(const std::vector<U>& u, int /*unused*/) const {
217 Eigen::Map<const Eigen::Matrix<U, 1, Eigen::Dynamic>> um(u.data(), 1,
218 u.size());
219 std::vector<U> result(u.size());
220 Eigen::Map<Eigen::Matrix<U, 1, Eigen::Dynamic>> rm(result.data(), 1,
221 u.size());
222 rm = um.conjugate();
223 return result;
224 }
225
226 // conjugate of eigen matrix
227 template <class S, int R, int C, int O, int MR, int MC>
228 auto operator()(const std::vector<Eigen::Matrix<S, R, C, O, MR, MC>>& u,
229 int /*unused*/) const {
230 std::vector<Eigen::Matrix<S, R, C>> result(u.size());
231 for (std::size_t i = 0; i < u.size(); ++i) {
232 result[i] = u[i].conjugate();
233 }
234 return result;
235 }
236
237 // conjugate of eigen array
238 template <class S, int R, int C, int O, int MR, int MC>
239 auto operator()(const std::vector<Eigen::Array<S, R, C, O, MR, MC>>& u,
240 int /*unused*/) const {
241 std::vector<Eigen::Array<S, R, C>> result(u.size());
242 for (std::size_t i = 0; i < u.size(); ++i) {
243 result[i] = u[i].conjugate();
244 }
245 return result;
246 }
247};
248
249} // namespace internal
250
262template <MeshFunction A>
264 return MeshFunctionUnary(internal::UnaryOpMinus{}, a);
265}
266
277template <MeshFunction A>
278auto squaredNorm(const A& a)
280 return MeshFunctionUnary(internal::UnaryOpSquaredNorm{}, a);
281}
282
290template <MeshFunction A>
294 "transpose() only supported for Eigen::Matrix and Eigen::Array "
295 "valued mesh functions");
296 return MeshFunctionUnary(internal::UnaryOpTranspose{}, a);
297}
298
307template <MeshFunction A>
309 using returnType_t = MeshFunctionReturnType<A>;
311 "adjoint only supported for Eigen::Matrix valued mesh "
312 "functions.");
313 return MeshFunctionUnary(internal::UnaryOpAdjoint{}, a);
314}
315
324template <MeshFunction A>
326 using returnType_t = MeshFunctionReturnType<A>;
327 static_assert(
330 "conjugate() supports only Eigen::Matrix, Eigen::Array or Scalar valued "
331 "mesh functions.");
332 return MeshFunctionUnary(internal::UnaryOpConjugate{}, a);
333}
334
335} // namespace lf::mesh::utils
336
337#endif // INCGb9b63bcccec548419a52fe0b06ffb3fc
Interface class representing a topological entity in a cellular complex
Definition entity.h:42
A mesh function representing another mesh function under a pointwise, unary operation.
auto operator-(const A &a) -> MeshFunctionUnary< internal::UnaryOpMinus, A >
Applies the unary minus operator to a mesh function.
auto operator()(const mesh::Entity &e, const Eigen::MatrixXd &local) const
auto squaredNorm(const A &a) -> MeshFunctionUnary< internal::UnaryOpSquaredNorm, A >
Pointwise squared norm of another mesh function.
auto transpose(const A &a) -> MeshFunctionUnary< internal::UnaryOpTranspose, A >
Pointwise transpose of an Eigen::Matrix or Eigen::Array
auto adjoint(const A &a) -> MeshFunctionUnary< internal::UnaryOpAdjoint, A >
Pointwise adjoint of an Eigen::Matrix, i.e. the conjugate transposed of the matrix.
auto conjugate(const A &a) -> MeshFunctionUnary< internal::UnaryOpConjugate, A >
Pointwise conjuagte of an Eigen::Matrix, Eigen::Array or scalar valued mesh function.
Check if a given type T is a Eigen::Array<...>&
Definition eigen_tools.h:86
Check if a given type T is an Eigen::Matrix.
Definition eigen_tools.h:70
Concept which is fulfilled if a type T is a scalar type, i.e. if it is a "field" in the mathematical ...
Contains helper functions and classes that all operate on the interface classes defined in lf::mesh.
internal::VectorElement_t< internal::MeshFunctionReturnType_t< R > > MeshFunctionReturnType
Determine the type of objects returned by a MeshFunction.