16#ifndef dealii_linear_operator_h
17#define dealii_linear_operator_h
35 namespace LinearOperatorImplementation
41template <
typename Number>
46template <
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,
77template <
typename Range,
typename Domain,
typename Payload>
178template <
typename Range,
typename Domain,
typename Payload>
194 vmult = [](Range &,
const Domain &) {
196 ExcMessage(
"Uninitialized LinearOperator<Range, "
197 "Domain>::vmult called"));
200 vmult_add = [](Range &,
const Domain &) {
202 ExcMessage(
"Uninitialized LinearOperator<Range, "
203 "Domain>::vmult_add called"));
206 Tvmult = [](Domain &,
const Range &) {
208 ExcMessage(
"Uninitialized LinearOperator<Range, "
209 "Domain>::Tvmult called"));
214 ExcMessage(
"Uninitialized LinearOperator<Range, "
215 "Domain>::Tvmult_add called"));
220 ExcMessage(
"Uninitialized LinearOperator<Range, "
221 "Domain>::reinit_range_vector method called"));
226 ExcMessage(
"Uninitialized LinearOperator<Range, "
227 "Domain>::reinit_domain_vector method called"));
243 typename = std::enable_if_t<
244 !std::is_base_of<LinearOperator<Range, Domain, Payload>, Op>::value>>
247 *
this = linear_operator<Range, Domain, Payload, Op>(op);
262 typename = std::enable_if_t<
263 !std::is_base_of<LinearOperator<Range, Domain, Payload>, Op>::value>>
267 *
this = linear_operator<Range, Domain, Payload, Op>(op);
275 std::function<void(Range &v,
const Domain &u)>
vmult;
281 std::function<void(Range &v,
const Domain &u)>
vmult_add;
287 std::function<void(Domain &v,
const Range &u)>
Tvmult;
311 std::function<void(Domain &v,
bool omit_zeroing_entries)>
326 *
this = *
this + second_op;
337 *
this = *
this - second_op;
348 *
this = *
this * second_op;
359 *
this = *
this * number;
388template <
typename Range,
typename Domain,
typename Payload>
404 static_cast<const Payload &
>(first_op) +
405 static_cast<const Payload &
>(second_op)};
413 return_op.vmult = [first_op, second_op](Range &v,
const Domain &u) {
414 first_op.
vmult(v, u);
418 return_op.vmult_add = [first_op, second_op](Range &v,
const Domain &u) {
423 return_op.Tvmult = [first_op, second_op](Domain &v,
const Range &u) {
428 return_op.Tvmult_add = [first_op, second_op](Domain &v,
const Range &u) {
447template <
typename Range,
typename Domain,
typename Payload>
454 return -1. * second_op;
463 return first_op + (-1. * second_op);
485template <
typename Range,
typename Domain,
typename Payload>
491 std::is_convertible<
typename Range::value_type,
492 typename Domain::value_type>::value,
493 "Range and Domain must have implicitly convertible 'value_type's");
499 else if (number == 0.)
510 return_op.
vmult = [number, op](Range &v,
const Domain &u) {
515 return_op.
vmult_add = [number, op](Range &v,
const Domain &u) {
521 return_op.
Tvmult = [number, op](Domain &v,
const Range &u) {
526 return_op.
Tvmult_add = [number, op](Domain &v,
const Range &u) {
552template <
typename Range,
typename Domain,
typename Payload>
555 typename Domain::value_type number)
558 std::is_convertible<
typename Range::value_type,
559 typename Domain::value_type>::value,
560 "Range and Domain must have implicitly convertible 'value_type's");
582template <
typename Range,
583 typename Intermediate,
600 static_cast<const Payload &
>(first_op) *
601 static_cast<const Payload &
>(second_op)};
609 return_op.vmult = [first_op, second_op](Range &v,
const Domain &u) {
614 second_op.
vmult(*i, u);
615 first_op.
vmult(v, *i);
618 return_op.vmult_add = [first_op, second_op](Range &v,
const Domain &u) {
623 second_op.
vmult(*i, u);
627 return_op.Tvmult = [first_op, second_op](Domain &v,
const Range &u) {
636 return_op.Tvmult_add = [first_op, second_op](Domain &v,
const Range &u) {
658template <
typename Range,
typename Domain,
typename Payload>
667 return_op.vmult = op.
Tvmult;
669 return_op.Tvmult = op.
vmult;
695template <
typename Payload,
697 typename Preconditioner,
698 typename Range =
typename Solver::vector_type,
699 typename Domain = Range>
703 const Preconditioner & preconditioner)
706 op.inverse_payload(solver, preconditioner)};
711 return_op.vmult = [op, &solver, &preconditioner](Range &v,
const Domain &u) {
713 solver.solve(op, v, u, preconditioner);
716 return_op.vmult_add = [op, &solver, &preconditioner](Range & v,
722 solver.solve(op, *v2, u, preconditioner);
726 return_op.Tvmult = [op, &solver, &preconditioner](Range &v,
const Domain &u) {
731 return_op.Tvmult_add = [op, &solver, &preconditioner](Range & v,
753template <
typename Payload,
755 typename Range =
typename Solver::vector_type,
756 typename Domain = Range>
763 op.inverse_payload(solver, preconditioner)};
768 return_op.vmult = [op, &solver, preconditioner](Range &v,
const Domain &u) {
770 solver.solve(op, v, u, preconditioner);
773 return_op.vmult_add = [op, &solver, preconditioner](Range & v,
779 solver.solve(op, *v2, u, preconditioner);
783 return_op.Tvmult = [op, &solver, preconditioner](Range &v,
const Domain &u) {
788 return_op.Tvmult_add = [op, &solver, preconditioner](Range & v,
811template <
typename Payload,
813 typename Range =
typename Solver::vector_type,
814 typename Domain = Range>
831template <
typename Payload,
833 typename Range =
typename Solver::vector_type,
834 typename Domain = Range>
871 return_op.reinit_domain_vector = reinit_vector;
873 return_op.vmult = [](Range &v,
const Range &u) { v = u; };
875 return_op.vmult_add = [](Range &v,
const Range &u) { v += u; };
877 return_op.Tvmult = [](Range &v,
const Range &u) { v = u; };
879 return_op.Tvmult_add = [](Range &v,
const Range &u) { v += u; };
897template <
typename Range,
typename Domain,
typename Payload>
902 static_cast<Payload &
>(return_op) = op.identity_payload();
917template <
typename Range,
typename Domain,
typename Payload>
928 return_op.vmult = [](Range &v,
const Domain &) { v = 0.; };
930 return_op.vmult_add = [](Range &,
const Domain &) {};
932 return_op.Tvmult = [](Domain &v,
const Range &) { v = 0.; };
934 return_op.Tvmult_add = [](Domain &,
const Range &) {};
961 return_op.reinit_domain_vector = reinit_vector;
963 return_op.vmult = [](Range &v,
const Range &u) {
964 const auto mean = u.mean_value();
970 return_op.vmult_add = [](Range &v,
const Range &u) {
971 const auto mean = u.mean_value();
977 return_op.Tvmult = return_op.vmult_add;
978 return_op.Tvmult_add = return_op.vmult_add;
996template <
typename Range,
typename Domain,
typename Payload>
1001 static_cast<Payload &
>(return_op) = op.identity_payload();
1009 namespace LinearOperatorImplementation
1022 template <
typename Vector>
1037 template <
typename Matrix>
1041 bool omit_zeroing_entries)
1043 v.
reinit(matrix.m(), omit_zeroing_entries);
1057 template <
typename Matrix>
1061 bool omit_zeroing_entries)
1063 v.
reinit(matrix.n(), omit_zeroing_entries);
1089 template <
typename... Args>
1127 template <
typename Solver,
typename Preconditioner>
1159 template <
typename Range,
typename Domain,
typename T>
1162 template <
typename C>
1163 static std::false_type
1166 template <
typename C>
1169 ->
decltype(std::declval<C>().vmult_add(*r, *d),
1170 std::declval<C>().Tvmult_add(*d, *r),
1177 using type =
decltype(test<T>(
nullptr,
nullptr));
1183 template <
typename Function,
typename Range,
typename Domain>
1206 template <
typename Range,
typename Domain,
typename Payload>
1210 template <
typename Matrix>
1213 const Matrix & matrix)
1215 op.
vmult = [&matrix](Range &v,
const Domain &u) {
1221 [&matrix](Range &b,
const Domain &a) { matrix.vmult(b, a); },
1232 op.
vmult_add = [&matrix](Range &v,
const Domain &u) {
1235 [&matrix](Range &b,
const Domain &a) { matrix.vmult(b, a); },
1241 op.
Tvmult = [&matrix](Domain &v,
const Range &u) {
1247 [&matrix](Domain &b,
const Range &a) { matrix.Tvmult(b, a); },
1254 matrix.Tvmult(v, u);
1258 op.
Tvmult_add = [&matrix](Domain &v,
const Range &u) {
1261 [&matrix](Domain &b,
const Range &a) { matrix.Tvmult(b, a); },
1271 template <
typename Range,
typename Domain,
typename Payload>
1275 template <
typename Matrix>
1278 const Matrix & matrix)
1287 op.
vmult_add = [&matrix](Range &v,
const Domain &u) {
1291 [&matrix](Range &b,
const Domain &a) { matrix.vmult(b, a); },
1298 matrix.vmult_add(v, u);
1302 op.
Tvmult_add = [&matrix](Domain &v,
const Range &u) {
1306 [&matrix](Domain &b,
const Range &a) { matrix.Tvmult(b, a); },
1313 matrix.Tvmult_add(v, u);
1378template <
typename Range,
typename Domain,
typename Payload,
typename Matrix>
1383 return linear_operator<Range, Domain, Payload, Matrix, Matrix>(matrix,
1402template <
typename Range,
1405 typename OperatorExemplar,
1413 Payload(operator_exemplar, matrix)};
1421 [&operator_exemplar](Range &v,
bool omit_zeroing_entries) {
1423 Range>::reinit_range_vector(operator_exemplar, v, omit_zeroing_entries);
1426 return_op.reinit_domain_vector = [&operator_exemplar](
1427 Domain &v,
bool omit_zeroing_entries) {
1429 Domain>::reinit_domain_vector(operator_exemplar, v, omit_zeroing_entries);
1432 typename std::conditional<
1437 operator()(return_op, matrix);
1460template <
typename Range,
typename Domain,
typename Payload,
typename Matrix>
1463 const Matrix & matrix)
1467 auto return_op = operator_exemplar;
1469 typename std::conditional<
1474 operator()(return_op, matrix);
1491 typename Domain = Range,
1493 typename OperatorExemplar,
1495 typename = std::enable_if_t<!std::is_lvalue_reference<Matrix>::value>>
1501 typename Domain = Range,
1503 typename OperatorExemplar,
1506 std::enable_if_t<!std::is_lvalue_reference<OperatorExemplar>::value>,
1507 typename = std::enable_if_t<
1508 !std::is_same<OperatorExemplar,
1515 typename Domain = Range,
1517 typename OperatorExemplar,
1519 typename = std::enable_if_t<!std::is_lvalue_reference<Matrix>::value>,
1521 std::enable_if_t<!std::is_lvalue_reference<OperatorExemplar>::value>,
1522 typename = std::enable_if_t<
1523 !std::is_same<OperatorExemplar,
1530 typename Domain = Range,
1533 typename = std::enable_if_t<!std::is_lvalue_reference<Matrix>::value>>
1536 Matrix &&) =
delete;
1540 typename Domain = Range,
1543 typename = std::enable_if_t<!std::is_lvalue_reference<Matrix>::value>>
1550 typename Preconditioner,
1551 typename Range =
typename Solver::vector_type,
1552 typename Domain = Range,
1553 typename = std::enable_if_t<!std::is_lvalue_reference<Preconditioner>::value>,
1554 typename = std::enable_if_t<
1555 !std::is_same<Preconditioner, PreconditionIdentity>::value>,
1556 typename = std::enable_if_t<
1557 !std::is_same<Preconditioner,
1562 Preconditioner &&) =
delete;
LinearOperator< Range, Domain, Payload > operator*=(typename Domain::value_type number)
LinearOperator< Range, Domain, Payload > & operator=(const LinearOperator< Range, Domain, Payload > &)=default
std::function< void(Range &v, const Domain &u)> vmult_add
LinearOperator< Range, Domain, Payload > & operator=(const Op &op)
std::function< void(Domain &v, const Range &u)> Tvmult
std::function< void(Domain &v, bool omit_zeroing_entries)> reinit_domain_vector
LinearOperator(const Payload &payload=Payload())
std::function< void(Range &v, const Domain &u)> vmult
std::function< void(Range &v, bool omit_zeroing_entries)> reinit_range_vector
LinearOperator< Range, Domain, Payload > & operator+=(const LinearOperator< Range, Domain, Payload > &second_op)
std::function< void(Domain &v, const Range &u)> Tvmult_add
LinearOperator(const Op &op)
LinearOperator< Range, Domain, Payload > & operator*=(const LinearOperator< Domain, Domain, Payload > &second_op)
LinearOperator(const LinearOperator< Range, Domain, Payload > &)=default
LinearOperator< Range, Domain, Payload > & operator-=(const LinearOperator< Range, Domain, Payload > &second_op)
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
EmptyPayload(const Args &...)
EmptyPayload transpose_payload() const
EmptyPayload identity_payload() const
EmptyPayload null_payload() const
EmptyPayload inverse_payload(Solver &, const Preconditioner &) const
void operator()(LinearOperator< Range, Domain, Payload > &op, const Matrix &matrix)
void operator()(LinearOperator< Range, Domain, Payload > &op, const Matrix &matrix)
static void reinit_domain_vector(const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
static void reinit_range_vector(const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
static std::false_type test(...)
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())
decltype(test< T >(nullptr, nullptr)) type
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
static ::ExceptionBase & ExcMessage(std::string arg1)
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver)
LinearOperator< Range, Domain, Payload > operator*(const LinearOperator< Range, Intermediate, Payload > &first_op, const LinearOperator< Intermediate, Domain, Payload > &second_op)
LinearOperator< Range, Domain, Payload > linear_operator(const OperatorExemplar &operator_exemplar, const Matrix &matrix)
LinearOperator< Range, Domain, Payload > operator-(const LinearOperator< Range, Domain, Payload > &first_op, const LinearOperator< Range, Domain, Payload > &second_op)
LinearOperator< Range, Range, Payload > identity_operator(const std::function< void(Range &, bool)> &reinit_vector)
LinearOperator< Range, Domain, Payload > null_operator(const LinearOperator< Range, Domain, Payload > &op)
LinearOperator< Range, Domain, Payload > identity_operator(const LinearOperator< Range, Domain, Payload > &op)
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver, const PreconditionIdentity &)
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver, const LinearOperator< Range, Domain, Payload > &preconditioner)
LinearOperator< Range, Domain, Payload > linear_operator(const OperatorExemplar &, const Matrix &)
LinearOperator< Range, Domain, Payload > null_operator(const LinearOperator< Range, Domain, Payload > &)
LinearOperator< Range, Domain, Payload > linear_operator(const Matrix &matrix)
LinearOperator< Domain, Range, Payload > transpose_operator(const LinearOperator< Range, Domain, Payload > &op)
LinearOperator< Range, Domain, Payload > mean_value_filter(const LinearOperator< Range, Domain, Payload > &op)
LinearOperator< Range, Domain, Payload > operator*(typename Range::value_type number, 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, Domain, Payload > operator*(const LinearOperator< Range, Domain, Payload > &op, typename Domain::value_type number)
LinearOperator< Range, Domain, Payload > linear_operator(const LinearOperator< Range, Domain, Payload > &operator_exemplar, const Matrix &matrix)
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 > &)
LinearOperator< Range, Domain, Payload > operator+(const LinearOperator< Range, Domain, Payload > &first_op, const LinearOperator< Range, Domain, Payload > &second_op)
EmptyPayload operator+(const EmptyPayload &, const EmptyPayload &)
void apply_with_intermediate_storage(Function function, Range &v, const Domain &u, bool add)
EmptyPayload operator*(const EmptyPayload &, const EmptyPayload &)
static bool equal(const T *p1, const T *p2)