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> 23 #ifdef DEAL_II_WITH_CXX11 27 #include <type_traits> 29 DEAL_II_NAMESPACE_OPEN
41 template <
typename Number>
class Vector;
43 template <
typename Range = Vector<
double>,
44 typename Domain = Range,
45 typename Payload =
internal::LinearOperator::EmptyPayload>
48 template <
typename Range = Vector<
double>,
49 typename Domain = Range,
50 typename Payload =
internal::LinearOperator::EmptyPayload,
51 typename OperatorExemplar,
56 template <
typename Range = Vector<
double>,
57 typename Domain = Range,
58 typename Payload =
internal::LinearOperator::EmptyPayload,
62 template <
typename Range = Vector<
double>,
63 typename Domain = Range,
64 typename Payload =
internal::LinearOperator::EmptyPayload>
155 template <
typename Range,
typename Domain,
typename Payload>
175 vmult = [](Range &,
const Domain &)
178 "Domain>::vmult called"));
184 "Domain>::vmult_add called"));
187 Tvmult = [](Domain &,
const Range &)
190 "Domain>::Tvmult called"));
196 "Domain>::Tvmult_add called"));
202 "Domain>::reinit_range_vector method called"));
208 "Domain>::reinit_domain_vector method called"));
222 template<
typename Op,
223 typename =
typename std::enable_if<!std::is_base_of<LinearOperator<Range, Domain, Payload>, Op>::value>::type>
226 *
this = linear_operator<Range, Domain, Payload, Op>(op);
239 template <
typename Op,
240 typename =
typename std::enable_if<!std::is_base_of<LinearOperator<Range, Domain, Payload>, Op>::value>::type>
243 *
this = linear_operator<Range, Domain, Payload, Op>(op);
251 std::function<void(Range &v, const Domain &u)>
vmult;
257 std::function<void(Range &v, const Domain &u)>
vmult_add;
263 std::function<void(Domain &v, const Range &u)>
Tvmult;
301 *
this = *
this + second_op;
312 *
this = *
this - second_op;
323 *
this = *
this * second_op;
334 *
this = *
this * number;
363 template <
typename Range,
typename Domain,
typename Payload>
379 static_cast<const Payload &>(first_op) + static_cast<const Payload &>(second_op)
388 return_op.
vmult = [first_op, second_op](Range &v,
const Domain &u)
390 first_op.
vmult(v, u);
394 return_op.
vmult_add = [first_op, second_op](Range &v,
const Domain &u)
400 return_op.
Tvmult = [first_op, second_op](Domain &v,
const Range &u)
406 return_op.
Tvmult_add = [first_op, second_op](Domain &v,
const Range &u)
426 template <
typename Range,
typename Domain,
typename Payload>
433 return -1. * second_op;
442 return first_op + (-1. * second_op);
464 template <
typename Range,
typename Domain,
typename Payload>
470 std::is_convertible<typename Range::value_type, typename Domain::value_type>::value,
471 "Range and Domain must have implicitly convertible 'value_type's");
477 else if (number == 0.)
488 return_op.
vmult = [number, op](Range &v,
const Domain &u)
494 return_op.
vmult_add = [number, op](Range &v,
const Domain &u)
501 return_op.
Tvmult = [number, op](Domain &v,
const Range &u)
507 return_op.
Tvmult_add = [number, op](Domain &v,
const Range &u)
534 template <
typename Range,
typename Domain,
typename Payload>
537 typename Domain::value_type number)
540 std::is_convertible<typename Range::value_type, typename Domain::value_type>::value,
541 "Range and Domain must have implicitly convertible 'value_type's");
563 template <
typename Range,
typename Intermediate,
typename Domain,
typename Payload>
578 static_cast<const Payload &>(first_op) * static_cast<const Payload &>(second_op)
587 return_op.
vmult = [first_op, second_op](Range &v,
const Domain &u)
591 Intermediate *i = vector_memory.
alloc();
593 second_op.
vmult(*i, u);
594 first_op.
vmult(v, *i);
595 vector_memory.
free(i);
598 return_op.
vmult_add = [first_op, second_op](Range &v,
const Domain &u)
602 Intermediate *i = vector_memory.
alloc();
604 second_op.
vmult(*i, u);
606 vector_memory.
free(i);
609 return_op.
Tvmult = [first_op, second_op](Domain &v,
const Range &u)
613 Intermediate *i = vector_memory.
alloc();
617 vector_memory.
free(i);
620 return_op.
Tvmult_add = [first_op, second_op](Domain &v,
const Range &u)
624 Intermediate *i = vector_memory.
alloc();
628 vector_memory.
free(i);
644 template <
typename Range,
typename Domain,
typename Payload>
649 op.transpose_payload()
655 return_op.vmult = op.
Tvmult;
657 return_op.Tvmult = op.
vmult;
684 template <
typename Payload,
685 typename Solver,
typename Preconditioner,
690 const Preconditioner &preconditioner)
693 op.inverse_payload(solver, preconditioner)
699 return_op.vmult = [op, &solver, &preconditioner](Range &v,
const Domain &u)
702 solver.solve(op, v, u, preconditioner);
705 return_op.vmult_add =
706 [op, &solver, &preconditioner](Range &v,
const Domain &u)
710 Range *v2 = vector_memory.
alloc();
712 solver.solve(op, *v2, u, preconditioner);
714 vector_memory.
free(v2);
717 return_op.Tvmult = [op, &solver, &preconditioner](Range &v,
const Domain &u)
723 return_op.Tvmult_add =
724 [op, &solver, &preconditioner](Range &v,
const Domain &u)
728 Range *v2 = vector_memory.
alloc();
732 vector_memory.
free(v2);
757 template <
typename Range,
767 return_op.
vmult = [](Range &v,
const Range &u)
772 return_op.
vmult_add = [](Range &v,
const Range &u)
777 return_op.
Tvmult = [](Range &v,
const Range &u)
782 return_op.
Tvmult_add = [](Range &v,
const Range &u)
803 template <
typename Range,
typename Domain,
typename Payload>
810 op.identity_payload()
815 return_op.vmult = id_op.
vmult;
817 return_op.Tvmult = id_op.
Tvmult;
833 template <
typename Range,
typename Domain,
typename Payload>
846 return_op.vmult = [](Range &v,
const Domain &)
851 return_op.vmult_add = [](Range &,
const Domain &)
854 return_op.Tvmult = [](Domain &v,
const Range &)
859 return_op.Tvmult_add = [](Domain &,
const Range &)
881 template<
typename Vector>
896 template <
typename Matrix>
900 v.
reinit(matrix.m(), omit_zeroing_entries);
914 template <
typename Matrix>
918 v.
reinit(matrix.n(), omit_zeroing_entries);
946 template <
typename... Args>
984 template <
typename Solver,
typename Preconditioner>
997 EmptyPayload operator+(
const EmptyPayload &,
998 const EmptyPayload &)
1000 return EmptyPayload();
1008 EmptyPayload operator*(
const EmptyPayload &,
1009 const EmptyPayload &)
1011 return EmptyPayload();
1022 template <
typename Range,
typename Domain,
typename T>
1023 class has_vmult_add_and_Tvmult_add
1025 template <
typename C>
1026 static std::false_type test(...);
1028 template <
typename C>
1029 static auto test(Range *r, Domain *d)
1030 -> decltype(std::declval<C>().vmult_add(*r,*d),
1031 std::declval<C>().Tvmult_add(*d,*r),
1038 typedef decltype(test<T>(
nullptr,
nullptr)) type;
1044 template <typename
Function, typename Range, typename Domain>
1045 void apply_with_intermediate_storage(
Function function, Range &v,
1046 const Domain &u,
bool add)
1050 Range *i = vector_memory.
alloc();
1060 vector_memory.
free(i);
1066 template <
typename Range,
typename Domain,
typename Payload>
1067 class MatrixInterfaceWithoutVmultAdd
1070 template <
typename Matrix>
1073 op.
vmult = [&matrix](Range &v,
const Domain &u)
1078 apply_with_intermediate_storage([&matrix](Range &b,
const Domain &a)
1090 op.
vmult_add = [&matrix](Range &v,
const Domain &u)
1093 apply_with_intermediate_storage([&matrix](Range &b,
const Domain &a)
1100 op.
Tvmult = [&matrix](Domain &v,
const Range &u)
1105 apply_with_intermediate_storage([&matrix](Domain &b,
const Range &a)
1107 matrix.Tvmult(b, a);
1118 op.
Tvmult_add = [&matrix](Domain &v,
const Range &u)
1121 apply_with_intermediate_storage([&matrix](Domain &b,
const Range &a)
1123 matrix.Tvmult(b, a);
1132 template <
typename Range,
typename Domain,
typename Payload>
1133 class MatrixInterfaceWithVmultAdd
1136 template <
typename Matrix>
1141 MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>().
operator()(op, matrix);
1145 op.
vmult_add = [&matrix](Range &v,
const Domain &u)
1149 apply_with_intermediate_storage([&matrix](Range &b,
const Domain &a)
1157 matrix.vmult_add(v,u);
1161 op.
Tvmult_add = [&matrix](Domain &v,
const Range &u)
1165 apply_with_intermediate_storage([&matrix](Domain &b,
const Range &a)
1167 matrix.Tvmult(b, a);
1173 matrix.Tvmult_add(v,u);
1239 template <
typename Range,
typename Domain,
1240 typename Payload,
typename Matrix>
1245 return linear_operator<Range, Domain, Payload, Matrix, Matrix>(matrix, matrix);
1264 template <
typename Range,
1267 typename OperatorExemplar,
1290 typename std::conditional<
1291 has_vmult_add_and_Tvmult_add<Range, Domain, Matrix>::type::value,
1292 MatrixInterfaceWithVmultAdd<Range, Domain, Payload>,
1293 MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>>::type().
1294 operator()(return_op, matrix);
1303 DEAL_II_NAMESPACE_CLOSE
1305 #endif // DEAL_II_WITH_CXX11 EmptyPayload inverse_payload(Solver &, const Preconditioner &) const
EmptyPayload transpose_payload() const
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)
static void reinit_domain_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)
EmptyPayload(const Args &...)
static ::ExceptionBase & ExcMessage(std::string arg1)
virtual VectorType * alloc()
#define Assert(cond, exc)
static bool equal(const T *p1, const T *p2)
std::function< void(Range &v, const Domain &u)> vmult
virtual void free(const VectorType *const)
LinearOperator< Range, Domain, Payload > operator*(const LinearOperator< Range, Intermediate, Payload > &first_op, const LinearOperator< Intermediate, Domain, Payload > &second_op)
LinearOperator< Range, Domain, Payload > & operator=(const Op &op)
LinearOperator< Range, Domain, Payload > & operator-=(const LinearOperator< Range, Domain, Payload > &second_op)
EmptyPayload identity_payload() const
LinearOperator< Range, Domain, Payload > operator*(const LinearOperator< Range, Domain, Payload > &op, typename Domain::value_type number)
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)
static void reinit_range_vector(const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
LinearOperator< Range, Range, Payload > identity_operator(const std::function< void(Range &, bool)> &reinit_vector)
LinearOperator< Range, Domain, Payload > operator-(const LinearOperator< Range, Domain, Payload > &first_op, const LinearOperator< Range, Domain, Payload > &second_op)
std::function< void(Range &v, const Domain &u)> vmult_add
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 Preconditioner &preconditioner)
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
LinearOperator< Range, Domain, Payload > linear_operator(const OperatorExemplar &operator_exemplar, const Matrix &matrix)
LinearOperator< Range, Domain, Payload > & operator+=(const LinearOperator< Range, Domain, Payload > &second_op)
LinearOperator(const Payload &payload=Payload())
EmptyPayload null_payload() const
LinearOperator< Range, Domain, Payload > linear_operator(const Matrix &matrix)
LinearOperator(const Op &op)