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