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,
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)
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
Contents is actually a matrix.
LinearOperator< Range, Range, Payload > mean_value_filter(const std::function< void(Range &, bool)> &reinit_vector)
std::function< void(Range &v, bool omit_zeroing_entries)> reinit_range_vector
std::function< void(Domain &v, const Range &u)> Tvmult_add
std::function< void(Domain &v, const Range &u)> Tvmult
LinearOperator< Range, Domain, Payload > operator*=(typename Domain::value_type number)
LinearOperator< Range, Domain, Payload > operator+(const LinearOperator< Range, Domain, Payload > &first_op, const LinearOperator< Range, Domain, Payload > &second_op)
LinearOperator< Range, Domain, Payload > & operator*=(const LinearOperator< Domain, Domain, Payload > &second_op)
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
EmptyPayload transpose_payload() const
EmptyPayload inverse_payload(Solver &, const Preconditioner &) const
EmptyPayload identity_payload() const
LinearAlgebra::distributed::Vector< Number > Vector
static void reinit_range_vector(const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
LinearOperator< Range, Domain, Payload > & operator=(const LinearOperator< Range, Domain, Payload > &)=default
LinearOperator< Domain, Range, Payload > transpose_operator(const LinearOperator< Range, Domain, Payload > &op)
LinearOperator< Range, Domain, Payload > null_operator(const LinearOperator< Range, Domain, Payload > &op)
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
static void reinit_domain_vector(const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
std::function< void(Range &v, const Domain &u)> vmult
LinearOperator< Range, Domain, Payload > & operator=(const Op &op)
LinearOperator< Range, Domain, Payload > & operator-=(const LinearOperator< Range, Domain, Payload > &second_op)
std::function< void(Domain &v, bool omit_zeroing_entries)> reinit_domain_vector
LinearOperator< Range, Domain, Payload > operator*(typename Range::value_type number, const LinearOperator< Range, Domain, Payload > &op)
LinearOperator< Range, Range, Payload > identity_operator(const std::function< void(Range &, bool)> &reinit_vector)
std::function< void(Range &v, const Domain &u)> vmult_add
EmptyPayload(const Args &...)
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver, const Preconditioner &preconditioner)
LinearOperator< Range, Domain, Payload > & operator+=(const LinearOperator< Range, Domain, Payload > &second_op)
LinearOperator(const Payload &payload=Payload())
static bool equal(const T *p1, const T *p2)
LinearOperator< Range, Domain, Payload > linear_operator(const Matrix &matrix)
EmptyPayload null_payload() const
LinearOperator(const Op &op)
Point< dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator*(const OtherNumber) const