13#ifndef dealii_linear_operator_h
14#define dealii_linear_operator_h
32 namespace LinearOperatorImplementation
38template <
typename Number>
43template <
typename Range = Vector<
double>,
44 typename Domain = Range,
46 internal::LinearOperatorImplementation::EmptyPayload>
52 typename Domain = Range,
54 typename OperatorExemplar,
61 typename Domain = Range,
69 typename Domain = Range,
74template <
typename Range,
typename Domain,
typename Payload>
197template <
typename Range,
typename Domain,
typename Payload>
213 vmult = [](Range &,
const Domain &) {
215 ExcMessage(
"Uninitialized LinearOperator<Range, "
216 "Domain>::vmult called"));
219 vmult_add = [](Range &,
const Domain &) {
221 ExcMessage(
"Uninitialized LinearOperator<Range, "
222 "Domain>::vmult_add called"));
225 Tvmult = [](Domain &,
const Range &) {
227 ExcMessage(
"Uninitialized LinearOperator<Range, "
228 "Domain>::Tvmult called"));
233 ExcMessage(
"Uninitialized LinearOperator<Range, "
234 "Domain>::Tvmult_add called"));
239 ExcMessage(
"Uninitialized LinearOperator<Range, "
240 "Domain>::reinit_range_vector method called"));
245 ExcMessage(
"Uninitialized LinearOperator<Range, "
246 "Domain>::reinit_domain_vector method called"));
260 template <
typename Op,
261 typename = std::enable_if_t<
262 !std::is_base_of_v<LinearOperator<Range, Domain, Payload>, Op>>>
265 *
this = linear_operator<Range, Domain, Payload, Op>(op);
278 template <
typename Op,
279 typename = std::enable_if_t<
280 !std::is_base_of_v<LinearOperator<Range, Domain, Payload>, Op>>>
284 *
this = linear_operator<Range, Domain, Payload, Op>(op);
292 std::function<void(Range &v,
const Domain &u)>
vmult;
298 std::function<void(Range &v,
const Domain &u)>
vmult_add;
304 std::function<void(Domain &v,
const Range &u)>
Tvmult;
328 std::function<void(Domain &v,
bool omit_zeroing_entries)>
343 *
this = *
this + second_op;
354 *
this = *
this - second_op;
365 *
this = *
this * second_op;
376 *
this = *
this * number;
405template <
typename Range,
typename Domain,
typename Payload>
421 static_cast<const Payload &
>(first_op) +
422 static_cast<const Payload &
>(second_op)};
430 return_op.vmult = [first_op, second_op](Range &v,
const Domain &u) {
431 first_op.
vmult(v, u);
435 return_op.vmult_add = [first_op, second_op](Range &v,
const Domain &u) {
440 return_op.Tvmult = [first_op, second_op](Domain &v,
const Range &u) {
445 return_op.Tvmult_add = [first_op, second_op](Domain &v,
const Range &u) {
464template <
typename Range,
typename Domain,
typename Payload>
471 return -1. * second_op;
480 return first_op + (-1. * second_op);
502template <
typename Range,
typename Domain,
typename Payload>
508 std::is_convertible_v<
typename Range::value_type,
509 typename Domain::value_type>,
510 "Range and Domain must have implicitly convertible 'value_type's");
516 else if (number == 0.)
527 return_op.
vmult = [number, op](Range &v,
const Domain &u) {
532 return_op.
vmult_add = [number, op](Range &v,
const Domain &u) {
538 return_op.
Tvmult = [number, op](Domain &v,
const Range &u) {
543 return_op.
Tvmult_add = [number, op](Domain &v,
const Range &u) {
569template <
typename Range,
typename Domain,
typename Payload>
572 typename Domain::value_type number)
575 std::is_convertible_v<
typename Range::value_type,
576 typename Domain::value_type>,
577 "Range and Domain must have implicitly convertible 'value_type's");
599template <
typename Range,
600 typename Intermediate,
617 static_cast<const Payload &
>(first_op) *
618 static_cast<const Payload &
>(second_op)};
626 return_op.vmult = [first_op, second_op](Range &v,
const Domain &u) {
631 second_op.
vmult(*i, u);
632 first_op.
vmult(v, *i);
635 return_op.vmult_add = [first_op, second_op](Range &v,
const Domain &u) {
640 second_op.
vmult(*i, u);
644 return_op.Tvmult = [first_op, second_op](Domain &v,
const Range &u) {
653 return_op.Tvmult_add = [first_op, second_op](Domain &v,
const Range &u) {
675template <
typename Range,
typename Domain,
typename Payload>
684 return_op.vmult = op.
Tvmult;
686 return_op.Tvmult = op.
vmult;
712template <
typename Payload,
714 typename Preconditioner,
715 typename Range =
typename Solver::vector_type,
716 typename Domain = Range>
720 const Preconditioner &preconditioner)
723 op.inverse_payload(solver, preconditioner)};
728 return_op.vmult = [op, &solver, &preconditioner](Range &v,
const Domain &u) {
730 solver.solve(op, v, u, preconditioner);
733 return_op.vmult_add = [op, &solver, &preconditioner](Range &v,
739 solver.solve(op, *v2, u, preconditioner);
743 return_op.Tvmult = [op, &solver, &preconditioner](Range &v,
const Domain &u) {
748 return_op.Tvmult_add = [op, &solver, &preconditioner](Range &v,
770template <
typename Payload,
772 typename Range =
typename Solver::vector_type,
773 typename Domain = Range>
780 op.inverse_payload(solver, preconditioner)};
785 return_op.vmult = [op, &solver, preconditioner](Range &v,
const Domain &u) {
787 solver.solve(op, v, u, preconditioner);
790 return_op.vmult_add = [op, &solver, preconditioner](Range &v,
796 solver.solve(op, *v2, u, preconditioner);
800 return_op.Tvmult = [op, &solver, preconditioner](Range &v,
const Domain &u) {
805 return_op.Tvmult_add = [op, &solver, preconditioner](Range &v,
828template <
typename Payload,
830 typename Range =
typename Solver::vector_type,
831 typename Domain = Range>
848template <
typename Payload,
850 typename Range =
typename Solver::vector_type,
851 typename Domain = Range>
888 return_op.reinit_domain_vector = reinit_vector;
890 return_op.vmult = [](Range &v,
const Range &u) { v = u; };
892 return_op.vmult_add = [](Range &v,
const Range &u) { v += u; };
894 return_op.Tvmult = [](Range &v,
const Range &u) { v = u; };
896 return_op.Tvmult_add = [](Range &v,
const Range &u) { v += u; };
914template <
typename Range,
typename Domain,
typename Payload>
919 static_cast<Payload &
>(return_op) = op.identity_payload();
934template <
typename Range,
typename Domain,
typename Payload>
945 return_op.vmult = [](Range &v,
const Domain &) { v = 0.; };
947 return_op.vmult_add = [](Range &,
const Domain &) {};
949 return_op.Tvmult = [](Domain &v,
const Range &) { v = 0.; };
951 return_op.Tvmult_add = [](Domain &,
const Range &) {};
966template <
typename Range,
972 const VectorType &diagonal)
978 return_op.
vmult = [&diagonal](Range &dst,
const Domain &src) {
979 Assert(src.size() == diagonal.size(),
981 Assert(dst.size() == diagonal.size(),
987 return_op.
vmult_add = [&diagonal](Range &dst,
const Domain &src) {
988 Assert(src.size() == diagonal.size(),
990 Assert(dst.size() == diagonal.size(),
998 return_op.
Tvmult = [&diagonal](Domain &dst,
const Range &src) {
999 Assert(src.size() == diagonal.size(),
1001 Assert(dst.size() == diagonal.size(),
1004 dst.scale(diagonal);
1007 return_op.
Tvmult_add = [&diagonal](Domain &dst,
const Range &src) {
1008 Assert(src.size() == diagonal.size(),
1010 Assert(dst.size() == diagonal.size(),
1014 tmp.scale(diagonal);
1043 return_op.reinit_domain_vector = reinit_vector;
1045 return_op.vmult = [](Range &v,
const Range &u) {
1046 const auto mean = u.mean_value();
1052 return_op.vmult_add = [](Range &v,
const Range &u) {
1053 const auto mean = u.mean_value();
1059 return_op.Tvmult = return_op.vmult_add;
1060 return_op.Tvmult_add = return_op.vmult_add;
1078template <
typename Range,
typename Domain,
typename Payload>
1083 static_cast<Payload &
>(return_op) = op.identity_payload();
1091 namespace LinearOperatorImplementation
1104 template <
typename Vector>
1119 template <
typename Matrix>
1123 bool omit_zeroing_entries)
1125 v.
reinit(matrix.m(), omit_zeroing_entries);
1139 template <
typename Matrix>
1143 bool omit_zeroing_entries)
1145 v.
reinit(matrix.n(), omit_zeroing_entries);
1171 template <
typename... Args>
1209 template <
typename Solver,
typename Preconditioner>
1241 template <
typename Range,
typename Domain,
typename T>
1244 template <
typename C>
1245 static std::false_type
1248 template <
typename C>
1251 ->
decltype(std::declval<C>().vmult_add(*r, *d),
1252 std::declval<C>().Tvmult_add(*d, *r),
1259 using type =
decltype(test<T>(
nullptr,
nullptr));
1265 template <
typename Function,
typename Range,
typename Domain>
1288 template <
typename Range,
typename Domain,
typename Payload>
1292 template <
typename Matrix>
1295 const Matrix &matrix)
1297 op.
vmult = [&matrix](Range &v,
const Domain &u) {
1303 [&matrix](Range &b,
const Domain &a) { matrix.vmult(b, a); },
1314 op.
vmult_add = [&matrix](Range &v,
const Domain &u) {
1317 [&matrix](Range &b,
const Domain &a) { matrix.vmult(b, a); },
1323 op.
Tvmult = [&matrix](Domain &v,
const Range &u) {
1329 [&matrix](Domain &b,
const Range &a) { matrix.Tvmult(b, a); },
1336 matrix.Tvmult(v, u);
1340 op.
Tvmult_add = [&matrix](Domain &v,
const Range &u) {
1343 [&matrix](Domain &b,
const Range &a) { matrix.Tvmult(b, a); },
1353 template <
typename Range,
typename Domain,
typename Payload>
1357 template <
typename Matrix>
1360 const Matrix &matrix)
1369 op.
vmult_add = [&matrix](Range &v,
const Domain &u) {
1373 [&matrix](Range &b,
const Domain &a) { matrix.vmult(b, a); },
1380 matrix.vmult_add(v, u);
1384 op.
Tvmult_add = [&matrix](Domain &v,
const Range &u) {
1388 [&matrix](Domain &b,
const Range &a) { matrix.Tvmult(b, a); },
1395 matrix.Tvmult_add(v, u);
1460template <
typename Range,
typename Domain,
typename Payload,
typename Matrix>
1465 return linear_operator<Range, Domain, Payload, Matrix, Matrix>(matrix,
1484template <
typename Range,
1487 typename OperatorExemplar,
1495 Payload(operator_exemplar, matrix)};
1503 [&operator_exemplar](Range &v,
bool omit_zeroing_entries) {
1505 Range>::reinit_range_vector(operator_exemplar, v, omit_zeroing_entries);
1508 return_op.reinit_domain_vector = [&operator_exemplar](
1509 Domain &v,
bool omit_zeroing_entries) {
1511 Domain>::reinit_domain_vector(operator_exemplar, v, omit_zeroing_entries);
1519 operator()(return_op, matrix);
1542template <
typename Range,
typename Domain,
typename Payload,
typename Matrix>
1545 const Matrix &matrix)
1549 auto return_op = operator_exemplar;
1556 operator()(return_op, matrix);
1573 typename Domain = Range,
1575 typename OperatorExemplar,
1577 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>>
1583 typename Domain = Range,
1585 typename OperatorExemplar,
1587 typename = std::enable_if_t<!std::is_lvalue_reference_v<OperatorExemplar>>,
1588 typename = std::enable_if_t<
1589 !std::is_same_v<OperatorExemplar, LinearOperator<Range, Domain, Payload>>>>
1595 typename Domain = Range,
1597 typename OperatorExemplar,
1599 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>,
1600 typename = std::enable_if_t<!std::is_lvalue_reference_v<OperatorExemplar>>,
1601 typename = std::enable_if_t<
1602 !std::is_same_v<OperatorExemplar, LinearOperator<Range, Domain, Payload>>>>
1608 typename Domain = Range,
1611 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>>
1614 Matrix &&) =
delete;
1618 typename Domain = Range,
1621 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>>
1628 typename Preconditioner,
1629 typename Range =
typename Solver::vector_type,
1630 typename Domain = Range,
1631 typename = std::enable_if_t<!std::is_lvalue_reference_v<Preconditioner>>,
1633 std::enable_if_t<!std::is_same_v<Preconditioner, PreconditionIdentity>>,
1634 typename = std::enable_if_t<
1635 !std::is_same_v<Preconditioner, LinearOperator<Range, Domain, Payload>>>>
1639 Preconditioner &&) =
delete;
* * reference operator*() const
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 & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
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, Domain, Payload > diagonal_operator(const LinearOperator< Range, Domain, Payload > &exemplar, const VectorType &diagonal)
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)
static bool equal(const T *p1, const T *p2)