Reference documentation for deal.II version 8.5.1
petsc_matrix_free.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2012 - 2016 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 
177 //TODO: Translate the given PETSc Vec* vector into a deal.II
178 // vector so we can call the vmult function with the usual
179 // interface; then convert back. This could be much more
180 // efficient, if the PETScWrappers::*::Vector classes
181 // had a way to simply generate such a vector object from
182 // a given PETSc Vec* object without allocating new memory
183 // and without taking ownership of the Vec*
184 
185  VectorBase *x = 0;
186  VectorBase *y = 0;
187  // because we do not know,
188  // if dst and src are sequential
189  // or distributed vectors,
190  // we ask for the vector-type
191  // and reinit x and y with
192  // ::PETScWrappers::*::Vector:
193  const char *vec_type;
194  PetscErrorCode ierr = VecGetType (src, &vec_type);
195  AssertThrow (ierr == 0, ExcPETScError(ierr));
196 
197  PetscInt local_size;
198  ierr = VecGetLocalSize (src, &local_size);
199  AssertThrow (ierr == 0, ExcPETScError(ierr));
200 
201  if (strcmp(vec_type,"mpi") == 0)
202  {
203  PetscInt size;
204  ierr = VecGetSize (src, &size);
205  AssertThrow (ierr == 0, ExcPETScError(ierr));
206 
209  }
210  else if (strcmp(vec_type,"seq") == 0)
211  {
214  }
215  else
216  AssertThrow (false, ExcMessage("PETScWrappers::MPI::MatrixFree::do_matrix_vector_action: "
217  "This only works for Petsc Vec Type = VECMPI | VECSEQ"));
218 
219  // copy src to x
220  x->equ(1., PETScWrappers::VectorBase(src));
221  // and call vmult(x,y) which must
222  // be reimplemented in derived classes
223  vmult (*y, *x);
224 
225  // copy the result back to dst
226  ierr = VecCopy (static_cast<const Vec &>(*y), dst);
227  AssertThrow (ierr == 0, ExcPETScError(ierr));
228 
229  delete (x);
230  delete (y);
231  }
232 
233 
234 
235  int MatrixFree::matrix_free_mult (Mat A, Vec src, Vec dst)
236  {
237  // create a pointer to this MatrixFree
238  // object and link the given matrix A
239  // to the matrix-vector multiplication
240  // of this MatrixFree object,
241  void *this_object;
242  const PetscErrorCode ierr = MatShellGetContext (A, &this_object);
243  AssertThrow (ierr == 0, ExcPETScError(ierr));
244 
245  // call vmult of this object:
246  reinterpret_cast<MatrixFree *>(this_object)->vmult (dst, src);
247 
248  return (0);
249  }
250 
251 
252 
253  void MatrixFree::do_reinit (const unsigned int m,
254  const unsigned int n,
255  const unsigned int local_rows,
256  const unsigned int local_columns)
257  {
258  Assert (local_rows <= m, ExcDimensionMismatch (local_rows, m));
259  Assert (local_columns <= n, ExcDimensionMismatch (local_columns, n));
260 
261  // create a PETSc MatShell matrix-type
262  // object of dimension m x n and local size
263  // local_rows x local_columns
264  PetscErrorCode ierr = MatCreateShell(communicator, local_rows, local_columns,
265  m, n, (void *)this, &matrix);
266  AssertThrow (ierr == 0, ExcPETScError(ierr));
267  // register the MatrixFree::matrix_free_mult function
268  // as the matrix multiplication used by this matrix
269  ierr = MatShellSetOperation (matrix, MATOP_MULT,
271  AssertThrow (ierr == 0, ExcPETScError(ierr));
272 
273  ierr = MatSetFromOptions (matrix);
274  AssertThrow (ierr == 0, ExcPETScError(ierr));
275  }
276 }
277 
278 
279 DEAL_II_NAMESPACE_CLOSE
280 
281 #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:369
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
Definition: exceptions.h:313
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)
const MPI_Comm & get_mpi_communicator() const
void equ(const PetscScalar a, const VectorBase &V)
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()