Reference documentation for deal.II version 9.1.0-pre
petsc_sparse_matrix.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/lac/petsc_sparse_matrix.h>
17 
18 #ifdef DEAL_II_WITH_PETSC
19 
20 # include <deal.II/lac/dynamic_sparsity_pattern.h>
21 # include <deal.II/lac/exceptions.h>
22 # include <deal.II/lac/petsc_compatibility.h>
23 # include <deal.II/lac/petsc_vector_base.h>
24 # include <deal.II/lac/sparsity_pattern.h>
25 
26 DEAL_II_NAMESPACE_OPEN
27 
28 namespace PETScWrappers
29 {
31  {
32  const int m = 0, n = 0, n_nonzero_per_row = 0;
33  const PetscErrorCode ierr = MatCreateSeqAIJ(
34  PETSC_COMM_SELF, m, n, n_nonzero_per_row, nullptr, &matrix);
35  AssertThrow(ierr == 0, ExcPETScError(ierr));
36  }
37 
38 
39 
41  const size_type n,
42  const size_type n_nonzero_per_row,
43  const bool is_symmetric)
44  {
45  do_reinit(m, n, n_nonzero_per_row, is_symmetric);
46  }
47 
48 
49 
51  const size_type n,
52  const std::vector<size_type> &row_lengths,
53  const bool is_symmetric)
54  {
55  do_reinit(m, n, row_lengths, is_symmetric);
56  }
57 
58 
59 
60  template <typename SparsityPatternType>
61  SparseMatrix::SparseMatrix(const SparsityPatternType &sparsity_pattern,
62  const bool preset_nonzero_locations)
63  {
64  do_reinit(sparsity_pattern, preset_nonzero_locations);
65  }
66 
67 
68 
69  SparseMatrix &
70  SparseMatrix::operator=(const double d)
71  {
73  return *this;
74  }
75 
76 
77 
78  void
80  const size_type n,
81  const size_type n_nonzero_per_row,
82  const bool is_symmetric)
83  {
84  // get rid of old matrix and generate a
85  // new one
86  const PetscErrorCode ierr = destroy_matrix(matrix);
87  AssertThrow(ierr == 0, ExcPETScError(ierr));
88 
89  do_reinit(m, n, n_nonzero_per_row, is_symmetric);
90  }
91 
92 
93 
94  void
96  const size_type n,
97  const std::vector<size_type> &row_lengths,
98  const bool is_symmetric)
99  {
100  // get rid of old matrix and generate a
101  // new one
102  const PetscErrorCode ierr = destroy_matrix(matrix);
103  AssertThrow(ierr == 0, ExcPETScError(ierr));
104 
105  do_reinit(m, n, row_lengths, is_symmetric);
106  }
107 
108 
109 
110  template <typename SparsityPatternType>
111  void
112  SparseMatrix::reinit(const SparsityPatternType &sparsity_pattern,
113  const bool preset_nonzero_locations)
114  {
115  // get rid of old matrix and generate a
116  // new one
117  const PetscErrorCode ierr = destroy_matrix(matrix);
118  AssertThrow(ierr == 0, ExcPETScError(ierr));
119 
120  do_reinit(sparsity_pattern, preset_nonzero_locations);
121  }
122 
123 
124 
125  const MPI_Comm &
127  {
128  static MPI_Comm comm;
129  const PetscErrorCode ierr = PetscObjectGetComm((PetscObject)matrix, &comm);
130  AssertThrow(ierr == 0, ExcPETScError(ierr));
131  return comm;
132  }
133 
134 
135 
136  void
138  const size_type n,
139  const size_type n_nonzero_per_row,
140  const bool is_symmetric)
141  {
142  // use the call sequence indicating only
143  // a maximal number of elements per row
144  // for all rows globally
145  const PetscErrorCode ierr = MatCreateSeqAIJ(
146  PETSC_COMM_SELF, m, n, n_nonzero_per_row, nullptr, &matrix);
147  AssertThrow(ierr == 0, ExcPETScError(ierr));
148 
149  // set symmetric flag, if so requested
150  if (is_symmetric == true)
151  {
152  set_matrix_option(matrix, MAT_SYMMETRIC, PETSC_TRUE);
153  }
154  }
155 
156 
157 
158  void
160  const size_type n,
161  const std::vector<size_type> &row_lengths,
162  const bool is_symmetric)
163  {
164  Assert(row_lengths.size() == m,
165  ExcDimensionMismatch(row_lengths.size(), m));
166 
167  // use the call sequence indicating a
168  // maximal number of elements for each
169  // row individually. annoyingly, we
170  // always use unsigned ints for cases
171  // like this, while PETSc wants to see
172  // signed integers. so we have to
173  // convert, unless we want to play dirty
174  // tricks with conversions of pointers
175  const std::vector<PetscInt> int_row_lengths(row_lengths.begin(),
176  row_lengths.end());
177 
178  const PetscErrorCode ierr = MatCreateSeqAIJ(
179  PETSC_COMM_SELF, m, n, 0, int_row_lengths.data(), &matrix);
180  AssertThrow(ierr == 0, ExcPETScError(ierr));
181 
182  // set symmetric flag, if so requested
183  if (is_symmetric == true)
184  {
185  set_matrix_option(matrix, MAT_SYMMETRIC, PETSC_TRUE);
186  }
187  }
188 
189 
190 
191  template <typename SparsityPatternType>
192  void
193  SparseMatrix::do_reinit(const SparsityPatternType &sparsity_pattern,
194  const bool preset_nonzero_locations)
195  {
196  std::vector<size_type> row_lengths(sparsity_pattern.n_rows());
197  for (size_type i = 0; i < sparsity_pattern.n_rows(); ++i)
198  row_lengths[i] = sparsity_pattern.row_length(i);
199 
200  do_reinit(sparsity_pattern.n_rows(),
201  sparsity_pattern.n_cols(),
202  row_lengths,
203  false);
204 
205  // next preset the exact given matrix
206  // entries with zeros, if the user
207  // requested so. this doesn't avoid any
208  // memory allocations, but it at least
209  // avoids some searches later on. the
210  // key here is that we can use the
211  // matrix set routines that set an
212  // entire row at once, not a single
213  // entry at a time
214  //
215  // for the usefulness of this option
216  // read the documentation of this
217  // class.
218  if (preset_nonzero_locations == true)
219  {
220  std::vector<PetscInt> row_entries;
221  std::vector<PetscScalar> row_values;
222  for (size_type i = 0; i < sparsity_pattern.n_rows(); ++i)
223  {
224  row_entries.resize(row_lengths[i]);
225  row_values.resize(row_lengths[i], 0.0);
226  for (size_type j = 0; j < row_lengths[i]; ++j)
227  row_entries[j] = sparsity_pattern.column_number(i, j);
228 
229  const PetscInt int_row = i;
230  const PetscErrorCode ierr = MatSetValues(matrix,
231  1,
232  &int_row,
233  row_lengths[i],
234  row_entries.data(),
235  row_values.data(),
236  INSERT_VALUES);
237  AssertThrow(ierr == 0, ExcPETScError(ierr));
238  }
240 
243  }
244  }
245 
246  size_t
248  {
249  PetscInt m, n;
250  const PetscErrorCode ierr = MatGetSize(matrix, &m, &n);
251  AssertThrow(ierr == 0, ExcPETScError(ierr));
252 
253  return m;
254  }
255 
256  size_t
258  {
259  PetscInt m, n;
260  const PetscErrorCode ierr = MatGetSize(matrix, &m, &n);
261  AssertThrow(ierr == 0, ExcPETScError(ierr));
262 
263  return n;
264  }
265 
266  void
268  const SparseMatrix &B,
269  const MPI::Vector & V) const
270  {
271  // Simply forward to the protected member function of the base class
272  // that takes abstract matrix and vector arguments (to which the compiler
273  // automatically casts the arguments).
274  MatrixBase::mmult(C, B, V);
275  }
276 
277  void
279  const SparseMatrix &B,
280  const MPI::Vector & V) const
281  {
282  // Simply forward to the protected member function of the base class
283  // that takes abstract matrix and vector arguments (to which the compiler
284  // automatically casts the arguments).
285  MatrixBase::Tmmult(C, B, V);
286  }
287 
288  // Explicit instantiations
289  //
290  template SparseMatrix::SparseMatrix(const SparsityPattern &, const bool);
292  const bool);
293 
294  template void
295  SparseMatrix::reinit(const SparsityPattern &, const bool);
296  template void
297  SparseMatrix::reinit(const DynamicSparsityPattern &, const bool);
298 
299  template void
300  SparseMatrix::do_reinit(const SparsityPattern &, const bool);
301  template void
302  SparseMatrix::do_reinit(const DynamicSparsityPattern &, const bool);
303 } // namespace PETScWrappers
304 
305 
306 DEAL_II_NAMESPACE_CLOSE
307 
308 #endif // DEAL_II_WITH_PETSC
PetscErrorCode destroy_matrix(Mat &matrix)
void Tmmult(MatrixBase &C, const MatrixBase &B, const VectorBase &V) const
virtual const MPI_Comm & get_mpi_communicator() const override
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
void Tmmult(SparseMatrix &C, const SparseMatrix &B, const MPI::Vector &V=MPI::Vector()) const
void set_matrix_option(Mat &matrix, const MatOption option_name, const PetscBool option_value=PETSC_FALSE)
PetscBool is_symmetric(const double tolerance=1.e-12)
void mmult(MatrixBase &C, const MatrixBase &B, const VectorBase &V) const
void compress(const VectorOperation::values operation)
MatrixBase & operator=(const MatrixBase &)=delete
SparseMatrix & operator=(const double d)
void reinit(const size_type m, const size_type n, const size_type n_nonzero_per_row, const bool is_symmetric=false)
#define Assert(cond, exc)
Definition: exceptions.h:1227
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
void set_keep_zero_rows(Mat &matrix)
types::global_dof_index size_type
void mmult(SparseMatrix &C, const SparseMatrix &B, const MPI::Vector &V=MPI::Vector()) const
void do_reinit(const size_type m, const size_type n, const size_type n_nonzero_per_row, const bool is_symmetric=false)
void close_matrix(Mat &matrix)