16 #ifndef dealii_linear_operator_h
17 #define dealii_linear_operator_h
27 #include <type_traits>
35 namespace LinearOperatorImplementation
41 template <
typename Number>
46 template <
typename Range = Vector<
double>,
47 typename Domain = Range,
49 internal::LinearOperatorImplementation::EmptyPayload>
55 typename Domain = Range,
57 typename OperatorExemplar,
64 typename Domain = Range,
72 typename Domain = Range,
77 template <
typename Range,
typename Domain,
typename Payload>
168 template <
typename Range,
typename Domain,
typename Payload>
184 vmult = [](Range &,
const Domain &) {
186 ExcMessage(
"Uninitialized LinearOperator<Range, "
187 "Domain>::vmult called"));
190 vmult_add = [](Range &,
const Domain &) {
192 ExcMessage(
"Uninitialized LinearOperator<Range, "
193 "Domain>::vmult_add called"));
196 Tvmult = [](Domain &,
const Range &) {
198 ExcMessage(
"Uninitialized LinearOperator<Range, "
199 "Domain>::Tvmult called"));
204 ExcMessage(
"Uninitialized LinearOperator<Range, "
205 "Domain>::Tvmult_add called"));
210 ExcMessage(
"Uninitialized LinearOperator<Range, "
211 "Domain>::reinit_range_vector method called"));
216 ExcMessage(
"Uninitialized LinearOperator<Range, "
217 "Domain>::reinit_domain_vector method called"));
231 template <
typename Op,
232 typename =
typename std::enable_if<
233 !std::is_base_of<LinearOperator<Range, Domain, Payload>,
237 *
this = linear_operator<Range, Domain, Payload, Op>(op);
250 template <
typename Op,
251 typename =
typename std::enable_if<
252 !std::is_base_of<LinearOperator<Range, Domain, Payload>,
257 *
this = linear_operator<Range, Domain, Payload, Op>(op);
265 std::function<void(Range &v,
const Domain &u)>
vmult;
271 std::function<void(Range &v,
const Domain &u)>
vmult_add;
277 std::function<void(Domain &v,
const Range &u)>
Tvmult;
301 std::function<void(Domain &v,
bool omit_zeroing_entries)>
316 *
this = *
this + second_op;
327 *
this = *
this - second_op;
338 *
this = *
this * second_op;
349 *
this = *
this * number;
378 template <
typename Range,
typename Domain,
typename Payload>
394 static_cast<const Payload &
>(first_op) +
395 static_cast<const Payload &
>(second_op)};
403 return_op.vmult = [first_op, second_op](Range &v,
const Domain &u) {
404 first_op.
vmult(v, u);
408 return_op.vmult_add = [first_op, second_op](Range &v,
const Domain &u) {
413 return_op.Tvmult = [first_op, second_op](Domain &v,
const Range &u) {
418 return_op.Tvmult_add = [first_op, second_op](Domain &v,
const Range &u) {
437 template <
typename Range,
typename Domain,
typename Payload>
444 return -1. * second_op;
453 return first_op + (-1. * second_op);
475 template <
typename Range,
typename Domain,
typename Payload>
481 std::is_convertible<
typename Range::value_type,
482 typename Domain::value_type>::
value,
483 "Range and Domain must have implicitly convertible 'value_type's");
489 else if (number == 0.)
500 return_op.
vmult = [number, op](Range &v,
const Domain &u) {
505 return_op.
vmult_add = [number, op](Range &v,
const Domain &u) {
511 return_op.
Tvmult = [number, op](Domain &v,
const Range &u) {
516 return_op.
Tvmult_add = [number, op](Domain &v,
const Range &u) {
542 template <
typename Range,
typename Domain,
typename Payload>
545 typename Domain::value_type number)
548 std::is_convertible<
typename Range::value_type,
549 typename Domain::value_type>::
value,
550 "Range and Domain must have implicitly convertible 'value_type's");
572 template <
typename Range,
573 typename Intermediate,
590 static_cast<const Payload &
>(first_op) *
591 static_cast<const Payload &
>(second_op)};
599 return_op.vmult = [first_op, second_op](Range &v,
const Domain &u) {
604 second_op.
vmult(*i, u);
605 first_op.
vmult(v, *i);
608 return_op.vmult_add = [first_op, second_op](Range &v,
const Domain &u) {
613 second_op.
vmult(*i, u);
617 return_op.Tvmult = [first_op, second_op](Domain &v,
const Range &u) {
626 return_op.Tvmult_add = [first_op, second_op](Domain &v,
const Range &u) {
649 template <
typename Range,
typename Domain,
typename Payload>
658 return_op.vmult = op.
Tvmult;
660 return_op.Tvmult = op.
vmult;
687 template <
typename Payload,
689 typename Preconditioner,
691 typename Domain = Range>
695 const Preconditioner & preconditioner)
698 op.inverse_payload(solver, preconditioner)};
703 return_op.vmult = [op, &solver, &preconditioner](Range &v,
const Domain &u) {
705 solver.solve(op, v, u, preconditioner);
708 return_op.vmult_add = [op, &solver, &preconditioner](Range & v,
714 solver.solve(op, *v2, u, preconditioner);
718 return_op.Tvmult = [op, &solver, &preconditioner](Range &v,
const Domain &u) {
723 return_op.Tvmult_add = [op, &solver, &preconditioner](Range & v,
745 template <
typename Payload,
748 typename Domain = Range>
755 op.inverse_payload(solver, preconditioner)};
760 return_op.vmult = [op, &solver, preconditioner](Range &v,
const Domain &u) {
762 solver.solve(op, v, u, preconditioner);
765 return_op.vmult_add = [op, &solver, preconditioner](Range & v,
771 solver.solve(op, *v2, u, preconditioner);
775 return_op.Tvmult = [op, &solver, preconditioner](Range &v,
const Domain &u) {
780 return_op.Tvmult_add = [op, &solver, preconditioner](Range & v,
803 template <
typename Payload,
806 typename Domain = Range>
823 template <
typename Payload,
826 typename Domain = Range>
863 return_op.reinit_domain_vector = reinit_vector;
865 return_op.vmult = [](Range &v,
const Range &u) { v = u; };
867 return_op.vmult_add = [](Range &v,
const Range &u) { v += u; };
869 return_op.Tvmult = [](Range &v,
const Range &u) { v = u; };
871 return_op.Tvmult_add = [](Range &v,
const Range &u) { v += u; };
889 template <
typename Range,
typename Domain,
typename Payload>
894 static_cast<Payload &
>(return_op) = op.identity_payload();
909 template <
typename Range,
typename Domain,
typename Payload>
920 return_op.vmult = [](Range &v,
const Domain &) { v = 0.; };
922 return_op.vmult_add = [](Range &,
const Domain &) {};
924 return_op.Tvmult = [](Domain &v,
const Range &) { v = 0.; };
926 return_op.Tvmult_add = [](Domain &,
const Range &) {};
953 return_op.reinit_domain_vector = reinit_vector;
955 return_op.vmult = [](Range &v,
const Range &u) {
956 const auto mean = u.mean_value();
962 return_op.vmult_add = [](Range &v,
const Range &u) {
963 const auto mean = u.mean_value();
969 return_op.Tvmult = return_op.vmult_add;
970 return_op.Tvmult_add = return_op.vmult_add;
988 template <
typename Range,
typename Domain,
typename Payload>
993 static_cast<Payload &
>(return_op) = op.identity_payload();
1001 namespace LinearOperatorImplementation
1014 template <
typename Vector>
1029 template <
typename Matrix>
1033 bool omit_zeroing_entries)
1035 v.reinit(
matrix.m(), omit_zeroing_entries);
1049 template <
typename Matrix>
1053 bool omit_zeroing_entries)
1055 v.reinit(
matrix.n(), omit_zeroing_entries);
1082 template <
typename... Args>
1120 template <
typename Solver,
typename Preconditioner>
1151 template <
typename Range,
typename Domain,
typename T>
1154 template <
typename C>
1155 static std::false_type
1158 template <
typename C>
1160 test(Range *r, Domain *
d)
1161 -> decltype(std::declval<C>().vmult_add(*r, *
d),
1162 std::declval<C>().Tvmult_add(*
d, *r),
1169 using type = decltype(test<T>(
nullptr,
nullptr));
1175 template <
typename Function,
typename Range,
typename Domain>
1198 template <
typename Range,
typename Domain,
typename Payload>
1202 template <
typename Matrix>
1263 template <
typename Range,
typename Domain,
typename Payload>
1267 template <
typename Matrix>
1371 template <
typename Range,
typename Domain,
typename Payload,
typename Matrix>
1376 return linear_operator<Range, Domain, Payload, Matrix, Matrix>(
matrix,
1396 template <
typename Range,
1399 typename OperatorExemplar,
1407 Payload(operator_exemplar,
matrix)};
1415 [&operator_exemplar](Range &v,
bool omit_zeroing_entries) {
1417 Range>::reinit_range_vector(operator_exemplar, v, omit_zeroing_entries);
1420 return_op.reinit_domain_vector = [&operator_exemplar](
1421 Domain &v,
bool omit_zeroing_entries) {
1423 Domain>::reinit_domain_vector(operator_exemplar, v, omit_zeroing_entries);
1426 typename std::conditional<
1431 operator()(return_op,
matrix);
1455 template <
typename Range,
typename Domain,
typename Payload,
typename Matrix>
1462 auto return_op = operator_exemplar;
1464 typename std::conditional<
1469 operator()(return_op,
matrix);
1486 typename Domain = Range,
1488 typename OperatorExemplar,
1497 typename Domain = Range,
1499 typename OperatorExemplar,
1501 typename =
typename std::enable_if<
1503 typename =
typename std::enable_if<
1504 !std::is_same<OperatorExemplar,
1511 typename Domain = Range,
1513 typename OperatorExemplar,
1517 typename =
typename std::enable_if<
1519 typename =
typename std::enable_if<
1520 !std::is_same<OperatorExemplar,
1527 typename Domain = Range,
1534 Matrix &&) =
delete;
1538 typename Domain = Range,
1546 template <
typename Payload,
1548 typename Preconditioner,
1550 typename Domain = Range,
1551 typename =
typename std::enable_if<
1553 typename =
typename std::enable_if<
1555 typename =
typename std::enable_if<
1556 !std::is_same<Preconditioner,
1561 Preconditioner &&) =
delete;