15#ifndef dealii_linear_operator_h
16#define dealii_linear_operator_h
34 namespace LinearOperatorImplementation
40template <
typename Number>
45template <
typename Range = Vector<
double>,
46 typename Domain = Range,
48 internal::LinearOperatorImplementation::EmptyPayload>
54 typename Domain = Range,
56 typename OperatorExemplar,
63 typename Domain = Range,
71 typename Domain = Range,
76template <
typename Range,
typename Domain,
typename Payload>
199template <
typename Range,
typename Domain,
typename Payload>
215 vmult = [](Range &,
const Domain &) {
217 ExcMessage(
"Uninitialized LinearOperator<Range, "
218 "Domain>::vmult called"));
221 vmult_add = [](Range &,
const Domain &) {
223 ExcMessage(
"Uninitialized LinearOperator<Range, "
224 "Domain>::vmult_add called"));
227 Tvmult = [](Domain &,
const Range &) {
229 ExcMessage(
"Uninitialized LinearOperator<Range, "
230 "Domain>::Tvmult called"));
235 ExcMessage(
"Uninitialized LinearOperator<Range, "
236 "Domain>::Tvmult_add called"));
241 ExcMessage(
"Uninitialized LinearOperator<Range, "
242 "Domain>::reinit_range_vector method called"));
247 ExcMessage(
"Uninitialized LinearOperator<Range, "
248 "Domain>::reinit_domain_vector method called"));
262 template <
typename Op,
263 typename = std::enable_if_t<
264 !std::is_base_of_v<LinearOperator<Range, Domain, Payload>, Op>>>
267 *
this = linear_operator<Range, Domain, Payload, Op>(op);
280 template <
typename Op,
281 typename = std::enable_if_t<
282 !std::is_base_of_v<LinearOperator<Range, Domain, Payload>, Op>>>
286 *
this = linear_operator<Range, Domain, Payload, Op>(op);
294 std::function<void(Range &v,
const Domain &u)>
vmult;
300 std::function<void(Range &v,
const Domain &u)>
vmult_add;
306 std::function<void(Domain &v,
const Range &u)>
Tvmult;
330 std::function<void(Domain &v,
bool omit_zeroing_entries)>
345 *
this = *
this + second_op;
356 *
this = *
this - second_op;
367 *
this = *
this * second_op;
378 *
this = *
this * number;
407template <
typename Range,
typename Domain,
typename Payload>
423 static_cast<const Payload &
>(first_op) +
424 static_cast<const Payload &
>(second_op)};
432 return_op.vmult = [first_op, second_op](Range &v,
const Domain &u) {
433 first_op.
vmult(v, u);
437 return_op.vmult_add = [first_op, second_op](Range &v,
const Domain &u) {
442 return_op.Tvmult = [first_op, second_op](Domain &v,
const Range &u) {
447 return_op.Tvmult_add = [first_op, second_op](Domain &v,
const Range &u) {
466template <
typename Range,
typename Domain,
typename Payload>
473 return -1. * second_op;
482 return first_op + (-1. * second_op);
504template <
typename Range,
typename Domain,
typename Payload>
510 std::is_convertible_v<
typename Range::value_type,
511 typename Domain::value_type>,
512 "Range and Domain must have implicitly convertible 'value_type's");
518 else if (number == 0.)
529 return_op.
vmult = [number, op](Range &v,
const Domain &u) {
534 return_op.
vmult_add = [number, op](Range &v,
const Domain &u) {
540 return_op.
Tvmult = [number, op](Domain &v,
const Range &u) {
545 return_op.
Tvmult_add = [number, op](Domain &v,
const Range &u) {
571template <
typename Range,
typename Domain,
typename Payload>
574 typename Domain::value_type number)
577 std::is_convertible_v<
typename Range::value_type,
578 typename Domain::value_type>,
579 "Range and Domain must have implicitly convertible 'value_type's");
601template <
typename Range,
602 typename Intermediate,
619 static_cast<const Payload &
>(first_op) *
620 static_cast<const Payload &
>(second_op)};
628 return_op.vmult = [first_op, second_op](Range &v,
const Domain &u) {
633 second_op.
vmult(*i, u);
634 first_op.
vmult(v, *i);
637 return_op.vmult_add = [first_op, second_op](Range &v,
const Domain &u) {
642 second_op.
vmult(*i, u);
646 return_op.Tvmult = [first_op, second_op](Domain &v,
const Range &u) {
655 return_op.Tvmult_add = [first_op, second_op](Domain &v,
const Range &u) {
677template <
typename Range,
typename Domain,
typename Payload>
686 return_op.vmult = op.
Tvmult;
688 return_op.Tvmult = op.
vmult;
714template <
typename Payload,
716 typename Preconditioner,
717 typename Range =
typename Solver::vector_type,
718 typename Domain = Range>
722 const Preconditioner &preconditioner)
725 op.inverse_payload(solver, preconditioner)};
730 return_op.vmult = [op, &solver, &preconditioner](Range &v,
const Domain &u) {
732 solver.solve(op, v, u, preconditioner);
735 return_op.vmult_add = [op, &solver, &preconditioner](Range &v,
741 solver.solve(op, *v2, u, preconditioner);
745 return_op.Tvmult = [op, &solver, &preconditioner](Range &v,
const Domain &u) {
750 return_op.Tvmult_add = [op, &solver, &preconditioner](Range &v,
772template <
typename Payload,
774 typename Range =
typename Solver::vector_type,
775 typename Domain = Range>
782 op.inverse_payload(solver, preconditioner)};
787 return_op.vmult = [op, &solver, preconditioner](Range &v,
const Domain &u) {
789 solver.solve(op, v, u, preconditioner);
792 return_op.vmult_add = [op, &solver, preconditioner](Range &v,
798 solver.solve(op, *v2, u, preconditioner);
802 return_op.Tvmult = [op, &solver, preconditioner](Range &v,
const Domain &u) {
807 return_op.Tvmult_add = [op, &solver, preconditioner](Range &v,
830template <
typename Payload,
832 typename Range =
typename Solver::vector_type,
833 typename Domain = Range>
850template <
typename Payload,
852 typename Range =
typename Solver::vector_type,
853 typename Domain = Range>
890 return_op.reinit_domain_vector = reinit_vector;
892 return_op.vmult = [](Range &v,
const Range &u) { v = u; };
894 return_op.vmult_add = [](Range &v,
const Range &u) { v += u; };
896 return_op.Tvmult = [](Range &v,
const Range &u) { v = u; };
898 return_op.Tvmult_add = [](Range &v,
const Range &u) { v += u; };
916template <
typename Range,
typename Domain,
typename Payload>
921 static_cast<Payload &
>(return_op) = op.identity_payload();
936template <
typename Range,
typename Domain,
typename Payload>
947 return_op.vmult = [](Range &v,
const Domain &) { v = 0.; };
949 return_op.vmult_add = [](Range &,
const Domain &) {};
951 return_op.Tvmult = [](Domain &v,
const Range &) { v = 0.; };
953 return_op.Tvmult_add = [](Domain &,
const Range &) {};
980 return_op.reinit_domain_vector = reinit_vector;
982 return_op.vmult = [](Range &v,
const Range &u) {
983 const auto mean = u.mean_value();
989 return_op.vmult_add = [](Range &v,
const Range &u) {
990 const auto mean = u.mean_value();
996 return_op.Tvmult = return_op.vmult_add;
997 return_op.Tvmult_add = return_op.vmult_add;
1015template <
typename Range,
typename Domain,
typename Payload>
1020 static_cast<Payload &
>(return_op) = op.identity_payload();
1028 namespace LinearOperatorImplementation
1041 template <
typename Vector>
1056 template <
typename Matrix>
1060 bool omit_zeroing_entries)
1062 v.
reinit(matrix.m(), omit_zeroing_entries);
1076 template <
typename Matrix>
1080 bool omit_zeroing_entries)
1082 v.
reinit(matrix.n(), omit_zeroing_entries);
1108 template <
typename... Args>
1146 template <
typename Solver,
typename Preconditioner>
1178 template <
typename Range,
typename Domain,
typename T>
1181 template <
typename C>
1182 static std::false_type
1185 template <
typename C>
1188 ->
decltype(std::declval<C>().vmult_add(*r, *d),
1189 std::declval<C>().Tvmult_add(*d, *r),
1196 using type =
decltype(test<T>(
nullptr,
nullptr));
1202 template <
typename Function,
typename Range,
typename Domain>
1225 template <
typename Range,
typename Domain,
typename Payload>
1229 template <
typename Matrix>
1232 const Matrix &matrix)
1234 op.
vmult = [&matrix](Range &v,
const Domain &u) {
1240 [&matrix](Range &b,
const Domain &a) { matrix.vmult(b, a); },
1251 op.
vmult_add = [&matrix](Range &v,
const Domain &u) {
1254 [&matrix](Range &b,
const Domain &a) { matrix.vmult(b, a); },
1260 op.
Tvmult = [&matrix](Domain &v,
const Range &u) {
1266 [&matrix](Domain &b,
const Range &a) { matrix.Tvmult(b, a); },
1273 matrix.Tvmult(v, u);
1277 op.
Tvmult_add = [&matrix](Domain &v,
const Range &u) {
1280 [&matrix](Domain &b,
const Range &a) { matrix.Tvmult(b, a); },
1290 template <
typename Range,
typename Domain,
typename Payload>
1294 template <
typename Matrix>
1297 const Matrix &matrix)
1306 op.
vmult_add = [&matrix](Range &v,
const Domain &u) {
1310 [&matrix](Range &b,
const Domain &a) { matrix.vmult(b, a); },
1317 matrix.vmult_add(v, u);
1321 op.
Tvmult_add = [&matrix](Domain &v,
const Range &u) {
1325 [&matrix](Domain &b,
const Range &a) { matrix.Tvmult(b, a); },
1332 matrix.Tvmult_add(v, u);
1397template <
typename Range,
typename Domain,
typename Payload,
typename Matrix>
1402 return linear_operator<Range, Domain, Payload, Matrix, Matrix>(matrix,
1421template <
typename Range,
1424 typename OperatorExemplar,
1432 Payload(operator_exemplar, matrix)};
1440 [&operator_exemplar](Range &v,
bool omit_zeroing_entries) {
1442 Range>::reinit_range_vector(operator_exemplar, v, omit_zeroing_entries);
1445 return_op.reinit_domain_vector = [&operator_exemplar](
1446 Domain &v,
bool omit_zeroing_entries) {
1448 Domain>::reinit_domain_vector(operator_exemplar, v, omit_zeroing_entries);
1456 operator()(return_op, matrix);
1479template <
typename Range,
typename Domain,
typename Payload,
typename Matrix>
1482 const Matrix &matrix)
1486 auto return_op = operator_exemplar;
1493 operator()(return_op, matrix);
1510 typename Domain = Range,
1512 typename OperatorExemplar,
1514 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>>
1520 typename Domain = Range,
1522 typename OperatorExemplar,
1524 typename = std::enable_if_t<!std::is_lvalue_reference_v<OperatorExemplar>>,
1525 typename = std::enable_if_t<
1526 !std::is_same_v<OperatorExemplar, LinearOperator<Range, Domain, Payload>>>>
1532 typename Domain = Range,
1534 typename OperatorExemplar,
1536 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>,
1537 typename = std::enable_if_t<!std::is_lvalue_reference_v<OperatorExemplar>>,
1538 typename = std::enable_if_t<
1539 !std::is_same_v<OperatorExemplar, LinearOperator<Range, Domain, Payload>>>>
1545 typename Domain = Range,
1548 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>>
1551 Matrix &&) =
delete;
1555 typename Domain = Range,
1558 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>>
1565 typename Preconditioner,
1566 typename Range =
typename Solver::vector_type,
1567 typename Domain = Range,
1568 typename = std::enable_if_t<!std::is_lvalue_reference_v<Preconditioner>>,
1570 std::enable_if_t<!std::is_same_v<Preconditioner, PreconditionIdentity>>,
1571 typename = std::enable_if_t<
1572 !std::is_same_v<Preconditioner, LinearOperator<Range, Domain, Payload>>>>
1576 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)