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
psblas_sparse_matrix.cc
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 2019 - 2023 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
18#include "deal.II/base/mpi.h"
19#include "deal.II/base/tensor.h"
20#include "deal.II/base/types.h"
21
26
27#include <psb_types.h>
28
29#include <utility>
30
31#ifdef DEAL_II_WITH_PSBLAS
32
34
35namespace PSCToolkitWrappers
36{
37
39 : psblas_sparse_matrix(nullptr)
40 , psblas_descriptor(nullptr)
41 , state(internal::State::Default)
42 {}
43
44 SparseMatrix::SparseMatrix(const SparsityPattern &psblas_sparsity_pattern,
45 const MPI_Comm communicator)
46 {
47 Assert(psblas_descriptor.get() == nullptr,
48 ExcMessage("PSBLAS matrix descriptor must not be initialized."));
49
50 Assert(psblas_sparsity_pattern.psblas_descriptor.get() != nullptr,
51 ExcMessage("The given SparsityPattern is not valid."));
52
53 this->communicator = communicator;
54 Assert(communicator != MPI_COMM_NULL,
55 ExcMessage("MPI_COMM_NULL passed to SparseMatrix::reinit()."));
56
57 psblas_descriptor = psblas_sparsity_pattern.psblas_descriptor;
58
59 // Create a new PSBLAS sparse matrix
60 psblas_sparse_matrix = psb_c_new_dspmat();
61
62 // Initialize the sparse matrix with the descriptor
63 int err =
64 psb_c_dspall_remote(psblas_sparse_matrix, psblas_descriptor.get());
65 Assert(err == 0, ExcAllocationPSBLASMatrix(err));
66 }
67
68
69
71 {
72 if (psblas_sparse_matrix != nullptr && psblas_descriptor.get() != nullptr)
73 {
74 // We clear the underlying PSBLAS sparse matrix
75 int err = psb_c_dspfree(psblas_sparse_matrix, psblas_descriptor.get());
76 Assert(err == 0, ExcCallingPSBLASFunction(err, "psb_c_dspfree"));
77 }
78 }
79
80
81
82 void
84 {
85 if (this == &other)
86 return;
87
89 }
90
91
92 void
93 SparseMatrix::reinit(const IndexSet &index_set, const MPI_Comm comm)
94 {
95 Assert(index_set.n_elements() > 0,
96 ExcMessage("An empty IndexSet has been given."));
97
98 Assert(comm != MPI_COMM_NULL,
99 ExcMessage("MPI_COMM_NULL passed to SparseMatrix::reinit()."));
100 communicator = comm;
101
102 // Free old resources before reinitializing
103 if (psblas_sparse_matrix != nullptr && psblas_descriptor.get() != nullptr)
104 {
105 int err = psb_c_dspfree(psblas_sparse_matrix, psblas_descriptor.get());
106 Assert(err == 0, ExcCallingPSBLASFunction(err, "psb_c_dspfree"));
107 psblas_sparse_matrix = nullptr;
108 }
109
110 // Create a new PSBLAS descriptor
111 psblas_descriptor.reset(psb_c_new_descriptor(),
112 PSCToolkitWrappers::internal::DescriptorDeleter());
113
114 // Use get_index_vector() from IndexSet to get the indexes
115 const std::vector<types::global_dof_index> &indexes =
116 index_set.get_index_vector();
117
118 psb_i_t number_of_local_indexes = indexes.size(); // Number of local indexes
119
120 // Copy the indexes into an array called vl
121 std::vector<psb_l_t> vl(number_of_local_indexes);
122 for (psb_i_t i = 0; i < number_of_local_indexes; ++i)
123 {
124 const auto psblas_index = static_cast<psb_l_t>(indexes[i]);
125 AssertIntegerConversion(psblas_index, indexes[i]);
126 vl[i] = psblas_index;
127 }
128
129 // Insert the indexes into the descriptor
130 psb_c_cdall_vl(number_of_local_indexes,
131 vl.data(),
132 *InitFinalize::get_psblas_context(),
133 psblas_descriptor.get());
134
135 // Create a new PSBLAS sparse matrix
136 psblas_sparse_matrix = psb_c_new_dspmat();
137
138 // Initialize the sparse matrix with the descriptor
139 int err =
140 psb_c_dspall_remote(psblas_sparse_matrix, psblas_descriptor.get());
141 Assert(err == 0, ExcAllocationPSBLASMatrix(err));
142
143 state = internal::State::Build;
144 }
145
146
147
148 void
149 SparseMatrix::reinit(const SparsityPattern &psblas_sparsity_pattern,
150 const MPI_Comm communicator)
151 {
152 Assert(psblas_sparsity_pattern.psblas_descriptor.get() != nullptr,
153 ExcMessage("The given SparsityPattern is not valid."));
154
155 this->communicator = communicator;
156 Assert(communicator != MPI_COMM_NULL,
157 ExcMessage("MPI_COMM_NULL passed to SparseMatrix::reinit()."));
158
159 // Free old resources before reinitializing
160 if (psblas_sparse_matrix != nullptr && psblas_descriptor.get() != nullptr)
161 {
162 int err = psb_c_dspfree(psblas_sparse_matrix, psblas_descriptor.get());
163 Assert(err == 0, ExcCallingPSBLASFunction(err, "psb_c_dspfree"));
164 psblas_sparse_matrix = nullptr;
165 }
166
167 psblas_descriptor = psblas_sparsity_pattern.psblas_descriptor;
168
169 // Create a new PSBLAS sparse matrix
170 psblas_sparse_matrix = psb_c_new_dspmat();
171
172 // Initialize the sparse matrix with the descriptor
173 int err =
174 psb_c_dspall_remote(psblas_sparse_matrix, psblas_descriptor.get());
175 Assert(err == 0, ExcAllocationPSBLASMatrix(err));
176
177 state = internal::State::Build;
178 }
179
180
181
182 void
183 SparseMatrix::reinit(const IndexSet &local_rows,
184 const DynamicSparsityPattern &sparsity_pattern,
185 const MPI_Comm communicator)
186 {
187 Assert(sparsity_pattern.n_rows() == sparsity_pattern.n_cols(),
189
190 // Check dimensions match IndexSet
191 Assert(sparsity_pattern.n_rows() == local_rows.size(),
193 "SparsityPattern and IndexSet have different number of rows"));
194
195 Assert(local_rows.is_ascending_and_one_to_one(communicator),
197
198 // Free old resources before reinitializing
199 if (psblas_sparse_matrix != nullptr && psblas_descriptor.get() != nullptr)
200 {
201 int err = psb_c_dspfree(psblas_sparse_matrix, psblas_descriptor.get());
202 Assert(err == 0, ExcCallingPSBLASFunction(err, "psb_c_dspfree"));
203 psblas_sparse_matrix = nullptr;
204 }
205
206
207 if constexpr (running_in_debug_mode())
208 {
209 types::global_dof_index row_owners =
210 Utilities::MPI::sum(local_rows.n_elements(), communicator);
211 Assert(row_owners == sparsity_pattern.n_rows(),
213 std::string(
214 "Each row has to be owned by exactly one owner (n_rows()=") +
215 std::to_string(sparsity_pattern.n_rows()) +
216 " but sum(local_rows.n_elements())=" +
217 std::to_string(row_owners) + ")"));
218 }
219
220 this->communicator = communicator;
221
222 // Set up the PSBLAS descriptor from the local IndexSet
223 psblas_descriptor.reset(psb_c_new_descriptor(),
224 PSCToolkitWrappers::internal::DescriptorDeleter());
225
226 {
227 const std::vector<types::global_dof_index> indexes =
228 local_rows.get_index_vector();
229 const psb_i_t n_local = static_cast<psb_i_t>(indexes.size());
230
231 std::vector<psb_l_t> vl(n_local);
232 for (psb_i_t i = 0; i < n_local; ++i)
233 {
234 const auto idx = static_cast<psb_l_t>(indexes[i]);
235 AssertIntegerConversion(idx, indexes[i]);
236 vl[i] = idx;
237 }
238
239 psb_c_cdall_vl(n_local,
240 vl.data(),
241 *InitFinalize::get_psblas_context(),
242 psblas_descriptor.get());
243 }
244
245 // Create and initialize the sparse matrix
246 psblas_sparse_matrix = psb_c_new_dspmat();
247
248 int err;
249
250 if (local_rows.n_elements() > 0)
251 {
252 const psb_l_t local_row_start =
253 static_cast<psb_l_t>(local_rows.nth_index_in_set(0));
254 const psb_l_t local_row_end =
255 local_row_start + static_cast<psb_l_t>(local_rows.n_elements());
256
257 // Insert entries from the sparsity pattern row by row
258 for (psb_l_t i = local_row_start; i < local_row_end; ++i)
259 {
260 const auto row_length =
261 static_cast<psb_i_t>(sparsity_pattern.row_length(i));
262 if (row_length == 0)
263 continue;
264
265 std::vector<psb_l_t> irw(row_length, i);
266 std::vector<psb_l_t> icl(row_length);
267
268 psb_i_t k = 0;
269 for (typename DynamicSparsityPattern::iterator p =
270 sparsity_pattern.begin(i);
271 p != sparsity_pattern.end(i);
272 ++p, ++k)
273 {
274 const auto col = static_cast<psb_l_t>(p->column());
275 AssertIntegerConversion(col, p->column());
276 icl[k] = col;
277 }
278
279 err = psb_c_cdins(row_length,
280 irw.data(),
281 icl.data(),
282 psblas_descriptor.get());
283 Assert(err == 0, ExcInsertionInPSBLASMatrix(err));
284 }
285
286 // Initialize the sparse matrix with the descriptor
287 err =
288 psb_c_dspall_remote(psblas_sparse_matrix, psblas_descriptor.get());
289 Assert(err == 0, ExcAllocationPSBLASMatrix(err));
290 }
291 else
292 {
293 // empty local partition: just initialize
294 err =
295 psb_c_dspall_remote(psblas_sparse_matrix, psblas_descriptor.get());
296 Assert(err == 0, ExcAllocationPSBLASMatrix(err));
297 }
298
299 state = internal::State::Build;
300 }
301
302
303
305 SparseMatrix::local_size() const
306 {
307 return psb_c_cd_get_local_rows(psblas_descriptor.get());
308 }
309
310
311 std::pair<SparseMatrix::size_type, SparseMatrix::size_type>
312 SparseMatrix::local_range() const
313 {
314 std::vector<psb_l_t> local_indices(local_size());
315 int err = psb_c_cd_get_global_indices(local_indices.data(),
316 local_size(),
317 true /*only owned indices*/,
318 psblas_descriptor.get());
319 Assert(err == 0,
320 ExcCallingPSBLASFunction(err, "psb_c_cd_get_global_indices"));
321
322 return {local_indices[0], local_indices.back() + 1};
323 }
324
325
326
327 bool
328 SparseMatrix::in_local_range(const size_type index) const
329 {
330 std::pair<size_type, size_type> local_range = this->local_range();
331 return index >= local_range.first && index < local_range.second;
332 }
333
334
335
337 SparseMatrix::m() const
338 {
339 return psb_c_cd_get_global_rows(psblas_descriptor.get());
340 }
341
342
343
345 SparseMatrix::n() const
346 {
347 return psb_c_cd_get_global_cols(psblas_descriptor.get());
348 }
349
350
351
354 {
355 return psb_c_dnnz(psblas_sparse_matrix, psblas_descriptor.get());
356 }
357
358
359
360 void
363 const SparseMatrix::value_type value)
364 {
365 // Insert a value into the sparse matrix
366 psb_l_t irw = i;
367 psb_l_t icl = j;
368 psb_d_t val = value;
369
370 int err = psb_c_dspins(
371 1, &irw, &icl, &val, psblas_sparse_matrix, psblas_descriptor.get());
372 Assert(err == 0, ExcInsertionInPSBLASMatrix(err));
373 }
374
375
376
379 const SparseMatrix::size_type j) const
380 {
381 const auto psblas_index_i = static_cast<psb_l_t>(i);
382 AssertIntegerConversion(psblas_index_i, i);
383 const auto psblas_index_j = static_cast<psb_l_t>(j);
384 AssertIntegerConversion(psblas_index_j, j);
385
386 return psb_c_dmatgetelem(psblas_sparse_matrix,
387 psblas_index_i,
388 psblas_index_j,
389 psblas_descriptor.get());
390 }
391
392
393
396 {
397 Assert(m() == n(), ExcNotQuadratic());
398 return el(i, i);
399 }
400
401
402
405 const SparseMatrix::size_type j) const
406 {
407 Assert(m() == n(), ExcNotQuadratic());
408 return el(i, j);
409 }
410
411
412
413 psb_c_dspmat *
414 SparseMatrix::get_psblas_matrix() const
415 {
416 return psblas_sparse_matrix;
417 }
418
419
420
421 psb_c_descriptor *
422 SparseMatrix::get_psblas_descriptor() const
423 {
424 return psblas_descriptor.get();
425 }
426
427
428
430 SparseMatrix::get_mpi_communicator() const
431 {
432 return communicator;
433 }
434
435
436
437 void
438 SparseMatrix::set(const std::vector<SparseMatrix::size_type> &indices,
439 const FullMatrix<double> &matrix)
440 {
441 Assert(psblas_sparse_matrix != nullptr,
442 ExcMessage("PSBLAS matrix has not been initialized."));
443 Assert(matrix.m() == indices.size(),
444 ExcDimensionMismatch(matrix.m(), indices.size()));
445 Assert(matrix.n() == indices.size(),
446 ExcDimensionMismatch(matrix.n(), indices.size()));
447
448 // Get the number of indices.
449 const unsigned int n_indices = indices.size();
450 psb_i_t nz = n_indices * n_indices; // Number of non-zero entries
451
452 // Fill the arrays with row indices, column indices, and values
453 std::vector<psb_l_t> irw(nz);
454 std::vector<psb_l_t> icl(nz);
455 std::vector<psb_d_t> val(nz);
456 for (unsigned int i = 0; i < n_indices; ++i)
457 {
458 for (unsigned int j = 0; j < n_indices; ++j)
459 {
460 const auto psblas_row_index = static_cast<psb_l_t>(indices[i]);
461 const auto psblas_col_index = static_cast<psb_l_t>(indices[j]);
462 AssertIntegerConversion(psblas_row_index, indices[i]);
463 AssertIntegerConversion(psblas_col_index, indices[j]);
464 irw[i * n_indices + j] = psblas_row_index;
465 icl[i * n_indices + j] = psblas_col_index;
466 val[i * n_indices + j] = matrix(i, j);
467 }
468 }
469
470 // Insert the values into the sparse matrix
471 int err = psb_c_dspins(nz,
472 irw.data(),
473 icl.data(),
474 val.data(),
475 psblas_sparse_matrix,
476 psblas_descriptor.get());
477
478 Assert(err == 0, ExcInsertionInPSBLASMatrix(err));
479 }
480
481
482
483 void
486 const SparseMatrix::value_type value)
487 {
488 AssertIsFinite(value);
489
490 psb_l_t irw = i;
491 psb_l_t icl = j;
492 int info = psb_c_dspins(1 /*nz*/,
493 &irw,
494 &icl,
495 &value,
496 psblas_sparse_matrix,
497 psblas_descriptor.get());
498 Assert(info == 0, ExcInsertionInPSBLASMatrix(info));
499 }
500
501
502
503 void
505 const SparseMatrix::size_type ncols,
506 const std::vector<SparseMatrix::size_type> &col_indices,
507 const SparseMatrix::value_type *values,
508 const bool,
509 const bool)
510 {
511 Assert(col_indices.size() == ncols,
512 ExcDimensionMismatch(col_indices.size(), ncols));
513 // Call the function below taking a raw pointer from the vector
514 add(row, ncols, col_indices.data(), values, false, false);
515 }
516
517
518
519 void
521 const SparseMatrix::size_type ncols,
522 const std::vector<SparseMatrix::size_type> &col_indices,
523 const std::vector<SparseMatrix::value_type> &values,
524 const bool,
525 const bool)
526 {
527 Assert(col_indices.size() == ncols,
528 ExcDimensionMismatch(col_indices.size(), ncols));
529 Assert(values.size() == ncols, ExcDimensionMismatch(ncols, values.size()));
530 // Call the function below taking a raw pointer from the vector
531 add(row, ncols, col_indices.data(), values.data(), false, false);
532 }
533
534
535
536 void
538 const SparseMatrix::size_type ncols,
539 const SparseMatrix::size_type *col_indices,
540 const SparseMatrix::value_type *values,
541 const bool,
542 const bool)
543 {
544 std::vector<psb_l_t> irw(ncols);
545 std::vector<psb_l_t> icl(ncols);
546 for (SparseMatrix::size_type i = 0; i < ncols; ++i)
547 {
548 irw[i] = static_cast<psb_l_t>(row);
549 icl[i] = static_cast<psb_l_t>(col_indices[i]);
550 }
551
552 int info = psb_c_dspins(ncols /*nz*/,
553 irw.data(),
554 icl.data(),
555 values,
556 psblas_sparse_matrix,
557 psblas_descriptor.get());
558 Assert(info == 0, ExcInsertionInPSBLASMatrix(info));
559 }
560
561
562
563 void
565 {
566 // We start by checking if the descriptor has already been assembled
567 // elsewhere
568 int err = -1;
569 if (!psb_c_cd_is_asb(psblas_descriptor.get()))
570 {
571 err = psb_c_cdasb(psblas_descriptor.get());
572 Assert(err == 0, ExcAssemblePSBLASDescriptor(err));
573 }
574
575 // Check if the sparse matrix is not already assembled
576 if (!psb_c_dis_matasb(psblas_sparse_matrix, psblas_descriptor.get()))
577 {
578 // ... and the sparse matrix
579 err = psb_c_dspasb(psblas_sparse_matrix, psblas_descriptor.get());
580 Assert(err == 0, ExcAssemblePSBLASMatrix(err));
581 state = internal::State::Assembled;
582 }
583 }
584
585
586
587 void
588 SparseMatrix::vmult(Vector &dst, const Vector &src) const
589 {
590 Assert(psblas_sparse_matrix != nullptr,
591 ExcMessage("PSBLAS matrix has not been initialized."));
592 Assert(src.psblas_vector != nullptr,
593 ExcMessage("Source PSBLAS vector has not been initialized."));
594 Assert(&src != &dst, ExcSourceEqualsDestination());
595 Assert(state == internal::State::Assembled,
596 ExcMessage("PSBLAS matrix has not been assembled."));
597
598 int err = psb_c_dspmm(value_type(1.0), // alpha
599 psblas_sparse_matrix,
600 src.psblas_vector,
601 value_type(0.0), // beta
602 dst.psblas_vector,
603 psblas_descriptor.get());
604 Assert(err == 0, ExcMatVecPSBLAS(err));
605 }
606
607
608
609 void
610 SparseMatrix::vmult_add(Vector &dst, const Vector &src) const
611 {
612 Assert(psblas_sparse_matrix != nullptr,
613 ExcMessage("PSBLAS matrix has not been initialized."));
614 Assert(src.psblas_vector != nullptr,
615 ExcMessage("Source PSBLAS vector has not been initialized."));
616 Assert(&src != &dst, ExcSourceEqualsDestination());
617 Assert(state == internal::State::Assembled,
618 ExcMessage("PSBLAS matrix has not been assembled."));
619
620 int err = psb_c_dspmm(value_type(1.0), // alpha
621 psblas_sparse_matrix,
622 src.psblas_vector,
623 value_type(1.0), // beta
624 dst.psblas_vector,
625 psblas_descriptor.get());
626 Assert(err == 0, ExcMatVecPSBLAS(err));
627 }
628
629
630
631 void
632 SparseMatrix::Tvmult(Vector &dst, const Vector &src) const
633 {
634 Assert(psblas_sparse_matrix != nullptr,
635 ExcMessage("PSBLAS matrix has not been initialized."));
636 Assert(src.psblas_vector != nullptr,
637 ExcMessage("Source PSBLAS vector has not been initialized."));
638 Assert(&src != &dst, ExcSourceEqualsDestination());
639 Assert(state == internal::State::Assembled,
640 ExcMessage("PSBLAS matrix has not been assembled."));
641
642 char transpose = 'T';
643 int err = psb_c_dspmm_opt(value_type(1.0), // alpha
644 psblas_sparse_matrix,
645 src.psblas_vector,
646 value_type(0.0), // beta
647 dst.psblas_vector,
648 psblas_descriptor.get(),
649 &transpose,
650 true);
651 Assert(err == 0, ExcMatVecPSBLAS(err));
652 }
653
654
655
656 void
657 SparseMatrix::Tvmult_add(Vector &dst, const Vector &src) const
658 {
659 Assert(psblas_sparse_matrix != nullptr,
660 ExcMessage("PSBLAS matrix has not been initialized."));
661 Assert(src.psblas_vector != nullptr,
662 ExcMessage("Source PSBLAS vector has not been initialized."));
663 Assert(&src != &dst, ExcSourceEqualsDestination());
664 Assert(state == internal::State::Assembled,
665 ExcMessage("PSBLAS matrix has not been assembled."));
666
667 char transpose = 'T';
668 int err = psb_c_dspmm_opt(value_type(1.0), // alpha
669 psblas_sparse_matrix,
670 src.psblas_vector,
671 value_type(1.0), // beta
672 dst.psblas_vector,
673 psblas_descriptor.get(),
674 &transpose,
675 true);
676 Assert(err == 0, ExcMatVecPSBLAS(err));
677 }
678
679
680
683 {
685 }
686
687
688
691 {
693 }
694
695
696
699 {
701 }
702
703
704
706 SparseMatrix::trace() const
707 {
708 Assert(m() == n(), ExcNotQuadratic());
709 value_type local_diagonal_sum = 0;
710 const auto local_indices = local_range();
711 for (types::global_dof_index idx = local_indices.first;
712 idx < local_indices.second;
713 ++idx)
714 local_diagonal_sum += diag_element(idx);
715
716 return Utilities::MPI::sum(local_diagonal_sum, communicator);
717 }
718
719
720
721} // namespace PSCToolkitWrappers
722
724#endif // DEAL_II_WITH_PSBLAS
size_type row_length(const size_type row) const
bool is_ascending_and_one_to_one(const MPI_Comm communicator) const
size_type size() const
Definition index_set.h:1759
size_type n_elements() const
Definition index_set.h:1917
size_type nth_index_in_set(const size_type local_index) const
Definition index_set.h:1958
std::vector< size_type > get_index_vector() const
Definition index_set.cc:911
std::size_t n_nonzero_elements() const
void Tvmult(OutVector &dst, const InVector &src) const
void set(const size_type i, const size_type j, const number value)
SparseMatrix< number > & copy_from(const SparseMatrix< somenumber > &source)
virtual ~SparseMatrix() override
void vmult_add(OutVector &dst, const InVector &src) const
number diag_element(const size_type i) const
void vmult(OutVector &dst, const InVector &src) const
const number & operator()(const size_type i, const size_type j) const
number el(const size_type i, const size_type j) const
std::unique_ptr< number[]> val
void add(const size_type i, const size_type j, const number value)
size_type n() const
size_type m() const
friend class SparseMatrix
void compress(VectorOperation::values)
real_type frobenius_norm() const
void Tvmult_add(OutVector &dst, const InVector &src) const
real_type linfty_norm() const
real_type l1_norm() const
virtual void reinit(const SparsityPattern &sparsity)
size_type n_rows() const
size_type n_cols() const
#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
DerivativeForm< 1, spacedim, dim, Number > transpose(const DerivativeForm< 1, dim, spacedim, Number > &DF)
#define AssertIntegerConversion(index1, index2)
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcSourceEqualsDestination()
#define AssertIsFinite(number)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcNotQuadratic()
static ::ExceptionBase & ExcMessage(std::string arg1)
std::pair< types::global_dof_index, types::global_dof_index > local_range
Definition mpi.cc:814
const MPI_Comm comm
Definition mpi.cc:912
@ matrix
Contents is actually a matrix.
T sum(const T &t, const MPI_Comm mpi_communicator)