16 #ifndef dealii_block_linear_operator_h 17 #define dealii_block_linear_operator_h 19 #include <deal.II/base/config.h> 20 #include <deal.II/base/exceptions.h> 22 #include <deal.II/lac/linear_operator.h> 25 DEAL_II_NAMESPACE_OPEN
31 namespace BlockLinearOperatorImplementation
33 template <
typename PayloadBlockType =
internal::LinearOperatorImplementation::EmptyPayload>
40 template <
typename Range = BlockVector<
double>,
41 typename Domain = Range,
42 typename BlockPayload =
internal::BlockLinearOperatorImplementation::EmptyBlockPayload<> >
45 template <
typename Range = BlockVector<
double>,
46 typename Domain = Range,
47 typename BlockPayload =
internal::BlockLinearOperatorImplementation::EmptyBlockPayload<>,
48 typename BlockMatrixType>
52 template <
size_t m,
size_t n,
54 typename Domain = Range,
61 typename Domain = Range,
68 typename Domain = Range,
80 template <
typename Range = BlockVector<
double>,
81 typename Domain = Range,
82 typename BlockPayload =
internal::BlockLinearOperatorImplementation::EmptyBlockPayload<>,
83 typename BlockMatrixType>
87 template <
typename Range = BlockVector<
double>,
88 typename Domain = Range,
89 typename BlockPayload =
internal::BlockLinearOperatorImplementation::EmptyBlockPayload<> >
94 template <
typename Range = BlockVector<
double>,
95 typename Domain = Range,
96 typename BlockPayload =
internal::BlockLinearOperatorImplementation::EmptyBlockPayload<> >
173 template <
typename Range,
typename Domain,
typename BlockPayload>
192 Assert(
false,
ExcMessage(
"Uninitialized BlockLinearOperator<Range, Domain>::n_block_rows called"));
198 Assert(
false,
ExcMessage(
"Uninitialized BlockLinearOperator<Range, Domain>::n_block_cols called"));
204 Assert(
false,
ExcMessage(
"Uninitialized BlockLinearOperator<Range, Domain>::block called"));
220 template <
typename Op>
223 *
this = block_operator<Range, Domain, BlockPayload, Op>(op);
231 template <
size_t m,
size_t n>
234 *
this = block_operator<m, n, Range, Domain, BlockPayload>(ops);
245 *
this = block_diagonal_operator<m, Range, Domain, BlockPayload>(ops);
258 template <
typename Op>
261 *
this = block_operator<Range, Domain, BlockPayload, Op>(op);
270 template <
size_t m,
size_t n>
272 operator=(
const std::array<std::array<BlockType, n>, m> &ops)
274 *
this = block_operator<m, n, Range, Domain, BlockPayload>(ops);
287 *
this = block_diagonal_operator<m, Range, Domain, BlockPayload>(ops);
308 std::function<BlockType(unsigned int, unsigned int)>
block;
315 namespace BlockLinearOperatorImplementation
319 template <
typename Range,
typename Domain,
typename BlockPayload>
321 populate_linear_operator_functions(
332 for (
unsigned int i = 0; i < m; ++i)
333 op.
block(i, 0).reinit_range_vector(v.block(i), omit_zeroing_entries);
346 for (
unsigned int i = 0; i < n; ++i)
347 op.
block(0, i).reinit_domain_vector(v.block(i), omit_zeroing_entries);
352 op.
vmult = [=](Range &v,
const Domain &u)
365 ExcMessage(
"BlockLinearOperator::vmult currently requires that " 366 "source and destination vectors are different memory " 369 for (
unsigned int i = 0; i < m; ++i)
371 op.
block(i, 0).vmult(v.block(i), u.block(0));
372 for (
unsigned int j = 1; j < n; ++j)
373 op.
block(i, j).vmult_add(v.block(i), u.block(j));
377 op.
vmult_add = [=](Range &v,
const Domain &u)
390 ExcMessage(
"BlockLinearOperator::vmult_add currently requires that " 391 "source and destination vectors are different memory " 394 for (
unsigned int i = 0; i < m; ++i)
395 for (
unsigned int j = 0; j < n; ++j)
396 op.
block(i, j).vmult_add(v.block(i), u.block(j));
399 op.
Tvmult = [=](Domain &v,
const Range &u)
412 ExcMessage(
"BlockLinearOperator::Tvmult currently requires that " 413 "source and destination vectors are different memory " 416 for (
unsigned int i = 0; i < n; ++i)
418 op.
block(0, i).Tvmult(v.block(i), u.block(0));
419 for (
unsigned int j = 1; j < m; ++j)
420 op.
block(j, i).Tvmult_add(v.block(i), u.block(j));
424 op.
Tvmult_add = [=](Domain &v,
const Range &u)
437 ExcMessage(
"BlockLinearOperator::Tvmult_add currently requires that " 438 "source and destination vectors are different memory " 441 for (
unsigned int i = 0; i < n; ++i)
442 for (
unsigned int j = 0; j < m; ++j)
443 op.
block(j, i).Tvmult_add(v.block(i), u.block(j));
462 template <
typename PayloadBlockType>
463 class EmptyBlockPayload
478 template <
typename... Args>
504 template <
typename Range,
506 typename BlockPayload,
507 typename BlockMatrixType>
515 return_op.
n_block_rows = [&block_matrix]() ->
unsigned int 517 return block_matrix.n_block_rows();
520 return_op.
n_block_cols = [&block_matrix]() ->
unsigned int 522 return block_matrix.n_block_cols();
525 return_op.
block = [&block_matrix](
unsigned int i,
unsigned int j) -> BlockType
528 const unsigned int m = block_matrix.n_block_rows();
529 const unsigned int n = block_matrix.n_block_cols();
534 return BlockType(block_matrix.block(i, j));
537 internal::BlockLinearOperatorImplementation::populate_linear_operator_functions(return_op);
570 template <
size_t m,
size_t n,
typename Range,
typename Domain,
typename BlockPayload>
574 static_assert(m > 0 && n > 0,
575 "a blocked LinearOperator must consist of at least one block");
591 return_op.
block = [ops](
unsigned int i,
unsigned int j) -> BlockType
599 internal::BlockLinearOperatorImplementation::populate_linear_operator_functions(return_op);
620 template <
typename Range,
622 typename BlockPayload,
623 typename BlockMatrixType>
631 return_op.
n_block_rows = [&block_matrix]() ->
unsigned int 633 return block_matrix.n_block_rows();
636 return_op.
n_block_cols = [&block_matrix]() ->
unsigned int 638 return block_matrix.n_block_cols();
641 return_op.
block = [&block_matrix](
unsigned int i,
unsigned int j) -> BlockType
644 const unsigned int m = block_matrix.n_block_rows();
645 const unsigned int n = block_matrix.n_block_cols();
651 return BlockType(block_matrix.block(i, j));
656 internal::BlockLinearOperatorImplementation::populate_linear_operator_functions(return_op);
679 template <
size_t m,
typename Range,
typename Domain,
typename BlockPayload>
684 "a blockdiagonal LinearOperator must consist of at least one block");
688 std::array<std::array<BlockType, m>, m> new_ops;
694 for (
unsigned int i = 0; i < m; ++i)
695 for (
unsigned int j = 0; j < m; ++j)
699 new_ops[i][j] = ops[i];
706 new_ops[i][j].reinit_domain_vector = ops[j].reinit_domain_vector;
709 return block_operator<m,m,Range,Domain>(new_ops);
723 template <
size_t m,
typename Range,
typename Domain,
typename BlockPayload>
728 "a blockdiagonal LinearOperator must consist of at least " 732 std::array<BlockType, m> new_ops;
781 template <
typename Range,
typename Domain,
typename BlockPayload>
806 diagonal_inverse.
block(0, 0).vmult(v.block(0), u.block(0));
807 for (
unsigned int i = 1; i < m; ++i)
809 auto &dst = v.block(i);
812 for (
unsigned int j = 0; j < i; ++j)
815 diagonal_inverse.
block(i, i).vmult(dst, dst);
837 diagonal_inverse.
block(0, 0).vmult_add(v.block(0), u.block(0));
839 for (
unsigned int i = 1; i < m; ++i)
841 diagonal_inverse.
block(i, i).reinit_range_vector(*tmp,
true);
844 for (
unsigned int j = 0; j < i; ++j)
847 diagonal_inverse.
block(i, i).vmult_add(v.block(i),*tmp);
891 template <
typename Range,
typename Domain,
typename BlockPayload>
916 diagonal_inverse.
block(m-1, m-1).vmult(v.block(m-1),u.block(m-1));
918 for (
int i = m - 2; i >= 0; --i)
920 auto &dst = v.block(i);
923 for (
unsigned int j = i + 1; j < m; ++j)
926 diagonal_inverse.
block(i, i).vmult(dst, dst);
947 diagonal_inverse.
block(m-1, m-1).vmult_add(v.block(m-1),u.block(m-1));
949 for (
int i = m - 2; i >= 0; --i)
951 diagonal_inverse.
block(i, i).reinit_range_vector(*tmp,
true);
954 for (
unsigned int j = i + 1; j < m; ++j)
957 diagonal_inverse.
block(i, i).vmult_add(v.block(i),*tmp);
966 DEAL_II_NAMESPACE_CLOSE
BlockLinearOperator(const std::array< BlockType, m > &ops)
LinearOperator< Domain, Range, typename BlockPayload::BlockType > block_forward_substitution(const BlockLinearOperator< Range, Domain, BlockPayload > &block_operator, const BlockLinearOperator< Domain, Range, BlockPayload > &diagonal_inverse)
BlockLinearOperator(const Op &op)
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
BlockLinearOperator< Range, Domain, BlockPayload > & operator=(const std::array< BlockType, m > &ops)
BlockLinearOperator< Range, Domain, BlockPayload > & operator=(const Op &op)
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
LinearOperator< Range, Domain, Payload > null_operator(const LinearOperator< Range, Domain, Payload > &op)
BlockLinearOperator< Range, Domain, BlockPayload > & operator=(const std::array< std::array< BlockType, n >, m > &ops)
static ::ExceptionBase & ExcMessage(std::string arg1)
BlockLinearOperator< Range, Domain, BlockPayload > block_operator(const BlockMatrixType &block_matrix)
#define Assert(cond, exc)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
BlockLinearOperator< Range, Domain, BlockPayload > & operator=(const BlockLinearOperator< Range, Domain, BlockPayload > &)=default
LinearOperator< Domain, Range, typename BlockPayload::BlockType > block_back_substitution(const BlockLinearOperator< Range, Domain, BlockPayload > &block_operator, const BlockLinearOperator< Domain, Range, BlockPayload > &diagonal_inverse)
PayloadBlockType BlockType
std::function< void(Range &v, const Domain &u)> vmult
std::function< void(Domain &v, bool omit_zeroing_entries)> reinit_domain_vector
BlockLinearOperator(const std::array< std::array< BlockType, n >, m > &ops)
std::function< void(Range &v, const Domain &u)> vmult_add
std::function< BlockType(unsigned int, unsigned int)> block
std::function< unsigned int()> n_block_cols
BlockLinearOperator(const BlockPayload &payload)
BlockLinearOperator< Range, Domain, BlockPayload > block_diagonal_operator(const BlockMatrixType &block_matrix)
EmptyBlockPayload(const Args &...)
std::function< unsigned int()> n_block_rows
static bool equal(const T *p1, const T *p2)