16 #ifndef dealii_linear_operator_h
17 #define dealii_linear_operator_h
19 #include <deal.II/base/config.h>
21 #include <deal.II/base/exceptions.h>
23 #include <deal.II/lac/vector_memory.h>
27 #include <type_traits>
29 DEAL_II_NAMESPACE_OPEN
35 namespace LinearOperatorImplementation
41 template <
typename Number>
46 template <
typename Range = Vector<
double>,
47 typename Domain = Range,
49 internal::LinearOperatorImplementation::EmptyPayload>
54 typename Domain = Range,
56 typename OperatorExemplar,
63 typename Domain = Range,
71 typename Domain = Range,
76 template <
typename Range,
typename Domain,
typename Payload>
167 template <
typename Range,
typename Domain,
typename Payload>
183 vmult = [](Range &,
const Domain &) {
185 ExcMessage(
"Uninitialized LinearOperator<Range, "
186 "Domain>::vmult called"));
189 vmult_add = [](Range &,
const Domain &) {
191 ExcMessage(
"Uninitialized LinearOperator<Range, "
192 "Domain>::vmult_add called"));
195 Tvmult = [](Domain &,
const Range &) {
197 ExcMessage(
"Uninitialized LinearOperator<Range, "
198 "Domain>::Tvmult called"));
203 ExcMessage(
"Uninitialized LinearOperator<Range, "
204 "Domain>::Tvmult_add called"));
209 ExcMessage(
"Uninitialized LinearOperator<Range, "
210 "Domain>::reinit_range_vector method called"));
215 ExcMessage(
"Uninitialized LinearOperator<Range, "
216 "Domain>::reinit_domain_vector method called"));
230 template <
typename Op,
231 typename =
typename std::enable_if<
232 !std::is_base_of<LinearOperator<Range, Domain, Payload>,
236 *
this = linear_operator<Range, Domain, Payload, Op>(op);
249 template <
typename Op,
250 typename =
typename std::enable_if<
251 !std::is_base_of<LinearOperator<Range, Domain, Payload>,
256 *
this = linear_operator<Range, Domain, Payload, Op>(op);
264 std::function<void(Range &v,
const Domain &u)>
vmult;
270 std::function<void(Range &v,
const Domain &u)>
vmult_add;
276 std::function<void(Domain &v,
const Range &u)>
Tvmult;
300 std::function<void(Domain &v,
bool omit_zeroing_entries)>
315 *
this = *
this + second_op;
326 *
this = *
this - second_op;
337 *
this = *
this * second_op;
348 *
this = *
this * number;
377 template <
typename Range,
typename Domain,
typename Payload>
393 static_cast<const Payload &>(first_op) +
394 static_cast<const Payload &>(second_op)};
402 return_op.vmult = [first_op, second_op](Range &v,
const Domain &u) {
403 first_op.
vmult(v, u);
407 return_op.vmult_add = [first_op, second_op](Range &v,
const Domain &u) {
412 return_op.Tvmult = [first_op, second_op](Domain &v,
const Range &u) {
417 return_op.Tvmult_add = [first_op, second_op](Domain &v,
const Range &u) {
436 template <
typename Range,
typename Domain,
typename Payload>
443 return -1. * second_op;
452 return first_op + (-1. * second_op);
474 template <
typename Range,
typename Domain,
typename Payload>
480 std::is_convertible<
typename Range::value_type,
481 typename Domain::value_type>::value,
482 "Range and Domain must have implicitly convertible 'value_type's");
488 else if (number == 0.)
499 return_op.
vmult = [number, op](Range &v,
const Domain &u) {
504 return_op.
vmult_add = [number, op](Range &v,
const Domain &u) {
510 return_op.
Tvmult = [number, op](Domain &v,
const Range &u) {
515 return_op.
Tvmult_add = [number, op](Domain &v,
const Range &u) {
541 template <
typename Range,
typename Domain,
typename Payload>
544 typename Domain::value_type number)
547 std::is_convertible<
typename Range::value_type,
548 typename Domain::value_type>::value,
549 "Range and Domain must have implicitly convertible 'value_type's");
571 template <
typename Range,
572 typename Intermediate,
589 static_cast<const Payload &>(first_op) *
590 static_cast<const Payload &>(second_op)};
598 return_op.vmult = [first_op, second_op](Range &v,
const Domain &u) {
603 second_op.
vmult(*i, u);
604 first_op.
vmult(v, *i);
607 return_op.vmult_add = [first_op, second_op](Range &v,
const Domain &u) {
612 second_op.
vmult(*i, u);
616 return_op.Tvmult = [first_op, second_op](Domain &v,
const Range &u) {
625 return_op.Tvmult_add = [first_op, second_op](Domain &v,
const Range &u) {
648 template <
typename Range,
typename Domain,
typename Payload>
657 return_op.vmult = op.
Tvmult;
659 return_op.Tvmult = op.
vmult;
686 template <
typename Payload,
688 typename Preconditioner,
690 typename Domain = Range>
694 const Preconditioner & preconditioner)
697 op.inverse_payload(solver, preconditioner)};
702 return_op.vmult = [op, &solver, &preconditioner](Range &v,
const Domain &u) {
704 solver.solve(op, v, u, preconditioner);
707 return_op.vmult_add = [op, &solver, &preconditioner](Range & v,
713 solver.solve(op, *v2, u, preconditioner);
717 return_op.Tvmult = [op, &solver, &preconditioner](Range &v,
const Domain &u) {
722 return_op.Tvmult_add = [op, &solver, &preconditioner](Range & v,
744 template <
typename Payload,
747 typename Domain = Range>
754 op.inverse_payload(solver, preconditioner)};
759 return_op.vmult = [op, &solver, preconditioner](Range &v,
const Domain &u) {
761 solver.solve(op, v, u, preconditioner);
764 return_op.vmult_add = [op, &solver, preconditioner](Range & v,
770 solver.solve(op, *v2, u, preconditioner);
774 return_op.Tvmult = [op, &solver, preconditioner](Range &v,
const Domain &u) {
779 return_op.Tvmult_add = [op, &solver, preconditioner](Range & v,
802 template <
typename Payload,
805 typename Domain = Range>
822 template <
typename Payload,
825 typename Domain = Range>
862 return_op.reinit_domain_vector = reinit_vector;
864 return_op.vmult = [](Range &v,
const Range &u) { v = u; };
866 return_op.vmult_add = [](Range &v,
const Range &u) { v += u; };
868 return_op.Tvmult = [](Range &v,
const Range &u) { v = u; };
870 return_op.Tvmult_add = [](Range &v,
const Range &u) { v += u; };
888 template <
typename Range,
typename Domain,
typename Payload>
893 static_cast<Payload &>(return_op) = op.identity_payload();
908 template <
typename Range,
typename Domain,
typename Payload>
919 return_op.vmult = [](Range &v,
const Domain &) { v = 0.; };
921 return_op.vmult_add = [](Range &,
const Domain &) {};
923 return_op.Tvmult = [](Domain &v,
const Range &) { v = 0.; };
925 return_op.Tvmult_add = [](Domain &,
const Range &) {};
952 return_op.reinit_domain_vector = reinit_vector;
954 return_op.vmult = [](Range &v,
const Range &u) {
955 const auto mean = u.mean_value();
961 return_op.vmult_add = [](Range &v,
const Range &u) {
962 const auto mean = u.mean_value();
968 return_op.Tvmult = return_op.vmult_add;
969 return_op.Tvmult_add = return_op.vmult_add;
987 template <
typename Range,
typename Domain,
typename Payload>
992 static_cast<Payload &>(return_op) = op.identity_payload();
1000 namespace LinearOperatorImplementation
1013 template <
typename Vector>
1028 template <
typename Matrix>
1032 bool omit_zeroing_entries)
1034 v.reinit(matrix.m(), omit_zeroing_entries);
1048 template <
typename Matrix>
1052 bool omit_zeroing_entries)
1054 v.reinit(matrix.n(), omit_zeroing_entries);
1081 template <
typename... Args>
1119 template <
typename Solver,
typename Preconditioner>
1132 operator+(
const EmptyPayload &,
const EmptyPayload &)
1141 inline EmptyPayload
operator*(
const EmptyPayload &,
const EmptyPayload &)
1150 template <
typename Range,
typename Domain,
typename T>
1151 class has_vmult_add_and_Tvmult_add
1153 template <
typename C>
1154 static std::false_type
1157 template <
typename C>
1159 test(Range *r, Domain *d)
1160 -> decltype(std::declval<C>().vmult_add(*r, *d),
1161 std::declval<C>().Tvmult_add(*d, *r),
1168 using type = decltype(test<T>(
nullptr,
nullptr));
1174 template <
typename Function,
typename Range,
typename Domain>
1176 apply_with_intermediate_storage(
Function function,
1197 template <
typename Range,
typename Domain,
typename Payload>
1198 class MatrixInterfaceWithoutVmultAdd
1201 template <
typename Matrix>
1204 const Matrix & matrix)
1211 apply_with_intermediate_storage(
1212 [&matrix](Range &b,
const Domain &a) {
matrix.vmult(b, a); },
1225 apply_with_intermediate_storage(
1226 [&matrix](Range &b,
const Domain &a) {
matrix.vmult(b, a); },
1237 apply_with_intermediate_storage(
1238 [&matrix](Domain &b,
const Range &a) {
matrix.Tvmult(b, a); },
1251 apply_with_intermediate_storage(
1252 [&matrix](Domain &b,
const Range &a) {
matrix.Tvmult(b, a); },
1262 template <
typename Range,
typename Domain,
typename Payload>
1263 class MatrixInterfaceWithVmultAdd
1266 template <
typename Matrix>
1269 const Matrix & matrix)
1273 MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>().operator()(
1281 apply_with_intermediate_storage(
1282 [&matrix](Range &b,
const Domain &a) {
matrix.vmult(b, a); },
1296 apply_with_intermediate_storage(
1297 [&matrix](Domain &b,
const Range &a) {
matrix.Tvmult(b, a); },
1370 template <
typename Range,
typename Domain,
typename Payload,
typename Matrix>
1375 return linear_operator<Range, Domain, Payload, Matrix, Matrix>(matrix,
1395 template <
typename Range,
1398 typename OperatorExemplar,
1403 using namespace internal::LinearOperatorImplementation;
1406 Payload(operator_exemplar, matrix)};
1414 [&operator_exemplar](Range &v,
bool omit_zeroing_entries) {
1416 Range>::reinit_range_vector(operator_exemplar, v, omit_zeroing_entries);
1419 return_op.reinit_domain_vector = [&operator_exemplar](
1420 Domain &v,
bool omit_zeroing_entries) {
1422 Domain>::reinit_domain_vector(operator_exemplar, v, omit_zeroing_entries);
1425 typename std::conditional<
1426 has_vmult_add_and_Tvmult_add<Range, Domain, Matrix>::type::value,
1427 MatrixInterfaceWithVmultAdd<Range, Domain, Payload>,
1428 MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>>::type()
1430 operator()(return_op, matrix);
1454 template <
typename Range,
typename Domain,
typename Payload,
typename Matrix>
1457 const Matrix & matrix)
1459 using namespace internal::LinearOperatorImplementation;
1461 auto return_op = operator_exemplar;
1463 typename std::conditional<
1464 has_vmult_add_and_Tvmult_add<Range, Domain, Matrix>::type::value,
1465 MatrixInterfaceWithVmultAdd<Range, Domain, Payload>,
1466 MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>>::type()
1468 operator()(return_op, matrix);
1485 typename Domain = Range,
1487 typename OperatorExemplar,
1490 typename std::enable_if<!std::is_lvalue_reference<Matrix>::value>::type>
1496 typename Domain = Range,
1498 typename OperatorExemplar,
1500 typename =
typename std::enable_if<
1501 !std::is_lvalue_reference<OperatorExemplar>::value>::type,
1502 typename =
typename std::enable_if<
1503 !std::is_same<OperatorExemplar,
1510 typename Domain = Range,
1512 typename OperatorExemplar,
1515 typename std::enable_if<!std::is_lvalue_reference<Matrix>::value>::type,
1516 typename =
typename std::enable_if<
1517 !std::is_lvalue_reference<OperatorExemplar>::value>::type,
1518 typename =
typename std::enable_if<
1519 !std::is_same<OperatorExemplar,
1526 typename Domain = Range,
1530 typename std::enable_if<!std::is_lvalue_reference<Matrix>::value>::type>
1533 Matrix &&) =
delete;
1537 typename Domain = Range,
1541 typename std::enable_if<!std::is_lvalue_reference<Matrix>::value>::type>
1545 template <
typename Payload,
1547 typename Preconditioner,
1549 typename Domain = Range,
1550 typename =
typename std::enable_if<
1551 !std::is_lvalue_reference<Preconditioner>::value>::type,
1552 typename =
typename std::enable_if<
1553 !std::is_same<Preconditioner, PreconditionIdentity>::value>::type,
1554 typename =
typename std::enable_if<
1555 !std::is_same<Preconditioner,
1560 Preconditioner &&) =
delete;
1564 DEAL_II_NAMESPACE_CLOSE