13#ifndef dealii_block_linear_operator_h
14#define dealii_block_linear_operator_h
29 namespace BlockLinearOperatorImplementation
31 template <
typename PayloadBlockType =
33 class EmptyBlockPayload;
37template <
typename Number>
40template <
typename Range = BlockVector<
double>,
41 typename Domain = Range,
42 typename BlockPayload =
43 internal::BlockLinearOperatorImplementation::EmptyBlockPayload<>>
47template <
typename Range = BlockVector<
double>,
48 typename Domain = Range,
49 typename BlockPayload =
50 internal::BlockLinearOperatorImplementation::EmptyBlockPayload<>,
51 typename BlockMatrixType>
55template <std::size_t m,
58 typename Domain = Range,
59 typename BlockPayload =
63 const std::array<std::array<
LinearOperator<
typename Range::BlockType,
64 typename Domain::BlockType,
65 typename BlockPayload::BlockType>,
69template <std::size_t m,
71 typename Domain = Range,
72 typename BlockPayload =
77 typename Domain::BlockType,
78 typename BlockPayload::BlockType>,
81template <std::size_t m,
83 typename Domain = Range,
84 typename BlockPayload =
89 typename Domain::BlockType,
90 typename BlockPayload::BlockType> &op);
162template <
typename Range,
typename Domain,
typename BlockPayload>
164 :
public LinearOperator<Range, Domain, typename BlockPayload::BlockType>
168 typename Domain::BlockType,
169 typename BlockPayload::BlockType>;
180 typename BlockPayload::
BlockType(payload, payload))
186 "Uninitialized BlockLinearOperator<Range, Domain>::n_block_rows called"));
194 "Uninitialized BlockLinearOperator<Range, Domain>::n_block_cols called"));
202 "Uninitialized BlockLinearOperator<Range, Domain>::block called"));
218 template <
typename Op>
221 *
this = block_operator<Range, Domain, BlockPayload, Op>(op);
229 template <std::
size_t m, std::
size_t n>
232 *
this = block_operator<m, n, Range, Domain, BlockPayload>(ops);
240 template <std::
size_t m>
243 *
this = block_diagonal_operator<m, Range, Domain, BlockPayload>(ops);
256 template <
typename Op>
260 *
this = block_operator<Range, Domain, BlockPayload, Op>(op);
269 template <std::
size_t m, std::
size_t n>
271 operator=(
const std::array<std::array<BlockType, n>, m> &ops)
273 *
this = block_operator<m, n, Range, Domain, BlockPayload>(ops);
282 template <std::
size_t m>
286 *
this = block_diagonal_operator<m, Range, Domain, BlockPayload>(ops);
313 namespace BlockLinearOperatorImplementation
320 template <
typename Function1,
326 const Function2 &loop_op,
334 tmp->reinit(v,
true);
336 const unsigned int n = u.n_blocks();
337 const unsigned int m = v.n_blocks();
339 for (
unsigned int i = 0; i < m; ++i)
341 first_op(*tmp, u, i, 0);
342 for (
unsigned int j = 1; j < n; ++j)
343 loop_op(*tmp, u, i, j);
354 template <
typename Range,
typename Domain,
typename BlockPayload>
366 for (
unsigned int i = 0; i < m; ++i)
367 op.
block(i, 0).reinit_range_vector(v.block(i), omit_zeroing_entries);
379 for (
unsigned int i = 0; i < n; ++i)
380 op.
block(0, i).reinit_domain_vector(v.block(i), omit_zeroing_entries);
385 op.
vmult = [&op](Range &v,
const Domain &u) {
393 const auto first_op = [&op](Range &v,
395 const unsigned int i,
396 const unsigned int j) {
397 op.
block(i, j).vmult(v.block(i), u.block(j));
400 const auto loop_op = [&op](Range &v,
402 const unsigned int i,
403 const unsigned int j) {
404 op.
block(i, j).vmult_add(v.block(i), u.block(j));
411 for (
unsigned int i = 0; i < m; ++i)
413 op.
block(i, 0).vmult(v.block(i), u.block(0));
414 for (
unsigned int j = 1; j < n; ++j)
415 op.
block(i, j).vmult_add(v.block(i), u.block(j));
420 op.
vmult_add = [&op](Range &v,
const Domain &u) {
428 const auto first_op = [&op](Range &v,
430 const unsigned int i,
431 const unsigned int j) {
432 op.
block(i, j).vmult(v.block(i), u.block(j));
435 const auto loop_op = [&op](Range &v,
437 const unsigned int i,
438 const unsigned int j) {
439 op.
block(i, j).vmult_add(v.block(i), u.block(j));
446 for (
unsigned int i = 0; i < m; ++i)
447 for (
unsigned int j = 0; j < n; ++j)
448 op.
block(i, j).vmult_add(v.block(i), u.block(j));
452 op.
Tvmult = [&op](Domain &v,
const Range &u) {
460 const auto first_op = [&op](Range &v,
462 const unsigned int i,
463 const unsigned int j) {
464 op.
block(j, i).Tvmult(v.block(i), u.block(j));
467 const auto loop_op = [&op](Range &v,
469 const unsigned int i,
470 const unsigned int j) {
471 op.
block(j, i).Tvmult_add(v.block(i), u.block(j));
478 for (
unsigned int i = 0; i < n; ++i)
480 op.
block(0, i).Tvmult(v.block(i), u.block(0));
481 for (
unsigned int j = 1; j < m; ++j)
482 op.
block(j, i).Tvmult_add(v.block(i), u.block(j));
487 op.
Tvmult_add = [&op](Domain &v,
const Range &u) {
495 const auto first_op = [&op](Range &v,
497 const unsigned int i,
498 const unsigned int j) {
499 op.
block(j, i).Tvmult(v.block(i), u.block(j));
502 const auto loop_op = [&op](Range &v,
504 const unsigned int i,
505 const unsigned int j) {
506 op.
block(j, i).Tvmult_add(v.block(i), u.block(j));
513 for (
unsigned int i = 0; i < n; ++i)
514 for (
unsigned int j = 0; j < m; ++j)
515 op.
block(j, i).Tvmult_add(v.block(i), u.block(j));
535 template <
typename PayloadBlockType>
551 template <
typename... Args>
577template <
typename Range,
579 typename BlockPayload,
580 typename BlockMatrixType>
588 BlockPayload(block_matrix, block_matrix)};
590 return_op.
n_block_rows = [&block_matrix]() ->
unsigned int {
591 return block_matrix.n_block_rows();
594 return_op.n_block_cols = [&block_matrix]() ->
unsigned int {
595 return block_matrix.n_block_cols();
598 return_op.block = [&block_matrix](
unsigned int i,
602 const unsigned int m = block_matrix.n_block_rows();
603 const unsigned int n = block_matrix.n_block_cols();
608 return BlockType(block_matrix.block(i, j));
611 populate_linear_operator_functions(return_op);
644template <std::size_t m,
648 typename BlockPayload>
651 const std::array<std::array<
LinearOperator<
typename Range::BlockType,
652 typename Domain::BlockType,
653 typename BlockPayload::BlockType>,
657 static_assert(m > 0 && n > 0,
658 "a blocked LinearOperator must consist of at least one block");
666 return_op.
n_block_rows = []() ->
unsigned int {
return m; };
668 return_op.n_block_cols = []() ->
unsigned int {
return n; };
670 return_op.block = [ops](
unsigned int i,
unsigned int j) ->
BlockType {
677 populate_linear_operator_functions(return_op);
698template <
typename Range = BlockVector<
double>,
699 typename Domain = Range,
700 typename BlockPayload =
701 internal::BlockLinearOperatorImplementation::EmptyBlockPayload<>,
702 typename BlockMatrixType>
710 BlockPayload(block_matrix, block_matrix)};
712 return_op.
n_block_rows = [&block_matrix]() ->
unsigned int {
713 return block_matrix.n_block_rows();
716 return_op.n_block_cols = [&block_matrix]() ->
unsigned int {
717 return block_matrix.n_block_cols();
720 return_op.block = [&block_matrix](
unsigned int i,
724 const unsigned int m = block_matrix.n_block_rows();
725 const unsigned int n = block_matrix.n_block_cols();
731 return BlockType(block_matrix.block(i, j));
736 populate_linear_operator_functions(return_op);
759template <std::
size_t m,
typename Range,
typename Domain,
typename BlockPayload>
763 typename Domain::BlockType,
764 typename BlockPayload::BlockType>,
768 m > 0,
"a blockdiagonal LinearOperator must consist of at least one block");
773 std::array<std::array<BlockType, m>, m> new_ops;
779 for (
unsigned int i = 0; i < m; ++i)
780 for (
unsigned int j = 0; j < m; ++j)
784 new_ops[i][j] = ops[i];
791 new_ops[i][j].reinit_domain_vector = ops[j].reinit_domain_vector;
794 return block_operator<m, m, Range, Domain>(new_ops);
808template <std::
size_t m,
typename Range,
typename Domain,
typename BlockPayload>
812 typename Domain::BlockType,
813 typename BlockPayload::BlockType> &op)
816 "a blockdiagonal LinearOperator must consist of at least "
821 std::array<BlockType, m> new_ops;
869template <
typename Range = BlockVector<
double>,
870 typename Domain = Range,
871 typename BlockPayload =
872 internal::BlockLinearOperatorImplementation::EmptyBlockPayload<>>
879 typename BlockPayload::BlockType(diagonal_inverse)};
899 diagonal_inverse.
block(0, 0).vmult(v.block(0), u.block(0));
900 for (
unsigned int i = 1; i < m; ++i)
902 auto &dst = v.block(i);
905 for (
unsigned int j = 0; j < i; ++j)
908 diagonal_inverse.
block(i, i).vmult(dst,
913 return_op.vmult_add = [
block_operator, diagonal_inverse](Range &v,
932 diagonal_inverse.
block(0, 0).vmult_add(v.block(0), u.block(0));
934 for (
unsigned int i = 1; i < m; ++i)
936 diagonal_inverse.
block(i, i).reinit_range_vector(
940 for (
unsigned int j = 0; j < i; ++j)
943 diagonal_inverse.
block(i, i).vmult_add(v.block(i), *tmp);
986template <
typename Range = BlockVector<
double>,
987 typename Domain = Range,
988 typename BlockPayload =
989 internal::BlockLinearOperatorImplementation::EmptyBlockPayload<>>
996 typename BlockPayload::BlockType(diagonal_inverse)};
1016 diagonal_inverse.
block(m - 1, m - 1).vmult(v.block(m - 1), u.block(m - 1));
1018 for (
int i = m - 2; i >= 0; --i)
1020 auto &dst = v.block(i);
1023 for (
unsigned int j = i + 1; j < m; ++j)
1026 diagonal_inverse.
block(i, i).vmult(dst,
1031 return_op.vmult_add = [
block_operator, diagonal_inverse](Range &v,
1049 diagonal_inverse.
block(m - 1, m - 1)
1050 .vmult_add(v.block(m - 1), u.block(m - 1));
1052 for (
int i = m - 2; i >= 0; --i)
1054 diagonal_inverse.
block(i, i).reinit_range_vector(
1058 for (
unsigned int j = i + 1; j < m; ++j)
1061 diagonal_inverse.
block(i, i).vmult_add(v.block(i), *tmp);
BlockLinearOperator< Range, Domain, BlockPayload > & operator=(const std::array< std::array< BlockType, n >, m > &ops)
BlockLinearOperator(const std::array< BlockType, m > &ops)
LinearOperator< typename Range::BlockType, typename Domain::BlockType, typename BlockPayload::BlockType > BlockType
BlockLinearOperator< Range, Domain, BlockPayload > & operator=(const std::array< BlockType, m > &ops)
std::function< BlockType(unsigned int, unsigned int)> block
BlockLinearOperator(const BlockLinearOperator< Range, Domain, BlockPayload > &)=default
BlockLinearOperator< Range, Domain, BlockPayload > & operator=(const BlockLinearOperator< Range, Domain, BlockPayload > &)=default
BlockLinearOperator< Range, Domain, BlockPayload > & operator=(const Op &op)
std::function< unsigned int()> n_block_cols
std::function< unsigned int()> n_block_rows
BlockLinearOperator(const Op &op)
BlockLinearOperator(const std::array< std::array< BlockType, n >, m > &ops)
BlockLinearOperator(const BlockPayload &payload)
std::function< void(Range &v, const Domain &u)> vmult_add
std::function< void(Domain &v, const Range &u)> Tvmult
std::function< void(Domain &v, bool omit_zeroing_entries)> reinit_domain_vector
std::function< void(Range &v, const Domain &u)> vmult
std::function< void(Range &v, bool omit_zeroing_entries)> reinit_range_vector
std::function< void(Domain &v, const Range &u)> Tvmult_add
EmptyBlockPayload(const Args &...)
PayloadBlockType BlockType
#define DEAL_II_NAMESPACE_OPEN
constexpr bool running_in_debug_mode()
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
BlockLinearOperator< Range, Domain, BlockPayload > block_diagonal_operator(const std::array< LinearOperator< typename Range::BlockType, typename Domain::BlockType, typename BlockPayload::BlockType >, m > &)
LinearOperator< Domain, Range, typename BlockPayload::BlockType > block_forward_substitution(const BlockLinearOperator< Range, Domain, BlockPayload > &block_operator, const BlockLinearOperator< Domain, Range, BlockPayload > &diagonal_inverse)
BlockLinearOperator< Range, Domain, BlockPayload > block_operator(const std::array< std::array< LinearOperator< typename Range::BlockType, typename Domain::BlockType, typename BlockPayload::BlockType >, n >, m > &ops)
BlockLinearOperator< Range, Domain, BlockPayload > block_diagonal_operator(const std::array< LinearOperator< typename Range::BlockType, typename Domain::BlockType, typename BlockPayload::BlockType >, m > &ops)
LinearOperator< Range, Domain, Payload > null_operator(const LinearOperator< Range, Domain, Payload > &)
LinearOperator< Domain, Range, typename BlockPayload::BlockType > block_back_substitution(const BlockLinearOperator< Range, Domain, BlockPayload > &block_operator, const BlockLinearOperator< Domain, Range, BlockPayload > &diagonal_inverse)
BlockLinearOperator< Range, Domain, BlockPayload > block_diagonal_operator(const BlockMatrixType &block_matrix)
BlockLinearOperator< Range, Domain, BlockPayload > block_diagonal_operator(const LinearOperator< typename Range::BlockType, typename Domain::BlockType, typename BlockPayload::BlockType > &op)
BlockLinearOperator< Range, Domain, BlockPayload > block_operator(const BlockMatrixType &block_matrix)
BlockLinearOperator< Range, Domain, BlockPayload > block_operator(const BlockMatrixType &matrix)
void populate_linear_operator_functions(::BlockLinearOperator< Range, Domain, BlockPayload > &op)
void apply_with_intermediate_storage(const Function1 &first_op, const Function2 &loop_op, Range &v, const Domain &u, bool add)
static bool equal(const T *p1, const T *p2)