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_parallel_sparse_matrix.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) 2004 - 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
14
15#ifdef DEAL_II_WITH_PETSC
16
17# include <deal.II/base/mpi.h>
18
24
25
26#endif // DEAL_II_WITH_PETSC
27
29
30#ifdef DEAL_II_WITH_PETSC
31
32namespace PETScWrappers
33{
34 namespace MPI
35 {
37 {
38 // just like for vectors: since we
39 // create an empty matrix, we can as
40 // well make it sequential
41 const int m = 0, n = 0, n_nonzero_per_row = 0;
42 const PetscErrorCode ierr = MatCreateSeqAIJ(
43 PETSC_COMM_SELF, m, n, n_nonzero_per_row, nullptr, &matrix);
44 AssertThrow(ierr == 0, ExcPETScError(ierr));
45 }
46
48 : MatrixBase(A)
49 {}
50
52 {
53 PetscErrorCode ierr = MatDestroy(&matrix);
54 AssertNothrow(ierr == 0, ExcPETScError(ierr));
55 }
56
57
58
59 template <typename SparsityPatternType>
61 const MPI_Comm communicator,
62 const SparsityPatternType &sparsity_pattern,
63 const std::vector<size_type> &local_rows_per_process,
64 const std::vector<size_type> &local_columns_per_process,
65 const unsigned int this_process,
66 const bool preset_nonzero_locations)
67 {
68 do_reinit(communicator,
69 sparsity_pattern,
70 local_rows_per_process,
71 local_columns_per_process,
72 this_process,
73 preset_nonzero_locations);
74 }
75
76
77
78 void
80 {
81 if (&other == this)
82 return;
83
84 PetscErrorCode ierr = MatDestroy(&matrix);
85 AssertThrow(ierr == 0, ExcPETScError(ierr));
86
87 ierr = MatDuplicate(other.matrix, MAT_DO_NOT_COPY_VALUES, &matrix);
88 AssertThrow(ierr == 0, ExcPETScError(ierr));
89 }
90
91 template <typename SparsityPatternType>
92 void
93 SparseMatrix::reinit(const IndexSet &local_rows,
94 const IndexSet &local_active_rows,
95 const IndexSet &local_columns,
96 const IndexSet &local_active_columns,
97 const SparsityPatternType &sparsity_pattern,
98 const MPI_Comm communicator)
99 {
100 // get rid of old matrix and generate a new one
101 const PetscErrorCode ierr = MatDestroy(&matrix);
102 AssertThrow(ierr == 0, ExcPETScError(ierr));
103
104 do_reinit(communicator,
105 local_rows,
106 local_active_rows,
107 local_columns,
108 local_active_columns,
109 sparsity_pattern);
110 }
111
112
115 {
117 return *this;
118 }
119
120 void
122 {
123 if (&other == this)
124 return;
125
126 const PetscErrorCode ierr =
127 MatCopy(other.matrix, matrix, SAME_NONZERO_PATTERN);
128 AssertThrow(ierr == 0, ExcPETScError(ierr));
129 }
130
131
132
133 template <typename SparsityPatternType>
134 void
136 const MPI_Comm communicator,
137 const SparsityPatternType &sparsity_pattern,
138 const std::vector<size_type> &local_rows_per_process,
139 const std::vector<size_type> &local_columns_per_process,
140 const unsigned int this_process,
141 const bool preset_nonzero_locations)
142 {
143 // get rid of old matrix and generate a new one
144 const PetscErrorCode ierr = MatDestroy(&matrix);
145 AssertThrow(ierr == 0, ExcPETScError(ierr));
146
147
148 do_reinit(communicator,
149 sparsity_pattern,
150 local_rows_per_process,
151 local_columns_per_process,
152 this_process,
153 preset_nonzero_locations);
154 }
155
156
157
158 template <typename SparsityPatternType>
159 void
161 const SparsityPatternType &sparsity_pattern,
162 const MPI_Comm communicator)
163 {
164 do_reinit(communicator, local_rows, local_rows, sparsity_pattern);
165 }
166
167 template <typename SparsityPatternType>
168 void
170 const IndexSet &local_columns,
171 const SparsityPatternType &sparsity_pattern,
172 const MPI_Comm communicator)
173 {
174 // get rid of old matrix and generate a new one
175 const PetscErrorCode ierr = MatDestroy(&matrix);
176 AssertThrow(ierr == 0, ExcPETScError(ierr));
177
178 do_reinit(communicator, local_rows, local_columns, sparsity_pattern);
179 }
180
181
182
183 template <typename SparsityPatternType>
184 void
186 const IndexSet &local_rows,
187 const IndexSet &local_columns,
188 const SparsityPatternType &sparsity_pattern)
189 {
190 // If the sparsity pattern's dimensions can be converted to PetscInts then
191 // the rest of the conversions will succeed
192 AssertThrowIntegerConversion(static_cast<PetscInt>(
193 sparsity_pattern.n_rows()),
194 sparsity_pattern.n_rows());
195 AssertThrowIntegerConversion(static_cast<PetscInt>(
196 sparsity_pattern.n_cols()),
197 sparsity_pattern.n_cols());
198
199 Assert(sparsity_pattern.n_rows() == local_rows.size(),
201 "SparsityPattern and IndexSet have different number of rows"));
202 Assert(
203 sparsity_pattern.n_cols() == local_columns.size(),
205 "SparsityPattern and IndexSet have different number of columns"));
206 Assert(local_rows.is_contiguous() && local_columns.is_contiguous(),
207 ExcMessage("PETSc only supports contiguous row/column ranges"));
208 Assert(local_rows.is_ascending_and_one_to_one(communicator),
210
211 if constexpr (running_in_debug_mode())
212 {
213 // check indexsets
214 types::global_dof_index row_owners =
215 Utilities::MPI::sum(local_rows.n_elements(), communicator);
216 types::global_dof_index col_owners =
217 Utilities::MPI::sum(local_columns.n_elements(), communicator);
218 Assert(
219 row_owners == sparsity_pattern.n_rows(),
221 std::string(
222 "Each row has to be owned by exactly one owner (n_rows()=") +
223 std::to_string(sparsity_pattern.n_rows()) +
224 " but sum(local_rows.n_elements())=" +
225 std::to_string(row_owners) + ")"));
226 Assert(
227 col_owners == sparsity_pattern.n_cols(),
229 std::string(
230 "Each column has to be owned by exactly one owner (n_cols()=") +
231 std::to_string(sparsity_pattern.n_cols()) +
232 " but sum(local_columns.n_elements())=" +
233 std::to_string(col_owners) + ")"));
234 }
235
236
237 // create the matrix. We do not set row length but set the
238 // correct SparsityPattern later.
239 PetscErrorCode ierr = MatCreate(communicator, &matrix);
240 AssertThrow(ierr == 0, ExcPETScError(ierr));
241
242 ierr = MatSetSizes(matrix,
243 local_rows.n_elements(),
244 local_columns.n_elements(),
245 sparsity_pattern.n_rows(),
246 sparsity_pattern.n_cols());
247 AssertThrow(ierr == 0, ExcPETScError(ierr));
248
249 // Use MATAIJ which dispatches to SEQAIJ
250 // if the size of the communicator is 1,
251 // and to MPIAIJ otherwise.
252 ierr = MatSetType(matrix, MATAIJ);
253 AssertThrow(ierr == 0, ExcPETScError(ierr));
254
255
256 // next preset the exact given matrix
257 // entries with zeros. this doesn't avoid any
258 // memory allocations, but it at least
259 // avoids some searches later on. the
260 // key here is that we can use the
261 // matrix set routines that set an
262 // entire row at once, not a single
263 // entry at a time
264 //
265 // for the usefulness of this option
266 // read the documentation of this
267 // class.
268 // if (preset_nonzero_locations == true)
269 if (local_rows.n_elements() > 0)
270 {
271 // MatXXXAIJSetPreallocationCSR
272 // can be used to allocate the sparsity
273 // pattern of a matrix
274
275 const PetscInt local_row_start = local_rows.nth_index_in_set(0);
276 const PetscInt local_row_end =
277 local_row_start + local_rows.n_elements();
278
279
280 // first set up the column number
281 // array for the rows to be stored
282 // on the local processor. have one
283 // dummy entry at the end to make
284 // sure petsc doesn't read past the
285 // end
286 std::vector<PetscInt> rowstart_in_window(local_row_end -
287 local_row_start + 1,
288 0),
289 colnums_in_window;
290 {
291 unsigned int n_cols = 0;
292 for (PetscInt i = local_row_start; i < local_row_end; ++i)
293 {
294 const PetscInt row_length = sparsity_pattern.row_length(i);
295 rowstart_in_window[i + 1 - local_row_start] =
296 rowstart_in_window[i - local_row_start] + row_length;
297 n_cols += row_length;
298 }
299 colnums_in_window.resize(n_cols + 1, -1);
300 }
301
302 // now copy over the information
303 // from the sparsity pattern.
304 {
305 PetscInt *ptr = colnums_in_window.data();
306 for (PetscInt i = local_row_start; i < local_row_end; ++i)
307 for (typename SparsityPatternType::iterator p =
308 sparsity_pattern.begin(i);
309 p != sparsity_pattern.end(i);
310 ++p, ++ptr)
311 *ptr = p->column();
312 }
313
314
315 // then call the petsc functions
316 // that summarily allocates these
317 // entries.
318 // Here we both call the specific API since this is how
319 // PETSc polymorphism works. If the matrix is of type MPIAIJ,
320 // the second call is dummy. If the matrix is of type SEQAIJ,
321 // the first call is dummy.
322 ierr = MatMPIAIJSetPreallocationCSR(matrix,
323 rowstart_in_window.data(),
324 colnums_in_window.data(),
325 nullptr);
326 ierr = MatSeqAIJSetPreallocationCSR(matrix,
327 rowstart_in_window.data(),
328 colnums_in_window.data(),
329 nullptr);
330 AssertThrow(ierr == 0, ExcPETScError(ierr));
331 }
332 else
333 {
334 PetscInt i = 0;
335
336 ierr = MatSeqAIJSetPreallocationCSR(matrix, &i, &i, nullptr);
337 AssertThrow(ierr == 0, ExcPETScError(ierr));
338 ierr = MatMPIAIJSetPreallocationCSR(matrix, &i, &i, nullptr);
339 AssertThrow(ierr == 0, ExcPETScError(ierr));
340 }
342
343 {
346 }
347 }
348
349
350 template <typename SparsityPatternType>
351 void
353 const MPI_Comm communicator,
354 const SparsityPatternType &sparsity_pattern,
355 const std::vector<size_type> &local_rows_per_process,
356 const std::vector<size_type> &local_columns_per_process,
357 const unsigned int this_process,
358 const bool preset_nonzero_locations)
359 {
360 Assert(local_rows_per_process.size() == local_columns_per_process.size(),
361 ExcDimensionMismatch(local_rows_per_process.size(),
362 local_columns_per_process.size()));
363 Assert(this_process < local_rows_per_process.size(), ExcInternalError());
365 // If the sparsity pattern's dimensions can be converted to PetscInts then
366 // the rest of the conversions will succeed
367 AssertThrowIntegerConversion(static_cast<PetscInt>(
368 sparsity_pattern.n_rows()),
369 sparsity_pattern.n_rows());
370 AssertThrowIntegerConversion(static_cast<PetscInt>(
371 sparsity_pattern.n_cols()),
372 sparsity_pattern.n_cols());
373
374 // for each row that we own locally, we
375 // have to count how many of the
376 // entries in the sparsity pattern lie
377 // in the column area we have locally,
378 // and how many aren't. for this, we
379 // first have to know which areas are
380 // ours
381 size_type local_row_start = 0;
382 for (unsigned int p = 0; p < this_process; ++p)
383 local_row_start += local_rows_per_process[p];
384 const size_type local_row_end =
385 local_row_start + local_rows_per_process[this_process];
386
387 // create the matrix. We
388 // do not set row length but set the
389 // correct SparsityPattern later.
390 PetscErrorCode ierr = MatCreate(communicator, &matrix);
391 AssertThrow(ierr == 0, ExcPETScError(ierr));
392
393 ierr = MatSetSizes(matrix,
394 local_rows_per_process[this_process],
395 local_columns_per_process[this_process],
396 sparsity_pattern.n_rows(),
397 sparsity_pattern.n_cols());
398 AssertThrow(ierr == 0, ExcPETScError(ierr));
399
400 // Use MATAIJ which dispatches to SEQAIJ
401 // if the size of the communicator is 1,
402 // and to MPIAIJ otherwise.
403 ierr = MatSetType(matrix, MATAIJ);
404 AssertThrow(ierr == 0, ExcPETScError(ierr));
405
406 // next preset the exact given matrix
407 // entries with zeros, if the user
408 // requested so. this doesn't avoid any
409 // memory allocations, but it at least
410 // avoids some searches later on. the
411 // key here is that we can use the
412 // matrix set routines that set an
413 // entire row at once, not a single
414 // entry at a time
415 //
416 // for the usefulness of this option
417 // read the documentation of this
418 // class.
419 if (preset_nonzero_locations == true)
420 {
421 // MatXXXAIJSetPreallocationCSR
422 // can be used to allocate the sparsity
423 // pattern of a matrix if it is already
424 // available:
425
426 // first set up the column number
427 // array for the rows to be stored
428 // on the local processor. have one
429 // dummy entry at the end to make
430 // sure petsc doesn't read past the
431 // end
432 std::vector<PetscInt> rowstart_in_window(local_row_end -
433 local_row_start + 1,
434 0),
435 colnums_in_window;
436 {
437 size_type n_cols = 0;
438 for (size_type i = local_row_start; i < local_row_end; ++i)
439 {
440 const size_type row_length = sparsity_pattern.row_length(i);
441 const auto row_start =
442 rowstart_in_window[i - local_row_start] + row_length;
443 const auto petsc_row_start = static_cast<PetscInt>(row_start);
444 AssertIntegerConversion(petsc_row_start, row_start);
445 rowstart_in_window[i + 1 - local_row_start] = petsc_row_start;
446 n_cols += row_length;
447 }
448 colnums_in_window.resize(n_cols + 1, -1);
449 }
450
451 // now copy over the information
452 // from the sparsity pattern.
453 {
454 PetscInt *ptr = colnums_in_window.data();
455 for (size_type i = local_row_start; i < local_row_end; ++i)
456 for (typename SparsityPatternType::iterator p =
457 sparsity_pattern.begin(i);
458 p != sparsity_pattern.end(i);
459 ++p, ++ptr)
460 {
461 const auto petsc_column = static_cast<PetscInt>(p->column());
462 AssertIntegerConversion(petsc_column, p->column());
463 *ptr = petsc_column;
464 }
465 }
466
467
468 // then call the petsc function
469 // that summarily allocates these
470 // entries.
471 // Here we both call the specific API since this is how
472 // PETSc polymorphism works. If the matrix is of type MPIAIJ,
473 // the second call is dummy. If the matrix is of type SEQAIJ,
474 // the first call is dummy.
475 ierr = MatSeqAIJSetPreallocationCSR(matrix,
476 rowstart_in_window.data(),
477 colnums_in_window.data(),
478 nullptr);
479 ierr = MatMPIAIJSetPreallocationCSR(matrix,
480 rowstart_in_window.data(),
481 colnums_in_window.data(),
482 nullptr);
483 AssertThrow(ierr == 0, ExcPETScError(ierr));
484
487 }
488 }
489
490 // BDDC
491 template <typename SparsityPatternType>
492 void
494 const IndexSet &local_rows,
495 const IndexSet &local_active_rows,
496 const IndexSet &local_columns,
497 const IndexSet &local_active_columns,
498 const SparsityPatternType &sparsity_pattern)
499 {
500 // If the sparsity pattern's dimensions can be converted to PetscInts then
501 // the rest of the conversions will succeed
502 AssertThrowIntegerConversion(static_cast<PetscInt>(
503 sparsity_pattern.n_rows()),
504 sparsity_pattern.n_rows());
505 AssertThrowIntegerConversion(static_cast<PetscInt>(
506 sparsity_pattern.n_cols()),
507 sparsity_pattern.n_cols());
508
509# if DEAL_II_PETSC_VERSION_GTE(3, 10, 0)
510 Assert(sparsity_pattern.n_rows() == local_rows.size(),
512 "SparsityPattern and IndexSet have different number of rows."));
513 Assert(
514 sparsity_pattern.n_cols() == local_columns.size(),
516 "SparsityPattern and IndexSet have different number of columns"));
517 Assert(local_rows.is_contiguous() && local_columns.is_contiguous(),
518 ExcMessage("PETSc only supports contiguous row/column ranges"));
519 Assert(local_rows.is_ascending_and_one_to_one(communicator),
521
522 if constexpr (running_in_debug_mode())
523 {
524 // check indexsets
525 const types::global_dof_index row_owners =
526 Utilities::MPI::sum(local_rows.n_elements(), communicator);
527 const types::global_dof_index col_owners =
528 Utilities::MPI::sum(local_columns.n_elements(), communicator);
529 Assert(
530 row_owners == sparsity_pattern.n_rows(),
532 std::string(
533 "Each row has to be owned by exactly one owner (n_rows()=") +
534 std::to_string(sparsity_pattern.n_rows()) +
535 " but sum(local_rows.n_elements())=" +
536 std::to_string(row_owners) + ")"));
537 Assert(
538 col_owners == sparsity_pattern.n_cols(),
540 std::string(
541 "Each column has to be owned by exactly one owner (n_cols()=") +
542 std::to_string(sparsity_pattern.n_cols()) +
543 " but sum(local_columns.n_elements())=" +
544 std::to_string(col_owners) + ")"));
545 }
546 PetscErrorCode ierr;
547
548 // create the local to global mappings as arrays.
549 const IndexSet::size_type n_local_active_rows =
550 local_active_rows.n_elements();
551 const IndexSet::size_type n_local_active_cols =
552 local_active_columns.n_elements();
553 std::vector<PetscInt> idx_glob_row(n_local_active_rows);
554 std::vector<PetscInt> idx_glob_col(n_local_active_cols);
555 for (IndexSet::size_type k = 0; k < n_local_active_rows; ++k)
556 {
557 idx_glob_row[k] = local_active_rows.nth_index_in_set(k);
558 }
559 for (IndexSet::size_type k = 0; k < n_local_active_cols; ++k)
560 {
561 idx_glob_col[k] = local_active_columns.nth_index_in_set(k);
562 }
563
564
565 IS is_glob_row, is_glob_col;
566 // Create row index set
567 ISLocalToGlobalMapping l2gmap_row;
568 ierr = ISCreateGeneral(communicator,
569 n_local_active_rows,
570 idx_glob_row.data(),
571 PETSC_COPY_VALUES,
572 &is_glob_row);
573 AssertThrow(ierr == 0, ExcPETScError(ierr));
574 ierr = ISLocalToGlobalMappingCreateIS(is_glob_row, &l2gmap_row);
575 AssertThrow(ierr == 0, ExcPETScError(ierr));
576 ierr = ISDestroy(&is_glob_row);
577 AssertThrow(ierr == 0, ExcPETScError(ierr));
578 ierr =
579 ISLocalToGlobalMappingViewFromOptions(l2gmap_row, nullptr, "-view_map");
580 AssertThrow(ierr == 0, ExcPETScError(ierr));
581
582 // Create column index set
583 ISLocalToGlobalMapping l2gmap_col;
584 ierr = ISCreateGeneral(communicator,
585 n_local_active_cols,
586 idx_glob_col.data(),
587 PETSC_COPY_VALUES,
588 &is_glob_col);
589 AssertThrow(ierr == 0, ExcPETScError(ierr));
590 ierr = ISLocalToGlobalMappingCreateIS(is_glob_col, &l2gmap_col);
591 AssertThrow(ierr == 0, ExcPETScError(ierr));
592 ierr = ISDestroy(&is_glob_col);
593 AssertThrow(ierr == 0, ExcPETScError(ierr));
594 ierr =
595 ISLocalToGlobalMappingViewFromOptions(l2gmap_col, nullptr, "-view_map");
596 AssertThrow(ierr == 0, ExcPETScError(ierr));
597
598 // create the matrix with the IS constructor.
599 ierr = MatCreateIS(communicator,
600 1,
601 local_rows.n_elements(),
602 local_columns.n_elements(),
603 sparsity_pattern.n_rows(),
604 sparsity_pattern.n_cols(),
605 l2gmap_row,
606 l2gmap_col,
607 &matrix);
608 AssertThrow(ierr == 0, ExcPETScError(ierr));
609 ierr = ISLocalToGlobalMappingDestroy(&l2gmap_row);
610 AssertThrow(ierr == 0, ExcPETScError(ierr));
611 ierr = ISLocalToGlobalMappingDestroy(&l2gmap_col);
612 AssertThrow(ierr == 0, ExcPETScError(ierr));
613
614 // next preset the exact given matrix
615 // entries with zeros. This doesn't avoid any
616 // memory allocations, but it at least
617 // avoids some searches later on. the
618 // key here is that we can use the
619 // matrix set routines that set an
620 // entire row at once, not a single
621 // entry at a time.
622 //
623 // for the usefulness of this option
624 // read the documentation of this
625 // class.
626
627 Mat local_matrix; // In the MATIS case, we use the local matrix instead
628 ierr = MatISGetLocalMat(matrix, &local_matrix);
629 AssertThrow(ierr == 0, ExcPETScError(ierr));
630 ierr = MatSetType(local_matrix,
631 MATSEQAIJ); // SEQ as it is local! TODO: Allow for
632 // OpenMP parallelization in local node.
633 AssertThrow(ierr == 0, ExcPETScError(ierr));
634 if (local_rows.n_elements() > 0)
635 {
636 // MatSEQAIJSetPreallocationCSR
637 // can be used to allocate the sparsity
638 // pattern of a matrix. Local matrices start from 0 (MATIS).
639 const PetscInt local_row_start = 0;
640 const PetscInt local_row_end = local_active_rows.n_elements();
641
642 // first set up the column number
643 // array for the rows to be stored
644 // on the local processor.
645 std::vector<PetscInt> rowstart_in_window(local_row_end -
646 local_row_start + 1,
647 0),
648 colnums_in_window;
649 unsigned int global_row_index = 0;
650 {
651 unsigned int n_cols = 0;
652 unsigned int global_row_index = 0;
653 for (PetscInt i = local_row_start; i < local_row_end; ++i)
654 {
655 global_row_index = local_active_rows.nth_index_in_set(i);
656 const PetscInt row_length =
657 sparsity_pattern.row_length(global_row_index);
658 rowstart_in_window[i + 1 - local_row_start] =
659 rowstart_in_window[i - local_row_start] + row_length;
660 n_cols += row_length;
661 }
662 colnums_in_window.resize(n_cols + 1, -1);
663 }
664
665
666 // now copy over the information
667 // from the sparsity pattern. For this we first invert the column
668 // index set.
669 std::map<unsigned int, unsigned int> loc_act_cols_inv;
670 for (unsigned int i = 0; i < local_active_columns.n_elements(); ++i)
671 {
672 loc_act_cols_inv[local_active_columns.nth_index_in_set(i)] = i;
673 }
674
675 {
676 PetscInt *ptr = colnums_in_window.data();
677 for (PetscInt i = local_row_start; i < local_row_end; ++i)
678 {
679 global_row_index = local_active_rows.nth_index_in_set(i);
680 for (typename SparsityPatternType::iterator p =
681 sparsity_pattern.begin(global_row_index);
682 p != sparsity_pattern.end(global_row_index);
683 ++p, ++ptr)
684 *ptr = loc_act_cols_inv[p->column()];
685 }
686 }
687
688 // then call the petsc function
689 // that summarily allocates these
690 // entries:
691 ierr = MatSeqAIJSetPreallocationCSR(local_matrix,
692 rowstart_in_window.data(),
693 colnums_in_window.data(),
694 nullptr);
695 AssertThrow(ierr == 0, ExcPETScError(ierr));
696 }
697 else
698 {
699 PetscInt i = 0;
700 ierr = MatSeqAIJSetPreallocationCSR(local_matrix, &i, &i, nullptr);
701 AssertThrow(ierr == 0, ExcPETScError(ierr));
702 }
704
705 {
706 close_matrix(local_matrix);
707 set_keep_zero_rows(local_matrix);
708 }
709 ierr = MatISRestoreLocalMat(matrix, &local_matrix);
710 AssertThrow(ierr == 0, ExcPETScError(ierr));
711# else
712 {
713 // Use this to avoid unused variables warning
714 (void)communicator;
715 (void)local_rows;
716 (void)local_active_rows;
717 (void)local_columns;
718 (void)local_active_columns;
719 (void)sparsity_pattern;
720 AssertThrow(false,
722 "BDDC preconditioner requires PETSc 3.10.0 or newer"));
723 }
724# endif
725 }
726
727# ifndef DOXYGEN
728 // explicit instantiations
729 //
731 const SparsityPattern &,
732 const std::vector<size_type> &,
733 const std::vector<size_type> &,
734 const unsigned int,
735 const bool);
738 const std::vector<size_type> &,
739 const std::vector<size_type> &,
740 const unsigned int,
741 const bool);
742
743 template void
745 const SparsityPattern &,
746 const std::vector<size_type> &,
747 const std::vector<size_type> &,
748 const unsigned int,
749 const bool);
750 template void
753 const std::vector<size_type> &,
754 const std::vector<size_type> &,
755 const unsigned int,
756 const bool);
757
758 template void
760 const SparsityPattern &,
761 const MPI_Comm);
762
763 template void
765 const IndexSet &,
766 const SparsityPattern &,
767 const MPI_Comm);
768
769 template void
772 const MPI_Comm);
773
774 template void
776 const IndexSet &,
778 const MPI_Comm);
779
780 template void
782 const SparsityPattern &,
783 const std::vector<size_type> &,
784 const std::vector<size_type> &,
785 const unsigned int,
786 const bool);
787 template void
790 const std::vector<size_type> &,
791 const std::vector<size_type> &,
792 const unsigned int,
793 const bool);
794
795 template void
797 const IndexSet &,
798 const IndexSet &,
799 const SparsityPattern &);
800
801 template void
803 const IndexSet &,
804 const IndexSet &,
805 const DynamicSparsityPattern &);
806
807 template void
809 const IndexSet &,
810 const IndexSet &,
811 const IndexSet &,
812 const SparsityPattern &,
813 const MPI_Comm);
814 template void
816 const IndexSet &,
817 const IndexSet &,
818 const IndexSet &,
820 const MPI_Comm);
821
822 template void
824 const IndexSet &,
825 const IndexSet &,
826 const IndexSet &,
827 const IndexSet &,
828 const SparsityPattern &);
829 template void
831 const IndexSet &,
832 const IndexSet &,
833 const IndexSet &,
834 const IndexSet &,
835 const DynamicSparsityPattern &);
836# endif
837
838
839 PetscScalar
841 {
842 Vector tmp(v);
843 vmult(tmp, v);
844 // note, that v*tmp returns sum_i conjugate(v)_i * tmp_i
845 return v * tmp;
846 }
847
848 PetscScalar
850 {
851 Vector tmp(v);
852 vmult(tmp, v);
853 // note, that v*tmp returns sum_i conjugate(v)_i * tmp_i
854 return u * tmp;
855 }
856
859 {
860 PetscInt n_rows, n_cols, n_loc_rows, n_loc_cols, min, max;
861 PetscErrorCode ierr;
862
863 ierr = MatGetSize(matrix, &n_rows, &n_cols);
864 AssertThrow(ierr == 0, ExcPETScError(ierr));
865
866 ierr = MatGetLocalSize(matrix, &n_loc_rows, &n_loc_cols);
867 AssertThrow(ierr == 0, ExcPETScError(ierr));
868
869 ierr = MatGetOwnershipRangeColumn(matrix, &min, &max);
870 AssertThrow(ierr == 0, ExcPETScError(ierr));
871
872 Assert(n_loc_cols == max - min,
874 "PETSc is requiring non contiguous memory allocation."));
875
876 IndexSet indices(n_cols);
877 indices.add_range(min, max);
878 indices.compress();
879
880 return indices;
881 }
882
885 {
886 PetscInt n_rows, n_cols, n_loc_rows, n_loc_cols, min, max;
887 PetscErrorCode ierr;
888
889 ierr = MatGetSize(matrix, &n_rows, &n_cols);
890 AssertThrow(ierr == 0, ExcPETScError(ierr));
891
892 ierr = MatGetLocalSize(matrix, &n_loc_rows, &n_loc_cols);
893 AssertThrow(ierr == 0, ExcPETScError(ierr));
894
895 ierr = MatGetOwnershipRange(matrix, &min, &max);
896 AssertThrow(ierr == 0, ExcPETScError(ierr));
897
898 Assert(n_loc_rows == max - min,
900 "PETSc is requiring non contiguous memory allocation."));
901
902 IndexSet indices(n_rows);
903 indices.add_range(min, max);
904 indices.compress();
905
906 return indices;
907 }
908
909 void
911 const SparseMatrix &B,
912 const MPI::Vector &V) const
913 {
914 // Simply forward to the protected member function of the base class
915 // that takes abstract matrix and vector arguments (to which the compiler
916 // automatically casts the arguments).
917 MatrixBase::mmult(C, B, V);
918 }
919
920 void
922 const SparseMatrix &B,
923 const MPI::Vector &V) const
924 {
925 // Simply forward to the protected member function of the base class
926 // that takes abstract matrix and vector arguments (to which the compiler
927 // automatically casts the arguments).
928 MatrixBase::Tmmult(C, B, V);
929 }
930
931 } // namespace MPI
932} // namespace PETScWrappers
933
934
935
936#endif // DEAL_II_WITH_PETSC
bool is_ascending_and_one_to_one(const MPI_Comm communicator) const
bool is_contiguous() const
Definition index_set.h:1900
size_type size() const
Definition index_set.h:1759
size_type n_elements() const
Definition index_set.h:1917
void add_range(const size_type begin, const size_type end)
Definition index_set.h:1786
size_type nth_index_in_set(const size_type local_index) const
Definition index_set.h:1958
void compress() const
Definition index_set.h:1767
SparseMatrix & operator=(const value_type d)
void copy_from(const SparseMatrix &other)
void reinit(const MPI_Comm communicator, const SparsityPatternType &sparsity_pattern, const std::vector< size_type > &local_rows_per_process, const std::vector< size_type > &local_columns_per_process, const unsigned int this_process, const bool preset_nonzero_locations=true)
void mmult(SparseMatrix &C, const SparseMatrix &B, const MPI::Vector &V=MPI::Vector()) const
PetscScalar matrix_scalar_product(const Vector &u, const Vector &v) const
void Tmmult(SparseMatrix &C, const SparseMatrix &B, const MPI::Vector &V=MPI::Vector()) const
PetscScalar matrix_norm_square(const Vector &v) const
void do_reinit(const MPI_Comm comm, const SparsityPatternType &sparsity_pattern, const std::vector< size_type > &local_rows_per_process, const std::vector< size_type > &local_columns_per_process, const unsigned int this_process, const bool preset_nonzero_locations)
size_type row_length(const size_type row) const
void vmult(VectorBase &dst, const VectorBase &src) const
void mmult(MatrixBase &C, const MatrixBase &B, const VectorBase &V) const
MatrixBase & operator=(const MatrixBase &)=delete
void Tmmult(MatrixBase &C, const MatrixBase &B, const VectorBase &V) const
void compress(const VectorOperation::values operation)
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
constexpr bool running_in_debug_mode()
Definition config.h:76
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define AssertIntegerConversion(index1, index2)
#define AssertThrowIntegerConversion(index1, index2)
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertNothrow(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
void set_keep_zero_rows(Mat &matrix)
void close_matrix(Mat &matrix)
T sum(const T &t, const MPI_Comm mpi_communicator)