deal.II version 9.7.0
\(\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: LGPL-2.1-or-later
4// Copyright (C) 2008 - 2024 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
15#ifndef dealii_trilinos_sparsity_pattern_h
16#define dealii_trilinos_sparsity_pattern_h
17
18#include <deal.II/base/config.h>
19
20#ifdef DEAL_II_WITH_TRILINOS
21
26
29
31# include <Epetra_FECrsGraph.h>
32# include <Epetra_Map.h>
33# include <Epetra_MpiComm.h>
35
36# include <cmath>
37# include <memory>
38# include <vector>
39
40
42
43// forward declarations
44# ifndef DOXYGEN
45class SparsityPattern;
47
48namespace TrilinosWrappers
49{
50 class SparsityPattern;
51 class SparseMatrix;
52
54 {
55 class Iterator;
56 }
57} // namespace TrilinosWrappers
58# endif
59
60namespace TrilinosWrappers
61{
63 {
76 {
77 public:
82
87 const size_type row,
88 const size_type index);
89
94 row() const;
95
100 index() const;
101
106 column() const;
107
112
117 size_type,
118 size_type,
119 size_type,
120 << "You tried to access row " << arg1
121 << " of a distributed sparsity pattern, "
122 << " but only rows " << arg2 << " through " << arg3
123 << " are stored locally and can be accessed.");
124
125 private:
130
135
140
153 std::shared_ptr<const std::vector<size_type>> colnum_cache;
154
160 void
162
163 // Make enclosing class a friend.
164 friend class Iterator;
165 };
166
173 {
174 public:
179
184 Iterator(const SparsityPattern *sparsity_pattern,
185 const size_type row,
186 const size_type index);
187
192
196 Iterator &
198
204
208 const Accessor &
209 operator*() const;
210
214 const Accessor *
215 operator->() const;
216
221 bool
222 operator==(const Iterator &) const;
223
227 bool
228 operator!=(const Iterator &) const;
229
235 bool
236 operator<(const Iterator &) const;
237
242 size_type,
243 size_type,
244 << "Attempt to access element " << arg2 << " of row "
245 << arg1 << " which doesn't have that many elements.");
246
247 private:
252
254 };
255
256 } // namespace SparsityPatternIterators
257
258
277 {
278 public:
283
288
297
313 const size_type n,
314 const size_type n_entries_per_row = 0);
315
325 const size_type n,
326 const std::vector<size_type> &n_entries_per_row);
327
332 SparsityPattern(SparsityPattern &&other) noexcept;
333
338 SparsityPattern(const SparsityPattern &input_sparsity_pattern);
339
343 virtual ~SparsityPattern() override = default;
344
356 void
357 reinit(const size_type m,
358 const size_type n,
359 const size_type n_entries_per_row = 0);
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 &input_sparsity_pattern);
380
386 template <typename SparsityPatternType>
387 void
388 copy_from(const SparsityPatternType &nontrilinos_sparsity_pattern);
389
397 operator=(const SparsityPattern &input_sparsity_pattern);
398
406 void
407 clear();
408
418 void
419 compress();
421
426
438 SparsityPattern(const IndexSet &parallel_partitioning,
439 const MPI_Comm communicator = MPI_COMM_WORLD,
440 const size_type n_entries_per_row = 0);
441
452 SparsityPattern(const IndexSet &parallel_partitioning,
453 const MPI_Comm communicator,
454 const std::vector<size_type> &n_entries_per_row);
455
470 SparsityPattern(const IndexSet &row_parallel_partitioning,
471 const IndexSet &col_parallel_partitioning,
472 const MPI_Comm communicator = MPI_COMM_WORLD,
473 const size_type n_entries_per_row = 0);
474
486 SparsityPattern(const IndexSet &row_parallel_partitioning,
487 const IndexSet &col_parallel_partitioning,
488 const MPI_Comm communicator,
489 const std::vector<size_type> &n_entries_per_row);
490
517 SparsityPattern(const IndexSet &row_parallel_partitioning,
518 const IndexSet &col_parallel_partitioning,
519 const IndexSet &writable_rows,
520 const MPI_Comm communicator = MPI_COMM_WORLD,
521 const size_type n_entries_per_row = 0);
522
538 void
539 reinit(const IndexSet &parallel_partitioning,
540 const MPI_Comm communicator = MPI_COMM_WORLD,
541 const size_type n_entries_per_row = 0);
542
553 void
554 reinit(const IndexSet &parallel_partitioning,
555 const MPI_Comm communicator,
556 const std::vector<size_type> &n_entries_per_row);
557
574 void
575 reinit(const IndexSet &row_parallel_partitioning,
576 const IndexSet &col_parallel_partitioning,
577 const MPI_Comm communicator = MPI_COMM_WORLD,
578 const size_type n_entries_per_row = 0);
579
605 void
606 reinit(const IndexSet &row_parallel_partitioning,
607 const IndexSet &col_parallel_partitioning,
608 const IndexSet &writeable_rows,
609 const MPI_Comm communicator = MPI_COMM_WORLD,
610 const size_type n_entries_per_row = 0);
611
616 void
617 reinit(const IndexSet &row_parallel_partitioning,
618 const IndexSet &col_parallel_partitioning,
619 const MPI_Comm communicator,
620 const std::vector<size_type> &n_entries_per_row);
621
631 template <typename SparsityPatternType>
632 void
633 reinit(const IndexSet &row_parallel_partitioning,
634 const IndexSet &col_parallel_partitioning,
635 const SparsityPatternType &nontrilinos_sparsity_pattern,
636 const MPI_Comm communicator = MPI_COMM_WORLD,
637 const bool exchange_data = false);
638
647 template <typename SparsityPatternType>
648 void
649 reinit(const IndexSet &parallel_partitioning,
650 const SparsityPatternType &nontrilinos_sparsity_pattern,
651 const MPI_Comm communicator = MPI_COMM_WORLD,
652 const bool exchange_data = false);
658
663 bool
665
669 unsigned int
670 max_entries_per_row() const;
671
681 unsigned int
682 local_size() const;
683
692 std::pair<size_type, size_type>
693 local_range() const;
694
699 bool
700 in_local_range(const size_type index) const;
701
705 std::uint64_t
706 n_nonzero_elements() const;
707
717 row_length(const size_type row) const;
718
726 bandwidth() const;
727
732 bool
733 empty() const;
734
739 bool
740 exists(const size_type i, const size_type j) const;
741
746 bool
747 row_is_stored_locally(const size_type i) const;
748
753 std::size_t
754 memory_consumption() const;
755
764 void
765 add(const size_type i, const size_type j);
766
767
771 template <typename ForwardIterator>
772 void
774 ForwardIterator begin,
775 ForwardIterator end,
776 const bool indices_are_sorted = false);
777
778 virtual void
779 add_row_entries(const size_type &row,
780 const ArrayView<const size_type> &columns,
781 const bool indices_are_sorted = false) override;
782
784
790
795 const Epetra_FECrsGraph &
797
804 const Epetra_Map &
805 domain_partitioner() const;
806
813 const Epetra_Map &
814 range_partitioner() const;
815
820 get_mpi_communicator() const;
821
823
828
836
844
846
851
856 begin() const;
857
862 end() const;
863
873 begin(const size_type r) const;
874
884 end(const size_type r) const;
885
891
897 void
898 write_ascii();
899
907 void
908 print(std::ostream &out,
909 const bool write_extended_trilinos_info = false) const;
910
925 void
926 print_gnuplot(std::ostream &out) const;
927
937 int,
938 << "An error with error number " << arg1
939 << " occurred while calling a Trilinos function");
940
945 size_type,
946 size_type,
947 << "The entry with index <" << arg1 << ',' << arg2
948 << "> does not exist.");
949
954 size_type,
955 size_type,
956 size_type,
957 size_type,
958 << "You tried to access element (" << arg1 << '/' << arg2
959 << ')'
960 << " of a distributed matrix, but only rows in range ["
961 << arg3 << ',' << arg4
962 << "] are stored locally and can be accessed.");
963
968 size_type,
969 size_type,
970 << "You tried to access element (" << arg1 << '/' << arg2
971 << ')' << " of a sparse matrix, but it appears to not"
972 << " exist in the Trilinos sparsity pattern.");
974 private:
979 std::unique_ptr<Epetra_Map> column_space_map;
980
986 std::unique_ptr<Epetra_FECrsGraph> graph;
987
994 std::unique_ptr<Epetra_CrsGraph> nonlocal_graph;
995
999 };
1000
1001
1002
1003 // ----------------------- inline and template functions --------------------
1004
1005
1006# ifndef DOXYGEN
1007
1008 namespace SparsityPatternIterators
1009 {
1010 inline Accessor::Accessor(const SparsityPattern *sp,
1011 const size_type row,
1012 const size_type index)
1013 : sparsity_pattern(const_cast<SparsityPattern *>(sp))
1014 , a_row(row)
1015 , a_index(index)
1016 {
1017 visit_present_row();
1018 }
1019
1020
1021
1022 inline Accessor::size_type
1023 Accessor::row() const
1024 {
1025 Assert(a_row < sparsity_pattern->n_rows(),
1026 ExcBeyondEndOfSparsityPattern());
1027 return a_row;
1028 }
1029
1030
1031
1032 inline Accessor::size_type
1033 Accessor::column() const
1034 {
1035 Assert(a_row < sparsity_pattern->n_rows(),
1036 ExcBeyondEndOfSparsityPattern());
1037 return (*colnum_cache)[a_index];
1038 }
1039
1040
1041
1042 inline Accessor::size_type
1043 Accessor::index() const
1044 {
1045 Assert(a_row < sparsity_pattern->n_rows(),
1046 ExcBeyondEndOfSparsityPattern());
1047 return a_index;
1048 }
1049
1050
1051
1052 inline Iterator::Iterator(const SparsityPattern *sp,
1053 const size_type row,
1054 const size_type index)
1055 : accessor(sp, row, index)
1056 {}
1057
1058
1059
1060 inline Iterator::Iterator(const Iterator &) = default;
1061
1062
1063
1064 inline Iterator &
1065 Iterator::operator++()
1066 {
1067 Assert(accessor.a_row < accessor.sparsity_pattern->n_rows(),
1069
1070 ++accessor.a_index;
1071
1072 // If at end of line: do one step, then cycle until we find a row with a
1073 // nonzero number of entries that is stored locally.
1074 if (accessor.a_index >= accessor.colnum_cache->size())
1075 {
1076 accessor.a_index = 0;
1077 ++accessor.a_row;
1078
1079 while (accessor.a_row < accessor.sparsity_pattern->n_rows())
1080 {
1081 const auto row_length =
1082 accessor.sparsity_pattern->row_length(accessor.a_row);
1083 if (row_length == 0 ||
1084 !accessor.sparsity_pattern->row_is_stored_locally(
1085 accessor.a_row))
1086 ++accessor.a_row;
1087 else
1088 break;
1089 }
1090
1091 accessor.visit_present_row();
1092 }
1093 return *this;
1094 }
1095
1096
1097
1098 inline Iterator
1099 Iterator::operator++(int)
1100 {
1101 const Iterator old_state = *this;
1102 ++(*this);
1103 return old_state;
1104 }
1105
1106
1107
1108 inline const Accessor &
1109 Iterator::operator*() const
1110 {
1111 return accessor;
1112 }
1113
1114
1115
1116 inline const Accessor *
1117 Iterator::operator->() const
1118 {
1119 return &accessor;
1120 }
1121
1122
1123
1124 inline bool
1125 Iterator::operator==(const Iterator &other) const
1126 {
1127 return (accessor.a_row == other.accessor.a_row &&
1128 accessor.a_index == other.accessor.a_index);
1129 }
1130
1131
1132
1133 inline bool
1134 Iterator::operator!=(const Iterator &other) const
1135 {
1136 return !(*this == other);
1137 }
1138
1139
1140
1141 inline bool
1142 Iterator::operator<(const Iterator &other) const
1143 {
1144 return (accessor.row() < other.accessor.row() ||
1145 (accessor.row() == other.accessor.row() &&
1146 accessor.index() < other.accessor.index()));
1147 }
1148
1149 } // namespace SparsityPatternIterators
1150
1151
1152
1155 {
1156 const size_type first_valid_row = this->local_range().first;
1157 return const_iterator(this, first_valid_row, 0);
1158 }
1159
1160
1161
1163 SparsityPattern::end() const
1164 {
1165 return const_iterator(this, n_rows(), 0);
1166 }
1167
1168
1169
1171 SparsityPattern::begin(const size_type r) const
1172 {
1174 if (row_length(r) > 0)
1175 return const_iterator(this, r, 0);
1176 else
1177 return end(r);
1178 }
1179
1180
1181
1183 SparsityPattern::end(const size_type r) const
1184 {
1186
1187 // place the iterator on the first entry
1188 // past this line, or at the end of the
1189 // matrix
1190 for (size_type i = r + 1; i < n_rows(); ++i)
1191 if (row_length(i) > 0)
1192 return const_iterator(this, i, 0);
1193
1194 // if there is no such line, then take the
1195 // end iterator of the matrix
1196 return end();
1197 }
1198
1199
1200
1201 inline bool
1202 SparsityPattern::in_local_range(const size_type index) const
1203 {
1205# ifndef DEAL_II_WITH_64BIT_INDICES
1206 begin = graph->RowMap().MinMyGID();
1207 end = graph->RowMap().MaxMyGID() + 1;
1208# else
1209 begin = graph->RowMap().MinMyGID64();
1210 end = graph->RowMap().MaxMyGID64() + 1;
1211# endif
1212
1213 return ((index >= static_cast<size_type>(begin)) &&
1214 (index < static_cast<size_type>(end)));
1215 }
1216
1217
1218
1219 inline bool
1221 {
1222 return graph->Filled();
1223 }
1224
1225
1226
1227 inline bool
1229 {
1230 return ((n_rows() == 0) && (n_cols() == 0));
1231 }
1232
1233
1234
1235 inline void
1236 SparsityPattern::add(const size_type i, const size_type j)
1237 {
1238 add_entries(i, &j, &j + 1);
1239 }
1240
1241
1242
1243 template <typename ForwardIterator>
1244 inline void
1245 SparsityPattern::add_entries(const size_type row,
1246 ForwardIterator begin,
1247 ForwardIterator end,
1248 const bool /*indices_are_sorted*/)
1249 {
1250 if (begin == end)
1251 return;
1252
1253 // verify that the size of the data type Trilinos expects matches that the
1254 // iterator points to. we allow for some slippage between signed and
1255 // unsigned and only compare that they are both either 32 or 64 bit. to
1256 // write this test properly, not that we cannot compare the size of
1257 // '*begin' because 'begin' may be an iterator and '*begin' may be an
1258 // accessor class. consequently, we need to somehow get an actual value
1259 // from it which we can by evaluating an expression such as when
1260 // multiplying the value produced by 2
1261 Assert(sizeof(TrilinosWrappers::types::int_type) == sizeof((*begin) * 2),
1263
1264 TrilinosWrappers::types::int_type *col_index_ptr =
1265 reinterpret_cast<TrilinosWrappers::types::int_type *>(
1266 const_cast<std::decay_t<decltype(*begin)> *>(&*begin));
1267 // Check at least for the first index that the conversion actually works
1268 AssertDimension(*col_index_ptr, *begin);
1269 TrilinosWrappers::types::int_type trilinos_row_index = row;
1270 const int n_cols = static_cast<int>(end - begin);
1271
1272 int ierr;
1273 if (row_is_stored_locally(row))
1274 ierr =
1275 graph->InsertGlobalIndices(trilinos_row_index, n_cols, col_index_ptr);
1276 else if (nonlocal_graph.get() != nullptr)
1277 {
1278 // this is the case when we have explicitly set the off-processor rows
1279 // and want to create a separate matrix object for them (to retain
1280 // thread-safety)
1281 Assert(nonlocal_graph->RowMap().LID(
1282 static_cast<TrilinosWrappers::types::int_type>(row)) != -1,
1283 ExcMessage("Attempted to write into off-processor matrix row " +
1285 " that has not been specified as being writable upon "
1286 "initialization."));
1287 ierr = nonlocal_graph->InsertGlobalIndices(trilinos_row_index,
1288 n_cols,
1289 col_index_ptr);
1290 }
1291 else
1292 ierr = graph->InsertGlobalIndices(1,
1293 &trilinos_row_index,
1294 n_cols,
1295 col_index_ptr);
1296
1297 AssertThrow(ierr >= 0, ExcTrilinosError(ierr));
1298 }
1299
1300
1301
1302 inline const Epetra_FECrsGraph &
1303 SparsityPattern::trilinos_sparsity_pattern() const
1304 {
1305 return *graph;
1306 }
1307
1308
1309
1310 inline IndexSet
1311 SparsityPattern::locally_owned_domain_indices() const
1312 {
1313 return IndexSet(graph->DomainMap());
1314 }
1315
1316
1317
1318 inline IndexSet
1319 SparsityPattern::locally_owned_range_indices() const
1320 {
1321 return IndexSet(graph->RangeMap());
1322 }
1323
1324# endif // DOXYGEN
1325} // namespace TrilinosWrappers
1326
1327
1329
1330
1331#else
1332
1333// Make sure the scripts that create the C++20 module input files have
1334// something to latch on if the preprocessor #ifdef above would
1335// otherwise lead to an empty content of the file.
1338
1339#endif // DEAL_II_WITH_TRILINOS
1340
1341#endif
size_type n_rows() const
virtual void add_entries(const ArrayView< const std::pair< size_type, size_type > > &entries)
size_type n_cols() const
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)
SparsityPatternIterators::Iterator const_iterator
iterator end() const
types::global_dof_index size_type
unsigned int row_length(const size_type row) 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
const_iterator begin(const size_type r) const
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 copy_from(const SparsityPattern &input_sparsity_pattern)
IndexSet locally_owned_range_indices() const
std::unique_ptr< Epetra_Map > column_space_map
const_iterator begin() const
const_iterator end(const size_type r) const
SparsityPatternIterators::Iterator const_iterator
bool in_local_range(const size_type index) const
virtual ~SparsityPattern() override=default
SparsityPattern & operator=(const SparsityPattern &input_sparsity_pattern)
bool row_is_stored_locally(const size_type i) const
void reinit(const size_type m, const size_type n, const size_type n_entries_per_row=0)
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:40
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition config.h:603
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:41
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition config.h:647
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 & ExcNotImplemented()
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 & 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:475
unsigned int global_dof_index
Definition types.h:94