Reference documentation for deal.II version 9.0.0
petsc_matrix_free.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2012 - 2017 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 at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/lac/petsc_matrix_free.h>
18 
19 #ifdef DEAL_II_WITH_PETSC
20 
21 #include <deal.II/lac/exceptions.h>
22 #include <deal.II/lac/petsc_compatibility.h>
23 
24 DEAL_II_NAMESPACE_OPEN
25 
26 namespace PETScWrappers
27 {
29  : communicator (PETSC_COMM_SELF)
30  {
31  const int m=0;
32  do_reinit (m, m, m, m);
33  }
34 
35 
36 
37  MatrixFree::MatrixFree (const MPI_Comm &communicator,
38  const unsigned int m,
39  const unsigned int n,
40  const unsigned int local_rows,
41  const unsigned int local_columns)
42  : communicator (communicator)
43  {
44  do_reinit (m, n, local_rows, local_columns);
45  }
46 
47 
48 
49  MatrixFree::MatrixFree (const MPI_Comm &communicator,
50  const unsigned int m,
51  const unsigned int n,
52  const std::vector<unsigned int> &local_rows_per_process,
53  const std::vector<unsigned int> &local_columns_per_process,
54  const unsigned int this_process)
55  : communicator (communicator)
56  {
57  Assert (local_rows_per_process.size() == local_columns_per_process.size(),
58  ExcDimensionMismatch (local_rows_per_process.size(),
59  local_columns_per_process.size()));
60  Assert (this_process < local_rows_per_process.size(),
62 
63  do_reinit (m, n,
64  local_rows_per_process[this_process],
65  local_columns_per_process[this_process]);
66  }
67 
68 
69 
70  MatrixFree::MatrixFree (const unsigned int m,
71  const unsigned int n,
72  const unsigned int local_rows,
73  const unsigned int local_columns)
74  : communicator (MPI_COMM_WORLD)
75  {
76  do_reinit (m, n, local_rows, local_columns);
77  }
78 
79 
80 
81  MatrixFree::MatrixFree (const unsigned int m,
82  const unsigned int n,
83  const std::vector<unsigned int> &local_rows_per_process,
84  const std::vector<unsigned int> &local_columns_per_process,
85  const unsigned int this_process)
86  : communicator (MPI_COMM_WORLD)
87  {
88  Assert (local_rows_per_process.size() == local_columns_per_process.size(),
89  ExcDimensionMismatch (local_rows_per_process.size(),
90  local_columns_per_process.size()));
91  Assert (this_process < local_rows_per_process.size(),
93 
94  do_reinit (m, n,
95  local_rows_per_process[this_process],
96  local_columns_per_process[this_process]);
97  }
98 
99 
100 
101  void MatrixFree::reinit (const MPI_Comm &communicator,
102  const unsigned int m,
103  const unsigned int n,
104  const unsigned int local_rows,
105  const unsigned int local_columns)
106  {
107  this->communicator = communicator;
108 
109  // destroy the matrix and generate a new one
110  const PetscErrorCode ierr = destroy_matrix (matrix);
111  AssertThrow (ierr == 0, ExcPETScError (ierr));
112 
113  do_reinit (m, n, local_rows, local_columns);
114  }
115 
116 
117 
118  void MatrixFree::reinit (const MPI_Comm &communicator,
119  const unsigned int m,
120  const unsigned int n,
121  const std::vector<unsigned int> &local_rows_per_process,
122  const std::vector<unsigned int> &local_columns_per_process,
123  const unsigned int this_process)
124  {
125  Assert (local_rows_per_process.size() == local_columns_per_process.size(),
126  ExcDimensionMismatch (local_rows_per_process.size(),
127  local_columns_per_process.size()));
128  Assert (this_process < local_rows_per_process.size(),
129  ExcInternalError());
130 
131  this->communicator = communicator;
132  const PetscErrorCode ierr = destroy_matrix (matrix);
133  AssertThrow (ierr != 0, ExcPETScError (ierr));
134 
135  do_reinit (m, n,
136  local_rows_per_process[this_process],
137  local_columns_per_process[this_process]);
138  }
139 
140 
141 
142  void MatrixFree::reinit (const unsigned int m,
143  const unsigned int n,
144  const unsigned int local_rows,
145  const unsigned int local_columns)
146  {
147  reinit (MPI_COMM_WORLD, m, n, local_rows, local_columns);
148  }
149 
150 
151 
152  void MatrixFree::reinit (const unsigned int m,
153  const unsigned int n,
154  const std::vector<unsigned int> &local_rows_per_process,
155  const std::vector<unsigned int> &local_columns_per_process,
156  const unsigned int this_process)
157  {
158  reinit (MPI_COMM_WORLD, m, n, local_rows_per_process, local_columns_per_process, this_process);
159  }
160 
161 
162 
164  {
165  const PetscErrorCode ierr = destroy_matrix (matrix);
166  AssertThrow (ierr == 0, ExcPETScError (ierr));
167 
168  const int m=0;
169  do_reinit (m, m, m, m);
170  }
171 
172 
173 
174  void MatrixFree::vmult (Vec &dst, const Vec &src) const
175  {
176  // VectorBase permits us to manipulate, but not own, a Vec
179 
180  // This is implemented by derived classes
181  vmult (y, x);
182  }
183 
184 
185 
186  int MatrixFree::matrix_free_mult (Mat A, Vec src, Vec dst)
187  {
188  // create a pointer to this MatrixFree
189  // object and link the given matrix A
190  // to the matrix-vector multiplication
191  // of this MatrixFree object,
192  void *this_object;
193  const PetscErrorCode ierr = MatShellGetContext (A, &this_object);
194  AssertThrow (ierr == 0, ExcPETScError(ierr));
195 
196  // call vmult of this object:
197  reinterpret_cast<MatrixFree *>(this_object)->vmult (dst, src);
198 
199  return (0);
200  }
201 
202 
203 
204  void MatrixFree::do_reinit (const unsigned int m,
205  const unsigned int n,
206  const unsigned int local_rows,
207  const unsigned int local_columns)
208  {
209  Assert (local_rows <= m, ExcDimensionMismatch (local_rows, m));
210  Assert (local_columns <= n, ExcDimensionMismatch (local_columns, n));
211 
212  // create a PETSc MatShell matrix-type
213  // object of dimension m x n and local size
214  // local_rows x local_columns
215  PetscErrorCode ierr = MatCreateShell(communicator, local_rows, local_columns,
216  m, n, (void *)this, &matrix);
217  AssertThrow (ierr == 0, ExcPETScError(ierr));
218  // register the MatrixFree::matrix_free_mult function
219  // as the matrix multiplication used by this matrix
220  ierr = MatShellSetOperation (matrix, MATOP_MULT,
222  AssertThrow (ierr == 0, ExcPETScError(ierr));
223 
224  ierr = MatSetFromOptions (matrix);
225  AssertThrow (ierr == 0, ExcPETScError(ierr));
226  }
227 }
228 
229 
230 DEAL_II_NAMESPACE_CLOSE
231 
232 #endif // DEAL_II_WITH_PETSC
PetscErrorCode destroy_matrix(Mat &matrix)
virtual void vmult(VectorBase &dst, const VectorBase &src) const =0
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
#define Assert(cond, exc)
Definition: exceptions.h:1142
void reinit(const MPI_Comm &communicator, const unsigned int m, const unsigned int n, const unsigned int local_rows, const unsigned int local_columns)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static int matrix_free_mult(Mat A, Vec src, Vec dst)
void do_reinit(const unsigned int m, const unsigned int n, const unsigned int local_rows, const unsigned int local_columns)
static ::ExceptionBase & ExcInternalError()