deal.II version GIT relicensing-6842-g793a97d2aa 2026-10-02 14:00:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
petsc_matrix_free.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2012 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13
15
16#ifdef DEAL_II_WITH_PETSC
17
20
21
22#endif // DEAL_II_WITH_PETSC
23
25
26#ifdef DEAL_II_WITH_PETSC
27
28namespace PETScWrappers
29{
31 {
32 const int m = 0;
33 do_reinit(MPI_COMM_SELF, m, m, m, m);
34 }
35
36
37
38 MatrixFree::MatrixFree(const MPI_Comm communicator,
39 const unsigned int m,
40 const unsigned int n,
41 const unsigned int local_rows,
42 const unsigned int local_columns)
43 {
44 do_reinit(communicator, m, n, local_rows, local_columns);
45 }
46
47
48
50 const MPI_Comm communicator,
51 const unsigned int m,
52 const unsigned int n,
53 const std::vector<unsigned int> &local_rows_per_process,
54 const std::vector<unsigned int> &local_columns_per_process,
55 const unsigned int this_process)
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(), ExcInternalError());
61
62 do_reinit(communicator,
63 m,
64 n,
65 local_rows_per_process[this_process],
66 local_columns_per_process[this_process]);
67 }
68
69
70
71 MatrixFree::MatrixFree(const unsigned int m,
72 const unsigned int n,
73 const unsigned int local_rows,
74 const unsigned int local_columns)
75 {
76 do_reinit(MPI_COMM_WORLD, m, n, local_rows, local_columns);
77 }
78
79
80
82 const unsigned int m,
83 const unsigned int n,
84 const std::vector<unsigned int> &local_rows_per_process,
85 const std::vector<unsigned int> &local_columns_per_process,
86 const unsigned int this_process)
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(), ExcInternalError());
92
93 do_reinit(MPI_COMM_WORLD,
94 m,
95 n,
96 local_rows_per_process[this_process],
97 local_columns_per_process[this_process]);
98 }
99
100
101
102 void
103 MatrixFree::reinit(const MPI_Comm communicator,
104 const unsigned int m,
105 const unsigned int n,
106 const unsigned int local_rows,
107 const unsigned int local_columns)
108 {
109 // destroy the matrix and generate a new one
110 const PetscErrorCode ierr = MatDestroy(&matrix);
111 AssertThrow(ierr == 0, ExcPETScError(ierr));
112
113 do_reinit(communicator, m, n, local_rows, local_columns);
114 }
115
116
117
118 void
119 MatrixFree::reinit(const MPI_Comm communicator,
120 const unsigned int m,
121 const unsigned int n,
122 const std::vector<unsigned int> &local_rows_per_process,
123 const std::vector<unsigned int> &local_columns_per_process,
124 const unsigned int this_process)
125 {
126 Assert(local_rows_per_process.size() == local_columns_per_process.size(),
127 ExcDimensionMismatch(local_rows_per_process.size(),
128 local_columns_per_process.size()));
129 Assert(this_process < local_rows_per_process.size(), ExcInternalError());
130
131 const PetscErrorCode ierr = MatDestroy(&matrix);
132 AssertThrow(ierr != 0, ExcPETScError(ierr));
133
134 do_reinit(communicator,
135 m,
136 n,
137 local_rows_per_process[this_process],
138 local_columns_per_process[this_process]);
139 }
140
141
142
143 void
144 MatrixFree::reinit(const unsigned int m,
145 const unsigned int n,
146 const unsigned int local_rows,
147 const unsigned int local_columns)
148 {
149 reinit(this->get_mpi_communicator(), m, n, local_rows, local_columns);
150 }
151
152
153
154 void
155 MatrixFree::reinit(const unsigned int m,
156 const unsigned int n,
157 const std::vector<unsigned int> &local_rows_per_process,
158 const std::vector<unsigned int> &local_columns_per_process,
159 const unsigned int this_process)
160 {
162 m,
163 n,
164 local_rows_per_process,
165 local_columns_per_process,
166 this_process);
167 }
168
169
170
171 void
173 {
174 const PetscErrorCode ierr = MatDestroy(&matrix);
175 AssertThrow(ierr == 0, ExcPETScError(ierr));
176
177 const int m = 0;
178 do_reinit(MPI_COMM_SELF, m, m, m, m);
179 }
180
181
182
183 void
184 MatrixFree::vmult(Vec &dst, const Vec &src) const
185 {
186 // VectorBase permits us to manipulate, but not own, a Vec
189
190 // This is implemented by derived classes
191 vmult(y, x);
192 }
193
194
195
196 int
197 MatrixFree::matrix_free_mult(Mat A, Vec src, Vec dst)
198 {
199 // create a pointer to this MatrixFree
200 // object and link the given matrix A
201 // to the matrix-vector multiplication
202 // of this MatrixFree object,
203 void *this_object;
204 const PetscErrorCode ierr = MatShellGetContext(A, &this_object);
205 AssertThrow(ierr == 0, ExcPETScError(ierr));
206
207 // call vmult of this object:
208 reinterpret_cast<MatrixFree *>(this_object)->vmult(dst, src);
209
210 return (0);
211 }
212
213
214
215 void
216 MatrixFree::do_reinit(const MPI_Comm communicator,
217 const unsigned int m,
218 const unsigned int n,
219 const unsigned int local_rows,
220 const unsigned int local_columns)
221 {
222 Assert(local_rows <= m, ExcDimensionMismatch(local_rows, m));
223 Assert(local_columns <= n, ExcDimensionMismatch(local_columns, n));
224
225 // create a PETSc MatShell matrix-type
226 // object of dimension m x n and local size
227 // local_rows x local_columns
228 PetscErrorCode ierr = MatCreateShell(communicator,
229 local_rows,
230 local_columns,
231 m,
232 n,
233 static_cast<void *>(this),
234 &matrix);
235 AssertThrow(ierr == 0, ExcPETScError(ierr));
236 // register the MatrixFree::matrix_free_mult function
237 // as the matrix multiplication used by this matrix
238 ierr = MatShellSetOperation(
239 matrix,
240 MATOP_MULT,
241 reinterpret_cast<void (*)()>(
243 AssertThrow(ierr == 0, ExcPETScError(ierr));
244
245 ierr = MatSetFromOptions(matrix);
246 AssertThrow(ierr == 0, ExcPETScError(ierr));
247 }
248} // namespace PETScWrappers
249
250
251
252#endif // DEAL_II_WITH_PETSC
MPI_Comm get_mpi_communicator() const
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 int matrix_free_mult(Mat A, Vec src, Vec dst)
void do_reinit(const MPI_Comm comm, const unsigned int m, const unsigned int n, const unsigned int local_rows, const unsigned int local_columns)
virtual void vmult(VectorBase &dst, const VectorBase &src) const =0
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
#define AssertThrow(cond, exc)