PolyDEAL
 
Loading...
Searching...
No Matches
linear_operator_for_mg.h
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 2015 - 2023 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_linear_operator_for_mg_h
16#define dealii_linear_operator_for_mg_h
17
18#include <deal.II/base/config.h>
19
21
23
24#include <array>
25#include <functional>
26#include <type_traits>
27
29
30// Forward declarations:
31#ifndef DOXYGEN
32namespace internal
33{
34 namespace LinearOperatorMGImplementation
35 {
36 class EmptyPayload;
37 }
38} // namespace internal
39
40template <typename Number>
41class Vector;
42
44
45template <typename Range = Vector<double>,
46 typename Domain = Range,
47 typename Payload =
48 internal::LinearOperatorMGImplementation::EmptyPayload>
50#endif
51
52template <
53 typename Range = Vector<double>,
54 typename Domain = Range,
56 typename OperatorExemplar,
57 typename Matrix>
59linear_operator_mg(const OperatorExemplar &, const Matrix &);
60
61template <
62 typename Range = Vector<double>,
63 typename Domain = Range,
65 typename Matrix>
67linear_operator_mg(const Matrix &);
68
69template <
70 typename Range = Vector<double>,
71 typename Domain = Range,
75
76template <typename Range, typename Domain, typename Payload>
79
80
200template <typename Range, typename Domain, typename Payload>
201class LinearOperatorMG : public Payload, public Subscriptor
202{
203public:
212 LinearOperatorMG(const Payload &payload = Payload())
213 : Payload(payload)
214 , is_null_operator(false)
215 {
216 vmult = [](Range &, const Domain &) {
217 Assert(false,
218 ExcMessage("Uninitialized LinearOperatorMG<Range, "
219 "Domain>::vmult called"));
220 };
221
222 vmult_add = [](Range &, const Domain &) {
223 Assert(false,
224 ExcMessage("Uninitialized LinearOperatorMG<Range, "
225 "Domain>::vmult_add called"));
226 };
227
228 Tvmult = [](Domain &, const Range &) {
229 Assert(false,
230 ExcMessage("Uninitialized LinearOperatorMG<Range, "
231 "Domain>::Tvmult called"));
232 };
233
234 Tvmult_add = [](Domain &, const Range &) {
235 Assert(false,
236 ExcMessage("Uninitialized LinearOperatorMG<Range, "
237 "Domain>::Tvmult_add called"));
238 };
239
240 reinit_range_vector = [](Range &, bool) {
241 Assert(false,
242 ExcMessage("Uninitialized LinearOperatorMG<Range, "
243 "Domain>::reinit_range_vector method called"));
244 };
245
246 reinit_domain_vector = [](Domain &, bool) {
247 Assert(false,
248 ExcMessage("Uninitialized LinearOperatorMG<Range, "
249 "Domain>::reinit_domain_vector method called"));
250 };
251 }
252
257
263 template <typename Op,
264 typename = std::enable_if_t<
265 !std::is_base_of_v<LinearOperatorMG<Range, Domain, Payload>, Op>>>
266 LinearOperatorMG(const Op &op)
267 {
268 *this = linear_operator_mg<Range, Domain, Payload, Op>(op);
269 }
270
276
281 template <typename Op,
282 typename = std::enable_if_t<
283 !std::is_base_of_v<LinearOperatorMG<Range, Domain, Payload>, Op>>>
285 operator=(const Op &op)
286 {
287 *this = linear_operator_mg<Range, Domain, Payload, Op>(op);
288 return *this;
289 }
290
295 std::function<void(Range &v, const Domain &u)> vmult;
296
301 std::function<void(Range &v, const Domain &u)> vmult_add;
302
307 std::function<void(Domain &v, const Range &u)> Tvmult;
308
313 std::function<void(Domain &v, const Range &u)> Tvmult_add;
314
322 std::function<void(Range &v, bool omit_zeroing_entries)> reinit_range_vector;
323
331 std::function<void(Domain &v, bool omit_zeroing_entries)>
333
337 std::function<typename Domain::value_type(const types::global_dof_index i,
340
345 m() const
346 {
347 return n_rows;
348 }
349
354 n() const
355 {
356 return n_cols;
357 }
358
370 {
371 *this = *this + second_op;
372 return *this;
373 }
374
381 {
382 *this = *this - second_op;
383 return *this;
384 }
385
392 {
393 *this = *this * second_op;
394 return *this;
395 }
396
402 operator*=(typename Domain::value_type number)
403 {
404 *this = *this * number;
405 return *this;
406 }
407
414
416
418
420};
421
422
437template <typename Range, typename Domain, typename Payload>
441{
442 if (first_op.is_null_operator)
443 {
444 return second_op;
445 }
446 else if (second_op.is_null_operator)
447 {
448 return first_op;
449 }
450 else
451 {
453 static_cast<const Payload &>(first_op) +
454 static_cast<const Payload &>(second_op)};
455
456 return_op.reinit_range_vector = first_op.reinit_range_vector;
457 return_op.reinit_domain_vector = first_op.reinit_domain_vector;
458
459 // ensure to have valid computation objects by catching first_op and
460 // second_op by value
461
462 return_op.vmult = [first_op, second_op](Range &v, const Domain &u) {
463 first_op.vmult(v, u);
464 second_op.vmult_add(v, u);
465 };
466
467 return_op.vmult_add = [first_op, second_op](Range &v, const Domain &u) {
468 first_op.vmult_add(v, u);
469 second_op.vmult_add(v, u);
470 };
471
472 return_op.Tvmult = [first_op, second_op](Domain &v, const Range &u) {
473 second_op.Tvmult(v, u);
474 first_op.Tvmult_add(v, u);
475 };
476
477 return_op.Tvmult_add = [first_op, second_op](Domain &v, const Range &u) {
478 second_op.Tvmult_add(v, u);
479 first_op.Tvmult_add(v, u);
480 };
481
482 return return_op;
483 }
484}
485
486
496template <typename Range, typename Domain, typename Payload>
500{
501 if (first_op.is_null_operator)
502 {
503 return -1. * second_op;
504 }
505 else if (second_op.is_null_operator)
506 {
507 return first_op;
508 }
509 else
510 {
511 // implement with addition and scalar multiplication
512 return first_op + (-1. * second_op);
513 }
514}
515
516
534template <typename Range, typename Domain, typename Payload>
536operator*(typename Range::value_type number,
538{
539 static_assert(
540 std::is_convertible<typename Range::value_type,
541 typename Domain::value_type>::value,
542 "Range and Domain must have implicitly convertible 'value_type's");
543
544 if (op.is_null_operator)
545 {
546 return op;
547 }
548 else if (number == 0.)
549 {
550 return null_operator(op);
551 }
552 else
553 {
555
556 // ensure to have valid computation objects by catching number and op by
557 // value
558
559 return_op.vmult = [number, op](Range &v, const Domain &u) {
560 op.vmult(v, u);
561 v *= number;
562 };
563
564 return_op.vmult_add = [number, op](Range &v, const Domain &u) {
565 v /= number;
566 op.vmult_add(v, u);
567 v *= number;
568 };
569
570 return_op.Tvmult = [number, op](Domain &v, const Range &u) {
571 op.Tvmult(v, u);
572 v *= number;
573 };
574
575 return_op.Tvmult_add = [number, op](Domain &v, const Range &u) {
576 v /= number;
577 op.Tvmult_add(v, u);
578 v *= number;
579 };
580
581 return return_op;
582 }
583}
584
585
601template <typename Range, typename Domain, typename Payload>
604 typename Domain::value_type number)
605{
606 static_assert(
607 std::is_convertible<typename Range::value_type,
608 typename Domain::value_type>::value,
609 "Range and Domain must have implicitly convertible 'value_type's");
610
611 return number * op;
612}
613
631template <typename Range,
632 typename Intermediate,
633 typename Domain,
634 typename Payload>
638{
639 if (first_op.is_null_operator || second_op.is_null_operator)
640 {
642 return_op.reinit_domain_vector = second_op.reinit_domain_vector;
643 return_op.reinit_range_vector = first_op.reinit_range_vector;
644 return null_operator(return_op);
645 }
646 else
647 {
649 static_cast<const Payload &>(first_op) *
650 static_cast<const Payload &>(second_op)};
651
652 return_op.reinit_domain_vector = second_op.reinit_domain_vector;
653 return_op.reinit_range_vector = first_op.reinit_range_vector;
654
655 // ensure to have valid computation objects by catching first_op and
656 // second_op by value
657
658 return_op.vmult = [first_op, second_op](Range &v, const Domain &u) {
660
661 typename VectorMemory<Intermediate>::Pointer i(vector_memory);
662 second_op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
663 second_op.vmult(*i, u);
664 first_op.vmult(v, *i);
665 };
666
667 return_op.vmult_add = [first_op, second_op](Range &v, const Domain &u) {
669
670 typename VectorMemory<Intermediate>::Pointer i(vector_memory);
671 second_op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
672 second_op.vmult(*i, u);
673 first_op.vmult_add(v, *i);
674 };
675
676 return_op.Tvmult = [first_op, second_op](Domain &v, const Range &u) {
678
679 typename VectorMemory<Intermediate>::Pointer i(vector_memory);
680 first_op.reinit_domain_vector(*i, /*bool omit_zeroing_entries =*/true);
681 first_op.Tvmult(*i, u);
682 second_op.Tvmult(v, *i);
683 };
684
685 return_op.Tvmult_add = [first_op, second_op](Domain &v, const Range &u) {
687
688 typename VectorMemory<Intermediate>::Pointer i(vector_memory);
689 first_op.reinit_domain_vector(*i, /*bool omit_zeroing_entries =*/true);
690 first_op.Tvmult(*i, u);
691 second_op.Tvmult_add(v, *i);
692 };
693
694 return return_op;
695 }
696}
697
698
707template <typename Range, typename Domain, typename Payload>
710{
711 LinearOperatorMG<Domain, Range, Payload> return_op{op.transpose_payload()};
712
715
716 return_op.vmult = op.Tvmult;
717 return_op.vmult_add = op.Tvmult_add;
718 return_op.Tvmult = op.vmult;
719 return_op.Tvmult_add = op.vmult_add;
720
721 return return_op;
722}
723
724
744template <typename Payload,
745 typename Solver,
746 typename Preconditioner,
747 typename Range = typename Solver::vector_type,
748 typename Domain = Range>
751 Solver &solver,
752 const Preconditioner &preconditioner)
753{
755 op.inverse_payload(solver, preconditioner)};
756
759
760 return_op.vmult = [op, &solver, &preconditioner](Range &v, const Domain &u) {
761 op.reinit_range_vector(v, /*bool omit_zeroing_entries =*/false);
762 solver.solve(op, v, u, preconditioner);
763 };
764
765 return_op.vmult_add = [op, &solver, &preconditioner](Range &v,
766 const Domain &u) {
767 GrowingVectorMemory<Range> vector_memory;
768
769 typename VectorMemory<Range>::Pointer v2(vector_memory);
770 op.reinit_range_vector(*v2, /*bool omit_zeroing_entries =*/false);
771 solver.solve(op, *v2, u, preconditioner);
772 v += *v2;
773 };
774
775 return_op.Tvmult = [op, &solver, &preconditioner](Range &v, const Domain &u) {
776 op.reinit_range_vector(v, /*bool omit_zeroing_entries =*/false);
777 solver.solve(transpose_operator(op), v, u, preconditioner);
778 };
779
780 return_op.Tvmult_add = [op, &solver, &preconditioner](Range &v,
781 const Domain &u) {
782 GrowingVectorMemory<Range> vector_memory;
783
784 typename VectorMemory<Range>::Pointer v2(vector_memory);
785 op.reinit_range_vector(*v2, /*bool omit_zeroing_entries =*/false);
786 solver.solve(transpose_operator(op), *v2, u, preconditioner);
787 v += *v2;
788 };
789
790 return return_op;
791}
792
793
802template <typename Payload,
803 typename Solver,
804 typename Range = typename Solver::vector_type,
805 typename Domain = Range>
808 Solver &solver,
809 const LinearOperatorMG<Range, Domain, Payload> &preconditioner)
810{
812 op.inverse_payload(solver, preconditioner)};
813
816
817 return_op.vmult = [op, &solver, preconditioner](Range &v, const Domain &u) {
818 op.reinit_range_vector(v, /*bool omit_zeroing_entries =*/false);
819 solver.solve(op, v, u, preconditioner);
820 };
821
822 return_op.vmult_add = [op, &solver, preconditioner](Range &v,
823 const Domain &u) {
824 GrowingVectorMemory<Range> vector_memory;
825
826 typename VectorMemory<Range>::Pointer v2(vector_memory);
827 op.reinit_range_vector(*v2, /*bool omit_zeroing_entries =*/false);
828 solver.solve(op, *v2, u, preconditioner);
829 v += *v2;
830 };
831
832 return_op.Tvmult = [op, &solver, preconditioner](Range &v, const Domain &u) {
833 op.reinit_range_vector(v, /*bool omit_zeroing_entries =*/false);
834 solver.solve(transpose_operator(op), v, u, preconditioner);
835 };
836
837 return_op.Tvmult_add = [op, &solver, preconditioner](Range &v,
838 const Domain &u) {
839 GrowingVectorMemory<Range> vector_memory;
840
841 typename VectorMemory<Range>::Pointer v2(vector_memory);
842 op.reinit_range_vector(*v2, /*bool omit_zeroing_entries =*/false);
843 solver.solve(transpose_operator(op), *v2, u, preconditioner);
844 v += *v2;
845 };
846
847 return return_op;
848}
849
850
860template <typename Payload,
861 typename Solver,
862 typename Range = typename Solver::vector_type,
863 typename Domain = Range>
866 Solver &solver)
867{
868 return inverse_operator(op, solver, identity_operator(op));
869}
870
871
880template <typename Payload,
881 typename Solver,
882 typename Range = typename Solver::vector_type,
883 typename Domain = Range>
886 Solver &solver,
887 const PreconditionIdentity &)
888{
889 return inverse_operator(op, solver);
890}
891
911template <
912 typename Range,
915identity_operator(const std::function<void(Range &, bool)> &reinit_vector)
916{
917 LinearOperatorMG<Range, Range, Payload> return_op{Payload()};
918
919 return_op.reinit_range_vector = reinit_vector;
920 return_op.reinit_domain_vector = reinit_vector;
921
922 return_op.vmult = [](Range &v, const Range &u) { v = u; };
923
924 return_op.vmult_add = [](Range &v, const Range &u) { v += u; };
925
926 return_op.Tvmult = [](Range &v, const Range &u) { v = u; };
927
928 return_op.Tvmult_add = [](Range &v, const Range &u) { v += u; };
929
930 return return_op;
931}
932
933
946template <typename Range, typename Domain, typename Payload>
949{
950 auto return_op = identity_operator<Range, Payload>(op.reinit_range_vector);
951 static_cast<Payload &>(return_op) = op.identity_payload();
952
953 return return_op;
954}
955
956
966template <typename Range, typename Domain, typename Payload>
969{
970 LinearOperatorMG<Range, Domain, Payload> return_op{op.null_payload()};
971
972 return_op.is_null_operator = true;
973
976
977 return_op.vmult = [](Range &v, const Domain &) { v = 0.; };
978
979 return_op.vmult_add = [](Range &, const Domain &) {};
980
981 return_op.Tvmult = [](Domain &v, const Range &) { v = 0.; };
982
983 return_op.Tvmult_add = [](Domain &, const Range &) {};
984
985 return return_op;
986}
987
988
1001template <
1002 typename Range,
1005mean_value_filter(const std::function<void(Range &, bool)> &reinit_vector)
1006{
1007 LinearOperatorMG<Range, Range, Payload> return_op{Payload()};
1008
1009 return_op.reinit_range_vector = reinit_vector;
1010 return_op.reinit_domain_vector = reinit_vector;
1011
1012 return_op.vmult = [](Range &v, const Range &u) {
1013 const auto mean = u.mean_value();
1014
1015 v = u;
1016 v.add(-mean);
1017 };
1018
1019 return_op.vmult_add = [](Range &v, const Range &u) {
1020 const auto mean = u.mean_value();
1021
1022 v += u;
1023 v.add(-mean);
1024 };
1025
1026 return_op.Tvmult = return_op.vmult_add;
1027 return_op.Tvmult_add = return_op.vmult_add;
1028
1029 return return_op;
1030}
1031
1032
1045template <typename Range, typename Domain, typename Payload>
1048{
1049 auto return_op = mean_value_filter<Range, Payload>(op.reinit_range_vector);
1050 static_cast<Payload &>(return_op) = op.identity_payload();
1051
1052 return return_op;
1053}
1054
1055
1056namespace internal
1057{
1058 namespace LinearOperatorMGImplementation
1059 {
1071 template <typename Vector>
1073 {
1074 public:
1086 template <typename Matrix>
1087 static void
1088 reinit_range_vector(const Matrix &matrix,
1089 Vector &v,
1090 bool omit_zeroing_entries)
1091 {
1092 v.reinit(matrix.m(), omit_zeroing_entries);
1093 }
1094
1106 template <typename Matrix>
1107 static void
1108 reinit_domain_vector(const Matrix &matrix,
1109 Vector &v,
1110 bool omit_zeroing_entries)
1111 {
1112 v.reinit(matrix.n(), omit_zeroing_entries);
1113 }
1114 };
1115
1116
1129 {
1130 public:
1138 template <typename... Args>
1139 EmptyPayload(const Args &...)
1140 {}
1141
1142
1148 {
1149 return *this;
1150 }
1151
1152
1158 {
1159 return *this;
1160 }
1161
1162
1168 {
1169 return *this;
1170 }
1171
1172
1176 template <typename Solver, typename Preconditioner>
1178 inverse_payload(Solver &, const Preconditioner &) const
1179 {
1180 return *this;
1181 }
1182 };
1183
1188 inline EmptyPayload
1190 {
1191 return {};
1192 }
1193
1198 inline EmptyPayload
1200 {
1201 return {};
1202 }
1203
1204
1205
1206 // A trait class that determines whether type T provides public
1207 // (templated or non-templated) vmult_add member functions
1208 template <typename Range, typename Domain, typename T>
1210 {
1211 template <typename C>
1212 static std::false_type
1213 test(...);
1214
1215 template <typename C>
1216 static auto
1217 test(Range *r, Domain *d)
1218 -> decltype(std::declval<C>().vmult_add(*r, *d),
1219 std::declval<C>().Tvmult_add(*d, *r),
1220 std::true_type());
1221
1222 public:
1223 // type is std::true_type if Matrix provides vmult_add and Tvmult_add,
1224 // otherwise it is std::false_type
1225
1226 using type = decltype(test<T>(nullptr, nullptr));
1227 };
1228
1229
1230 // A helper function to apply a given vmult, or Tvmult to a vector with
1231 // intermediate storage
1232 template <typename Function, typename Range, typename Domain>
1233 void
1235 Range &v,
1236 const Domain &u,
1237 bool add)
1238 {
1239 GrowingVectorMemory<Range> vector_memory;
1240
1241 typename VectorMemory<Range>::Pointer i(vector_memory);
1242 i->reinit(v, /*bool omit_zeroing_entries =*/true);
1243
1244 function(*i, u);
1245
1246 if (add)
1247 v += *i;
1248 else
1249 v = *i;
1250 }
1251
1252
1253 // A helper class to add a reduced matrix interface to a LinearOperatorMG
1254 // (typically provided by Preconditioner classes)
1255 template <typename Range, typename Domain, typename Payload>
1257 {
1258 public:
1259 template <typename Matrix>
1260 void
1262 const Matrix &matrix)
1263 {
1264 op.vmult = [&matrix](Range &v, const Domain &u) {
1265 if (PointerComparison::equal(&v, &u))
1266 {
1267 // If v and u are the same memory location use intermediate
1268 // storage
1270 [&matrix](Range &b, const Domain &a) { matrix.vmult(b, a); },
1271 v,
1272 u,
1273 /*bool add =*/false);
1274 }
1275 else
1276 {
1277 matrix.vmult(v, u);
1278 }
1279 };
1280
1281 op.vmult_add = [&matrix](Range &v, const Domain &u) {
1282 // use intermediate storage to implement vmult_add with vmult
1284 [&matrix](Range &b, const Domain &a) { matrix.vmult(b, a); },
1285 v,
1286 u,
1287 /*bool add =*/true);
1288 };
1289
1290 op.Tvmult = [&matrix](Domain &v, const Range &u) {
1291 if (PointerComparison::equal(&v, &u))
1292 {
1293 // If v and u are the same memory location use intermediate
1294 // storage
1296 [&matrix](Domain &b, const Range &a) { matrix.Tvmult(b, a); },
1297 v,
1298 u,
1299 /*bool add =*/false);
1300 }
1301 else
1302 {
1303 matrix.Tvmult(v, u);
1304 }
1305 };
1306
1307 op.Tvmult_add = [&matrix](Domain &v, const Range &u) {
1308 // use intermediate storage to implement Tvmult_add with Tvmult
1310 [&matrix](Domain &b, const Range &a) { matrix.Tvmult(b, a); },
1311 v,
1312 u,
1313 /*bool add =*/true);
1314 };
1315 }
1316 };
1317
1318
1319 // A helper class to add the full matrix interface to a LinearOperatorMG
1320 template <typename Range, typename Domain, typename Payload>
1322 {
1323 public:
1324 template <typename Matrix>
1325 void
1327 const Matrix &matrix)
1328 {
1329 // As above ...
1330
1332 op, matrix);
1333
1334 // ... but add native vmult_add and Tvmult_add variants:
1335
1336 op.vmult_add = [&matrix](Range &v, const Domain &u) {
1337 if (PointerComparison::equal(&v, &u))
1338 {
1340 [&matrix](Range &b, const Domain &a) { matrix.vmult(b, a); },
1341 v,
1342 u,
1343 /*bool add =*/true);
1344 }
1345 else
1346 {
1347 matrix.vmult_add(v, u);
1348 }
1349 };
1350
1351 op.Tvmult_add = [&matrix](Domain &v, const Range &u) {
1352 if (PointerComparison::equal(&v, &u))
1353 {
1355 [&matrix](Domain &b, const Range &a) { matrix.Tvmult(b, a); },
1356 v,
1357 u,
1358 /*bool add =*/true);
1359 }
1360 else
1361 {
1362 matrix.Tvmult_add(v, u);
1363 }
1364 };
1365 }
1366 };
1367 } // namespace LinearOperatorMGImplementation
1368} // namespace internal
1369
1370
1427template <typename Range, typename Domain, typename Payload, typename Matrix>
1429linear_operator_mg(const Matrix &matrix)
1430{
1431 // implement with the more generic variant below...
1432 return linear_operator_mg<Range, Domain, Payload, Matrix, Matrix>(matrix,
1433 matrix);
1434}
1435
1436
1451template <typename Range,
1452 typename Domain,
1453 typename Payload,
1454 typename OperatorExemplar,
1455 typename Matrix>
1457linear_operator_mg(const OperatorExemplar &operator_exemplar,
1458 const Matrix &matrix)
1459{
1461 // Initialize the payload based on the input exemplar matrix
1463 Payload(operator_exemplar, matrix)};
1464
1465 // Always store a reference to matrix and operator_exemplar in the lambda
1466 // functions. This ensures that a modification of the matrix after the
1467 // creation of a LinearOperatorMG wrapper is respected - further a matrix
1468 // or an operator_exemplar cannot usually be copied...
1469
1470 return_op.reinit_range_vector =
1471 [&operator_exemplar](Range &v, bool omit_zeroing_entries) {
1473 Range>::reinit_range_vector(operator_exemplar, v, omit_zeroing_entries);
1474 };
1475
1476 return_op.reinit_domain_vector = [&operator_exemplar](
1477 Domain &v, bool omit_zeroing_entries) {
1479 Domain>::reinit_domain_vector(operator_exemplar, v, omit_zeroing_entries);
1480 };
1481
1482 std::conditional_t<
1486 .
1487 operator()(return_op, matrix);
1488
1489 return return_op;
1490}
1491
1492
1493
1510template <typename Range, typename Domain, typename Payload, typename Matrix>
1512linear_operator_mg(
1513 const LinearOperatorMG<Range, Domain, Payload> &operator_exemplar,
1514 const Matrix &matrix)
1515{
1517 // Initialize the payload based on the LinearOperatorMG exemplar
1518 auto return_op = operator_exemplar;
1519
1520 std::conditional_t<
1524 .
1525 operator()(return_op, matrix);
1526
1527 return return_op;
1528}
1529
1530
1533#ifndef DOXYGEN
1534
1535//
1536// Ensure that we never capture a reference to a temporary by accident.
1537// to avoid "stack use after free".
1538//
1539
1540template <
1541 typename Range = Vector<double>,
1542 typename Domain = Range,
1544 typename OperatorExemplar,
1545 typename Matrix,
1546 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>>
1548linear_operator_mg(const OperatorExemplar &, Matrix &&) = delete;
1549
1550template <
1551 typename Range = Vector<double>,
1552 typename Domain = Range,
1554 typename OperatorExemplar,
1555 typename Matrix,
1556 typename = std::enable_if_t<!std::is_lvalue_reference_v<OperatorExemplar>>,
1557 typename =
1558 std::enable_if_t<!std::is_same_v<OperatorExemplar,
1561linear_operator_mg(OperatorExemplar &&, const Matrix &) = delete;
1562
1563template <
1564 typename Range = Vector<double>,
1565 typename Domain = Range,
1567 typename OperatorExemplar,
1568 typename Matrix,
1569 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>,
1570 typename = std::enable_if_t<!std::is_lvalue_reference_v<OperatorExemplar>>,
1571 typename =
1572 std::enable_if_t<!std::is_same_v<OperatorExemplar,
1575linear_operator_mg(OperatorExemplar &&, Matrix &&) = delete;
1576
1577template <
1578 typename Range = Vector<double>,
1579 typename Domain = Range,
1581 typename Matrix,
1582 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>>
1585 Matrix &&) = delete;
1586
1587template <
1588 typename Range = Vector<double>,
1589 typename Domain = Range,
1591 typename Matrix,
1592 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>>
1594linear_operator_mg(Matrix &&) = delete;
1595
1596template <
1597 typename Payload,
1598 typename Solver,
1599 typename Preconditioner,
1600 typename Range = typename Solver::vector_type,
1601 typename Domain = Range,
1602 typename = std::enable_if_t<!std::is_lvalue_reference_v<Preconditioner>>,
1603 typename =
1604 std::enable_if_t<!std::is_same_v<Preconditioner, PreconditionIdentity>>,
1605 typename = std::enable_if_t<
1606 !std::is_same_v<Preconditioner, LinearOperatorMG<Range, Domain, Payload>>>>
1609 Solver &,
1610 Preconditioner &&) = delete;
1611
1612#endif // DOXYGEN
1613
1615
1616#endif
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
std::function< void(Range &v, bool omit_zeroing_entries)> reinit_range_vector
std::function< void(Range &v, const Domain &u)> vmult_add
LinearOperatorMG< Range, Domain, Payload > & operator=(const LinearOperatorMG< Range, Domain, Payload > &)=default
LinearOperatorMG< Range, Domain, Payload > operator*=(typename Domain::value_type number)
LinearOperatorMG< Range, Domain, Payload > & operator+=(const LinearOperatorMG< Range, Domain, Payload > &second_op)
std::function< void(Domain &v, const Range &u)> Tvmult_add
LinearOperatorMG(const Payload &payload=Payload())
LinearOperatorMG< Range, Domain, Payload > & operator=(const Op &op)
LinearOperatorMG< Range, Domain, Payload > & operator*=(const LinearOperatorMG< Domain, Domain, Payload > &second_op)
types::global_dof_index n_cols
LinearOperatorMG< Range, Domain, Payload > & operator-=(const LinearOperatorMG< Range, Domain, Payload > &second_op)
std::function< typename Domain::value_type(const types::global_dof_index i, const types::global_dof_index j)> el
types::global_dof_index m() const
types::global_dof_index n_rows
std::function< void(Domain &v, bool omit_zeroing_entries)> reinit_domain_vector
types::global_dof_index n() const
std::function< void(Domain &v, const Range &u)> Tvmult
std::function< void(Range &v, const Domain &u)> vmult
LinearOperatorMG(const LinearOperatorMG< Range, Domain, Payload > &)=default
EmptyPayload inverse_payload(Solver &, const Preconditioner &) const
void operator()(LinearOperatorMG< Range, Domain, Payload > &op, const Matrix &matrix)
void operator()(LinearOperatorMG< Range, Domain, Payload > &op, const Matrix &matrix)
static void reinit_range_vector(const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
static void reinit_domain_vector(const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
static auto test(Range *r, Domain *d) -> decltype(std::declval< C >().vmult_add(*r, *d), std::declval< C >().Tvmult_add(*d, *r), std::true_type())
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U >, typename ProductType< std::complex< T >, std::complex< U > >::type > operator*(const std::complex< T > &left, const std::complex< U > &right)
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
LinearOperator< Range, Domain, Payload > null_operator(const LinearOperator< Range, Domain, Payload > &)
LinearOperator< Domain, Range, Payload > transpose_operator(const LinearOperator< Range, Domain, Payload > &op)
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver, const Preconditioner &preconditioner)
LinearOperator< Range, Range, Payload > mean_value_filter(const std::function< void(Range &, bool)> &reinit_vector)
LinearOperator< Range, Domain, Payload > identity_operator(const LinearOperator< Range, Domain, Payload > &)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
EmptyPayload operator*(const EmptyPayload &, const EmptyPayload &)
EmptyPayload operator+(const EmptyPayload &, const EmptyPayload &)
void apply_with_intermediate_storage(Function function, Range &v, const Domain &u, bool add)
unsigned int global_dof_index
BarycentricPolynomial< dim, Number1 > operator-(const Number2 &a, const BarycentricPolynomial< dim, Number1 > &bp)
BarycentricPolynomial< dim, Number1 > operator+(const Number2 &a, const BarycentricPolynomial< dim, Number1 > &bp)
static bool equal(const T *p1, const T *p2)