Reference documentation for deal.II version 9.0.0
chunk_sparsity_pattern.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2008 - 2017 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 at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_chunk_sparsity_pattern_h
17 #define dealii_chunk_sparsity_pattern_h
18 
19 
20 #include <deal.II/base/config.h>
21 #include <deal.II/base/exceptions.h>
22 #include <deal.II/base/subscriptor.h>
23 #include <deal.II/base/vector_slice.h>
24 
25 #include <deal.II/lac/sparsity_pattern.h>
26 
27 #include <vector>
28 #include <iostream>
29 
30 DEAL_II_NAMESPACE_OPEN
31 
32 
33 template <typename> class ChunkSparseMatrix;
34 
35 
46 {
47  // forward declaration
48  class Iterator;
49 
62  class Accessor
63  {
64  public:
68  Accessor (const ChunkSparsityPattern *matrix,
69  const unsigned int row);
70 
74  Accessor (const ChunkSparsityPattern *matrix);
75 
80  unsigned int row () const;
81 
85  std::size_t reduced_index() const;
86 
91  unsigned int column () const;
92 
102  bool is_valid_entry () const;
103 
104 
108  bool operator == (const Accessor &) const;
109 
110 
118  bool operator < (const Accessor &) const;
119 
120  protected:
125 
130 
134  unsigned int chunk_row;
135 
139  unsigned int chunk_col;
140 
144  void advance ();
145 
149  friend class Iterator;
150  };
151 
152 
153 
157  class Iterator
158  {
159  public:
164  Iterator (const ChunkSparsityPattern *sp,
165  const unsigned int row);
166 
171 
175  Iterator operator++ (int);
176 
180  const Accessor &operator* () const;
181 
185  const Accessor *operator-> () const;
186 
190  bool operator == (const Iterator &) const;
191 
195  bool operator != (const Iterator &) const;
196 
204  bool operator < (const Iterator &) const;
205 
206  private:
211  };
212 }
213 
214 
215 
227 {
228 public:
238 
247 
263 
270 
287 
295  const size_type n,
296  const size_type max_chunks_per_row,
297  const size_type chunk_size);
298 
307  const size_type n,
308  const std::vector<size_type> &row_lengths,
309  const size_type chunk_size);
310 
320  const size_type max_per_row,
321  const size_type chunk_size);
322 
331  const std::vector<size_type> &row_lengths,
332  const size_type chunk_size);
333 
337  ~ChunkSparsityPattern () = default;
338 
345 
354  void reinit (const size_type m,
355  const size_type n,
356  const size_type max_per_row,
357  const size_type chunk_size);
358 
373  void reinit (const size_type m,
374  const size_type n,
375  const std::vector<size_type> &row_lengths,
376  const size_type chunk_size);
377 
381  void reinit (const size_type m,
382  const size_type n,
383  const VectorSlice<const std::vector<size_type> > &row_lengths,
384  const size_type chunk_size);
385 
398  void compress ();
399 
476  template <typename ForwardIterator>
477  void copy_from (const size_type n_rows,
478  const size_type n_cols,
479  const ForwardIterator begin,
480  const ForwardIterator end,
481  const size_type chunk_size);
482 
488  template <typename SparsityPatternType>
489  void copy_from (const SparsityPatternType &dsp,
490  const size_type chunk_size);
491 
499  template <typename number>
500  void copy_from (const FullMatrix<number> &matrix,
501  const size_type chunk_size);
502 
520  template <typename Sparsity>
521  void create_from (const unsigned int m,
522  const unsigned int n,
523  const Sparsity &sparsity_pattern_for_chunks,
524  const unsigned int chunk_size,
525  const bool optimize_diagonal = true);
526 
531  bool empty () const;
532 
536  size_type get_chunk_size () const;
537 
544 
551  void add (const size_type i,
552  const size_type j);
553 
561  void symmetrize ();
562 
567  inline size_type n_rows () const;
568 
573  inline size_type n_cols () const;
574 
578  bool exists (const size_type i,
579  const size_type j) const;
580 
584  size_type row_length (const size_type row) const;
585 
592  size_type bandwidth () const;
593 
602  size_type n_nonzero_elements () const;
603 
607  bool is_compressed () const;
608 
621  bool stores_only_added_elements () const;
622 
628  iterator begin () const;
629 
633  iterator end () const;
634 
643  iterator begin (const unsigned int r) const;
644 
653  iterator end (const unsigned int r) const;
654 
665  void block_write (std::ostream &out) const;
666 
680  void block_read (std::istream &in);
681 
687  void print (std::ostream &out) const;
688 
702  void print_gnuplot (std::ostream &out) const;
703 
708  std::size_t memory_consumption () const;
709 
718  int,
719  << "The provided number is invalid here: " << arg1);
724  int, int,
725  << "The given index " << arg1
726  << " should be less than " << arg2 << ".");
731  int, int,
732  << "Upon entering a new entry to row " << arg1
733  << ": there was no free entry any more. " << std::endl
734  << "(Maximum number of entries for this row: "
735  << arg2 << "; maybe the matrix is already compressed?)");
741  "The operation you attempted is only allowed after the SparsityPattern "
742  "has been set up and compress() was called.");
748  "The operation you attempted changes the structure of the SparsityPattern "
749  "and is not possible after compress() has been called.");
758  int, int,
759  << "The iterators denote a range of " << arg1
760  << " elements, but the given number of rows was " << arg2);
769  int,
770  << "The number of partitions you gave is " << arg1
771  << ", but must be greater than zero.");
776  int, int,
777  << "The array has size " << arg1 << " but should have size "
778  << arg2);
780 private:
785 
790 
795 
801 
805  template <typename> friend class ChunkSparseMatrix;
806 
811 };
812 
813 
815 /*---------------------- Inline functions -----------------------------------*/
816 
817 #ifndef DOXYGEN
818 
820 {
821  inline
822  Accessor::
823  Accessor (const ChunkSparsityPattern *sparsity_pattern,
824  const unsigned int row)
825  :
826  sparsity_pattern(sparsity_pattern),
827  reduced_accessor(row==sparsity_pattern->n_rows() ?
828  *sparsity_pattern->sparsity_pattern.end() :
829  *sparsity_pattern->sparsity_pattern.
830  begin(row/sparsity_pattern->get_chunk_size())),
831  chunk_row (row==sparsity_pattern->n_rows() ? 0 :
832  row%sparsity_pattern->get_chunk_size()),
833  chunk_col (0)
834  {}
835 
836 
837 
838  inline
839  Accessor::
840  Accessor (const ChunkSparsityPattern *sparsity_pattern)
841  :
842  sparsity_pattern(sparsity_pattern),
843  reduced_accessor(*sparsity_pattern->sparsity_pattern.end()),
844  chunk_row (0),
845  chunk_col (0)
846  {}
847 
848 
849 
850  inline
851  bool
852  Accessor::is_valid_entry () const
853  {
854  return reduced_accessor.is_valid_entry()
855  &&
856  sparsity_pattern->get_chunk_size()*reduced_accessor.row()+chunk_row <
857  sparsity_pattern->n_rows()
858  &&
859  sparsity_pattern->get_chunk_size()*reduced_accessor.column()+chunk_col <
860  sparsity_pattern->n_cols();
861  }
862 
863 
864 
865  inline
866  unsigned int
867  Accessor::row() const
868  {
869  Assert (is_valid_entry() == true, ExcInvalidIterator());
870 
871  return sparsity_pattern->get_chunk_size()*reduced_accessor.row() +
872  chunk_row;
873  }
874 
875 
876 
877  inline
878  unsigned int
879  Accessor::column() const
880  {
881  Assert (is_valid_entry() == true, ExcInvalidIterator());
882 
883  return sparsity_pattern->get_chunk_size()*reduced_accessor.column() +
884  chunk_col;
885  }
886 
887 
888 
889  inline
890  std::size_t
891  Accessor::reduced_index() const
892  {
893  Assert (is_valid_entry() == true, ExcInvalidIterator());
894 
895  return reduced_accessor.index_within_sparsity;
896  }
897 
898 
899 
900 
901  inline
902  bool
903  Accessor::operator == (const Accessor &other) const
904  {
905  // no need to check for equality of sparsity patterns as this is done in
906  // the reduced case already and every ChunkSparsityPattern has its own
907  // reduced sparsity pattern
908  return (reduced_accessor == other.reduced_accessor &&
909  chunk_row == other.chunk_row &&
910  chunk_col == other.chunk_col);
911  }
912 
913 
914 
915  inline
916  bool
917  Accessor::operator < (const Accessor &other) const
918  {
919  Assert (sparsity_pattern == other.sparsity_pattern,
920  ExcInternalError());
921 
922  if (chunk_row != other.chunk_row)
923  {
924  if (reduced_accessor.index_within_sparsity ==
925  reduced_accessor.sparsity_pattern->n_nonzero_elements())
926  return false;
927  if (other.reduced_accessor.index_within_sparsity ==
928  reduced_accessor.sparsity_pattern->n_nonzero_elements())
929  return true;
930 
931  const unsigned int
932  global_row = sparsity_pattern->get_chunk_size()*reduced_accessor.row()
933  +chunk_row,
934  other_global_row = sparsity_pattern->get_chunk_size()*
935  other.reduced_accessor.row()+other.chunk_row;
936  if (global_row < other_global_row)
937  return true;
938  else if (global_row > other_global_row)
939  return false;
940  }
941 
942  return (reduced_accessor.index_within_sparsity <
943  other.reduced_accessor.index_within_sparsity ||
944  (reduced_accessor.index_within_sparsity ==
945  other.reduced_accessor.index_within_sparsity &&
946  chunk_col < other.chunk_col));
947  }
948 
949 
950  inline
951  void
952  Accessor::advance ()
953  {
954  const unsigned int chunk_size = sparsity_pattern->get_chunk_size();
955  Assert (chunk_row < chunk_size && chunk_col < chunk_size,
957  Assert (reduced_accessor.row() * chunk_size + chunk_row <
958  sparsity_pattern->n_rows()
959  &&
960  reduced_accessor.column() * chunk_size + chunk_col <
961  sparsity_pattern->n_cols(),
963  if (chunk_size == 1)
964  {
965  reduced_accessor.advance();
966  return;
967  }
968 
969  ++chunk_col;
970 
971  // end of chunk
972  if (chunk_col == chunk_size
973  ||
974  reduced_accessor.column() * chunk_size + chunk_col ==
975  sparsity_pattern->n_cols())
976  {
977  const unsigned int reduced_row = reduced_accessor.row();
978  // end of row
979  if (reduced_accessor.index_within_sparsity + 1 ==
980  reduced_accessor.sparsity_pattern->rowstart[reduced_row+1])
981  {
982  ++chunk_row;
983 
984  chunk_col = 0;
985 
986  // end of chunk rows or end of matrix
987  if (chunk_row == chunk_size ||
988  (reduced_row * chunk_size + chunk_row ==
989  sparsity_pattern->n_rows()))
990  {
991  chunk_row = 0;
992  reduced_accessor.advance();
993  }
994  // go back to the beginning of the same reduced row but with
995  // chunk_row increased by one
996  else
997  reduced_accessor.index_within_sparsity =
998  reduced_accessor.sparsity_pattern->rowstart[reduced_row];
999  }
1000  // advance within chunk
1001  else
1002  {
1003  reduced_accessor.advance();
1004  chunk_col = 0;
1005  }
1006  }
1007  }
1008 
1009 
1010 
1011  inline
1012  Iterator::Iterator (const ChunkSparsityPattern *sparsity_pattern,
1013  const unsigned int row)
1014  :
1015  accessor(sparsity_pattern, row)
1016  {}
1017 
1018 
1019 
1020  inline
1021  Iterator &
1022  Iterator::operator++ ()
1023  {
1024  accessor.advance ();
1025  return *this;
1026  }
1027 
1028 
1029 
1030  inline
1031  Iterator
1032  Iterator::operator++ (int)
1033  {
1034  const Iterator iter = *this;
1035  accessor.advance ();
1036  return iter;
1037  }
1038 
1039 
1040 
1041  inline
1042  const Accessor &
1043  Iterator::operator* () const
1044  {
1045  return accessor;
1046  }
1047 
1048 
1049 
1050  inline
1051  const Accessor *
1052  Iterator::operator-> () const
1053  {
1054  return &accessor;
1055  }
1056 
1057 
1058  inline
1059  bool
1060  Iterator::operator == (const Iterator &other) const
1061  {
1062  return (accessor == other.accessor);
1063  }
1064 
1065 
1066 
1067  inline
1068  bool
1069  Iterator::operator != (const Iterator &other) const
1070  {
1071  return ! (accessor == other.accessor);
1072  }
1073 
1074 
1075  inline
1076  bool
1077  Iterator::operator < (const Iterator &other) const
1078  {
1079  return accessor < other.accessor;
1080  }
1081 
1082 }
1083 
1084 
1085 
1086 inline
1089 {
1090  return iterator(this, 0);
1091 }
1092 
1093 
1094 inline
1097 {
1098  return iterator(this, n_rows());
1099 }
1100 
1101 
1102 
1103 inline
1105 ChunkSparsityPattern::begin (const unsigned int r) const
1106 {
1107  Assert (r<n_rows(), ExcIndexRange(r,0,n_rows()));
1108  return iterator(this, r);
1109 }
1110 
1111 
1112 
1113 inline
1115 ChunkSparsityPattern::end (const unsigned int r) const
1116 {
1117  Assert (r<n_rows(), ExcIndexRange(r,0,n_rows()))
1118  return iterator(this, r+1);
1119 }
1120 
1121 
1122 
1123 inline
1125 ChunkSparsityPattern::n_rows () const
1126 {
1127  return rows;
1128 }
1129 
1130 
1131 inline
1134 {
1135  return cols;
1136 }
1137 
1138 
1139 
1140 inline
1143 {
1144  return chunk_size;
1145 }
1146 
1147 
1148 
1149 inline
1150 bool
1152 {
1154 }
1155 
1156 
1157 
1158 template <typename ForwardIterator>
1159 void
1161  const size_type n_cols,
1162  const ForwardIterator begin,
1163  const ForwardIterator end,
1164  const size_type chunk_size)
1165 {
1166  Assert (static_cast<size_type>(std::distance (begin, end)) == n_rows,
1167  ExcIteratorRange (std::distance (begin, end), n_rows));
1168 
1169  // first determine row lengths for each row. if the matrix is quadratic,
1170  // then we might have to add an additional entry for the diagonal, if that
1171  // is not yet present. as we have to call compress anyway later on, don't
1172  // bother to check whether that diagonal entry is in a certain row or not
1173  const bool is_square = (n_rows == n_cols);
1174  std::vector<size_type> row_lengths;
1175  row_lengths.reserve(n_rows);
1176  for (ForwardIterator i=begin; i!=end; ++i)
1177  row_lengths.push_back (std::distance (i->begin(), i->end())
1178  +
1179  (is_square ? 1 : 0));
1180  reinit (n_rows, n_cols, row_lengths, chunk_size);
1181 
1182  // now enter all the elements into the matrix
1183  size_type row = 0;
1184  typedef typename std::iterator_traits<ForwardIterator>::value_type::const_iterator inner_iterator;
1185  for (ForwardIterator i=begin; i!=end; ++i, ++row)
1186  {
1187  const inner_iterator end_of_row = i->end();
1188  for (inner_iterator j=i->begin(); j!=end_of_row; ++j)
1189  {
1190  const size_type col
1191  = internal::SparsityPatternTools::get_column_index_from_iterator(*j);
1192  Assert (col < n_cols, ExcInvalidIndex(col,n_cols));
1193 
1194  add (row, col);
1195  }
1196  }
1197 
1198  // finally compress everything. this also sorts the entries within each row
1199  compress ();
1200 }
1201 
1202 
1203 #endif // DOXYGEN
1204 
1205 DEAL_II_NAMESPACE_CLOSE
1206 
1207 #endif
bool operator==(const Iterator &) const
size_type get_chunk_size() const
void block_write(std::ostream &out) const
void copy_from(const size_type n_rows, const size_type n_cols, const ForwardIterator begin, const ForwardIterator end, const size_type chunk_size)
std::size_t memory_consumption() const
static ::ExceptionBase & ExcEmptyObject()
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:358
Iterator(const ChunkSparsityPattern *sp, const unsigned int row)
static ::ExceptionBase & ExcInvalidNumber(int arg1)
static ::ExceptionBase & ExcInvalidIndex(int arg1, int arg2)
static const size_type invalid_entry
iterator end() const
ChunkSparsityPatternIterators::Iterator const_iterator
void block_read(std::istream &in)
bool operator!=(const Iterator &) const
bool exists(const size_type i, const size_type j) const
const ChunkSparsityPattern * sparsity_pattern
void add(const size_type i, const size_type j)
static ::ExceptionBase & ExcInvalidArraySize(int arg1, int arg2)
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
SymmetricTensor< rank_, dim, Number > operator*(const SymmetricTensor< rank_, dim, Number > &t, const Number &factor)
SparsityPattern sparsity_pattern
bool operator<(const Iterator &) const
static ::ExceptionBase & ExcInvalidIterator()
size_type n_cols() const
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:346
unsigned int global_dof_index
Definition: types.h:88
bool is_compressed() const
ChunkSparsityPatternIterators::Iterator iterator
#define Assert(cond, exc)
Definition: exceptions.h:1142
#define DeclExceptionMsg(Exception, defaulttext)
Definition: exceptions.h:335
#define DeclException0(Exception0)
Definition: exceptions.h:323
size_type row_length(const size_type row) const
static ::ExceptionBase & ExcIteratorRange(int arg1, int arg2)
size_type n_rows() const
size_type n_nonzero_elements() const
const Accessor & operator*() const
ChunkSparsityPattern & operator=(const ChunkSparsityPattern &)
static ::ExceptionBase & ExcIteratorPastEnd()
types::global_dof_index size_type
Accessor(const ChunkSparsityPattern *matrix, const unsigned int row)
static ::ExceptionBase & ExcMatrixIsCompressed()
static ::ExceptionBase & ExcInvalidNumberOfPartitions(int arg1)
constexpr int chunk_size
Definition: cuda_size.h:33
static ::ExceptionBase & ExcMETISNotInstalled()
iterator begin() const
static ::ExceptionBase & ExcNotCompressed()
static const size_type invalid_entry
bool operator<(const Accessor &) const
static ::ExceptionBase & ExcNotEnoughSpace(int arg1, int arg2)
void print(std::ostream &out) const
void create_from(const unsigned int m, const unsigned int n, const Sparsity &sparsity_pattern_for_chunks, const unsigned int chunk_size, const bool optimize_diagonal=true)
SparsityPatternIterators::Accessor reduced_accessor
void print_gnuplot(std::ostream &out) const
void reinit(const size_type m, const size_type n, const size_type max_per_row, const size_type chunk_size)
bool operator==(const Accessor &) const
static ::ExceptionBase & ExcInternalError()
const Accessor * operator->() const
~ChunkSparsityPattern()=default
size_type max_entries_per_row() const