deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20: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
trilinos_sparsity_pattern.h
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) 2008 - 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#ifndef dealii_trilinos_sparsity_pattern_h
14#define dealii_trilinos_sparsity_pattern_h
15
16#include <deal.II/base/config.h>
17
18#ifndef DEAL_II_TRILINOS_WITH_EPETRA
21
22#endif
23
24#ifdef DEAL_II_TRILINOS_WITH_EPETRA
29
32
34# include <Epetra_FECrsGraph.h>
35# include <Epetra_Map.h>
36# include <Epetra_MpiComm.h>
38
39# include <cmath>
40# include <memory>
41# include <vector>
42
43#endif
44
46
47#ifdef DEAL_II_TRILINOS_WITH_EPETRA
48// forward declarations
49# ifndef DOXYGEN
50class SparsityPattern;
52
53namespace TrilinosWrappers
54{
55 class SparsityPattern;
56 class SparseMatrix;
57
59 {
60 class Iterator;
61 }
62} // namespace TrilinosWrappers
63# endif
64
65namespace TrilinosWrappers
66{
68 {
81 {
82 public:
87
92 const size_type row,
93 const size_type index);
94
99 row() const;
100
105 index() const;
106
111 column() const;
112
117
122 size_type,
123 size_type,
124 size_type,
125 << "You tried to access row " << arg1
126 << " of a distributed sparsity pattern, "
127 << " but only rows " << arg2 << " through " << arg3
128 << " are stored locally and can be accessed.");
129
130 private:
135
140
145
158 std::shared_ptr<const std::vector<size_type>> colnum_cache;
159
165 void
167
168 // Make enclosing class a friend.
169 friend class Iterator;
170 };
171
178 {
179 public:
184
189 Iterator(const SparsityPattern *sparsity_pattern,
190 const size_type row,
191 const size_type index);
192
197
201 Iterator &
203
209
213 const Accessor &
214 operator*() const;
215
219 const Accessor *
220 operator->() const;
221
226 bool
227 operator==(const Iterator &) const;
228
232 bool
233 operator!=(const Iterator &) const;
234
240 bool
241 operator<(const Iterator &) const;
242
247 size_type,
248 size_type,
249 << "Attempt to access element " << arg2 << " of row "
250 << arg1 << " which doesn't have that many elements.");
251
252 private:
257
259 };
260
261 } // namespace SparsityPatternIterators
262
263
282 {
283 public:
288
293
302
318 const size_type n,
319 const size_type n_entries_per_row);
320
322 "Use the overload specifying the number of entries per row!")
323 SparsityPattern(const size_type m, const size_type n);
324
334 const size_type n,
335 const std::vector<size_type> &n_entries_per_row);
336
341 SparsityPattern(SparsityPattern &&other) noexcept;
342
347 SparsityPattern(const SparsityPattern &input_sparsity_pattern);
348
352 virtual ~SparsityPattern() override = default;
353
365 void
366 reinit(const size_type m,
367 const size_type n,
368 const size_type n_entries_per_row);
369
371 "Use the overload specifying the number of entries per row!")
372 void
373 reinit(const size_type m, const size_type n);
374
383 void
384 reinit(const size_type m,
385 const size_type n,
386 const std::vector<size_type> &n_entries_per_row);
387
392 void
393 copy_from(const SparsityPattern &input_sparsity_pattern);
394
400 template <typename SparsityPatternType>
401 void
402 copy_from(const SparsityPatternType &nontrilinos_sparsity_pattern);
403
411 operator=(const SparsityPattern &input_sparsity_pattern);
412
420 void
421 clear();
422
432 void
433 compress();
452 SparsityPattern(const IndexSet &parallel_partitioning,
453 const MPI_Comm communicator,
454 const size_type n_entries_per_row);
455
456
458 "Use the overload specifying the number of entries per row!")
459 SparsityPattern(const IndexSet &parallel_partitioning,
460 const MPI_Comm communicator);
461
463 "Use the overload specifying the MPI communicator and the number of entries per row!")
464 SparsityPattern(const IndexSet &parallel_partitioning);
465
476 SparsityPattern(const IndexSet &parallel_partitioning,
477 const MPI_Comm communicator,
478 const std::vector<size_type> &n_entries_per_row);
479
494 SparsityPattern(const IndexSet &row_parallel_partitioning,
495 const IndexSet &col_parallel_partitioning,
496 const MPI_Comm communicator,
497 const size_type n_entries_per_row);
498
500 "Use the overload specifying the number of entries per row!")
501 SparsityPattern(const IndexSet &row_parallel_partitioning,
502 const IndexSet &col_parallel_partitioning,
503 const MPI_Comm communicator);
504
506 "Use the overload specifying the MPI communicator and the number of entries per row!")
507 SparsityPattern(const IndexSet &row_parallel_partitioning,
508 const IndexSet &col_parallel_partitioning);
509
521 SparsityPattern(const IndexSet &row_parallel_partitioning,
522 const IndexSet &col_parallel_partitioning,
523 const MPI_Comm communicator,
524 const std::vector<size_type> &n_entries_per_row);
525
552 SparsityPattern(const IndexSet &row_parallel_partitioning,
553 const IndexSet &col_parallel_partitioning,
554 const IndexSet &writable_rows,
555 const MPI_Comm communicator,
556 const size_type n_entries_per_row);
557
559 "Use the overload specifying the number of entries per row!")
560 SparsityPattern(const IndexSet &row_parallel_partitioning,
561 const IndexSet &col_parallel_partitioning,
562 const IndexSet &writable_rows,
563 const MPI_Comm communicator);
564
566 "Use the overload specifying the MPI communicator and the number of entries per row!")
567 SparsityPattern(const IndexSet &row_parallel_partitioning,
568 const IndexSet &col_parallel_partitioning,
569 const IndexSet &writable_rows);
570
586 void
587 reinit(const IndexSet &parallel_partitioning,
588 const MPI_Comm communicator,
589 const size_type n_entries_per_row);
590
592 "Use the overload specifying the number of entries per row!")
593 void
594 reinit(const IndexSet &parallel_partitioning, const MPI_Comm communicator);
595
597 "Use the overload specifying the MPI communicator and the number of entries per row!")
598 void
599 reinit(const IndexSet &parallel_partitioning);
600
611 void
612 reinit(const IndexSet &parallel_partitioning,
613 const MPI_Comm communicator,
614 const std::vector<size_type> &n_entries_per_row);
615
632 void
633 reinit(const IndexSet &row_parallel_partitioning,
634 const IndexSet &col_parallel_partitioning,
635 const MPI_Comm communicator,
636 const size_type n_entries_per_row);
637
639 "Use the overload specifying the number of entries per row!")
640 void
641 reinit(const IndexSet &row_parallel_partitioning,
642 const IndexSet &col_parallel_partitioning,
643 const MPI_Comm communicator);
644
646 "Use the overload specifying the MPI communicator and the number of entries per row!")
647 void
648 reinit(const IndexSet &row_parallel_partitioning,
649 const IndexSet &col_parallel_partitioning);
650
676 void
677 reinit(const IndexSet &row_parallel_partitioning,
678 const IndexSet &col_parallel_partitioning,
679 const IndexSet &writable_rows,
680 const MPI_Comm communicator,
681 const size_type n_entries_per_row);
682
684 "Use the overload specifying the number of entries per row!")
685 void
686 reinit(const IndexSet &row_parallel_partitioning,
687 const IndexSet &col_parallel_partitioning,
688 const IndexSet &writable_rows,
689 const MPI_Comm communicator);
690
692 "Use the overload specifying the MPI communicator and the number of entries per row!")
693 void
694 reinit(const IndexSet &row_parallel_partitioning,
695 const IndexSet &col_parallel_partitioning,
696 const IndexSet &writable_rows);
697
702 void
703 reinit(const IndexSet &row_parallel_partitioning,
704 const IndexSet &col_parallel_partitioning,
705 const MPI_Comm communicator,
706 const std::vector<size_type> &n_entries_per_row);
707
717 template <
718 typename SparsityPatternType,
719 typename = std::enable_if_t<!std::is_integral_v<SparsityPatternType>>>
720 void
721 reinit(const IndexSet &row_parallel_partitioning,
722 const IndexSet &col_parallel_partitioning,
723 const SparsityPatternType &nontrilinos_sparsity_pattern,
724 const MPI_Comm communicator = MPI_COMM_WORLD,
725 const bool exchange_data = false);
726
735 template <
736 typename SparsityPatternType,
737 typename = std::enable_if_t<!std::is_integral_v<SparsityPatternType>>>
738 void
739 reinit(const IndexSet &parallel_partitioning,
740 const SparsityPatternType &nontrilinos_sparsity_pattern,
741 const MPI_Comm communicator = MPI_COMM_WORLD,
742 const bool exchange_data = false);
753 bool
755
759 unsigned int
760 max_entries_per_row() const;
761
771 unsigned int
772 local_size() const;
773
782 std::pair<size_type, size_type>
783 local_range() const;
784
789 bool
790 in_local_range(const size_type index) const;
791
795 std::uint64_t
796 n_nonzero_elements() const;
797
807 row_length(const size_type row) const;
808
816 bandwidth() const;
817
822 bool
823 empty() const;
824
829 bool
830 exists(const size_type i, const size_type j) const;
831
836 bool
837 row_is_stored_locally(const size_type i) const;
838
843 std::size_t
844 memory_consumption() const;
845
854 void
855 add(const size_type i, const size_type j);
856
857
861 template <typename ForwardIterator>
862 void
864 ForwardIterator begin,
865 ForwardIterator end,
866 const bool indices_are_sorted = false);
867
868 virtual void
869 add_row_entries(const size_type &row,
870 const ArrayView<const size_type> &columns,
871 const bool indices_are_sorted = false) override;
872
874
885 const Epetra_FECrsGraph &
887
894 const Epetra_Map &
895 domain_partitioner() const;
896
903 const Epetra_Map &
904 range_partitioner() const;
905
910 get_mpi_communicator() const;
911
926
934
946 begin() const;
947
952 end() const;
953
963 begin(const size_type r) const;
964
974 end(const size_type r) const;
975
987 void
988 write_ascii();
989
997 void
998 print(std::ostream &out,
999 const bool write_extended_trilinos_info = false) const;
1000
1015 void
1016 print_gnuplot(std::ostream &out) const;
1017
1027 int,
1028 << "An error with error number " << arg1
1029 << " occurred while calling a Trilinos function");
1030
1035 size_type,
1036 size_type,
1037 << "The entry with index <" << arg1 << ',' << arg2
1038 << "> does not exist.");
1039
1044 size_type,
1045 size_type,
1046 size_type,
1047 size_type,
1048 << "You tried to access element (" << arg1 << '/' << arg2
1049 << ')'
1050 << " of a distributed matrix, but only rows in range ["
1051 << arg3 << ',' << arg4
1052 << "] are stored locally and can be accessed.");
1053
1058 size_type,
1059 size_type,
1060 << "You tried to access element (" << arg1 << '/' << arg2
1061 << ')' << " of a sparse matrix, but it appears to not"
1062 << " exist in the Trilinos sparsity pattern.");
1064 private:
1069 std::unique_ptr<Epetra_Map> column_space_map;
1070
1076 std::unique_ptr<Epetra_FECrsGraph> graph;
1077
1084 std::unique_ptr<Epetra_CrsGraph> nonlocal_graph;
1085
1089 };
1090
1091
1092
1093 // ----------------------- inline and template functions --------------------
1094
1095
1096# ifndef DOXYGEN
1097
1098 namespace SparsityPatternIterators
1099 {
1100 inline Accessor::Accessor(const SparsityPattern *sp,
1101 const size_type row,
1102 const size_type index)
1103 : sparsity_pattern(const_cast<SparsityPattern *>(sp))
1104 , a_row(row)
1105 , a_index(index)
1106 {
1107 visit_present_row();
1108 }
1109
1110
1111
1112 inline Accessor::size_type
1113 Accessor::row() const
1114 {
1115 Assert(a_row < sparsity_pattern->n_rows(),
1116 ExcBeyondEndOfSparsityPattern());
1117 return a_row;
1118 }
1119
1120
1121
1122 inline Accessor::size_type
1123 Accessor::column() const
1124 {
1125 Assert(a_row < sparsity_pattern->n_rows(),
1126 ExcBeyondEndOfSparsityPattern());
1127 return (*colnum_cache)[a_index];
1128 }
1129
1130
1131
1132 inline Accessor::size_type
1133 Accessor::index() const
1134 {
1135 Assert(a_row < sparsity_pattern->n_rows(),
1136 ExcBeyondEndOfSparsityPattern());
1137 return a_index;
1138 }
1139
1140
1141
1142 inline Iterator::Iterator(const SparsityPattern *sp,
1143 const size_type row,
1144 const size_type index)
1145 : accessor(sp, row, index)
1146 {}
1147
1148
1149
1150 inline Iterator::Iterator(const Iterator &) = default;
1151
1152
1153
1154 inline Iterator &
1155 Iterator::operator++()
1156 {
1157 Assert(accessor.a_row < accessor.sparsity_pattern->n_rows(),
1159
1160 ++accessor.a_index;
1161
1162 // If at end of line: do one step, then cycle until we find a row with a
1163 // nonzero number of entries that is stored locally.
1164 if (accessor.a_index >= accessor.colnum_cache->size())
1165 {
1166 accessor.a_index = 0;
1167 ++accessor.a_row;
1168
1169 while (accessor.a_row < accessor.sparsity_pattern->n_rows())
1170 {
1171 const auto row_length =
1172 accessor.sparsity_pattern->row_length(accessor.a_row);
1173 if (row_length == 0 ||
1174 !accessor.sparsity_pattern->row_is_stored_locally(
1175 accessor.a_row))
1176 ++accessor.a_row;
1177 else
1178 break;
1179 }
1180
1181 accessor.visit_present_row();
1182 }
1183 return *this;
1184 }
1185
1186
1187
1188 inline Iterator
1189 Iterator::operator++(int)
1190 {
1191 const Iterator old_state = *this;
1192 ++(*this);
1193 return old_state;
1194 }
1195
1196
1197
1198 inline const Accessor &
1199 Iterator::operator*() const
1200 {
1201 return accessor;
1202 }
1203
1204
1205
1206 inline const Accessor *
1207 Iterator::operator->() const
1208 {
1209 return &accessor;
1210 }
1211
1212
1213
1214 inline bool
1215 Iterator::operator==(const Iterator &other) const
1216 {
1217 return (accessor.a_row == other.accessor.a_row &&
1218 accessor.a_index == other.accessor.a_index);
1219 }
1220
1221
1222
1223 inline bool
1224 Iterator::operator!=(const Iterator &other) const
1225 {
1226 return !(*this == other);
1227 }
1228
1229
1230
1231 inline bool
1232 Iterator::operator<(const Iterator &other) const
1233 {
1234 return (accessor.row() < other.accessor.row() ||
1235 (accessor.row() == other.accessor.row() &&
1236 accessor.index() < other.accessor.index()));
1237 }
1238
1239 } // namespace SparsityPatternIterators
1240
1241
1242
1245 {
1246 const size_type first_valid_row = this->local_range().first;
1247 return const_iterator(this, first_valid_row, 0);
1248 }
1249
1250
1251
1253 SparsityPattern::end() const
1254 {
1255 return const_iterator(this, n_rows(), 0);
1256 }
1257
1258
1259
1261 SparsityPattern::begin(const size_type r) const
1262 {
1264 if (row_length(r) > 0)
1265 return const_iterator(this, r, 0);
1266 else
1267 return end(r);
1268 }
1269
1270
1271
1273 SparsityPattern::end(const size_type r) const
1274 {
1276
1277 // place the iterator on the first entry
1278 // past this line, or at the end of the
1279 // matrix
1280 for (size_type i = r + 1; i < n_rows(); ++i)
1281 if (row_length(i) > 0)
1282 return const_iterator(this, i, 0);
1283
1284 // if there is no such line, then take the
1285 // end iterator of the matrix
1286 return end();
1287 }
1288
1289
1290
1291 inline bool
1293 {
1295# ifndef DEAL_II_WITH_64BIT_INDICES
1296 begin = graph->RowMap().MinMyGID();
1297 end = graph->RowMap().MaxMyGID() + 1;
1298# else
1299 begin = graph->RowMap().MinMyGID64();
1300 end = graph->RowMap().MaxMyGID64() + 1;
1301# endif
1302
1303 return ((index >= static_cast<size_type>(begin)) &&
1304 (index < static_cast<size_type>(end)));
1305 }
1306
1307
1308
1309 inline bool
1311 {
1312 return graph->Filled();
1313 }
1314
1315
1316
1317 inline bool
1319 {
1320 return ((n_rows() == 0) && (n_cols() == 0));
1321 }
1322
1323
1324
1325 inline void
1326 SparsityPattern::add(const size_type i, const size_type j)
1327 {
1328 add_entries(i, &j, &j + 1);
1329 }
1330
1331
1332
1333 template <typename ForwardIterator>
1334 inline void
1336 ForwardIterator begin,
1337 ForwardIterator end,
1338 const bool /*indices_are_sorted*/)
1339 {
1340 if (begin == end)
1341 return;
1342
1343 // verify that the size of the data type Trilinos expects matches that the
1344 // iterator points to. we allow for some slippage between signed and
1345 // unsigned and only compare that they are both either 32 or 64 bit. to
1346 // write this test properly, not that we cannot compare the size of
1347 // '*begin' because 'begin' may be an iterator and '*begin' may be an
1348 // accessor class. consequently, we need to somehow get an actual value
1349 // from it which we can by evaluating an expression such as when
1350 // multiplying the value produced by 2
1351 static_assert(sizeof(TrilinosWrappers::types::int_type) ==
1352 sizeof((*begin) * 2));
1353
1354 TrilinosWrappers::types::int_type *col_index_ptr =
1355 reinterpret_cast<TrilinosWrappers::types::int_type *>(
1356 const_cast<std::decay_t<decltype(*begin)> *>(&*begin));
1357 // Check at least for the first index that the conversion actually works
1358 AssertDimension(*col_index_ptr, *begin);
1359 TrilinosWrappers::types::int_type trilinos_row_index = row;
1360 const int n_cols = static_cast<int>(end - begin);
1361
1362 int ierr;
1363 if (row_is_stored_locally(row))
1364 ierr =
1365 graph->InsertGlobalIndices(trilinos_row_index, n_cols, col_index_ptr);
1366 else if (nonlocal_graph.get() != nullptr)
1367 {
1368 // this is the case when we have explicitly set the off-processor rows
1369 // and want to create a separate matrix object for them (to retain
1370 // thread-safety)
1371 Assert(nonlocal_graph->RowMap().LID(
1372 static_cast<TrilinosWrappers::types::int_type>(row)) != -1,
1373 ExcMessage("Attempted to write into off-processor matrix row " +
1375 " that has not been specified as being writable upon "
1376 "initialization."));
1377 ierr = nonlocal_graph->InsertGlobalIndices(trilinos_row_index,
1378 n_cols,
1379 col_index_ptr);
1380 }
1381 else
1382 ierr = graph->InsertGlobalIndices(1,
1383 &trilinos_row_index,
1384 n_cols,
1385 col_index_ptr);
1386
1387 AssertThrow(ierr >= 0, ExcTrilinosError(ierr));
1388 }
1389
1390
1391
1392 inline const Epetra_FECrsGraph &
1394 {
1395 return *graph;
1396 }
1397
1398
1399
1400 inline IndexSet
1402 {
1403 return IndexSet(graph->DomainMap());
1404 }
1405
1406
1407
1408 inline IndexSet
1410 {
1411 return IndexSet(graph->RangeMap());
1412 }
1413
1414# endif // DOXYGEN
1415} // namespace TrilinosWrappers
1416
1417#endif
1418
1420
1421#endif
size_type n_rows() const
size_type n_cols() const
std::shared_ptr< const std::vector< size_type > > colnum_cache
Accessor(const SparsityPattern *sparsity_pattern, const size_type row, const size_type index)
Iterator(const SparsityPattern *sparsity_pattern, const size_type row, const size_type index)
IndexSet locally_owned_domain_indices() const
size_type row_length(const size_type row) const
std::unique_ptr< Epetra_FECrsGraph > graph
void add(const size_type i, const size_type j)
void print(std::ostream &out, const bool write_extended_trilinos_info=false) const
void print_gnuplot(std::ostream &out) const
const_iterator end() const
virtual void add_row_entries(const size_type &row, const ArrayView< const size_type > &columns, const bool indices_are_sorted=false) override
friend class SparsityPatternIterators::Iterator
std::unique_ptr< Epetra_CrsGraph > nonlocal_graph
bool exists(const size_type i, const size_type j) const
std::pair< size_type, size_type > local_range() const
const Epetra_FECrsGraph & trilinos_sparsity_pattern() const
void add_entries(const size_type row, ForwardIterator begin, ForwardIterator end, const bool indices_are_sorted=false)
void reinit(const size_type m, const size_type n, const size_type n_entries_per_row)
void copy_from(const SparsityPattern &input_sparsity_pattern)
IndexSet locally_owned_range_indices() const
std::unique_ptr< Epetra_Map > column_space_map
friend class SparsityPatternIterators::Accessor
const_iterator begin() const
SparsityPatternIterators::Iterator const_iterator
bool in_local_range(const size_type index) const
bool row_is_stored_locally(const size_type i) const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition config.h:636
#define DEAL_II_DEPRECATED_WITH_COMMENT(comment)
Definition config.h:295
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition config.h:680
static ::ExceptionBase & ExcAccessToNonPresentElement(size_type arg1, size_type arg2)
#define DeclException0(Exception0)
static ::ExceptionBase & ExcBeyondEndOfSparsityPattern()
#define DeclException4(Exception4, type1, type2, type3, type4, outsequence)
static ::ExceptionBase & ExcInvalidIndexWithinRow(size_type arg1, size_type arg2)
#define Assert(cond, exc)
static ::ExceptionBase & ExcIteratorPastEnd()
static ::ExceptionBase & ExcAccessToNonlocalRow(size_type arg1, size_type arg2, size_type arg3)
#define DeclException2(Exception2, type1, type2, outsequence)
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcAccessToNonLocalElement(size_type arg1, size_type arg2, size_type arg3, size_type arg4)
static ::ExceptionBase & ExcInvalidIndex(size_type arg1, size_type arg2)
#define AssertIndexRange(index, range)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
#define DeclException1(Exception1, type1, outsequence)
static ::ExceptionBase & ExcTrilinosError(int arg1)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition utilities.cc:473
STL namespace.
unsigned int global_dof_index
Definition types.h:92