Reference documentation for deal.II version 9.1.0-pre
trilinos_sparsity_pattern.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2008 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_trilinos_sparsity_pattern_h
17 # define dealii_trilinos_sparsity_pattern_h
18 
19 
20 # include <deal.II/base/config.h>
21 
22 # ifdef DEAL_II_WITH_TRILINOS
23 
24 # include <deal.II/base/index_set.h>
25 # include <deal.II/base/subscriptor.h>
26 
27 # include <deal.II/lac/exceptions.h>
28 
29 # include <Epetra_FECrsGraph.h>
30 # include <Epetra_Map.h>
31 
32 # include <cmath>
33 # include <memory>
34 # include <vector>
35 # ifdef DEAL_II_WITH_MPI
36 # include <Epetra_MpiComm.h>
37 # include <mpi.h>
38 # else
39 # include <Epetra_SerialComm.h>
40 # endif
41 
42 
43 DEAL_II_NAMESPACE_OPEN
44 
45 // forward declarations
46 class SparsityPattern;
48 
49 namespace TrilinosWrappers
50 {
51  // forward declarations
52  class SparsityPattern;
53  class SparseMatrix;
54 
55  namespace SparsityPatternIterators
56  {
57  // forward declaration
58  class Iterator;
59 
73  class Accessor
74  {
75  public:
80 
85  const size_type row,
86  const size_type index);
87 
91  size_type
92  row() const;
93 
97  size_type
98  index() const;
99 
103  size_type
104  column() const;
105 
110 
115  size_type,
116  size_type,
117  size_type,
118  << "You tried to access row " << arg1
119  << " of a distributed sparsity pattern, "
120  << " but only rows " << arg2 << " through " << arg3
121  << " are stored locally and can be accessed.");
122 
123  private:
128 
133 
138 
151  std::shared_ptr<const std::vector<size_type>> colnum_cache;
152 
158  void
160 
164  friend class Iterator;
165  };
166 
172  class Iterator
173  {
174  public:
179 
185  const size_type row,
186  const size_type index);
187 
191  Iterator(const Iterator &i);
192 
196  Iterator &
197  operator++();
198 
202  Iterator
203  operator++(int);
204 
208  const Accessor &operator*() const;
209 
213  const Accessor *operator->() const;
214 
219  bool
220  operator==(const Iterator &) const;
221 
225  bool
226  operator!=(const Iterator &) const;
227 
233  bool
234  operator<(const Iterator &) const;
235 
239  DeclException2(ExcInvalidIndexWithinRow,
240  size_type,
241  size_type,
242  << "Attempt to access element " << arg2 << " of row "
243  << arg1 << " which doesn't have that many elements.");
244 
245  private:
250 
252  };
253 
254  } // namespace SparsityPatternIterators
255 
256 
276  {
277  public:
282 
287 
295  SparsityPattern();
296 
311  SparsityPattern(const size_type m,
312  const size_type n,
313  const size_type n_entries_per_row = 0);
314 
323  SparsityPattern(const size_type m,
324  const size_type n,
325  const std::vector<size_type> &n_entries_per_row);
326 
331  SparsityPattern(SparsityPattern &&other) noexcept;
332 
337  SparsityPattern(const SparsityPattern &input_sparsity_pattern);
338 
342  virtual ~SparsityPattern() override = default;
343 
355  void
356  reinit(const size_type m,
357  const size_type n,
358  const size_type n_entries_per_row = 0);
359 
368  void
369  reinit(const size_type m,
370  const size_type n,
371  const std::vector<size_type> &n_entries_per_row);
372 
377  void
378  copy_from(const SparsityPattern &input_sparsity_pattern);
379 
385  template <typename SparsityPatternType>
386  void
387  copy_from(const SparsityPatternType &nontrilinos_sparsity_pattern);
388 
396  operator=(const SparsityPattern &input_sparsity_pattern);
397 
405  void
406  clear();
407 
417  void
418  compress();
420 
424 
439  DEAL_II_DEPRECATED
440  SparsityPattern(const Epetra_Map &parallel_partitioning,
441  const size_type n_entries_per_row = 0);
442 
455  DEAL_II_DEPRECATED
456  SparsityPattern(const Epetra_Map & parallel_partitioning,
457  const std::vector<size_type> &n_entries_per_row);
458 
477  DEAL_II_DEPRECATED
478  SparsityPattern(const Epetra_Map &row_parallel_partitioning,
479  const Epetra_Map &col_parallel_partitioning,
480  const size_type n_entries_per_row = 0);
481 
495  DEAL_II_DEPRECATED
496  SparsityPattern(const Epetra_Map & row_parallel_partitioning,
497  const Epetra_Map & col_parallel_partitioning,
498  const std::vector<size_type> &n_entries_per_row);
499 
516  DEAL_II_DEPRECATED
517  void
518  reinit(const Epetra_Map &parallel_partitioning,
519  const size_type n_entries_per_row = 0);
520 
533  DEAL_II_DEPRECATED
534  void
535  reinit(const Epetra_Map & parallel_partitioning,
536  const std::vector<size_type> &n_entries_per_row);
537 
556  DEAL_II_DEPRECATED
557  void
558  reinit(const Epetra_Map &row_parallel_partitioning,
559  const Epetra_Map &col_parallel_partitioning,
560  const size_type n_entries_per_row = 0);
561 
575  DEAL_II_DEPRECATED
576  void
577  reinit(const Epetra_Map & row_parallel_partitioning,
578  const Epetra_Map & col_parallel_partitioning,
579  const std::vector<size_type> &n_entries_per_row);
580 
591  template <typename SparsityPatternType>
592  DEAL_II_DEPRECATED void
593  reinit(const Epetra_Map & row_parallel_partitioning,
594  const Epetra_Map & col_parallel_partitioning,
595  const SparsityPatternType &nontrilinos_sparsity_pattern,
596  const bool exchange_data = false);
597 
608  template <typename SparsityPatternType>
609  DEAL_II_DEPRECATED void
610  reinit(const Epetra_Map & parallel_partitioning,
611  const SparsityPatternType &nontrilinos_sparsity_pattern,
612  const bool exchange_data = false);
614 
618 
630  SparsityPattern(const IndexSet &parallel_partitioning,
631  const MPI_Comm &communicator = MPI_COMM_WORLD,
632  const size_type n_entries_per_row = 0);
633 
644  SparsityPattern(const IndexSet & parallel_partitioning,
645  const MPI_Comm & communicator,
646  const std::vector<size_type> &n_entries_per_row);
647 
662  SparsityPattern(const IndexSet &row_parallel_partitioning,
663  const IndexSet &col_parallel_partitioning,
664  const MPI_Comm &communicator = MPI_COMM_WORLD,
665  const size_type n_entries_per_row = 0);
666 
678  SparsityPattern(const IndexSet & row_parallel_partitioning,
679  const IndexSet & col_parallel_partitioning,
680  const MPI_Comm & communicator,
681  const std::vector<size_type> &n_entries_per_row);
682 
709  SparsityPattern(const IndexSet &row_parallel_partitioning,
710  const IndexSet &col_parallel_partitioning,
711  const IndexSet &writable_rows,
712  const MPI_Comm &communicator = MPI_COMM_WORLD,
713  const size_type n_entries_per_row = 0);
714 
730  void
731  reinit(const IndexSet &parallel_partitioning,
732  const MPI_Comm &communicator = MPI_COMM_WORLD,
733  const size_type n_entries_per_row = 0);
734 
745  void
746  reinit(const IndexSet & parallel_partitioning,
747  const MPI_Comm & communicator,
748  const std::vector<size_type> &n_entries_per_row);
749 
766  void
767  reinit(const IndexSet &row_parallel_partitioning,
768  const IndexSet &col_parallel_partitioning,
769  const MPI_Comm &communicator = MPI_COMM_WORLD,
770  const size_type n_entries_per_row = 0);
771 
797  void
798  reinit(const IndexSet &row_parallel_partitioning,
799  const IndexSet &col_parallel_partitioning,
800  const IndexSet &writeable_rows,
801  const MPI_Comm &communicator = MPI_COMM_WORLD,
802  const size_type n_entries_per_row = 0);
803 
808  void
809  reinit(const IndexSet & row_parallel_partitioning,
810  const IndexSet & col_parallel_partitioning,
811  const MPI_Comm & communicator,
812  const std::vector<size_type> &n_entries_per_row);
813 
823  template <typename SparsityPatternType>
824  void
825  reinit(const IndexSet & row_parallel_partitioning,
826  const IndexSet & col_parallel_partitioning,
827  const SparsityPatternType &nontrilinos_sparsity_pattern,
828  const MPI_Comm & communicator = MPI_COMM_WORLD,
829  const bool exchange_data = false);
830 
839  template <typename SparsityPatternType>
840  void
841  reinit(const IndexSet & parallel_partitioning,
842  const SparsityPatternType &nontrilinos_sparsity_pattern,
843  const MPI_Comm & communicator = MPI_COMM_WORLD,
844  const bool exchange_data = false);
846 
850 
855  bool
856  is_compressed() const;
857 
861  unsigned int
862  max_entries_per_row() const;
863 
867  size_type
868  n_rows() const;
869 
873  size_type
874  n_cols() const;
875 
885  unsigned int
886  local_size() const;
887 
896  std::pair<size_type, size_type>
897  local_range() const;
898 
903  bool
904  in_local_range(const size_type index) const;
905 
909  size_type
910  n_nonzero_elements() const;
911 
920  size_type
921  row_length(const size_type row) const;
922 
929  size_type
930  bandwidth() const;
931 
936  bool
937  empty() const;
938 
943  bool
944  exists(const size_type i, const size_type j) const;
945 
950  bool
951  row_is_stored_locally(const size_type i) const;
952 
957  std::size_t
958  memory_consumption() const;
959 
961 
968  void
969  add(const size_type i, const size_type j);
970 
971 
975  template <typename ForwardIterator>
976  void
977  add_entries(const size_type row,
978  ForwardIterator begin,
979  ForwardIterator end,
980  const bool indices_are_sorted = false);
982 
986 
991  const Epetra_FECrsGraph &
992  trilinos_sparsity_pattern() const;
993 
1002  DEAL_II_DEPRECATED
1003  const Epetra_Map &
1004  domain_partitioner() const;
1005 
1014  DEAL_II_DEPRECATED
1015  const Epetra_Map &
1016  range_partitioner() const;
1017 
1025  DEAL_II_DEPRECATED
1026  const Epetra_Map &
1027  row_partitioner() const;
1028 
1038  DEAL_II_DEPRECATED
1039  const Epetra_Map &
1040  col_partitioner() const;
1041 
1047  DEAL_II_DEPRECATED
1048  const Epetra_Comm &
1049  trilinos_communicator() const;
1050 
1054  MPI_Comm
1055  get_mpi_communicator() const;
1057 
1062 
1068  IndexSet
1069  locally_owned_domain_indices() const;
1070 
1076  IndexSet
1077  locally_owned_range_indices() const;
1078 
1080 
1085 
1090  begin() const;
1091 
1096  end() const;
1097 
1107  begin(const size_type r) const;
1108 
1118  end(const size_type r) const;
1119 
1121 
1125 
1131  void
1132  write_ascii();
1133 
1141  void
1142  print(std::ostream &out,
1143  const bool write_extended_trilinos_info = false) const;
1144 
1159  void
1160  print_gnuplot(std::ostream &out) const;
1161 
1163 
1171  int,
1172  << "An error with error number " << arg1
1173  << " occurred while calling a Trilinos function");
1174 
1178  DeclException2(ExcInvalidIndex,
1179  size_type,
1180  size_type,
1181  << "The entry with index <" << arg1 << ',' << arg2
1182  << "> does not exist.");
1183 
1188  ExcSourceEqualsDestination,
1189  "You are attempting an operation on two sparsity patterns that "
1190  "are the same object, but the operation requires that the "
1191  "two objects are in fact different.");
1192 
1196  DeclException4(ExcAccessToNonLocalElement,
1197  size_type,
1198  size_type,
1199  size_type,
1200  size_type,
1201  << "You tried to access element (" << arg1 << "/" << arg2
1202  << ")"
1203  << " of a distributed matrix, but only rows " << arg3
1204  << " through " << arg4
1205  << " are stored locally and can be accessed.");
1206 
1210  DeclException2(ExcAccessToNonPresentElement,
1211  size_type,
1212  size_type,
1213  << "You tried to access element (" << arg1 << "/" << arg2
1214  << ")"
1215  << " of a sparse matrix, but it appears to not"
1216  << " exist in the Trilinos sparsity pattern.");
1218  private:
1223  std::unique_ptr<Epetra_Map> column_space_map;
1224 
1230  std::unique_ptr<Epetra_FECrsGraph> graph;
1231 
1238  std::unique_ptr<Epetra_CrsGraph> nonlocal_graph;
1239 
1240  friend class TrilinosWrappers::SparseMatrix;
1241  friend class SparsityPatternIterators::Accessor;
1242  friend class SparsityPatternIterators::Iterator;
1243  };
1244 
1245 
1246 
1247  // ----------------------- inline and template functions --------------------
1248 
1249 
1250 # ifndef DOXYGEN
1251 
1252  namespace SparsityPatternIterators
1253  {
1254  inline Accessor::Accessor(const SparsityPattern *sp,
1255  const size_type row,
1256  const size_type index)
1257  : sparsity_pattern(const_cast<SparsityPattern *>(sp))
1258  , a_row(row)
1259  , a_index(index)
1260  {
1262  }
1263 
1264 
1265 
1266  inline Accessor::size_type
1267  Accessor::row() const
1268  {
1269  Assert(a_row < sparsity_pattern->n_rows(),
1271  return a_row;
1272  }
1273 
1274 
1275 
1276  inline Accessor::size_type
1277  Accessor::column() const
1278  {
1279  Assert(a_row < sparsity_pattern->n_rows(),
1281  return (*colnum_cache)[a_index];
1282  }
1283 
1284 
1285 
1286  inline Accessor::size_type
1287  Accessor::index() const
1288  {
1289  Assert(a_row < sparsity_pattern->n_rows(),
1291  return a_index;
1292  }
1293 
1294 
1295 
1296  inline Iterator::Iterator(const SparsityPattern *sp,
1297  const size_type row,
1298  const size_type index)
1299  : accessor(sp, row, index)
1300  {}
1301 
1302 
1303 
1304  inline Iterator::Iterator(const Iterator &) = default;
1305 
1306 
1307 
1308  inline Iterator &
1310  {
1311  Assert(accessor.a_row < accessor.sparsity_pattern->n_rows(),
1312  ExcIteratorPastEnd());
1313 
1314  ++accessor.a_index;
1315 
1316  // If at end of line: do one step, then cycle until we find a row with a
1317  // nonzero number of entries that is stored locally.
1318  if (accessor.a_index >= accessor.colnum_cache->size())
1319  {
1320  accessor.a_index = 0;
1321  ++accessor.a_row;
1322 
1323  while (accessor.a_row < accessor.sparsity_pattern->n_rows())
1324  {
1325  const auto row_length =
1326  accessor.sparsity_pattern->row_length(accessor.a_row);
1327  if (row_length == 0 ||
1328  !accessor.sparsity_pattern->row_is_stored_locally(
1329  accessor.a_row))
1330  ++accessor.a_row;
1331  else
1332  break;
1333  }
1334 
1335  accessor.visit_present_row();
1336  }
1337  return *this;
1338  }
1339 
1340 
1341 
1342  inline Iterator
1344  {
1345  const Iterator old_state = *this;
1346  ++(*this);
1347  return old_state;
1348  }
1349 
1350 
1351 
1352  inline const Accessor &Iterator::operator*() const
1353  {
1354  return accessor;
1355  }
1356 
1357 
1358 
1359  inline const Accessor *Iterator::operator->() const
1360  {
1361  return &accessor;
1362  }
1363 
1364 
1365 
1366  inline bool
1367  Iterator::operator==(const Iterator &other) const
1368  {
1369  return (accessor.a_row == other.accessor.a_row &&
1370  accessor.a_index == other.accessor.a_index);
1371  }
1372 
1373 
1374 
1375  inline bool
1376  Iterator::operator!=(const Iterator &other) const
1377  {
1378  return !(*this == other);
1379  }
1380 
1381 
1382 
1383  inline bool
1384  Iterator::operator<(const Iterator &other) const
1385  {
1386  return (accessor.row() < other.accessor.row() ||
1387  (accessor.row() == other.accessor.row() &&
1388  accessor.index() < other.accessor.index()));
1389  }
1390 
1391  } // namespace SparsityPatternIterators
1392 
1393 
1394 
1396  SparsityPattern::begin() const
1397  {
1398  const size_type first_valid_row = this->local_range().first;
1399  return const_iterator(this, first_valid_row, 0);
1400  }
1401 
1402 
1403 
1405  SparsityPattern::end() const
1406  {
1407  return const_iterator(this, n_rows(), 0);
1408  }
1409 
1410 
1411 
1413  SparsityPattern::begin(const size_type r) const
1414  {
1415  Assert(r < n_rows(), ExcIndexRangeType<size_type>(r, 0, n_rows()));
1416  if (row_length(r) > 0)
1417  return const_iterator(this, r, 0);
1418  else
1419  return end(r);
1420  }
1421 
1422 
1423 
1425  SparsityPattern::end(const size_type r) const
1426  {
1427  Assert(r < n_rows(), ExcIndexRangeType<size_type>(r, 0, n_rows()));
1428 
1429  // place the iterator on the first entry
1430  // past this line, or at the end of the
1431  // matrix
1432  for (size_type i = r + 1; i < n_rows(); ++i)
1433  if (row_length(i) > 0)
1434  return const_iterator(this, i, 0);
1435 
1436  // if there is no such line, then take the
1437  // end iterator of the matrix
1438  return end();
1439  }
1440 
1441 
1442 
1443  inline bool
1444  SparsityPattern::in_local_range(const size_type index) const
1445  {
1446  TrilinosWrappers::types::int_type begin, end;
1447 # ifndef DEAL_II_WITH_64BIT_INDICES
1448  begin = graph->RowMap().MinMyGID();
1449  end = graph->RowMap().MaxMyGID() + 1;
1450 # else
1451  begin = graph->RowMap().MinMyGID64();
1452  end = graph->RowMap().MaxMyGID64() + 1;
1453 # endif
1454 
1455  return ((index >= static_cast<size_type>(begin)) &&
1456  (index < static_cast<size_type>(end)));
1457  }
1458 
1459 
1460 
1461  inline bool
1463  {
1464  return graph->Filled();
1465  }
1466 
1467 
1468 
1469  inline bool
1470  SparsityPattern::empty() const
1471  {
1472  return ((n_rows() == 0) && (n_cols() == 0));
1473  }
1474 
1475 
1476 
1477  inline void
1478  SparsityPattern::add(const size_type i, const size_type j)
1479  {
1480  add_entries(i, &j, &j + 1);
1481  }
1482 
1483 
1484 
1485  template <typename ForwardIterator>
1486  inline void
1487  SparsityPattern::add_entries(const size_type row,
1488  ForwardIterator begin,
1489  ForwardIterator end,
1490  const bool /*indices_are_sorted*/)
1491  {
1492  if (begin == end)
1493  return;
1494 
1495  // verify that the size of the data type Trilinos expects matches that the
1496  // iterator points to. we allow for some slippage between signed and
1497  // unsigned and only compare that they are both either 32 or 64 bit. to
1498  // write this test properly, not that we cannot compare the size of
1499  // '*begin' because 'begin' may be an iterator and '*begin' may be an
1500  // accessor class. consequently, we need to somehow get an actual value
1501  // from it which we can by evaluating an expression such as when
1502  // multiplying the value produced by 2
1503  Assert(sizeof(TrilinosWrappers::types::int_type) == sizeof((*begin) * 2),
1504  ExcNotImplemented());
1505 
1506  TrilinosWrappers::types::int_type *col_index_ptr =
1507  (TrilinosWrappers::types::int_type *)(&*begin);
1508  const int n_cols = static_cast<int>(end - begin);
1509 
1510  int ierr;
1511  if (row_is_stored_locally(row))
1512  ierr = graph->InsertGlobalIndices(row, n_cols, col_index_ptr);
1513  else if (nonlocal_graph.get() != nullptr)
1514  {
1515  // this is the case when we have explicitly set the off-processor rows
1516  // and want to create a separate matrix object for them (to retain
1517  // thread-safety)
1518  Assert(nonlocal_graph->RowMap().LID(
1519  static_cast<TrilinosWrappers::types::int_type>(row)) != -1,
1520  ExcMessage("Attempted to write into off-processor matrix row "
1521  "that has not be specified as being writable upon "
1522  "initialization"));
1523  ierr = nonlocal_graph->InsertGlobalIndices(row, n_cols, col_index_ptr);
1524  }
1525  else
1526  ierr = graph->InsertGlobalIndices(
1527  1, (TrilinosWrappers::types::int_type *)&row, n_cols, col_index_ptr);
1528 
1529  AssertThrow(ierr >= 0, ExcTrilinosError(ierr));
1530  }
1531 
1532 
1533 
1534  inline const Epetra_FECrsGraph &
1536  {
1537  return *graph;
1538  }
1539 
1540 
1541 
1542  inline IndexSet
1544  {
1545  return IndexSet(static_cast<const Epetra_Map &>(graph->DomainMap()));
1546  }
1547 
1548 
1549 
1550  inline IndexSet
1552  {
1553  return IndexSet(static_cast<const Epetra_Map &>(graph->RangeMap()));
1554  }
1555 
1556 # endif // DOXYGEN
1557 } // namespace TrilinosWrappers
1558 
1559 
1560 DEAL_II_NAMESPACE_CLOSE
1561 
1562 
1563 # endif // DEAL_II_WITH_TRILINOS
1564 
1565 
1566 /*-------------------- trilinos_sparsity_pattern.h --------------------*/
1567 
1568 #endif
1569 /*-------------------- trilinos_sparsity_pattern.h --------------------*/
static::ExceptionBase & ExcTrilinosError(int arg1)
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:420
const_iterator end() const
bool in_local_range(const size_type index) const
std::shared_ptr< const std::vector< size_type > > colnum_cache
STL namespace.
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
const Epetra_FECrsGraph & trilinos_sparsity_pattern() const
void add(const size_type i, const size_type j)
void add_entries(const size_type row, ForwardIterator begin, ForwardIterator end, const bool indices_are_sorted=false)
SymmetricTensor< rank_, dim, Number > operator*(const SymmetricTensor< rank_, dim, Number > &t, const Number &factor)
unsigned long long int global_dof_index
Definition: types.h:72
static::ExceptionBase & ExcMessage(std::string arg1)
const_iterator begin() const
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:408
IndexSet locally_owned_range_indices() const
#define Assert(cond, exc)
Definition: exceptions.h:1227
#define DeclExceptionMsg(Exception, defaulttext)
Definition: exceptions.h:397
#define DeclException0(Exception0)
Definition: exceptions.h:385
IndexSet locally_owned_domain_indices() const
static::ExceptionBase & ExcIteratorPastEnd()
Iterator(const SparsityPattern *sparsity_pattern, const size_type row, const size_type index)
static::ExceptionBase & ExcAccessToNonlocalRow(size_type arg1, size_type arg2, size_type arg3)
#define DeclException4(Exception4, type1, type2, type3, type4, outsequence)
Definition: exceptions.h:444
static::ExceptionBase & ExcNotImplemented()
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition: exceptions.h:432
Accessor(const SparsityPattern *sparsity_pattern, const size_type row, const size_type index)