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_tpetra_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) 2024 - 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_tpetra_sparsity_pattern_h
14#define dealii_trilinos_tpetra_sparsity_pattern_h
15
16#include <deal.II/base/config.h>
17
18#include <deal.II/base/types.h>
19
21
22#ifdef DEAL_II_TRILINOS_WITH_TPETRA
23
27
30
31# include <Tpetra_CrsGraph.hpp>
32
33# include <cmath>
34# include <memory>
35# include <vector>
36
37#endif // DEAL_II_TRILINOS_WITH_TPETRA
38
40
41#ifdef DEAL_II_TRILINOS_WITH_TPETRA
42// forward declarations
43# ifndef DOXYGEN
45
46namespace LinearAlgebra
47{
48 namespace TpetraWrappers
49 {
50 template <typename MemorySpace>
51 class SparsityPattern;
52
53 template <typename Number, typename MemorySpace>
54 class SparseMatrix;
55
57 {
58 template <typename MemorySpace>
59 class Iterator;
60 }
61 } // namespace TpetraWrappers
62} // namespace LinearAlgebra
63# endif
64
65namespace LinearAlgebra
66{
67 namespace TpetraWrappers
68 {
70 {
82 template <typename MemorySpace = ::MemorySpace::Host>
84 {
85 public:
90
95 const size_type row,
96 const size_type index);
97
102 row() const;
103
108 index() const;
109
114 column() const;
115
120
125 size_type,
126 size_type,
127 size_type,
128 << "You tried to access row " << arg1
129 << " of a distributed sparsity pattern, "
130 << " but only rows " << arg2 << " through " << arg3
131 << " are stored locally and can be accessed.");
132
133 private:
138
143
148
161 std::shared_ptr<std::vector<::types::signed_global_dof_index>>
163
169 void
171
172 // Make enclosing class a friend.
173 friend class Iterator<MemorySpace>;
174 };
175
181 template <typename MemorySpace = ::MemorySpace::Host>
183 {
184 public:
189
194 Iterator(const SparsityPattern<MemorySpace> *sparsity_pattern,
195 const size_type row,
196 const size_type index);
197
202
208
214
219 operator*() const;
220
225 operator->() const;
226
231 bool
233
237 bool
239
245 bool
246 operator<(const Iterator<MemorySpace> &) const;
247
252 size_type,
253 size_type,
254 << "Attempt to access element " << arg2 << " of row "
255 << arg1 << " which doesn't have that many elements.");
256
257 private:
262
264 };
265
266 } // namespace SparsityPatternIterators
267
268
286 template <typename MemorySpace = ::MemorySpace::Host>
288 {
289 public:
298
307
316 const size_type n,
317 const size_type n_entries_per_row);
318
328 const size_type n,
329 const std::vector<size_type> &n_entries_per_row);
330
336
342 const SparsityPattern<MemorySpace> &input_sparsity_pattern);
343
347 virtual ~SparsityPattern() override = default;
348
356 void
357 reinit(const size_type m,
358 const size_type n,
359 const size_type n_entries_per_row);
360
369 void
370 reinit(const size_type m,
371 const size_type n,
372 const std::vector<size_type> &n_entries_per_row);
373
378 void
379 copy_from(const SparsityPattern<MemorySpace> &input_sparsity_pattern);
380
386 template <typename SparsityPatternType>
387 void
388 copy_from(const SparsityPatternType &nontrilinos_sparsity_pattern);
389
397 operator=(const SparsityPattern<MemorySpace> &input_sparsity_pattern);
398
406 void
407 clear();
408
418 void
419 compress();
432 SparsityPattern(const IndexSet &parallel_partitioning,
433 const MPI_Comm communicator,
434 const size_type n_entries_per_row);
435
446 SparsityPattern(const IndexSet &parallel_partitioning,
447 const MPI_Comm communicator,
448 const std::vector<size_type> &n_entries_per_row);
449
464 SparsityPattern(const IndexSet &row_parallel_partitioning,
465 const IndexSet &col_parallel_partitioning,
466 const MPI_Comm communicator,
467 const size_type n_entries_per_row);
468
480 SparsityPattern(const IndexSet &row_parallel_partitioning,
481 const IndexSet &col_parallel_partitioning,
482 const MPI_Comm communicator,
483 const std::vector<size_type> &n_entries_per_row);
484
511 SparsityPattern(const IndexSet &row_parallel_partitioning,
512 const IndexSet &col_parallel_partitioning,
513 const IndexSet &writable_rows,
514 const MPI_Comm communicator,
515 const size_type n_entries_per_row);
516
532 void
533 reinit(const IndexSet &parallel_partitioning,
534 const MPI_Comm communicator,
535 const size_type n_entries_per_row);
536
547 void
548 reinit(const IndexSet &parallel_partitioning,
549 const MPI_Comm communicator,
550 const std::vector<size_type> &n_entries_per_row);
551
568 void
569 reinit(const IndexSet &row_parallel_partitioning,
570 const IndexSet &col_parallel_partitioning,
571 const MPI_Comm communicator,
572 const size_type n_entries_per_row);
573
599 void
600 reinit(const IndexSet &row_parallel_partitioning,
601 const IndexSet &col_parallel_partitioning,
602 const IndexSet &writable_rows,
603 const MPI_Comm communicator,
604 const size_type n_entries_per_row);
605
610 void
611 reinit(const IndexSet &row_parallel_partitioning,
612 const IndexSet &col_parallel_partitioning,
613 const MPI_Comm communicator,
614 const std::vector<size_type> &n_entries_per_row);
615
625 template <typename SparsityPatternType>
626 void
627 reinit(const IndexSet &row_parallel_partitioning,
628 const IndexSet &col_parallel_partitioning,
629 const SparsityPatternType &nontrilinos_sparsity_pattern,
630 const MPI_Comm communicator = MPI_COMM_WORLD,
631 const bool exchange_data = false);
632
641 template <typename SparsityPatternType>
642 void
643 reinit(const IndexSet &parallel_partitioning,
644 const SparsityPatternType &nontrilinos_sparsity_pattern,
645 const MPI_Comm communicator = MPI_COMM_WORLD,
646 const bool exchange_data = false);
657 bool
659
663 unsigned int
664 max_entries_per_row() const;
665
675 unsigned int
676 local_size() const;
677
686 std::pair<size_type, size_type>
687 local_range() const;
688
693 bool
694 in_local_range(const size_type index) const;
695
699 std::uint64_t
700 n_nonzero_elements() const;
701
711 row_length(const size_type row) const;
712
720 bandwidth() const;
721
726 bool
727 empty() const;
728
733 bool
734 exists(const size_type i, const size_type j) const;
735
740 bool
741 row_is_stored_locally(const size_type i) const;
742
747 std::size_t
748 memory_consumption() const;
749
758 void
759 add(const size_type i, const size_type j);
760
761
765 template <typename ForwardIterator>
766 void
768 ForwardIterator begin,
769 ForwardIterator end,
770 const bool indices_are_sorted = false);
771
772 virtual void
774 const ::types::global_dof_index &row,
776 const bool indices_are_sorted = false) override;
777
779
790 Teuchos::RCP<TpetraTypes::GraphType<MemorySpace>>
792
799 Teuchos::RCP<const TpetraTypes::MapType<MemorySpace>>
800 domain_partitioner() const;
801
808 Teuchos::RCP<const TpetraTypes::MapType<MemorySpace>>
809 range_partitioner() const;
810
815 get_mpi_communicator() const;
816
820 Teuchos::RCP<const Teuchos::Comm<int>>
822
837
845
857 begin() const;
858
863 end() const;
864
874 begin(const size_type r) const;
875
885 end(const size_type r) const;
886
900 void
901 print(std::ostream &out,
902 const bool write_extended_trilinos_info = false) const;
903
918 void
919 print_gnuplot(std::ostream &out) const;
920
930 int,
931 << "An error with error number " << arg1
932 << " occurred while calling a Trilinos function");
933
938 size_type,
939 size_type,
940 << "The entry with index <" << arg1 << ',' << arg2
941 << "> does not exist.");
942
947 size_type,
948 size_type,
949 size_type,
950 size_type,
951 << "You tried to access element (" << arg1 << '/' << arg2
952 << ')'
953 << " of a distributed matrix, but only rows in range ["
954 << arg3 << ',' << arg4
955 << "] are stored locally and can be accessed.");
956
961 size_type,
962 size_type,
963 << "You tried to access element (" << arg1 << '/' << arg2
964 << ')' << " of a sparse matrix, but it appears to not"
965 << " exist in the Trilinos sparsity pattern.");
967 private:
972 Teuchos::RCP<TpetraTypes::MapType<MemorySpace>> column_space_map;
973
979 Teuchos::RCP<TpetraTypes::GraphType<MemorySpace>> graph;
980
987 Teuchos::RCP<TpetraTypes::GraphType<MemorySpace>> nonlocal_graph;
988
989 // TODO: currently only for double
990 friend class SparseMatrix<double, MemorySpace>;
993 };
994
995
996
997 // ---------------- inline and template functions -----------------
998
999
1000# ifndef DOXYGEN
1001
1002 namespace SparsityPatternIterators
1003 {
1004 template <typename MemorySpace>
1007 const size_type row,
1008 const size_type index)
1009 : sparsity_pattern(const_cast<SparsityPattern<MemorySpace> *>(sp))
1010 , a_row(row)
1011 , a_index(index)
1012 {
1013 visit_present_row();
1014 }
1015
1016
1017
1018 template <typename MemorySpace>
1019 inline typename Accessor<MemorySpace>::size_type
1020 Accessor<MemorySpace>::row() const
1021 {
1022 Assert(a_row < sparsity_pattern->n_rows(),
1023 ExcBeyondEndOfSparsityPattern());
1024 return a_row;
1025 }
1026
1027
1028
1029 template <typename MemorySpace>
1030 inline typename Accessor<MemorySpace>::size_type
1031 Accessor<MemorySpace>::column() const
1032 {
1033 Assert(a_row < sparsity_pattern->n_rows(),
1034 ExcBeyondEndOfSparsityPattern());
1035 return (*colnum_cache)[a_index];
1036 }
1037
1038
1039
1040 template <typename MemorySpace>
1041 inline typename Accessor<MemorySpace>::size_type
1042 Accessor<MemorySpace>::index() const
1043 {
1044 Assert(a_row < sparsity_pattern->n_rows(),
1045 ExcBeyondEndOfSparsityPattern());
1046 return a_index;
1047 }
1048
1049
1050
1051 template <typename MemorySpace>
1052 inline Iterator<MemorySpace>::Iterator(
1054 const size_type row,
1055 const size_type index)
1056 : accessor(sp, row, index)
1057 {}
1058
1059
1060
1061 template <typename MemorySpace>
1062 inline Iterator<MemorySpace>::Iterator(const Iterator<MemorySpace> &) =
1063 default;
1064
1065
1066
1067 template <typename MemorySpace>
1068 inline Iterator<MemorySpace> &
1069 Iterator<MemorySpace>::operator++()
1070 {
1071 Assert(accessor.a_row < accessor.sparsity_pattern->n_rows(),
1073
1074 ++accessor.a_index;
1075
1076 // If at end of line: do one step, then cycle until we find a row with a
1077 // nonzero number of entries that is stored locally.
1078 if (accessor.a_index >=
1079 static_cast<::types::signed_global_dof_index>(
1080 accessor.colnum_cache->size()))
1081 {
1082 accessor.a_index = 0;
1083 ++accessor.a_row;
1084
1085 while (accessor.a_row <
1086 static_cast<::types::signed_global_dof_index>(
1087 accessor.sparsity_pattern->n_rows()))
1088 {
1089 const auto row_length =
1090 accessor.sparsity_pattern->row_length(accessor.a_row);
1091 if (row_length == 0 ||
1092 !accessor.sparsity_pattern->row_is_stored_locally(
1093 accessor.a_row))
1094 ++accessor.a_row;
1095 else
1096 break;
1097 }
1098
1099 accessor.visit_present_row();
1100 }
1101 return *this;
1102 }
1103
1104
1105
1106 template <typename MemorySpace>
1107 inline Iterator<MemorySpace>
1108 Iterator<MemorySpace>::operator++(int)
1109 {
1110 const Iterator<MemorySpace> old_state = *this;
1111 ++(*this);
1112 return old_state;
1113 }
1114
1115
1116
1117 template <typename MemorySpace>
1118 inline const Accessor<MemorySpace> &
1119 Iterator<MemorySpace>::operator*() const
1120 {
1121 return accessor;
1122 }
1123
1124
1125
1126 template <typename MemorySpace>
1127 inline const Accessor<MemorySpace> *
1128 Iterator<MemorySpace>::operator->() const
1129 {
1130 return &accessor;
1131 }
1132
1133
1134
1135 template <typename MemorySpace>
1136 inline bool
1137 Iterator<MemorySpace>::operator==(
1138 const Iterator<MemorySpace> &other) const
1139 {
1140 return (accessor.a_row == other.accessor.a_row &&
1141 accessor.a_index == other.accessor.a_index);
1142 }
1143
1144
1145
1146 template <typename MemorySpace>
1147 inline bool
1148 Iterator<MemorySpace>::operator!=(
1149 const Iterator<MemorySpace> &other) const
1150 {
1151 return !(*this == other);
1152 }
1153
1154
1155
1156 template <typename MemorySpace>
1157 inline bool
1158 Iterator<MemorySpace>::operator<(const Iterator<MemorySpace> &other) const
1159 {
1160 return (accessor.row() < other.accessor.row() ||
1161 (accessor.row() == other.accessor.row() &&
1162 accessor.index() < other.accessor.index()));
1163 }
1164
1165 } // namespace SparsityPatternIterators
1166
1167
1168
1169 template <typename MemorySpace>
1172 {
1173 const size_type first_valid_row = this->local_range().first;
1174 return const_iterator(this, first_valid_row, 0);
1175 }
1176
1177
1178
1179 template <typename MemorySpace>
1182 {
1183 return const_iterator(this, n_rows(), 0);
1184 }
1185
1186
1187
1188 template <typename MemorySpace>
1190 SparsityPattern<MemorySpace>::begin(const size_type r) const
1191 {
1192 AssertIndexRange(r, n_rows());
1193 if (row_length(r) > 0)
1194 return const_iterator(this, r, 0);
1195 else
1196 return end(r);
1197 }
1198
1199
1200
1201 template <typename MemorySpace>
1203 SparsityPattern<MemorySpace>::end(const size_type r) const
1204 {
1205 AssertIndexRange(r, n_rows());
1206
1207 // place the iterator on the first entry
1208 // past this line, or at the end of the
1209 // matrix
1210 for (size_type i = r + 1; i < n_rows(); ++i)
1211 if (row_length(i) > 0)
1212 return const_iterator(this, i, 0);
1213
1214 // if there is no such line, then take the
1215 // end iterator of the matrix
1216 return end();
1217 }
1218
1219
1220
1221 template <typename MemorySpace>
1222 inline bool
1223 SparsityPattern<MemorySpace>::in_local_range(const size_type index) const
1224 {
1226 graph->getRowMap()->getMinGlobalIndex();
1228 graph->getRowMap()->getMaxGlobalIndex() + 1;
1229
1230 return ((index >= static_cast<size_type>(begin)) &&
1231 (index < static_cast<size_type>(end)));
1232 }
1233
1234
1235
1236 template <typename MemorySpace>
1237 inline bool
1239 {
1240 return graph->isFillComplete();
1241 }
1242
1243
1244
1245 template <typename MemorySpace>
1246 inline bool
1248 {
1249 return ((n_rows() == 0) && (n_cols() == 0));
1250 }
1251
1252
1253
1254 template <typename MemorySpace>
1255 inline void
1256 SparsityPattern<MemorySpace>::add(const size_type i, const size_type j)
1257 {
1258 add_entries(i, &j, &j + 1);
1259 }
1260
1261
1262
1263 template <typename MemorySpace>
1264 template <typename ForwardIterator>
1265 inline void
1267 ForwardIterator begin,
1268 ForwardIterator end,
1269 const bool /*indices_are_sorted*/)
1270 {
1271 if (begin == end)
1272 return;
1273
1274 // verify that the size of the data type Trilinos expects matches that the
1275 // iterator points to. we allow for some slippage between signed and
1276 // unsigned and only compare that they are both either 32 or 64 bit. to
1277 // write this test properly, not that we cannot compare the size of
1278 // '*begin' because 'begin' may be an iterator and '*begin' may be an
1279 // accessor class. consequently, we need to somehow get an actual value
1280 // from it which we can by evaluating an expression such as when
1281 // multiplying the value produced by 2
1282 static_assert(sizeof(TrilinosWrappers::types::int_type) ==
1283 sizeof((*begin) * 2));
1284
1285 const TrilinosWrappers::types::int_type *col_index_ptr_begin =
1286 reinterpret_cast<TrilinosWrappers::types::int_type *>(
1287 const_cast<std::decay_t<decltype(*begin)> *>(&*begin));
1288
1289 const TrilinosWrappers::types::int_type *col_index_ptr_end =
1290 reinterpret_cast<TrilinosWrappers::types::int_type *>(
1291 const_cast<std::decay_t<decltype(*end)> *>(&*end));
1292
1293 // Check at least for the first index that the conversion actually works
1294 AssertDimension(*col_index_ptr_begin, *begin);
1295 AssertDimension(*col_index_ptr_end, *end);
1296 TrilinosWrappers::types::int_type trilinos_row_index = row;
1297
1298 // TODO: The following line creates an array by copying the entries.
1299 // Perhaps there is a way to only create a 'view' of these arrays
1300 // and pass that to Tpetra?
1301 Teuchos::Array<TrilinosWrappers::types::int_type> array(
1302 col_index_ptr_begin, col_index_ptr_end);
1303
1304 if (row_is_stored_locally(row))
1305 graph->insertGlobalIndices(trilinos_row_index, array());
1306 else if (nonlocal_graph.get() != nullptr)
1307 {
1308 // this is the case when we have explicitly set the off-processor rows
1309 // and want to create a separate matrix object for them (to retain
1310 // thread-safety)
1311 Assert(nonlocal_graph->getRowMap()->getLocalElement(row) !=
1312 Teuchos::OrdinalTraits<
1314 ExcMessage("Attempted to write into off-processor matrix row "
1315 "that has not be specified as being writable upon "
1316 "initialization"));
1317 nonlocal_graph->insertGlobalIndices(trilinos_row_index, array);
1318 }
1319 else
1320 graph->insertGlobalIndices(trilinos_row_index, array);
1321 }
1322
1323
1324
1325 template <typename MemorySpace>
1326 inline Teuchos::RCP<Tpetra::CrsGraph<int,
1328 TpetraTypes::NodeType<MemorySpace>>>
1330 {
1331 return graph;
1332 }
1333
1334
1335
1336 template <typename MemorySpace>
1337 inline IndexSet
1339 {
1340 return IndexSet(graph->getDomainMap().getConst());
1341 }
1342
1343
1344
1345 template <typename MemorySpace>
1346 inline IndexSet
1348 {
1349 return IndexSet(graph->getRangeMap().getConst());
1350 }
1351
1352# endif // DOXYGEN
1353 } // namespace TpetraWrappers
1354
1355} // namespace LinearAlgebra
1356
1357#endif // DEAL_II_TRILINOS_WITH_TPETRA
1358
1360
1361#endif
*  iterator end()
*  *  iterator begin()
*  *  const_iterator()=default
Accessor(const SparsityPattern< MemorySpace > *sparsity_pattern, const size_type row, const size_type index)
std::shared_ptr< std::vector<::types::signed_global_dof_index > > colnum_cache
Iterator(const SparsityPattern< MemorySpace > *sparsity_pattern, const size_type row, const size_type index)
bool operator!=(const Iterator< MemorySpace > &) const
bool operator<(const Iterator< MemorySpace > &) const
bool operator==(const Iterator< MemorySpace > &) const
Teuchos::RCP< TpetraTypes::GraphType< MemorySpace > > graph
Teuchos::RCP< const Teuchos::Comm< int > > get_teuchos_mpi_communicator() const
Teuchos::RCP< const TpetraTypes::MapType< MemorySpace > > range_partitioner() const
Teuchos::RCP< TpetraTypes::GraphType< MemorySpace > > trilinos_sparsity_pattern() const
void copy_from(const SparsityPattern< MemorySpace > &input_sparsity_pattern)
SparsityPattern< MemorySpace > & operator=(const SparsityPattern< MemorySpace > &input_sparsity_pattern)
void print(std::ostream &out, const bool write_extended_trilinos_info=false) const
Teuchos::RCP< TpetraTypes::GraphType< MemorySpace > > nonlocal_graph
Teuchos::RCP< const TpetraTypes::MapType< MemorySpace > > domain_partitioner() const
const_iterator end(const size_type r) const
bool exists(const size_type i, const size_type j) const
void add_entries(const size_type row, ForwardIterator begin, ForwardIterator end, const bool indices_are_sorted=false)
Teuchos::RCP< TpetraTypes::MapType< MemorySpace > > column_space_map
void reinit(const size_type m, const size_type n, const size_type n_entries_per_row)
virtual void add_row_entries(const ::types::global_dof_index &row, const ArrayView< const ::types::global_dof_index > &columns, const bool indices_are_sorted=false) override
void add(const size_type i, const size_type j)
const_iterator begin(const size_type r) const
virtual ~SparsityPattern() override=default
bool in_local_range(const size_type index) const
virtual void add_entries(const ArrayView< const std::pair< size_type, size_type > > &entries)
void add_entries(const size_type row, ForwardIterator begin, ForwardIterator end, const bool indices_are_sorted=false)
bool is_compressed() const
iterator begin() const
void add(const size_type i, const size_type j)
iterator end() const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
static ::ExceptionBase & ExcTrilinosError(int arg1)
#define DeclException0(Exception0)
static ::ExceptionBase & ExcAccessToNonPresentElement(size_type arg1, size_type arg2)
#define DeclException4(Exception4, type1, type2, type3, type4, outsequence)
static ::ExceptionBase & ExcAccessToNonLocalElement(size_type arg1, size_type arg2, size_type arg3, size_type arg4)
#define Assert(cond, exc)
static ::ExceptionBase & ExcIteratorPastEnd()
#define DeclException2(Exception2, type1, type2, outsequence)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcAccessToNonlocalRow(size_type arg1, size_type arg2, size_type arg3)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
static ::ExceptionBase & ExcInvalidIndex(size_type arg1, size_type arg2)
#define DeclException1(Exception1, type1, outsequence)
static ::ExceptionBase & ExcInvalidIndexWithinRow(size_type arg1, size_type arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
std::pair< types::global_dof_index, types::global_dof_index > local_range
Definition mpi.cc:814
int signed_global_dof_index
Definition types.h:103
unsigned int global_dof_index
Definition types.h:92