15#ifndef dealii_linear_operator_for_mg_h
16#define dealii_linear_operator_for_mg_h
34 namespace LinearOperatorMGImplementation
40template <
typename Number>
45template <
typename Range = Vector<
double>,
46 typename Domain = Range,
48 internal::LinearOperatorMGImplementation::EmptyPayload>
54 typename Domain = Range,
56 typename OperatorExemplar,
59linear_operator_mg(
const OperatorExemplar &,
const Matrix &);
63 typename Domain = Range,
67linear_operator_mg(
const Matrix &);
71 typename Domain = Range,
76template <
typename Range,
typename Domain,
typename Payload>
200template <
typename Range,
typename Domain,
typename Payload>
216 vmult = [](Range &,
const Domain &) {
218 ExcMessage(
"Uninitialized LinearOperatorMG<Range, "
219 "Domain>::vmult called"));
222 vmult_add = [](Range &,
const Domain &) {
224 ExcMessage(
"Uninitialized LinearOperatorMG<Range, "
225 "Domain>::vmult_add called"));
228 Tvmult = [](Domain &,
const Range &) {
230 ExcMessage(
"Uninitialized LinearOperatorMG<Range, "
231 "Domain>::Tvmult called"));
236 ExcMessage(
"Uninitialized LinearOperatorMG<Range, "
237 "Domain>::Tvmult_add called"));
242 ExcMessage(
"Uninitialized LinearOperatorMG<Range, "
243 "Domain>::reinit_range_vector method called"));
248 ExcMessage(
"Uninitialized LinearOperatorMG<Range, "
249 "Domain>::reinit_domain_vector method called"));
263 template <
typename Op,
264 typename = std::enable_if_t<
265 !std::is_base_of_v<LinearOperatorMG<Range, Domain, Payload>, Op>>>
268 *
this = linear_operator_mg<Range, Domain, Payload, Op>(op);
281 template <
typename Op,
282 typename = std::enable_if_t<
283 !std::is_base_of_v<LinearOperatorMG<Range, Domain, Payload>, Op>>>
287 *
this = linear_operator_mg<Range, Domain, Payload, Op>(op);
295 std::function<void(Range &v,
const Domain &u)>
vmult;
301 std::function<void(Range &v,
const Domain &u)>
vmult_add;
307 std::function<void(Domain &v,
const Range &u)>
Tvmult;
331 std::function<void(Domain &v,
bool omit_zeroing_entries)>
371 *
this = *
this + second_op;
382 *
this = *
this - second_op;
393 *
this = *
this * second_op;
404 *
this = *
this * number;
437template <
typename Range,
typename Domain,
typename Payload>
453 static_cast<const Payload &
>(first_op) +
454 static_cast<const Payload &
>(second_op)};
462 return_op.vmult = [first_op, second_op](Range &v,
const Domain &u) {
463 first_op.
vmult(v, u);
467 return_op.vmult_add = [first_op, second_op](Range &v,
const Domain &u) {
472 return_op.Tvmult = [first_op, second_op](Domain &v,
const Range &u) {
477 return_op.Tvmult_add = [first_op, second_op](Domain &v,
const Range &u) {
496template <
typename Range,
typename Domain,
typename Payload>
503 return -1. * second_op;
512 return first_op + (-1. * second_op);
534template <
typename Range,
typename Domain,
typename Payload>
536operator*(
typename Range::value_type number,
540 std::is_convertible<
typename Range::value_type,
541 typename Domain::value_type>::value,
542 "Range and Domain must have implicitly convertible 'value_type's");
548 else if (number == 0.)
559 return_op.
vmult = [number, op](Range &v,
const Domain &u) {
564 return_op.
vmult_add = [number, op](Range &v,
const Domain &u) {
570 return_op.
Tvmult = [number, op](Domain &v,
const Range &u) {
575 return_op.
Tvmult_add = [number, op](Domain &v,
const Range &u) {
601template <
typename Range,
typename Domain,
typename Payload>
604 typename Domain::value_type number)
607 std::is_convertible<
typename Range::value_type,
608 typename Domain::value_type>::value,
609 "Range and Domain must have implicitly convertible 'value_type's");
631template <
typename Range,
632 typename Intermediate,
649 static_cast<const Payload &
>(first_op) *
650 static_cast<const Payload &
>(second_op)};
658 return_op.
vmult = [first_op, second_op](Range &v,
const Domain &u) {
663 second_op.
vmult(*i, u);
664 first_op.
vmult(v, *i);
667 return_op.
vmult_add = [first_op, second_op](Range &v,
const Domain &u) {
672 second_op.
vmult(*i, u);
676 return_op.
Tvmult = [first_op, second_op](Domain &v,
const Range &u) {
685 return_op.
Tvmult_add = [first_op, second_op](Domain &v,
const Range &u) {
707template <
typename Range,
typename Domain,
typename Payload>
744template <
typename Payload,
746 typename Preconditioner,
747 typename Range =
typename Solver::vector_type,
748 typename Domain = Range>
752 const Preconditioner &preconditioner)
755 op.inverse_payload(solver, preconditioner)};
760 return_op.
vmult = [op, &solver, &preconditioner](Range &v,
const Domain &u) {
762 solver.solve(op, v, u, preconditioner);
765 return_op.
vmult_add = [op, &solver, &preconditioner](Range &v,
771 solver.solve(op, *v2, u, preconditioner);
775 return_op.
Tvmult = [op, &solver, &preconditioner](Range &v,
const Domain &u) {
780 return_op.
Tvmult_add = [op, &solver, &preconditioner](Range &v,
802template <
typename Payload,
804 typename Range =
typename Solver::vector_type,
805 typename Domain = Range>
812 op.inverse_payload(solver, preconditioner)};
817 return_op.
vmult = [op, &solver, preconditioner](Range &v,
const Domain &u) {
819 solver.solve(op, v, u, preconditioner);
822 return_op.
vmult_add = [op, &solver, preconditioner](Range &v,
828 solver.solve(op, *v2, u, preconditioner);
832 return_op.
Tvmult = [op, &solver, preconditioner](Range &v,
const Domain &u) {
837 return_op.
Tvmult_add = [op, &solver, preconditioner](Range &v,
860template <
typename Payload,
862 typename Range =
typename Solver::vector_type,
863 typename Domain = Range>
880template <
typename Payload,
882 typename Range =
typename Solver::vector_type,
883 typename Domain = Range>
922 return_op.
vmult = [](Range &v,
const Range &u) { v = u; };
924 return_op.
vmult_add = [](Range &v,
const Range &u) { v += u; };
926 return_op.
Tvmult = [](Range &v,
const Range &u) { v = u; };
928 return_op.
Tvmult_add = [](Range &v,
const Range &u) { v += u; };
946template <
typename Range,
typename Domain,
typename Payload>
951 static_cast<Payload &
>(return_op) = op.identity_payload();
966template <
typename Range,
typename Domain,
typename Payload>
977 return_op.
vmult = [](Range &v,
const Domain &) { v = 0.; };
979 return_op.
vmult_add = [](Range &,
const Domain &) {};
981 return_op.
Tvmult = [](Domain &v,
const Range &) { v = 0.; };
983 return_op.
Tvmult_add = [](Domain &,
const Range &) {};
1012 return_op.
vmult = [](Range &v,
const Range &u) {
1013 const auto mean = u.mean_value();
1019 return_op.
vmult_add = [](Range &v,
const Range &u) {
1020 const auto mean = u.mean_value();
1045template <
typename Range,
typename Domain,
typename Payload>
1050 static_cast<Payload &
>(return_op) = op.identity_payload();
1058 namespace LinearOperatorMGImplementation
1071 template <
typename Vector>
1086 template <
typename Matrix>
1090 bool omit_zeroing_entries)
1092 v.
reinit(matrix.m(), omit_zeroing_entries);
1106 template <
typename Matrix>
1110 bool omit_zeroing_entries)
1112 v.
reinit(matrix.n(), omit_zeroing_entries);
1138 template <
typename... Args>
1176 template <
typename Solver,
typename Preconditioner>
1208 template <
typename Range,
typename Domain,
typename T>
1211 template <
typename C>
1212 static std::false_type
1215 template <
typename C>
1218 ->
decltype(std::declval<C>().vmult_add(*r, *d),
1219 std::declval<C>().Tvmult_add(*d, *r),
1232 template <
typename Function,
typename Range,
typename Domain>
1255 template <
typename Range,
typename Domain,
typename Payload>
1259 template <
typename Matrix>
1262 const Matrix &matrix)
1264 op.
vmult = [&matrix](Range &v,
const Domain &u) {
1270 [&matrix](Range &
b,
const Domain &a) { matrix.vmult(
b, a); },
1281 op.
vmult_add = [&matrix](Range &v,
const Domain &u) {
1284 [&matrix](Range &
b,
const Domain &a) { matrix.vmult(
b, a); },
1290 op.
Tvmult = [&matrix](Domain &v,
const Range &u) {
1296 [&matrix](Domain &
b,
const Range &a) { matrix.Tvmult(
b, a); },
1303 matrix.Tvmult(v, u);
1307 op.
Tvmult_add = [&matrix](Domain &v,
const Range &u) {
1310 [&matrix](Domain &
b,
const Range &a) { matrix.Tvmult(
b, a); },
1320 template <
typename Range,
typename Domain,
typename Payload>
1324 template <
typename Matrix>
1327 const Matrix &matrix)
1336 op.
vmult_add = [&matrix](Range &v,
const Domain &u) {
1340 [&matrix](Range &
b,
const Domain &a) { matrix.vmult(
b, a); },
1347 matrix.vmult_add(v, u);
1351 op.
Tvmult_add = [&matrix](Domain &v,
const Range &u) {
1355 [&matrix](Domain &
b,
const Range &a) { matrix.Tvmult(
b, a); },
1362 matrix.Tvmult_add(v, u);
1427template <
typename Range,
typename Domain,
typename Payload,
typename Matrix>
1429linear_operator_mg(
const Matrix &matrix)
1432 return linear_operator_mg<Range, Domain, Payload, Matrix, Matrix>(matrix,
1451template <
typename Range,
1454 typename OperatorExemplar,
1457linear_operator_mg(
const OperatorExemplar &operator_exemplar,
1458 const Matrix &matrix)
1463 Payload(operator_exemplar, matrix)};
1471 [&operator_exemplar](Range &v,
bool omit_zeroing_entries) {
1473 Range>::reinit_range_vector(operator_exemplar, v, omit_zeroing_entries);
1477 Domain &v,
bool omit_zeroing_entries) {
1479 Domain>::reinit_domain_vector(operator_exemplar, v, omit_zeroing_entries);
1487 operator()(return_op,
matrix);
1510template <
typename Range,
typename Domain,
typename Payload,
typename Matrix>
1514 const Matrix &matrix)
1518 auto return_op = operator_exemplar;
1525 operator()(return_op,
matrix);
1542 typename Domain = Range,
1544 typename OperatorExemplar,
1546 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>>
1548linear_operator_mg(
const OperatorExemplar &, Matrix &&) =
delete;
1552 typename Domain = Range,
1554 typename OperatorExemplar,
1556 typename = std::enable_if_t<!std::is_lvalue_reference_v<OperatorExemplar>>,
1558 std::enable_if_t<!std::is_same_v<OperatorExemplar,
1561linear_operator_mg(OperatorExemplar &&,
const Matrix &) =
delete;
1565 typename Domain = Range,
1567 typename OperatorExemplar,
1569 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>,
1570 typename = std::enable_if_t<!std::is_lvalue_reference_v<OperatorExemplar>>,
1572 std::enable_if_t<!std::is_same_v<OperatorExemplar,
1575linear_operator_mg(OperatorExemplar &&, Matrix &&) =
delete;
1579 typename Domain = Range,
1582 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>>
1585 Matrix &&) =
delete;
1589 typename Domain = Range,
1592 typename = std::enable_if_t<!std::is_lvalue_reference_v<Matrix>>>
1594linear_operator_mg(Matrix &&) =
delete;
1599 typename Preconditioner,
1600 typename Range =
typename Solver::vector_type,
1601 typename Domain = Range,
1602 typename = std::enable_if_t<!std::is_lvalue_reference_v<Preconditioner>>,
1604 std::enable_if_t<!std::is_same_v<Preconditioner, PreconditionIdentity>>,
1605 typename = std::enable_if_t<
1606 !std::is_same_v<Preconditioner, LinearOperatorMG<Range, Domain, Payload>>>>
1610 Preconditioner &&) =
delete;
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
std::function< void(Range &v, bool omit_zeroing_entries)> reinit_range_vector
std::function< void(Range &v, const Domain &u)> vmult_add
LinearOperatorMG< Range, Domain, Payload > & operator=(const LinearOperatorMG< Range, Domain, Payload > &)=default
LinearOperatorMG< Range, Domain, Payload > operator*=(typename Domain::value_type number)
LinearOperatorMG< Range, Domain, Payload > & operator+=(const LinearOperatorMG< Range, Domain, Payload > &second_op)
std::function< void(Domain &v, const Range &u)> Tvmult_add
LinearOperatorMG(const Payload &payload=Payload())
LinearOperatorMG< Range, Domain, Payload > & operator=(const Op &op)
LinearOperatorMG(const Op &op)
LinearOperatorMG< Range, Domain, Payload > & operator*=(const LinearOperatorMG< Domain, Domain, Payload > &second_op)
types::global_dof_index n_cols
LinearOperatorMG< Range, Domain, Payload > & operator-=(const LinearOperatorMG< Range, Domain, Payload > &second_op)
std::function< typename Domain::value_type(const types::global_dof_index i, const types::global_dof_index j)> el
types::global_dof_index m() const
types::global_dof_index n_rows
std::function< void(Domain &v, bool omit_zeroing_entries)> reinit_domain_vector
types::global_dof_index n() const
std::function< void(Domain &v, const Range &u)> Tvmult
std::function< void(Range &v, const Domain &u)> vmult
LinearOperatorMG(const LinearOperatorMG< Range, Domain, Payload > &)=default
EmptyPayload inverse_payload(Solver &, const Preconditioner &) const
EmptyPayload(const Args &...)
EmptyPayload transpose_payload() const
EmptyPayload null_payload() const
EmptyPayload identity_payload() const
void operator()(LinearOperatorMG< Range, Domain, Payload > &op, const Matrix &matrix)
void operator()(LinearOperatorMG< Range, Domain, Payload > &op, const Matrix &matrix)
static void reinit_range_vector(const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
static void reinit_domain_vector(const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
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())
static std::false_type test(...)
decltype(test< T >(nullptr, nullptr)) type
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U >, typename ProductType< std::complex< T >, std::complex< U > >::type > operator*(const std::complex< T > &left, const std::complex< U > &right)
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
LinearOperator< Range, Domain, Payload > null_operator(const LinearOperator< Range, Domain, Payload > &)
LinearOperator< Domain, Range, Payload > transpose_operator(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, Range, Payload > mean_value_filter(const std::function< void(Range &, bool)> &reinit_vector)
LinearOperator< Range, Domain, Payload > identity_operator(const LinearOperator< Range, Domain, Payload > &)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
EmptyPayload operator*(const EmptyPayload &, const EmptyPayload &)
EmptyPayload operator+(const EmptyPayload &, const EmptyPayload &)
void apply_with_intermediate_storage(Function function, Range &v, const Domain &u, bool add)
unsigned int global_dof_index
BarycentricPolynomial< dim, Number1 > operator-(const Number2 &a, const BarycentricPolynomial< dim, Number1 > &bp)
BarycentricPolynomial< dim, Number1 > operator+(const Number2 &a, const BarycentricPolynomial< dim, Number1 > &bp)
static bool equal(const T *p1, const T *p2)