LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
Loading...
Searching...
No Matches
mesh_function_binary.h
1
9#ifndef INCG9bad469d38e04e8ab67391ce50c2c480
10#define INCG9bad469d38e04e8ab67391ce50c2c480
11
12#include <type_traits>
13#include <vector>
14
15#include "mesh_function_traits.h"
16
17namespace lf::mesh::utils {
18
50template <class OP, class A, class B>
52 public:
59 MeshFunctionBinary(OP op, A a, B b)
60 : op_(std::move(op)), a_(std::move(a)), b_(std::move(b)) {}
61
66 const Eigen::MatrixXd& local) const {
67 return op_(a_(e, local), b_(e, local), 0);
68 }
69
70 private:
71 OP op_;
72 A a_;
73 B b_;
74};
75
81namespace internal {
82
95struct OperatorAddition {
105 template <base::Scalar U, base::Scalar V>
106 auto operator()(const std::vector<U>& u, const std::vector<V>& v, int
107 /*unused*/) const {
108 const Eigen::Map<const Eigen::Matrix<U, 1, Eigen::Dynamic>> um(u.data(), 1,
109 u.size());
110 const Eigen::Map<const Eigen::Matrix<U, 1, Eigen::Dynamic>> vm(v.data(), 1,
111 v.size());
112 std::vector<decltype(U(0) + V(0))> result(u.size()); // NOLINT
113 // NOLINTNEXTLINE(google-readability-casting)
114 Eigen::Map<Eigen::Matrix<decltype(U(0) + V(0)), 1, Eigen::Dynamic>> rm(
115 result.data(), 1, u.size());
116 rm = um + vm;
117 return result;
118 }
119
123 template <class S1, int R1, int C1, int O1, int MR1, int MC1, class S2,
124 int R2, int C2, int O2, int MR2, int MC2>
125 auto operator()(const std::vector<Eigen::Matrix<S1, R1, C1, O1, MR1, MC1>>& u,
126 const std::vector<Eigen::Matrix<S2, R2, C2, O2, MR2, MC2>>& v,
127 int /*unused*/) const {
128 using scalar_t = decltype(S1(0) + S2(0));
129 if constexpr (R1 != Eigen::Dynamic && C1 != Eigen::Dynamic &&
130 R2 != Eigen::Dynamic && C2 != Eigen::Dynamic) { // NOLINT
131 // add two static size eigen matrices to each other
132 static_assert(R1 == R2, "cannot add matrices with different #rows.");
133 static_assert(C1 == C2, "cannot add matrices with different #cols.");
134
135 Eigen::Map<const Eigen::Matrix<S1, 1, Eigen::Dynamic>> um(
136 &u[0](0, 0), 1, u.size() * R1 * C1);
137 Eigen::Map<const Eigen::Matrix<S2, 1, Eigen::Dynamic>> vm(
138 &v[0](0, 0), 1, v.size() * R1 * C1);
139
140 std::vector<Eigen::Matrix<scalar_t, R1, C1>> result(u.size());
141 Eigen::Map<Eigen::Matrix<scalar_t, 1, Eigen::Dynamic>> rm(
142 &result[0](0, 0), 1, u.size() * R1 * C1);
143 rm = um + vm;
144 return result;
145 }
146 if constexpr ((R1 != Eigen::Dynamic && C1 != Eigen::Dynamic) ||
147 (R2 != Eigen::Dynamic && C2 != Eigen::Dynamic)) { // NOLINT
148 // One of the matrices is fixed size:
149 constexpr int fixedRows = std::max(R1, R2);
150 constexpr int fixedCols = std::max(C1, C2);
151
152 std::vector<Eigen::Matrix<scalar_t, fixedRows, fixedCols>> result(
153 u.size());
154 for (int i = 0; i < u.size(); ++i) {
155 LF_ASSERT_MSG(u[i].rows() == v[i].rows(),
156 "mismatch in #rows of matrices added to each other.");
157 LF_ASSERT_MSG(u[i].cols() == v[i].cols(),
158 "mismatch in #cols of matrices added to each other.");
159 result[i] = u[i] + v[i];
160 }
161 return result;
162 } else { // NOLINT
163 // add two dynamic sized matrices:
164 std::vector<Eigen::Matrix<scalar_t, Eigen::Dynamic, Eigen::Dynamic>>
165 result;
166 result.reserve(u.size());
167 for (int i = 0; i < u.size(); ++i) {
168 LF_ASSERT_MSG(u[i].rows() == v[i].rows(),
169 "mismatch in #rows of matrices added to each other.");
170 LF_ASSERT_MSG(u[i].cols() == v[i].cols(),
171 "mismatch in #cols of matrices added to each other.");
172 result.emplace_back(u[i] + v[i]);
173 }
174 return result;
175 }
176 }
177
181 template <class S1, int R1, int C1, int O1, int MR1, int MC1, class S2,
182 int R2, int C2, int O2, int MR2, int MC2>
183 auto operator()(const std::vector<Eigen::Array<S1, R1, C1, O1, MR1, MC1>>& u,
184 const std::vector<Eigen::Array<S2, R2, C2, O2, MR2, MC2>>& v,
185 int /*unused*/) const {
186 using scalar_t = decltype(S1(0) + S2(0));
187 if constexpr (R1 != Eigen::Dynamic && C1 != Eigen::Dynamic &&
188 R2 != Eigen::Dynamic && C2 != Eigen::Dynamic) { // NOLINT
189 // add two static size eigen arrays to each other
190 static_assert(R1 == R2, "cannot add arrays with different #rows.");
191 static_assert(C1 == C2, "cannot add arrays with different #cols.");
192
193 Eigen::Map<const Eigen::Array<S1, 1, Eigen::Dynamic>> um(
194 &u[0](0, 0), 1, u.size() * R1 * C1);
195 Eigen::Map<const Eigen::Array<S2, 1, Eigen::Dynamic>> vm(
196 &v[0](0, 0), 1, v.size() * R1 * C1);
197
198 std::vector<Eigen::Array<scalar_t, R1, C1>> result(u.size());
199 Eigen::Map<Eigen::Array<scalar_t, 1, Eigen::Dynamic>> rm(
200 &result[0](0, 0), 1, u.size() * R1 * C1);
201 rm = um + vm;
202 return result;
203 }
204 if constexpr ((R1 != Eigen::Dynamic && C1 != Eigen::Dynamic) ||
205 (R2 != Eigen::Dynamic && C2 != Eigen::Dynamic)) { // NOLINT
206 // One of the arrays is fixed size:
207 constexpr int fixedRows = std::max(R1, R2);
208 constexpr int fixedCols = std::max(C1, C2);
209
210 std::vector<Eigen::Array<scalar_t, fixedRows, fixedCols>> result(
211 u.size());
212 for (int i = 0; i < u.size(); ++i) {
213 LF_ASSERT_MSG(u[i].rows() == v[i].rows(),
214 "mismatch in #rows of arrays added to each other.");
215 LF_ASSERT_MSG(u[i].cols() == v[i].cols(),
216 "mismatch in #cols of arrays added to each other.");
217 result[i] = u[i] + v[i];
218 }
219 return result;
220 } else { // NOLINT
221 // add two dynamic sized arrays:
222 std::vector<Eigen::Array<scalar_t, Eigen::Dynamic, Eigen::Dynamic>>
223 result;
224 result.reserve(u.size());
225 for (int i = 0; i < u.size(); ++i) {
226 LF_ASSERT_MSG(u[i].rows() == v[i].rows(),
227 "mismatch in #rows of arrays added to each other.");
228 LF_ASSERT_MSG(u[i].cols() == v[i].cols(),
229 "mismatch in #cols of arrays added to each other.");
230 result.emplace_back(u[i] + v[i]);
231 }
232 return result;
233 }
234 }
235
239 template <class U, class V>
240 auto operator()(const std::vector<U>& u, const std::vector<V>& v,
241 long /*unused*/) const {
242 std::vector<decltype(u[0] + v[0])> result(u.size());
243 for (int i = 0; i < result.size(); ++i) {
244 result[i] = u[i] + v[i];
245 }
246 return result;
247 }
248};
249
262struct OperatorSubtraction {
273 template <base::Scalar U, base::Scalar V>
274 auto operator()(const std::vector<U>& u, const std::vector<V>& v, int
275 /*unused*/) const {
276 const Eigen::Map<const Eigen::Matrix<U, 1, Eigen::Dynamic>> um(u.data(), 1,
277 u.size());
278 const Eigen::Map<const Eigen::Matrix<U, 1, Eigen::Dynamic>> vm(v.data(), 1,
279 v.size());
280 std::vector<decltype(U(0) + V(0))> result(u.size()); // NOLINT
281 // NOLINTNEXTLINE(google-readability-casting)
282 Eigen::Map<Eigen::Matrix<decltype(U(0) + V(0)), 1, Eigen::Dynamic>> rm(
283 result.data(), 1, u.size());
284 rm = um - vm;
285 return result;
286 }
287
291 template <class S1, int R1, int C1, int O1, int MR1, int MC1, class S2,
292 int R2, int C2, int O2, int MR2, int MC2>
293 auto operator()(const std::vector<Eigen::Matrix<S1, R1, C1, O1, MR1, MC1>>& u,
294 const std::vector<Eigen::Matrix<S2, R2, C2, O2, MR2, MC2>>& v,
295 int /*unused*/) const {
296 using scalar_t = decltype(S1(0) + S2(0)); // NOLINT
297 if constexpr (R1 != Eigen::Dynamic && C1 != Eigen::Dynamic &&
298 R2 != Eigen::Dynamic && C2 != Eigen::Dynamic) { // NOLINT
299 // subtract two static size eigen matrices from each other
300 static_assert(R1 == R2, "cannot subtract matrices with different #rows.");
301 static_assert(C1 == C2, "cannot subtract matrices with different #cols.");
302
303 Eigen::Map<const Eigen::Matrix<S1, 1, Eigen::Dynamic>> um(
304 &u[0](0, 0), 1, u.size() * R1 * C1);
305 Eigen::Map<const Eigen::Matrix<S2, 1, Eigen::Dynamic>> vm(
306 &v[0](0, 0), 1, v.size() * R1 * C1);
307
308 std::vector<Eigen::Matrix<scalar_t, R1, C1>> result(u.size());
309 Eigen::Map<Eigen::Matrix<scalar_t, 1, Eigen::Dynamic>> rm(
310 &result[0](0, 0), 1, u.size() * R1 * C1);
311 rm = um - vm;
312 return result;
313 }
314 if constexpr ((R1 != Eigen::Dynamic && C1 != Eigen::Dynamic) ||
315 (R2 != Eigen::Dynamic && C2 != Eigen::Dynamic)) { // NOLINT
316 // One of the matrices is fixed size:
317 constexpr int fixedRows = std::max(R1, R2);
318 constexpr int fixedCols = std::max(C1, C2);
319
320 std::vector<Eigen::Matrix<scalar_t, fixedRows, fixedCols>> result(
321 u.size());
322 for (std::size_t i = 0; i < u.size(); ++i) {
323 LF_ASSERT_MSG(
324 u[i].rows() == v[i].rows(),
325 "mismatch in #rows of matrices subtracted from each other.");
326 LF_ASSERT_MSG(
327 u[i].cols() == v[i].cols(),
328 "mismatch in #cols of matrices subtracted from each other.");
329 result[i] = u[i] - v[i];
330 }
331 return result;
332 } else { // NOLINT
333 // subtract two dynamic sized matrices from each other:
334 std::vector<Eigen::Matrix<scalar_t, Eigen::Dynamic, Eigen::Dynamic>>
335 result;
336 result.reserve(u.size());
337 for (unsigned long i = 0; i < u.size(); ++i) {
338 LF_ASSERT_MSG(
339 u[i].rows() == v[i].rows(),
340 "mismatch in #rows of matrices subtracted from each other.");
341 LF_ASSERT_MSG(
342 u[i].cols() == v[i].cols(),
343 "mismatch in #cols of matrices subtracted from each other.");
344 result.emplace_back(u[i] - v[i]);
345 }
346 return result;
347 }
348 }
349
353 template <class S1, int R1, int C1, int O1, int MR1, int MC1, class S2,
354 int R2, int C2, int O2, int MR2, int MC2>
355 auto operator()(const std::vector<Eigen::Array<S1, R1, C1, O1, MR1, MC1>>& u,
356 const std::vector<Eigen::Array<S2, R2, C2, O2, MR2, MC2>>& v,
357 int /*unused*/) const {
358 using scalar_t = decltype(S1(0) - S2(0));
359 if constexpr (R1 != Eigen::Dynamic && C1 != Eigen::Dynamic &&
360 R2 != Eigen::Dynamic && C2 != Eigen::Dynamic) { // NOLINT
361 // subtract two static size eigen arrays to each other
362 static_assert(R1 == R2, "cannot subtract arrays with different #rows.");
363 static_assert(C1 == C2, "cannot subtract arrays with different #cols.");
364
365 Eigen::Map<const Eigen::Array<S1, 1, Eigen::Dynamic>> um(
366 &u[0](0, 0), 1, u.size() * R1 * C1);
367 Eigen::Map<const Eigen::Array<S2, 1, Eigen::Dynamic>> vm(
368 &v[0](0, 0), 1, v.size() * R1 * C1);
369
370 std::vector<Eigen::Array<scalar_t, R1, C1>> result(u.size());
371 Eigen::Map<Eigen::Array<scalar_t, 1, Eigen::Dynamic>> rm(
372 &result[0](0, 0), 1, u.size() * R1 * C1);
373 rm = um - vm;
374 return result;
375 }
376 if constexpr ((R1 != Eigen::Dynamic && C1 != Eigen::Dynamic) ||
377 (R2 != Eigen::Dynamic && C2 != Eigen::Dynamic)) { // NOLINT
378 // One of the arrays is fixed size:
379 constexpr int fixedRows = std::max(R1, R2);
380 constexpr int fixedCols = std::max(C1, C2);
381
382 std::vector<Eigen::Array<scalar_t, fixedRows, fixedCols>> result(
383 u.size());
384 for (int i = 0; i < u.size(); ++i) {
385 LF_ASSERT_MSG(
386 u[i].rows() == v[i].rows(),
387 "mismatch in #rows of arrays subtracted from each other.");
388 LF_ASSERT_MSG(
389 u[i].cols() == v[i].cols(),
390 "mismatch in #cols of arrays subtracted from each other.");
391 result[i] = u[i] - v[i];
392 }
393 return result;
394 } else { // NOLINT
395 // subtract two dynamic sized arrays:
396 std::vector<Eigen::Array<scalar_t, Eigen::Dynamic, Eigen::Dynamic>>
397 result;
398 result.reserve(u.size());
399 for (int i = 0; i < u.size(); ++i) {
400 LF_ASSERT_MSG(
401 u[i].rows() == v[i].rows(),
402 "mismatch in #rows of arrays subtracted from each other.");
403 LF_ASSERT_MSG(
404 u[i].cols() == v[i].cols(),
405 "mismatch in #cols of arrays subtracted from each other.");
406 result.emplace_back(u[i] - v[i]);
407 }
408 return result;
409 }
410 }
411
415 template <class U, class V>
416 auto operator()(const std::vector<U>& u, const std::vector<V>& v,
417 long /*unused*/) const {
418 std::vector<decltype(u[0] + v[0])> result(u.size(),
419 decltype(u[0] + v[0])());
420 for (int i = 0; i < result.size(); ++i) {
421 result[i] = u[i] - v[i];
422 }
423 return result;
424 }
425};
426
439struct OperatorMultiplication {
450 template <base::Scalar U, base::Scalar V>
451 auto operator()(const std::vector<U>& u, const std::vector<V>& v, int
452 /*unused*/) const {
453 Eigen::Map<const Eigen::Array<U, 1, Eigen::Dynamic>> um(u.data(), 1,
454 u.size());
455 Eigen::Map<const Eigen::Array<V, 1, Eigen::Dynamic>> vm(v.data(), 1,
456 v.size());
457 std::vector<decltype(U(0) * V(0))> result(u.size());
458 Eigen::Map<Eigen::Array<decltype(U(0) * V(0)), 1, Eigen::Dynamic>> rm(
459 result.data(), 1, u.size());
460 rm = um * vm;
461 return result;
462 }
463
464 // multiplication of fixed size eigen matrices
465 template <class S1, int R1, int C1, int O1, int MR1, int MC1, class S2,
466 int R2, int C2, int O2, int MR2, int MC2>
467 auto operator()(const std::vector<Eigen::Matrix<S1, R1, C1, O1, MR1, MC1>>& u,
468 const std::vector<Eigen::Matrix<S2, R2, C2, O2, MR2, MC2>>& v,
469 int /*unused*/) const {
470 using scalar_t = decltype(S1(0) * S2(0)); // NOLINT
471 if constexpr (R1 != Eigen::Dynamic && C2 != Eigen::Dynamic) { // NOLINT
472 // The result is fixed size
473 static_assert(C1 == Eigen::Dynamic || R2 == Eigen::Dynamic || C1 == R2,
474 "#cols of lhs doesn't match #rows of rhs");
475
476 std::vector<Eigen::Matrix<scalar_t, R1, C2>> result(u.size());
477 for (std::size_t i = 0; i < u.size(); ++i) {
478 LF_ASSERT_MSG(u[i].cols() == v[i].rows(),
479 "#cols of lhs doesn't match #rows of rhs");
480 result[i] = u[i] * v[i];
481 }
482 return result;
483 } else { // NOLINT
484 // multiply dynamic sized matrices
485 std::vector<Eigen::Matrix<scalar_t, Eigen::Dynamic, Eigen::Dynamic>>
486 result;
487 result.reserve(u.size());
488 for (int i = 0; i < u.size(); ++i) {
489 LF_ASSERT_MSG(u[i].cols() == v[i].rows(),
490 "#cols of lhs doesn't match #rows of rhs");
491 result.emplace_back(u[i] * v[i]);
492 }
493 return result;
494 }
495 }
496
500 template <class S1, int R1, int C1, int O1, int MR1, int MC1, class S2,
501 int R2, int C2, int O2, int MR2, int MC2>
502 auto operator()(const std::vector<Eigen::Array<S1, R1, C1, O1, MR1, MC1>>& u,
503 const std::vector<Eigen::Array<S2, R2, C2, O2, MR2, MC2>>& v,
504 int /*unused*/) const {
505 using scalar_t = decltype(S1(0) * S2(0));
506 if constexpr (R1 != Eigen::Dynamic && C1 != Eigen::Dynamic &&
507 R2 != Eigen::Dynamic && C2 != Eigen::Dynamic) { // NOLINT
508 // multiply two static size eigen arrays to each other
509 static_assert(R1 == R2, "cannot multiply arrays with different #rows.");
510 static_assert(C1 == C2, "cannot multiply arrays with different #cols.");
511
512 Eigen::Map<const Eigen::Array<S1, 1, Eigen::Dynamic>> um(
513 &u[0](0, 0), 1, u.size() * R1 * C1);
514 Eigen::Map<const Eigen::Array<S2, 1, Eigen::Dynamic>> vm(
515 &v[0](0, 0), 1, v.size() * R1 * C1);
516
517 std::vector<Eigen::Array<scalar_t, R1, C1>> result(u.size());
518 Eigen::Map<Eigen::Array<scalar_t, 1, Eigen::Dynamic>> rm(
519 &result[0](0, 0), 1, u.size() * R1 * C1);
520 rm = um * vm;
521 return result;
522 }
523 if constexpr ((R1 != Eigen::Dynamic && C1 != Eigen::Dynamic) ||
524 (R2 != Eigen::Dynamic && C2 != Eigen::Dynamic)) { // NOLINT
525 // One of the arrays is fixed size:
526 constexpr int fixedRows = std::max(R1, R2);
527 constexpr int fixedCols = std::max(C1, C2);
528
529 std::vector<Eigen::Array<scalar_t, fixedRows, fixedCols>> result(
530 u.size());
531 for (int i = 0; i < u.size(); ++i) {
532 LF_ASSERT_MSG(
533 u[i].rows() == v[i].rows(),
534 "mismatch in #rows of arrays multiplied with each other.");
535 LF_ASSERT_MSG(
536 u[i].cols() == v[i].cols(),
537 "mismatch in #cols of arrays multiplied with each other.");
538 result[i] = u[i] * v[i];
539 }
540 return result;
541 } else { // NOLINT
542 // multiply two dynamic sized arrays:
543 std::vector<Eigen::Array<scalar_t, Eigen::Dynamic, Eigen::Dynamic>>
544 result;
545 result.reserve(u.size());
546 for (int i = 0; i < u.size(); ++i) {
547 LF_ASSERT_MSG(
548 u[i].rows() == v[i].rows(),
549 "mismatch in #rows of arrays multiplied with each other.");
550 LF_ASSERT_MSG(
551 u[i].cols() == v[i].cols(),
552 "mismatch in #cols of arrays multiplied with each other.");
553 result.emplace_back(u[i] * v[i]);
554 }
555 return result;
556 }
557 }
558
559 // multiplication of a scalar with matrix
560 template <base::Scalar U, class S1, int R1, int C1, int O1, int MR1, int MC1>
561 auto operator()(const std::vector<U>& u,
562 const std::vector<Eigen::Matrix<S1, R1, C1, O1, MR1, MC1>>& v,
563 int /*unused*/) const {
564 using scalar_t = decltype(u[0] * v[0](0, 0));
565 std::vector<Eigen::Matrix<scalar_t, R1, C1>> result(u.size());
566 if constexpr (R1 != Eigen::Dynamic && C1 != Eigen::Dynamic) { // NOLINT
567 // result is a static sized matrix:
568 Eigen::Map<const Eigen::Array<S1, R1 * C1, Eigen::Dynamic>> vm(
569 v[0].data(), R1 * C1, v.size());
570 Eigen::Map<Eigen::Array<scalar_t, R1 * C1, Eigen::Dynamic>> rm(
571 result[0].data(), R1 * C1, v.size());
572 Eigen::Map<const Eigen::Array<U, 1, Eigen::Dynamic>> um(u.data(), 1,
573 u.size());
574
575 rm = vm * um.template replicate<R1 * C1, 1>();
576 } else { // NOLINT
577 // result is not static sized:
578 for (std::size_t i = 0; i < u.size(); ++i) {
579 result[i] = u[i] * v[i];
580 }
581 }
582 return result;
583 }
584
585 // multiplication of matrix with scalar (other way around)
586 template <base::Scalar U, class S1, int R1, int C1, int O1, int MR1, int MC1>
587 auto operator()(const std::vector<Eigen::Matrix<S1, R1, C1, O1, MR1, MC1>>& v,
588 const std::vector<U>& u, int /*unused*/) const {
589 return operator()(u, v, 0);
590 }
591
592 // multiplication of a scalar with array
593 template <base::Scalar U, class S1, int R1, int C1, int O1, int MR1, int MC1>
594 auto operator()(const std::vector<U>& u,
595 const std::vector<Eigen::Array<S1, R1, C1, O1, MR1, MC1>>& v,
596 int /*unused*/) const {
597 using scalar_t = decltype(u[0] * v[0](0, 0));
598 std::vector<Eigen::Array<scalar_t, R1, C1>> result(u.size());
599 if constexpr (R1 != Eigen::Dynamic && C1 != Eigen::Dynamic) {
600 // result is a static sized array:
601 Eigen::Map<const Eigen::Array<S1, R1 * C1, Eigen::Dynamic>> vm(
602 v[0].data(), R1 * C1, v.size());
603 Eigen::Map<Eigen::Array<scalar_t, R1 * C1, Eigen::Dynamic>> rm(
604 result[0].data(), R1 * C1, v.size());
605 Eigen::Map<const Eigen::Array<U, 1, Eigen::Dynamic>> um(u.data(), 1,
606 u.size());
607
608 rm = vm * um.template replicate<R1 * C1, 1>();
609 } else {
610 // result is not static sized:
611 for (std::size_t i = 0; i < u.size(); ++i) {
612 result[i] = u[i] * v[i];
613 }
614 }
615 return result;
616 }
617
618 // multiplication of array with scalar (other way around)
619 template <base::Scalar U, class S1, int R1, int C1, int O1, int MR1, int MC1>
620 auto operator()(const std::vector<Eigen::Array<S1, R1, C1, O1, MR1, MC1>>& v,
621 const std::vector<U>& u, int /*unused*/) const {
622 return operator()(u, v, 0);
623 }
624
625 // multiplication of arbitrary types supporting operator*:
626 template <class U, class V>
627 auto operator()(const std::vector<U>& u, const std::vector<V>& v,
628 long /*unused*/) const {
629 std::vector<decltype(u[0] * v[0])> result;
630 result.reserve(u.size());
631 for (int i = 0; i < result.size(); ++i) {
632 result.emplace_back(u[i] * v[i]);
633 }
634 return result;
635 }
636};
637
638} // namespace internal
639
663template <MeshFunction A, MeshFunction B>
664auto operator+(const A& a, const B& b)
666 return MeshFunctionBinary(internal::OperatorAddition{}, a, b);
667}
668
692template <MeshFunction A, MeshFunction B>
693auto operator-(const A& a, const B& b)
695 return MeshFunctionBinary(internal::OperatorSubtraction{}, a, b);
696}
697
721template <MeshFunction A, MeshFunction B>
722auto operator*(const A& a, const B& b)
724 return MeshFunctionBinary(internal::OperatorMultiplication{}, a, b);
725}
726
727} // namespace lf::mesh::utils
728
729#endif // INCG9bad469d38e04e8ab67391ce50c2c480
Interface class representing a topological entity in a cellular complex
Definition entity.h:42
A MeshFunction which combines two other mesh functions using a binary operator (advanced use).
MeshFunctionBinary(OP op, A a, B b)
Create a new MeshFunctionBinary.
auto operator*(const A &a, const B &b) -> MeshFunctionBinary< internal::OperatorMultiplication, A, B >
Multiply two mesh functions with each other.
auto operator-(const A &a, const B &b) -> MeshFunctionBinary< internal::OperatorSubtraction, A, B >
Subtracts two mesh functions.
auto operator()(const lf::mesh::Entity &e, const Eigen::MatrixXd &local) const
auto operator+(const A &a, const B &b) -> MeshFunctionBinary< internal::OperatorAddition, A, B >
Add's two mesh functions.
Contains helper functions and classes that all operate on the interface classes defined in lf::mesh.