13#ifndef dealii_petsc_matrix_base_h
14#define dealii_petsc_matrix_base_h
19#ifdef DEAL_II_WITH_PETSC
29# include <boost/container/small_vector.hpp>
42#ifdef DEAL_II_WITH_PETSC
45template <
typename Matrix>
55 namespace MatrixIterators
134 <<
"You tried to access row " << arg1
135 <<
" of a distributed matrix, but only rows " << arg2
136 <<
" through " << arg3
137 <<
" are stored locally and can be accessed.");
250 <<
"Attempt to access element " << arg2 <<
" of row "
251 << arg1 <<
" which doesn't have that many elements.");
418 set(
const std::vector<size_type> &indices,
420 const bool elide_zero_values =
false);
428 set(
const std::vector<size_type> &row_indices,
429 const std::vector<size_type> &col_indices,
431 const bool elide_zero_values =
false);
449 const std::vector<size_type> &col_indices,
450 const std::vector<PetscScalar> &values,
451 const bool elide_zero_values =
false);
471 const PetscScalar *values,
472 const bool elide_zero_values =
false);
506 add(
const std::vector<size_type> &indices,
508 const bool elide_zero_values =
true);
516 add(
const std::vector<size_type> &row_indices,
517 const std::vector<size_type> &col_indices,
519 const bool elide_zero_values =
true);
537 const std::vector<size_type> &col_indices,
538 const std::vector<PetscScalar> &values,
539 const bool elide_zero_values =
true);
559 const PetscScalar *values,
560 const bool elide_zero_values =
true,
561 const bool col_indices_are_sorted =
false);
592 const PetscScalar new_diag_value = 0);
599 const PetscScalar new_diag_value = 0);
682 std::pair<size_type, size_type>
707 std::pair<size_type, size_type>
942 operator Mat()
const;
980 write_ascii(
const PetscViewerFormat format = PETSC_VIEWER_DEFAULT);
990 print(std::ostream &out,
const bool alternative_output =
false)
const;
1002 "You are attempting an operation on two vectors that "
1003 "are the same object, but the operation requires that the "
1004 "two objects are in fact different.");
1012 <<
"You tried to do a "
1013 << (arg1 == 1 ?
"'set'" : (arg1 == 2 ?
"'add'" :
"???"))
1014 <<
" operation but the matrix is currently in "
1015 << (arg2 == 1 ?
"'set'" : (arg2 == 2 ?
"'add'" :
"???"))
1016 <<
" mode. You first have to call 'compress()'.");
1106 friend class ::BlockMatrixBase;
1117 const PetscScalar *values,
1118 const bool elide_zero_values);
1127 namespace MatrixIterators
1130 const size_type row,
1131 const size_type index)
1136 visit_present_row();
1141 inline const_iterator::Accessor::size_type
1142 const_iterator::Accessor::row()
const
1144 Assert(a_row < matrix->m(), ExcBeyondEndOfMatrix());
1149 inline const_iterator::Accessor::size_type
1150 const_iterator::Accessor::column()
const
1152 Assert(a_row < matrix->m(), ExcBeyondEndOfMatrix());
1153 return (*colnum_cache)[a_index];
1157 inline const_iterator::Accessor::size_type
1158 const_iterator::Accessor::index()
const
1160 Assert(a_row < matrix->m(), ExcBeyondEndOfMatrix());
1166 const_iterator::Accessor::value()
const
1168 Assert(a_row < matrix->m(), ExcBeyondEndOfMatrix());
1169 return (*value_cache)[a_index];
1173 inline const_iterator::const_iterator(
const MatrixBase *matrix,
1174 const size_type row,
1175 const size_type index)
1182 const_iterator::operator++()
1190 if (accessor.a_index >= accessor.colnum_cache->size())
1192 accessor.a_index = 0;
1195 while ((accessor.a_row < accessor.matrix->m()) &&
1196 (accessor.a_row < accessor.matrix->local_range().second) &&
1197 (accessor.matrix->row_length(accessor.a_row) == 0))
1200 accessor.visit_present_row();
1207 const_iterator::operator++(
int)
1215 inline const const_iterator::Accessor &
1216 const_iterator::operator*()
const
1222 inline const const_iterator::Accessor *
1223 const_iterator::operator->()
const
1230 const_iterator::operator==(
const const_iterator &other)
const
1232 return (accessor.a_row == other.accessor.a_row &&
1233 accessor.a_index == other.accessor.a_index);
1238 const_iterator::operator!=(
const const_iterator &other)
const
1240 return !(*
this == other);
1245 const_iterator::operator<(
const const_iterator &other)
const
1247 return (accessor.row() < other.accessor.row() ||
1248 (accessor.row() == other.accessor.row() &&
1249 accessor.index() < other.accessor.index()));
1264 MatrixBase::set(
const size_type i,
const size_type j,
const PetscScalar value)
1268 set(i, 1, &j, &value,
false);
1274 MatrixBase::set(
const std::vector<size_type> &indices,
1276 const bool elide_zero_values)
1282 for (size_type i = 0; i < indices.size(); ++i)
1293 MatrixBase::set(
const std::vector<size_type> &row_indices,
1294 const std::vector<size_type> &col_indices,
1296 const bool elide_zero_values)
1303 for (size_type i = 0; i < row_indices.size(); ++i)
1314 MatrixBase::set(
const size_type row,
1315 const std::vector<size_type> &col_indices,
1316 const std::vector<PetscScalar> &values,
1317 const bool elide_zero_values)
1332 MatrixBase::set(
const size_type row,
1333 const size_type n_cols,
1334 const size_type *col_indices,
1335 const PetscScalar *values,
1336 const bool elide_zero_values)
1349 MatrixBase::add(
const size_type i,
const size_type j,
const PetscScalar value)
1353 if (value == PetscScalar())
1364 add(i, 1, &j, &value,
false);
1370 MatrixBase::add(
const std::vector<size_type> &indices,
1372 const bool elide_zero_values)
1378 for (size_type i = 0; i < indices.size(); ++i)
1389 MatrixBase::add(
const std::vector<size_type> &row_indices,
1390 const std::vector<size_type> &col_indices,
1392 const bool elide_zero_values)
1399 for (size_type i = 0; i < row_indices.size(); ++i)
1410 MatrixBase::add(
const size_type row,
1411 const std::vector<size_type> &col_indices,
1412 const std::vector<PetscScalar> &values,
1413 const bool elide_zero_values)
1428 MatrixBase::add(
const size_type row,
1429 const size_type n_cols,
1430 const size_type *col_indices,
1431 const PetscScalar *values,
1432 const bool elide_zero_values,
1447 const size_type row,
1448 const size_type n_cols,
1449 const size_type *col_indices,
1450 const PetscScalar *values,
1451 const bool elide_zero_values)
1453 prepare_action(operation);
1455 const auto petsc_row =
static_cast<PetscInt
>(row);
1465 boost::container::small_vector<PetscInt, 100> column_indices;
1466 std::optional<boost::container::small_vector<PetscScalar, 100>>
1469 const PetscScalar *values_ptr =
nullptr;
1470 if (elide_zero_values ==
false)
1472 column_indices.resize(n_cols);
1474 for (size_type j = 0; j < n_cols; ++j)
1477 column_indices[j] =
static_cast<PetscInt
>(col_indices[j]);
1487 column_values.emplace();
1488 for (size_type j = 0; j < n_cols; ++j)
1492 if (value != PetscScalar())
1494 column_indices.push_back(
static_cast<PetscInt
>(col_indices[j]));
1496 column_values->push_back(value);
1499 values_ptr = column_values->data();
1502 const auto petsc_n_columns =
static_cast<PetscInt
>(column_indices.size());
1508 const PetscErrorCode ierr =
1509 MatSetValues(matrix,
1513 column_indices.data(),
1523 MatrixBase::operator()(
const size_type i,
const size_type j)
const
1530 inline MatrixBase::const_iterator
1531 MatrixBase::begin()
const
1534 (in_local_range(0) && in_local_range(m() - 1)),
1536 "begin() and end() can only be called on a processor owning the entire matrix. If this is a distributed matrix, use begin(row) and end(row) instead."));
1541 while ((first_nonempty_row < m()) && (row_length(first_nonempty_row) == 0))
1542 ++first_nonempty_row;
1548 inline MatrixBase::const_iterator
1549 MatrixBase::end()
const
1552 (in_local_range(0) && in_local_range(m() - 1)),
1554 "begin() and end() can only be called on a processor owning the entire matrix. If this is a distributed matrix, use begin(row) and end(row) instead."));
1560 inline MatrixBase::const_iterator
1561 MatrixBase::begin(
const size_type r)
const
1563 Assert(in_local_range(r),
1566 if (row_length(r) > 0)
1573 inline MatrixBase::const_iterator
1574 MatrixBase::end(
const size_type r)
const
1576 Assert(in_local_range(r),
1589 for (size_type i = r + 1; i < m(); ++i)
1590 if (i ==
local_range().second || (row_length(i) > 0))
1597 return {
this, m(), 0};
1603 MatrixBase::in_local_range(
const size_type index)
const
1605 PetscInt petsc_begin, petsc_end;
1607 const PetscErrorCode ierr =
1608 MatGetOwnershipRange(
static_cast<const Mat &
>(matrix),
1618 return ((index >=
begin) && (index <
end));
1627 last_action = new_action;
1629 Assert(last_action == new_action, ExcWrongMode(last_action, new_action));
1635 MatrixBase::assert_is_compressed()
1640 ExcMessage(
"Error: missing compress() call."));
1646 MatrixBase::prepare_add()
1654 MatrixBase::prepare_set()
1660 MatrixBase::get_mpi_communicator()
const
1662 return PetscObjectComm(
reinterpret_cast<PetscObject
>(matrix));
* x_component_mask set(0, true)
* * const_iterator()=default
void add(const size_type i, const size_type j, const PetscScalar value)
void add(const std::vector< size_type > &row_indices, const std::vector< size_type > &col_indices, const FullMatrix< PetscScalar > &full_matrix, const bool elide_zero_values=true)
const_iterator end(const size_type r) const
size_type row_length(const size_type row) const
std::size_t memory_consumption() const
PetscReal l1_norm() const
VectorOperation::values last_action
void vmult(VectorBase &dst, const VectorBase &src) const
MPI_Comm get_mpi_communicator() const
PetscScalar diag_element(const size_type i) const
MatrixBase(const MatrixBase &)=delete
size_type local_domain_size() const
const_iterator begin() const
MatrixBase & operator/=(const PetscScalar factor)
void mmult(MatrixBase &C, const MatrixBase &B, const VectorBase &V) const
PetscBool is_symmetric(const double tolerance=1.e-12)
PetscReal frobenius_norm() const
virtual ~MatrixBase() override
std::pair< size_type, size_type > local_domain() const
const_iterator end() const
void Tvmult_add(VectorBase &dst, const VectorBase &src) const
void print(std::ostream &out, const bool alternative_output=false) const
const_iterator begin(const size_type r) const
void add_or_set(const VectorOperation::values &operation, const size_type row, const size_type n_cols, const size_type *col_indices, const PetscScalar *values, const bool elide_zero_values)
void add(const size_type row, const std::vector< size_type > &col_indices, const std::vector< PetscScalar > &values, const bool elide_zero_values=true)
PetscScalar el(const size_type i, const size_type j) const
size_type local_size() const
PetscScalar operator()(const size_type i, const size_type j) const
MatrixBase & operator=(const MatrixBase &)=delete
void set(const std::vector< size_type > &row_indices, const std::vector< size_type > &col_indices, const FullMatrix< PetscScalar > &full_matrix, const bool elide_zero_values=false)
PetscScalar trace() const
void prepare_action(const VectorOperation::values new_action)
void add(const std::vector< size_type > &indices, const FullMatrix< PetscScalar > &full_matrix, const bool elide_zero_values=true)
bool in_local_range(const size_type index) const
PetscBool is_hermitian(const double tolerance=1.e-12)
PetscScalar matrix_scalar_product(const VectorBase &u, const VectorBase &v) const
void assert_is_compressed()
void Tvmult(VectorBase &dst, const VectorBase &src) const
void clear_rows_columns(const std::vector< size_type > &row_and_column_indices, const PetscScalar new_diag_value=0)
MatrixBase & operator*=(const PetscScalar factor)
PetscScalar residual(VectorBase &dst, const VectorBase &x, const VectorBase &b) const
void Tmmult(MatrixBase &C, const MatrixBase &B, const VectorBase &V) const
void set(const size_type row, const std::vector< size_type > &col_indices, const std::vector< PetscScalar > &values, const bool elide_zero_values=false)
void add(const size_type row, const size_type n_cols, const size_type *col_indices, const PetscScalar *values, const bool elide_zero_values=true, const bool col_indices_are_sorted=false)
void write_ascii(const PetscViewerFormat format=PETSC_VIEWER_DEFAULT)
void vmult_add(VectorBase &dst, const VectorBase &src) const
std::pair< size_type, size_type > local_range() const
void compress(const VectorOperation::values operation)
PetscScalar matrix_norm_square(const VectorBase &v) const
void set(const size_type row, const size_type n_cols, const size_type *col_indices, const PetscScalar *values, const bool elide_zero_values=false)
void clear_rows(const ArrayView< const size_type > &rows, const PetscScalar new_diag_value=0)
void set(const std::vector< size_type > &indices, const FullMatrix< PetscScalar > &full_matrix, const bool elide_zero_values=false)
void set(const size_type i, const size_type j, const PetscScalar value)
std::uint64_t n_nonzero_elements() const
void clear_row(const size_type row, const PetscScalar new_diag_value=0)
PetscReal linfty_norm() const
std::shared_ptr< const std::vector< PetscScalar > > value_cache
PetscScalar value() const
std::shared_ptr< const std::vector< size_type > > colnum_cache
Accessor(const MatrixBase *matrix, const size_type row, const size_type index)
const_iterator operator++(int)
bool operator!=(const const_iterator &) const
const_iterator(const MatrixBase *matrix, const size_type row, const size_type index)
bool operator==(const const_iterator &) const
bool operator<(const const_iterator &) const
const_iterator & operator++()
const Accessor * operator->() const
const Accessor & operator*() const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define AssertIntegerConversion(index1, index2)
#define DeclException0(Exception0)
static ::ExceptionBase & ExcAccessToNonlocalRow(int arg1, int arg2, int arg3)
#define Assert(cond, exc)
static ::ExceptionBase & ExcIteratorPastEnd()
static ::ExceptionBase & ExcInvalidIndexWithinRow(int arg1, int arg2)
#define AssertIsFinite(number)
#define DeclException2(Exception2, type1, type2, outsequence)
static ::ExceptionBase & ExcBeyondEndOfMatrix()
#define DeclExceptionMsg(Exception, defaulttext)
static ::ExceptionBase & ExcSourceEqualsDestination()
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcWrongMode(int arg1, int arg2)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
static ::ExceptionBase & ExcIndexRange(std::size_t arg1, std::size_t arg2, std::size_t arg3)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcNotQuadratic()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::pair< types::global_dof_index, types::global_dof_index > local_range
types::global_dof_index size_type
@ matrix
Contents is actually a matrix.
unsigned int global_dof_index