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