Reference documentation for deal.II version 8.4.2
chunk_sparsity_pattern.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2008 - 2015 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 
170  Iterator &operator++ ();
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 
262  static const size_type invalid_entry = SparsityPattern::invalid_entry;
263 
270 
287 
294  ChunkSparsityPattern (const size_type m,
295  const size_type n,
296  const size_type max_chunks_per_row,
297  const size_type chunk_size);
298 
306  ChunkSparsityPattern (const size_type m,
307  const size_type n,
308  const std::vector<size_type> &row_lengths,
309  const size_type chunk_size);
310 
319  ChunkSparsityPattern (const size_type n,
320  const size_type max_per_row,
321  const size_type chunk_size);
322 
330  ChunkSparsityPattern (const size_type m,
331  const std::vector<size_type> &row_lengths,
332  const size_type chunk_size);
333 
338 
344  ChunkSparsityPattern &operator = (const ChunkSparsityPattern &);
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 
543  size_type max_entries_per_row () const;
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 
717  DeclException1 (ExcInvalidNumber,
718  int,
719  << "The provided number is invalid here: " << arg1);
723  DeclException2 (ExcInvalidIndex,
724  int, int,
725  << "The given index " << arg1
726  << " should be less than " << arg2 << ".");
730  DeclException2 (ExcNotEnoughSpace,
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?)");
739  DeclException0 (ExcNotCompressed);
743  DeclException0 (ExcMatrixIsCompressed);
747  DeclException0 (ExcEmptyObject);
751  DeclException0 (ExcInvalidConstructorCall);
755  DeclException2 (ExcIteratorRange,
756  int, int,
757  << "The iterators denote a range of " << arg1
758  << " elements, but the given number of rows was " << arg2);
762  DeclException0 (ExcMETISNotInstalled);
766  DeclException1 (ExcInvalidNumberOfPartitions,
767  int,
768  << "The number of partitions you gave is " << arg1
769  << ", but must be greater than zero.");
773  DeclException2 (ExcInvalidArraySize,
774  int, int,
775  << "The array has size " << arg1 << " but should have size "
776  << arg2);
778 private:
782  size_type rows;
783 
787  size_type cols;
788 
792  size_type chunk_size;
793 
799 
803  template <typename> friend class ChunkSparseMatrix;
804 
809 };
810 
811 
813 /*---------------------- Inline functions -----------------------------------*/
814 
815 #ifndef DOXYGEN
816 
818 {
819  inline
820  Accessor::
822  const unsigned int row)
823  :
824  sparsity_pattern(sparsity_pattern),
825  reduced_accessor(row==sparsity_pattern->n_rows() ?
826  *sparsity_pattern->sparsity_pattern.end() :
827  *sparsity_pattern->sparsity_pattern.
828  begin(row/sparsity_pattern->get_chunk_size())),
829  chunk_row (row==sparsity_pattern->n_rows() ? 0 :
830  row%sparsity_pattern->get_chunk_size()),
831  chunk_col (0)
832  {}
833 
834 
835 
836  inline
837  Accessor::
838  Accessor (const ChunkSparsityPattern *sparsity_pattern)
839  :
840  sparsity_pattern(sparsity_pattern),
841  reduced_accessor(*sparsity_pattern->sparsity_pattern.end()),
842  chunk_row (0),
843  chunk_col (0)
844  {}
845 
846 
847 
848  inline
849  bool
850  Accessor::is_valid_entry () const
851  {
852  return reduced_accessor.is_valid_entry()
853  &&
854  sparsity_pattern->get_chunk_size()*reduced_accessor.row()+chunk_row <
856  &&
857  sparsity_pattern->get_chunk_size()*reduced_accessor.column()+chunk_col <
859  }
860 
861 
862 
863  inline
864  unsigned int
865  Accessor::row() const
866  {
867  Assert (is_valid_entry() == true, ExcInvalidIterator());
868 
869  return sparsity_pattern->get_chunk_size()*reduced_accessor.row() +
870  chunk_row;
871  }
872 
873 
874 
875  inline
876  unsigned int
877  Accessor::column() const
878  {
879  Assert (is_valid_entry() == true, ExcInvalidIterator());
880 
881  return sparsity_pattern->get_chunk_size()*reduced_accessor.column() +
882  chunk_col;
883  }
884 
885 
886 
887  inline
888  std::size_t
889  Accessor::reduced_index() const
890  {
891  Assert (is_valid_entry() == true, ExcInvalidIterator());
892 
893  return reduced_accessor.index_within_sparsity;
894  }
895 
896 
897 
898 
899  inline
900  bool
901  Accessor::operator == (const Accessor &other) const
902  {
903  // no need to check for equality of sparsity patterns as this is done in
904  // the reduced case already and every ChunkSparsityPattern has its own
905  // reduced sparsity pattern
906  return (reduced_accessor == other.reduced_accessor &&
907  chunk_row == other.chunk_row &&
908  chunk_col == other.chunk_col);
909  }
910 
911 
912 
913  inline
914  bool
915  Accessor::operator < (const Accessor &other) const
916  {
917  Assert (sparsity_pattern == other.sparsity_pattern,
918  ExcInternalError());
919 
920  if (chunk_row != other.chunk_row)
921  {
922  if (reduced_accessor.index_within_sparsity ==
923  reduced_accessor.sparsity_pattern->n_nonzero_elements())
924  return false;
925  if (other.reduced_accessor.index_within_sparsity ==
926  reduced_accessor.sparsity_pattern->n_nonzero_elements())
927  return true;
928 
929  const unsigned int
930  global_row = sparsity_pattern->get_chunk_size()*reduced_accessor.row()
931  +chunk_row,
932  other_global_row = sparsity_pattern->get_chunk_size()*
933  other.reduced_accessor.row()+other.chunk_row;
934  if (global_row < other_global_row)
935  return true;
936  else if (global_row > other_global_row)
937  return false;
938  }
939 
940  return (reduced_accessor.index_within_sparsity <
941  other.reduced_accessor.index_within_sparsity ||
942  (reduced_accessor.index_within_sparsity ==
943  other.reduced_accessor.index_within_sparsity &&
944  chunk_col < other.chunk_col));
945  }
946 
947 
948  inline
949  void
950  Accessor::advance ()
951  {
952  const unsigned int chunk_size = sparsity_pattern->get_chunk_size();
953  Assert (chunk_row < chunk_size && chunk_col < chunk_size,
954  ExcIteratorPastEnd());
955  Assert (reduced_accessor.row() * chunk_size + chunk_row <
957  &&
958  reduced_accessor.column() * chunk_size + chunk_col <
960  ExcIteratorPastEnd());
961  if (chunk_size == 1)
962  {
963  reduced_accessor.advance();
964  return;
965  }
966 
967  ++chunk_col;
968 
969  // end of chunk
970  if (chunk_col == chunk_size
971  ||
972  reduced_accessor.column() * chunk_size + chunk_col ==
974  {
975  const unsigned int reduced_row = reduced_accessor.row();
976  // end of row
977  if (reduced_accessor.index_within_sparsity + 1 ==
978  reduced_accessor.sparsity_pattern->rowstart[reduced_row+1])
979  {
980  ++chunk_row;
981 
982  chunk_col = 0;
983 
984  // end of chunk rows or end of matrix
985  if (chunk_row == chunk_size ||
986  (reduced_row * chunk_size + chunk_row ==
988  {
989  chunk_row = 0;
990  reduced_accessor.advance();
991  }
992  // go back to the beginning of the same reduced row but with
993  // chunk_row increased by one
994  else
995  reduced_accessor.index_within_sparsity =
996  reduced_accessor.sparsity_pattern->rowstart[reduced_row];
997  }
998  // advance within chunk
999  else
1000  {
1001  reduced_accessor.advance();
1002  chunk_col = 0;
1003  }
1004  }
1005  }
1006 
1007 
1008 
1009  inline
1010  Iterator::Iterator (const ChunkSparsityPattern *sparsity_pattern,
1011  const unsigned int row)
1012  :
1013  accessor(sparsity_pattern, row)
1014  {}
1015 
1016 
1017 
1018  inline
1019  Iterator &
1020  Iterator::operator++ ()
1021  {
1022  accessor.advance ();
1023  return *this;
1024  }
1025 
1026 
1027 
1028  inline
1029  Iterator
1030  Iterator::operator++ (int)
1031  {
1032  const Iterator iter = *this;
1033  accessor.advance ();
1034  return iter;
1035  }
1036 
1037 
1038 
1039  inline
1040  const Accessor &
1041  Iterator::operator* () const
1042  {
1043  return accessor;
1044  }
1045 
1046 
1047 
1048  inline
1049  const Accessor *
1050  Iterator::operator-> () const
1051  {
1052  return &accessor;
1053  }
1054 
1055 
1056  inline
1057  bool
1058  Iterator::operator == (const Iterator &other) const
1059  {
1060  return (accessor == other.accessor);
1061  }
1062 
1063 
1064 
1065  inline
1066  bool
1067  Iterator::operator != (const Iterator &other) const
1068  {
1069  return ! (accessor == other.accessor);
1070  }
1071 
1072 
1073  inline
1074  bool
1075  Iterator::operator < (const Iterator &other) const
1076  {
1077  return accessor < other.accessor;
1078  }
1079 
1080 }
1081 
1082 
1083 
1084 inline
1087 {
1088  return iterator(this, 0);
1089 }
1090 
1091 
1092 inline
1095 {
1096  return iterator(this, n_rows());
1097 }
1098 
1099 
1100 
1101 inline
1103 ChunkSparsityPattern::begin (const unsigned int r) const
1104 {
1105  Assert (r<n_rows(), ExcIndexRange(r,0,n_rows()));
1106  return iterator(this, r);
1107 }
1108 
1109 
1110 
1111 inline
1113 ChunkSparsityPattern::end (const unsigned int r) const
1114 {
1115  Assert (r<n_rows(), ExcIndexRange(r,0,n_rows()))
1116  return iterator(this, r+1);
1117 }
1118 
1119 
1120 
1121 inline
1123 ChunkSparsityPattern::n_rows () const
1124 {
1125  return rows;
1126 }
1127 
1128 
1129 inline
1132 {
1133  return cols;
1134 }
1135 
1136 
1137 
1138 inline
1141 {
1142  return chunk_size;
1143 }
1144 
1145 
1146 
1147 inline
1148 bool
1150 {
1152 }
1153 
1154 
1155 
1156 template <typename ForwardIterator>
1157 void
1159  const size_type n_cols,
1160  const ForwardIterator begin,
1161  const ForwardIterator end,
1162  const size_type chunk_size)
1163 {
1164  Assert (static_cast<size_type>(std::distance (begin, end)) == n_rows,
1165  ExcIteratorRange (std::distance (begin, end), n_rows));
1166 
1167  // first determine row lengths for each row. if the matrix is quadratic,
1168  // then we might have to add an additional entry for the diagonal, if that
1169  // is not yet present. as we have to call compress anyway later on, don't
1170  // bother to check whether that diagonal entry is in a certain row or not
1171  const bool is_square = (n_rows == n_cols);
1172  std::vector<size_type> row_lengths;
1173  row_lengths.reserve(n_rows);
1174  for (ForwardIterator i=begin; i!=end; ++i)
1175  row_lengths.push_back (std::distance (i->begin(), i->end())
1176  +
1177  (is_square ? 1 : 0));
1178  reinit (n_rows, n_cols, row_lengths, chunk_size);
1179 
1180  // now enter all the elements into the matrix
1181  size_type row = 0;
1182  typedef typename std::iterator_traits<ForwardIterator>::value_type::const_iterator inner_iterator;
1183  for (ForwardIterator i=begin; i!=end; ++i, ++row)
1184  {
1185  const inner_iterator end_of_row = i->end();
1186  for (inner_iterator j=i->begin(); j!=end_of_row; ++j)
1187  {
1188  const size_type col
1189  = internal::SparsityPatternTools::get_column_index_from_iterator(*j);
1190  Assert (col < n_cols, ExcInvalidIndex(col,n_cols));
1191 
1192  add (row, col);
1193  }
1194  }
1195 
1196  // finally compress everything. this also sorts the entries within each row
1197  compress ();
1198 }
1199 
1200 
1201 #endif // DOXYGEN
1202 
1203 DEAL_II_NAMESPACE_CLOSE
1204 
1205 #endif
size_type get_chunk_size() 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)
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:552
static const size_type invalid_entry
iterator end() const
ChunkSparsityPatternIterators::Iterator const_iterator
const ChunkSparsityPattern * sparsity_pattern
void add(const size_type i, const size_type j)
size_type n_cols() const
SparsityPattern sparsity_pattern
size_type n_rows() const
size_type n_cols() const
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:542
unsigned int global_dof_index
Definition: types.h:88
bool is_compressed() const
ChunkSparsityPatternIterators::Iterator iterator
#define Assert(cond, exc)
Definition: exceptions.h:294
#define DeclException0(Exception0)
Definition: exceptions.h:522
size_type n_rows() const
types::global_dof_index size_type
Accessor(const ChunkSparsityPattern *matrix, const unsigned int row)
iterator begin() const
bool operator<(const Accessor &) const
SparsityPatternIterators::Accessor reduced_accessor
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