16 #ifndef dealii_linear_operator_h 17 #define dealii_linear_operator_h 19 #include <deal.II/base/config.h> 20 #include <deal.II/base/exceptions.h> 21 #include <deal.II/lac/vector_memory.h> 25 #include <type_traits> 27 DEAL_II_NAMESPACE_OPEN
33 namespace LinearOperatorImplementation
39 template <
typename Number>
class Vector;
41 template <
typename Range = Vector<
double>,
42 typename Domain = Range,
43 typename Payload =
internal::LinearOperatorImplementation::EmptyPayload>
46 template <
typename Range = Vector<
double>,
47 typename Domain = Range,
48 typename Payload =
internal::LinearOperatorImplementation::EmptyPayload,
49 typename OperatorExemplar,
54 template <
typename Range = Vector<
double>,
55 typename Domain = Range,
56 typename Payload =
internal::LinearOperatorImplementation::EmptyPayload,
60 template <
typename Range = Vector<
double>,
61 typename Domain = Range,
62 typename Payload =
internal::LinearOperatorImplementation::EmptyPayload>
149 template <
typename Range,
typename Domain,
typename Payload>
169 vmult = [](Range &,
const Domain &)
172 "Domain>::vmult called"));
178 "Domain>::vmult_add called"));
181 Tvmult = [](Domain &,
const Range &)
184 "Domain>::Tvmult called"));
190 "Domain>::Tvmult_add called"));
196 "Domain>::reinit_range_vector method called"));
202 "Domain>::reinit_domain_vector method called"));
216 template <
typename Op,
217 typename =
typename std::enable_if<!std::is_base_of<LinearOperator<Range, Domain, Payload>, Op>::value>::type>
220 *
this = linear_operator<Range, Domain, Payload, Op>(op);
233 template <
typename Op,
234 typename =
typename std::enable_if<!std::is_base_of<LinearOperator<Range, Domain, Payload>, Op>::value>::type>
237 *
this = linear_operator<Range, Domain, Payload, Op>(op);
245 std::function<void(Range &v, const Domain &u)>
vmult;
251 std::function<void(Range &v, const Domain &u)>
vmult_add;
257 std::function<void(Domain &v, const Range &u)>
Tvmult;
295 *
this = *
this + second_op;
306 *
this = *
this - second_op;
317 *
this = *
this * second_op;
328 *
this = *
this * number;
357 template <
typename Range,
typename Domain,
typename Payload>
373 static_cast<const Payload &>(first_op) + static_cast<const Payload &>(second_op)
382 return_op.
vmult = [first_op, second_op](Range &v,
const Domain &u)
384 first_op.
vmult(v, u);
388 return_op.
vmult_add = [first_op, second_op](Range &v,
const Domain &u)
394 return_op.
Tvmult = [first_op, second_op](Domain &v,
const Range &u)
400 return_op.
Tvmult_add = [first_op, second_op](Domain &v,
const Range &u)
420 template <
typename Range,
typename Domain,
typename Payload>
427 return -1. * second_op;
436 return first_op + (-1. * second_op);
458 template <
typename Range,
typename Domain,
typename Payload>
464 std::is_convertible<typename Range::value_type, typename Domain::value_type>::value,
465 "Range and Domain must have implicitly convertible 'value_type's");
471 else if (number == 0.)
482 return_op.
vmult = [number, op](Range &v,
const Domain &u)
488 return_op.
vmult_add = [number, op](Range &v,
const Domain &u)
495 return_op.
Tvmult = [number, op](Domain &v,
const Range &u)
501 return_op.
Tvmult_add = [number, op](Domain &v,
const Range &u)
528 template <
typename Range,
typename Domain,
typename Payload>
531 typename Domain::value_type number)
534 std::is_convertible<typename Range::value_type, typename Domain::value_type>::value,
535 "Range and Domain must have implicitly convertible 'value_type's");
557 template <
typename Range,
typename Intermediate,
typename Domain,
typename Payload>
572 static_cast<const Payload &>(first_op) * static_cast<const Payload &>(second_op)
581 return_op.
vmult = [first_op, second_op](Range &v,
const Domain &u)
587 second_op.
vmult(*i, u);
588 first_op.
vmult(v, *i);
591 return_op.
vmult_add = [first_op, second_op](Range &v,
const Domain &u)
597 second_op.
vmult(*i, u);
601 return_op.
Tvmult = [first_op, second_op](Domain &v,
const Range &u)
611 return_op.
Tvmult_add = [first_op, second_op](Domain &v,
const Range &u)
634 template <
typename Range,
typename Domain,
typename Payload>
639 op.transpose_payload()
645 return_op.vmult = op.
Tvmult;
647 return_op.Tvmult = op.
vmult;
674 template <
typename Payload,
675 typename Solver,
typename Preconditioner,
680 const Preconditioner &preconditioner)
683 op.inverse_payload(solver, preconditioner)
689 return_op.vmult = [op, &solver, &preconditioner](Range &v,
const Domain &u)
692 solver.solve(op, v, u, preconditioner);
695 return_op.vmult_add =
696 [op, &solver, &preconditioner](Range &v,
const Domain &u)
702 solver.solve(op, *v2, u, preconditioner);
706 return_op.Tvmult = [op, &solver, &preconditioner](Range &v,
const Domain &u)
712 return_op.Tvmult_add =
713 [op, &solver, &preconditioner](Range &v,
const Domain &u)
745 template <
typename Range,
755 return_op.
vmult = [](Range &v,
const Range &u)
760 return_op.
vmult_add = [](Range &v,
const Range &u)
765 return_op.
Tvmult = [](Range &v,
const Range &u)
770 return_op.
Tvmult_add = [](Range &v,
const Range &u)
791 template <
typename Range,
typename Domain,
typename Payload>
796 static_cast<Payload &
>(return_op) = op.identity_payload();
811 template <
typename Range,
typename Domain,
typename Payload>
824 return_op.vmult = [](Range &v,
const Domain &)
829 return_op.vmult_add = [](Range &,
const Domain &)
832 return_op.Tvmult = [](Domain &v,
const Range &)
837 return_op.Tvmult_add = [](Domain &,
const Range &)
856 template <
typename Range,
866 return_op.
vmult = [](Range &v,
const Range &u)
868 const auto mean = u.mean_value();
874 return_op.
vmult_add = [](Range &v,
const Range &u)
876 const auto mean = u.mean_value();
901 template <
typename Range,
typename Domain,
typename Payload>
906 static_cast<Payload &
>(return_op) = op.identity_payload();
914 namespace LinearOperatorImplementation
927 template <
typename Vector>
942 template <
typename Matrix>
946 v.reinit(matrix.m(), omit_zeroing_entries);
960 template <
typename Matrix>
964 v.reinit(matrix.n(), omit_zeroing_entries);
992 template <
typename... Args>
1030 template <
typename Solver,
typename Preconditioner>
1043 EmptyPayload
operator+(
const EmptyPayload &,
1044 const EmptyPayload &)
1046 return EmptyPayload();
1054 EmptyPayload
operator*(
const EmptyPayload &,
1055 const EmptyPayload &)
1057 return EmptyPayload();
1068 template <
typename Range,
typename Domain,
typename T>
1069 class has_vmult_add_and_Tvmult_add
1071 template <
typename C>
1072 static std::false_type test(...);
1074 template <
typename C>
1075 static auto test(Range *r, Domain *d)
1076 -> decltype(std::declval<C>().vmult_add(*r,*d),
1077 std::declval<C>().Tvmult_add(*d,*r),
1084 typedef decltype(test<T>(
nullptr,
nullptr)) type;
1090 template <typename
Function, typename Range, typename Domain>
1091 void apply_with_intermediate_storage(
Function function, Range &v,
1092 const Domain &u,
bool add)
1110 template <
typename Range,
typename Domain,
typename Payload>
1111 class MatrixInterfaceWithoutVmultAdd
1114 template <
typename Matrix>
1122 apply_with_intermediate_storage([&matrix](Range &b,
const Domain &a)
1137 apply_with_intermediate_storage([&matrix](Range &b,
const Domain &a)
1149 apply_with_intermediate_storage([&matrix](Domain &b,
const Range &a)
1165 apply_with_intermediate_storage([&matrix](Domain &b,
const Range &a)
1176 template <
typename Range,
typename Domain,
typename Payload>
1177 class MatrixInterfaceWithVmultAdd
1180 template <
typename Matrix>
1185 MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>().
operator()(op,
matrix);
1193 apply_with_intermediate_storage([&matrix](Range &b,
const Domain &a)
1209 apply_with_intermediate_storage([&matrix](Domain &b,
const Range &a)
1283 template <
typename Range,
typename Domain,
1284 typename Payload,
typename Matrix>
1289 return linear_operator<Range, Domain, Payload, Matrix, Matrix>(matrix, matrix);
1308 template <
typename Range,
1311 typename OperatorExemplar,
1334 typename std::conditional<
1335 has_vmult_add_and_Tvmult_add<Range, Domain, Matrix>::type::value,
1336 MatrixInterfaceWithVmultAdd<Range, Domain, Payload>,
1337 MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>>::type().
1338 operator()(return_op, matrix);
1362 template <
typename Range,
1368 const Matrix &matrix)
1371 auto return_op = operator_exemplar;
1373 typename std::conditional<
1374 has_vmult_add_and_Tvmult_add<Range, Domain, Matrix>::type::value,
1375 MatrixInterfaceWithVmultAdd<Range, Domain, Payload>,
1376 MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>>::type().
1377 operator()(return_op, matrix);
1386 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
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())
Point< dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator*(const OtherNumber) const
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)