Dune Core Modules (2.5.2)

bcrsmatrix.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 
4 #ifndef DUNE_ISTL_BCRSMATRIX_HH
5 #define DUNE_ISTL_BCRSMATRIX_HH
6 
7 #include <cmath>
8 #include <complex>
9 #include <set>
10 #include <iostream>
11 #include <algorithm>
12 #include <numeric>
13 #include <vector>
14 #include <map>
15 
16 #include "istlexception.hh"
17 #include "bvector.hh"
18 #include "matrixutils.hh"
22 #include <dune/common/ftraits.hh>
23 
28 namespace Dune {
29 
69  template<typename M>
70  struct MatrixDimension;
71 
73 
79  template<typename size_type>
81  {
83  double avg;
85  size_type maximum;
87  size_type overflow_total;
89 
92  double mem_ratio;
93  };
94 
96 
108  template<class M_>
110  {
111 
112  public:
113 
115  typedef M_ Matrix;
116 
118  typedef typename Matrix::block_type block_type;
119 
121  typedef typename Matrix::size_type size_type;
122 
124 
130  {
131 
132  public:
133 
136  {
137  return _m.entry(_i,j);
138  }
139 
140 #ifndef DOXYGEN
141 
143  : _m(m)
144  , _i(i)
145  {}
146 
147 #endif
148 
149  private:
150 
151  Matrix& _m;
152  size_type _i;
153 
154  };
155 
157 
164  : _m(m)
165  {
166  if (m.buildMode() != Matrix::implicit)
167  DUNE_THROW(BCRSMatrixError,"You can only create an ImplicitBuilder for a matrix in implicit build mode");
168  if (m.buildStage() != Matrix::building)
169  DUNE_THROW(BCRSMatrixError,"You can only create an ImplicitBuilder for a matrix with set size that has not been compressed() yet");
170  }
171 
173 
187  ImplicitMatrixBuilder(Matrix& m, size_type rows, size_type cols, size_type avg_cols_per_row, double overflow_fraction)
188  : _m(m)
189  {
190  if (m.buildStage() != Matrix::notAllocated)
191  DUNE_THROW(BCRSMatrixError,"You can only set up a matrix for this ImplicitBuilder if it has no memory allocated yet");
192  m.setBuildMode(Matrix::implicit);
193  m.setImplicitBuildModeParameters(avg_cols_per_row,overflow_fraction);
194  m.setSize(rows,cols);
195  }
196 
199  {
200  return row_object(_m,i);
201  }
202 
204  size_type N() const
205  {
206  return _m.N();
207  }
208 
210  size_type M() const
211  {
212  return _m.M();
213  }
214 
215  private:
216 
217  Matrix& _m;
218 
219  };
220 
421  template<class B, class A=std::allocator<B> >
423  {
424  friend struct MatrixDimension<BCRSMatrix>;
425  public:
426  enum BuildStage {
439  built=3
440  };
441 
442  //===== type definitions and constants
443 
445  typedef typename B::field_type field_type;
446 
448  typedef B block_type;
449 
451  typedef A allocator_type;
452 
455 
457  typedef typename A::size_type size_type;
458 
460  typedef ::Dune::CompressionStatistics<size_type> CompressionStatistics;
461 
463  enum {
465  blocklevel = B::blocklevel+1
466  };
467 
469  enum BuildMode {
502  unknown
503  };
504 
505  //===== random access interface to rows of the matrix
506 
509  {
510 #ifdef DUNE_ISTL_WITH_CHECKING
511  if (build_mode == implicit && ready != built)
512  DUNE_THROW(BCRSMatrixError,"You cannot use operator[] in implicit build mode before calling compress()");
513  if (r==0) DUNE_THROW(BCRSMatrixError,"row not initialized yet");
514  if (i>=n) DUNE_THROW(BCRSMatrixError,"index out of range");
515 #endif
516  return r[i];
517  }
518 
521  {
522 #ifdef DUNE_ISTL_WITH_CHECKING
523  if (build_mode == implicit && ready != built)
524  DUNE_THROW(BCRSMatrixError,"You cannot use operator[] in implicit build mode before calling compress()");
525  if (built!=ready) DUNE_THROW(BCRSMatrixError,"row not initialized yet");
526  if (i>=n) DUNE_THROW(BCRSMatrixError,"index out of range");
527 #endif
528  return r[i];
529  }
530 
531 
532  //===== iterator interface to rows of the matrix
533 
535  template<class T>
537  : public RandomAccessIteratorFacade<RealRowIterator<T>, T>
538  {
539 
540  public:
542  typedef typename std::remove_const<T>::type ValueType;
543 
546  friend class RealRowIterator<const ValueType>;
547  friend class RealRowIterator<ValueType>;
548 
551  : p(_p), i(_i)
552  {}
553 
556  : p(0), i(0)
557  {}
558 
560  : p(it.p), i(it.i)
561  {}
562 
563 
565  size_type index () const
566  {
567  return i;
568  }
569 
570  std::ptrdiff_t distanceTo(const RealRowIterator<ValueType>& other) const
571  {
572  assert(other.p==p);
573  return (other.i-i);
574  }
575 
576  std::ptrdiff_t distanceTo(const RealRowIterator<const ValueType>& other) const
577  {
578  assert(other.p==p);
579  return (other.i-i);
580  }
581 
583  bool equals (const RealRowIterator<ValueType>& other) const
584  {
585  assert(other.p==p);
586  return i==other.i;
587  }
588 
590  bool equals (const RealRowIterator<const ValueType>& other) const
591  {
592  assert(other.p==p);
593  return i==other.i;
594  }
595 
596  private:
598  void increment()
599  {
600  ++i;
601  }
602 
604  void decrement()
605  {
606  --i;
607  }
608 
609  void advance(std::ptrdiff_t diff)
610  {
611  i+=diff;
612  }
613 
614  T& elementAt(std::ptrdiff_t diff) const
615  {
616  return p[i+diff];
617  }
618 
620  row_type& dereference () const
621  {
622  return p[i];
623  }
624 
625  row_type* p;
626  size_type i;
627  };
628 
632 
635  {
636  return Iterator(r,0);
637  }
638 
641  {
642  return Iterator(r,n);
643  }
644 
648  {
649  return Iterator(r,n-1);
650  }
651 
655  {
656  return Iterator(r,-1);
657  }
658 
661 
663  typedef typename row_type::Iterator ColIterator;
664 
668 
669 
672  {
673  return ConstIterator(r,0);
674  }
675 
678  {
679  return ConstIterator(r,n);
680  }
681 
685  {
686  return ConstIterator(r,n-1);
687  }
688 
692  {
693  return ConstIterator(r,-1);
694  }
695 
698 
701 
702  //===== constructors & resizers
703 
704  // we use a negative overflowsize to indicate that the implicit
705  // mode parameters have not been set yet
706 
709  : build_mode(unknown), ready(notAllocated), n(0), m(0), nnz_(0),
710  allocationSize_(0), r(0), a(0),
711  avg(0), overflowsize(-1.0)
712  {}
713 
716  : build_mode(bm), ready(notAllocated), n(0), m(0), nnz_(0),
717  allocationSize_(0), r(0), a(0),
718  avg(0), overflowsize(-1.0)
719  {
720  allocate(_n, _m, _nnz,true,false);
721  }
722 
725  : build_mode(bm), ready(notAllocated), n(0), m(0), nnz_(0),
726  allocationSize_(0), r(0), a(0),
727  avg(0), overflowsize(-1.0)
728  {
729  allocate(_n, _m,0,true,false);
730  }
731 
733 
743  BCRSMatrix (size_type _n, size_type _m, size_type _avg, double _overflowsize, BuildMode bm)
744  : build_mode(bm), ready(notAllocated), n(0), m(0), nnz_(0),
745  allocationSize_(0), r(0), a(0),
746  avg(_avg), overflowsize(_overflowsize)
747  {
748  if (bm != implicit)
749  DUNE_THROW(BCRSMatrixError,"Only call this constructor when using the implicit build mode");
750  // Prevent user from setting a negative overflowsize:
751  // 1) It doesn't make sense
752  // 2) We use a negative overflow value to indicate that the parameters
753  // have not been set yet
754  if (_overflowsize < 0.0)
755  DUNE_THROW(BCRSMatrixError,"You cannot set a negative overflow fraction");
756  implicit_allocate(_n,_m);
757  }
758 
764  BCRSMatrix (const BCRSMatrix& Mat)
765  : build_mode(Mat.build_mode), ready(notAllocated), n(0), m(0), nnz_(0),
766  allocationSize_(0), r(0), a(0),
767  avg(Mat.avg), overflowsize(Mat.overflowsize)
768  {
769  if (!(Mat.ready == notAllocated || Mat.ready == built))
770  DUNE_THROW(InvalidStateException,"BCRSMatrix can only be copy-constructed when source matrix is completely empty (size not set) or fully built)");
771 
772  // deep copy in global array
773  size_type _nnz = Mat.nnz_;
774 
775  // in case of row-wise allocation
776  if (_nnz<=0)
777  {
778  _nnz = 0;
779  for (size_type i=0; i<Mat.n; i++)
780  _nnz += Mat.r[i].getsize();
781  }
782 
783  j_ = Mat.j_; // enable column index sharing, release array in case of row-wise allocation
784  allocate(Mat.n, Mat.m, _nnz, true, true);
785 
786  // build window structure
787  copyWindowStructure(Mat);
788  }
789 
792  {
793  deallocate();
794  }
795 
801  {
802  if (ready == notAllocated)
803  {
804  build_mode = bm;
805  return;
806  }
807  if (ready == building && (build_mode == unknown || build_mode == random || build_mode == row_wise) && (bm == row_wise || bm == random))
808  build_mode = bm;
809  else
810  DUNE_THROW(InvalidStateException, "Matrix structure cannot be changed at this stage anymore (ready == "<<ready<<").");
811  }
812 
828  void setSize(size_type rows, size_type columns, size_type nnz=0)
829  {
830  // deallocate already setup memory
831  deallocate();
832 
833  if (build_mode == implicit)
834  {
835  if (nnz>0)
836  DUNE_THROW(Dune::BCRSMatrixError,"number of non-zeroes may not be set in implicit mode, use setImplicitBuildModeParameters() instead");
837 
838  // implicit allocates differently
839  implicit_allocate(rows,columns);
840  }
841  else
842  {
843  // allocate matrix memory
844  allocate(rows, columns, nnz, true, false);
845  }
846  }
847 
856  void setImplicitBuildModeParameters(size_type _avg, double _overflow)
857  {
858  // Prevent user from setting a negative overflowsize:
859  // 1) It doesn't make sense
860  // 2) We use a negative overflow value to indicate that the parameters
861  // have not been set yet
862  if (_overflow < 0.0)
863  DUNE_THROW(BCRSMatrixError,"You cannot set a negative overflow fraction");
864 
865  // make sure the parameters aren't changed after memory has been allocated
866  if (ready != notAllocated)
867  DUNE_THROW(InvalidStateException,"You cannot modify build mode parameters at this stage anymore");
868  avg = _avg;
869  overflowsize = _overflow;
870  }
871 
879  {
880  // return immediately when self-assignment
881  if (&Mat==this) return *this;
882 
883  if (!((ready == notAllocated || ready == built) && (Mat.ready == notAllocated || Mat.ready == built)))
884  DUNE_THROW(InvalidStateException,"BCRSMatrix can only be copied when both target and source are empty or fully built)");
885 
886  // make it simple: ALWAYS throw away memory for a and j_
887  // and deallocate rows only if n != Mat.n
888  deallocate(n!=Mat.n);
889 
890  // reallocate the rows if required
891  if (n>0 && n!=Mat.n) {
892  // free rows
893  for(row_type *riter=r+(n-1), *rend=r-1; riter!=rend; --riter)
894  rowAllocator_.destroy(riter);
895  rowAllocator_.deallocate(r,n);
896  }
897 
898  nnz_ = Mat.nnz_;
899  if (nnz_ <= 0)
900  {
901  for (size_type i=0; i<Mat.n; i++)
902  nnz_ += Mat.r[i].getsize();
903  }
904 
905  // allocate a, share j_
906  j_ = Mat.j_;
907  allocate(Mat.n, Mat.m, nnz_, n!=Mat.n, true);
908 
909  // build window structure
910  copyWindowStructure(Mat);
911  return *this;
912  }
913 
916  {
917 
918  if (!(ready == notAllocated || ready == built))
919  DUNE_THROW(InvalidStateException,"Scalar assignment only works on fully built BCRSMatrix)");
920 
921  for (size_type i=0; i<n; i++) r[i] = k;
922  return *this;
923  }
924 
925  //===== row-wise creation interface
926 
929  {
930  public:
933  : Mat(_Mat), i(_i), nnz(0), current_row(nullptr, Mat.j_.get(), 0)
934  {
935  if (Mat.build_mode == unknown && Mat.ready == building)
936  {
937  Mat.build_mode = row_wise;
938  }
939  if (i==0 && Mat.ready != building)
940  DUNE_THROW(BCRSMatrixError,"creation only allowed for uninitialized matrix");
941  if(Mat.build_mode!=row_wise)
942  DUNE_THROW(BCRSMatrixError,"creation only allowed if row wise allocation was requested in the constructor");
943  }
944 
947  {
948  // this should only be called if matrix is in creation
949  if (Mat.ready != building)
950  DUNE_THROW(BCRSMatrixError,"matrix already built up");
951 
952  // row i is defined through the pattern
953  // get memory for the row and initialize the j_ array
954  // this depends on the allocation mode
955 
956  // compute size of the row
957  size_type s = pattern.size();
958 
959  if(s>0) {
960  // update number of nonzeroes including this row
961  nnz += s;
962 
963  // alloc memory / set window
964  if (Mat.nnz_ > 0)
965  {
966  // memory is allocated in one long array
967 
968  // check if that memory is sufficient
969  if (nnz > Mat.nnz_)
970  DUNE_THROW(BCRSMatrixError,"allocated nnz too small");
971 
972  // set row i
973  Mat.r[i].set(s,nullptr,current_row.getindexptr());
974  current_row.setindexptr(current_row.getindexptr()+s);
975  }else{
976  // memory is allocated individually per row
977  // allocate and set row i
978  B* b = Mat.allocator_.allocate(s);
979  // use placement new to call constructor that allocates
980  // additional memory.
981  new (b) B[s];
982  size_type* j = Mat.sizeAllocator_.allocate(s);
983  Mat.r[i].set(s,b,j);
984  }
985  }else
986  // setup empty row
987  Mat.r[i].set(0,nullptr,nullptr);
988 
989  // initialize the j array for row i from pattern
990  std::copy(pattern.cbegin(), pattern.cend(), Mat.r[i].getindexptr());
991 
992  // now go to next row
993  i++;
994  pattern.clear();
995 
996  // check if this was last row
997  if (i==Mat.n)
998  {
999  Mat.ready = built;
1000  if(Mat.nnz_ > 0)
1001  {
1002  // Set nnz to the exact number of nonzero blocks inserted
1003  // as some methods rely on it
1004  Mat.nnz_ = nnz;
1005  // allocate data array
1006  Mat.allocateData();
1007  Mat.setDataPointers();
1008  }
1009  }
1010  // done
1011  return *this;
1012  }
1013 
1015  bool operator!= (const CreateIterator& it) const
1016  {
1017  return (i!=it.i) || (&Mat!=&it.Mat);
1018  }
1019 
1021  bool operator== (const CreateIterator& it) const
1022  {
1023  return (i==it.i) && (&Mat==&it.Mat);
1024  }
1025 
1027  size_type index () const
1028  {
1029  return i;
1030  }
1031 
1034  {
1035  pattern.insert(j);
1036  }
1037 
1040  {
1041  return pattern.find(j) != pattern.end();
1042  }
1048  size_type size() const
1049  {
1050  return pattern.size();
1051  }
1052 
1053  private:
1054  BCRSMatrix& Mat; // the matrix we are defining
1055  size_type i; // current row to be defined
1056  size_type nnz; // count total number of nonzeros
1057  typedef std::set<size_type,std::less<size_type> > PatternType;
1058  PatternType pattern; // used to compile entries in a row
1059  row_type current_row; // row pointing to the current row to setup
1060  };
1061 
1063  friend class CreateIterator;
1064 
1067  {
1068  return CreateIterator(*this,0);
1069  }
1070 
1073  {
1074  return CreateIterator(*this,n);
1075  }
1076 
1077 
1078  //===== random creation interface
1079 
1087  {
1088  if (build_mode!=random)
1089  DUNE_THROW(BCRSMatrixError,"requires random build mode");
1090  if (ready != building)
1091  DUNE_THROW(BCRSMatrixError,"matrix row sizes already built up");
1092 
1093  r[i].setsize(s);
1094  }
1095 
1098  {
1099 #ifdef DUNE_ISTL_WITH_CHECKING
1100  if (r==0) DUNE_THROW(BCRSMatrixError,"row not initialized yet");
1101  if (i>=n) DUNE_THROW(BCRSMatrixError,"index out of range");
1102 #endif
1103  return r[i].getsize();
1104  }
1105 
1108  {
1109  if (build_mode!=random)
1110  DUNE_THROW(BCRSMatrixError,"requires random build mode");
1111  if (ready != building)
1112  DUNE_THROW(BCRSMatrixError,"matrix row sizes already built up");
1113 
1114  r[i].setsize(r[i].getsize()+s);
1115  }
1116 
1118  void endrowsizes ()
1119  {
1120  if (build_mode!=random)
1121  DUNE_THROW(BCRSMatrixError,"requires random build mode");
1122  if (ready != building)
1123  DUNE_THROW(BCRSMatrixError,"matrix row sizes already built up");
1124 
1125  // compute total size, check positivity
1126  size_type total=0;
1127  for (size_type i=0; i<n; i++)
1128  {
1129  total += r[i].getsize();
1130  }
1131 
1132  if(nnz_ == 0)
1133  // allocate/check memory
1134  allocate(n,m,total,false,false);
1135  else if(nnz_ < total)
1136  DUNE_THROW(BCRSMatrixError,"Specified number of nonzeros ("<<nnz_<<") not "
1137  <<"sufficient for calculated nonzeros ("<<total<<"! ");
1138 
1139  // set the window pointers correctly
1141 
1142  // initialize j_ array with m (an invalid column index)
1143  // this indicates an unused entry
1144  for (size_type k=0; k<nnz_; k++)
1145  j_.get()[k] = m;
1146  ready = rowSizesBuilt;
1147  }
1148 
1150 
1160  void addindex (size_type row, size_type col)
1161  {
1162  if (build_mode!=random)
1163  DUNE_THROW(BCRSMatrixError,"requires random build mode");
1164  if (ready==built)
1165  DUNE_THROW(BCRSMatrixError,"matrix already built up");
1166  if (ready==building)
1167  DUNE_THROW(BCRSMatrixError,"matrix row sizes not built up yet");
1168  if (ready==notAllocated)
1169  DUNE_THROW(BCRSMatrixError,"matrix size not set and no memory allocated yet");
1170 
1171  if (col >= m)
1172  DUNE_THROW(BCRSMatrixError,"column index exceeds matrix size");
1173 
1174  // get row range
1175  size_type* const first = r[row].getindexptr();
1176  size_type* const last = first + r[row].getsize();
1177 
1178  // find correct insertion position for new column index
1179  size_type* pos = std::lower_bound(first,last,col);
1180 
1181  // check if index is already in row
1182  if (pos!=last && *pos == col) return;
1183 
1184  // find end of already inserted column indices
1185  size_type* end = std::lower_bound(pos,last,m);
1186  if (end==last)
1187  DUNE_THROW(BCRSMatrixError,"row is too small");
1188 
1189  // insert new column index at correct position
1190  std::copy_backward(pos,end,end+1);
1191  *pos = col;
1192  }
1193 
1195 
1202  template<typename It>
1203  void setIndices(size_type row, It begin, It end)
1204  {
1205  size_type row_size = r[row].size();
1206  size_type* col_begin = r[row].getindexptr();
1207  size_type* col_end;
1208  // consistency check between allocated row size and number of passed column indices
1209  if ((col_end = std::copy(begin,end,r[row].getindexptr())) != col_begin + row_size)
1210  DUNE_THROW(BCRSMatrixError,"Given size of row " << row
1211  << " (" << row_size
1212  << ") does not match number of passed entries (" << (col_end - col_begin) << ")");
1213  std::sort(col_begin,col_end);
1214  }
1215 
1217  void endindices ()
1218  {
1219  if (build_mode!=random)
1220  DUNE_THROW(BCRSMatrixError,"requires random build mode");
1221  if (ready==built)
1222  DUNE_THROW(BCRSMatrixError,"matrix already built up");
1223  if (ready==building)
1224  DUNE_THROW(BCRSMatrixError,"row sizes are not built up yet");
1225  if (ready==notAllocated)
1226  DUNE_THROW(BCRSMatrixError,"matrix size not set and no memory allocated yet");
1227 
1228  // check if there are undefined indices
1229  RowIterator endi=end();
1230  for (RowIterator i=begin(); i!=endi; ++i)
1231  {
1232  ColIterator endj = (*i).end();
1233  for (ColIterator j=(*i).begin(); j!=endj; ++j) {
1234  if (j.index() >= m) {
1235  dwarn << "WARNING: size of row "<< i.index()<<" is "<<j.offset()<<". But was specified as being "<< (*i).end().offset()
1236  <<". This means you are wasting valuable space and creating additional cache misses!"<<std::endl;
1237  r[i.index()].setsize(j.offset());
1238  break;
1239  }
1240  }
1241  }
1242 
1243  allocateData();
1244  setDataPointers();
1245 
1246  // if not, set matrix to built
1247  ready = built;
1248  }
1249 
1250  //===== implicit creation interface
1251 
1253 
1265  {
1266 #ifdef DUNE_ISTL_WITH_CHECKING
1267  if (build_mode!=implicit)
1268  DUNE_THROW(BCRSMatrixError,"requires implicit build mode");
1269  if (ready==built)
1270  DUNE_THROW(BCRSMatrixError,"matrix already built up, use operator[] for entry access now");
1271  if (ready==notAllocated)
1272  DUNE_THROW(BCRSMatrixError,"matrix size not set and no memory allocated yet");
1273  if (ready!=building)
1274  DUNE_THROW(InvalidStateException,"You may only use entry() during the 'building' stage");
1275 
1276  if (row >= n)
1277  DUNE_THROW(BCRSMatrixError,"row index exceeds matrix size");
1278  if (col >= m)
1279  DUNE_THROW(BCRSMatrixError,"column index exceeds matrix size");
1280 #endif
1281 
1282  size_type* begin = r[row].getindexptr();
1283  size_type* end = begin + r[row].getsize();
1284 
1285  size_type* pos = std::find(begin, end, col);
1286 
1287  //treat the case that there was a match in the array
1288  if (pos != end)
1289  if (*pos == col)
1290  {
1291  std::ptrdiff_t offset = pos - r[row].getindexptr();
1292  B* aptr = r[row].getptr() + offset;
1293 
1294  return *aptr;
1295  }
1296 
1297  //determine whether overflow has to be taken into account or not
1298  if (r[row].getsize() == avg)
1299  return overflow[std::make_pair(row,col)];
1300  else
1301  {
1302  //modify index array
1303  *end = col;
1304 
1305  //do simulatenous operations on data array a
1306  std::ptrdiff_t offset = end - r[row].getindexptr();
1307  B* apos = r[row].getptr() + offset;
1308 
1309  //increase rowsize
1310  r[row].setsize(r[row].getsize()+1);
1311 
1312  //return reference to the newly created entry
1313  return *apos;
1314  }
1315  }
1316 
1318 
1329  {
1330  if (build_mode!=implicit)
1331  DUNE_THROW(BCRSMatrixError,"requires implicit build mode");
1332  if (ready==built)
1333  DUNE_THROW(BCRSMatrixError,"matrix already built up, no more need for compression");
1334  if (ready==notAllocated)
1335  DUNE_THROW(BCRSMatrixError,"matrix size not set and no memory allocated yet");
1336  if (ready!=building)
1337  DUNE_THROW(InvalidStateException,"You may only call compress() at the end of the 'building' stage");
1338 
1339  //calculate statistics
1340  CompressionStatistics stats;
1341  stats.overflow_total = overflow.size();
1342  stats.maximum = 0;
1343 
1344  //get insertion iterators pointing to one before start (for later use of ++it)
1345  size_type* jiit = j_.get();
1346  B* aiit = a;
1347 
1348  //get iterator to the smallest overflow element
1349  typename OverflowType::iterator oit = overflow.begin();
1350 
1351  //store a copy of index pointers on which to perform sortation
1352  std::vector<size_type*> perm;
1353 
1354  //iterate over all rows and copy elements into their position in the compressed array
1355  for (size_type i=0; i<n; i++)
1356  {
1357  //get old pointers into a and j and size without overflow changes
1358  size_type* begin = r[i].getindexptr();
1359  //B* apos = r[i].getptr();
1360  size_type size = r[i].getsize();
1361 
1362  perm.resize(size);
1363 
1364  typename std::vector<size_type*>::iterator it = perm.begin();
1365  for (size_type* iit = begin; iit < begin + size; ++iit, ++it)
1366  *it = iit;
1367 
1368  //sort permutation array
1369  std::sort(perm.begin(),perm.end(),PointerCompare<size_type>());
1370 
1371  //change row window pointer to their new positions
1372  r[i].setindexptr(jiit);
1373  r[i].setptr(aiit);
1374 
1375  for (it = perm.begin(); it != perm.end(); ++it)
1376  {
1377  //check whether there are elements in the overflow area which take precedence
1378  while ((oit!=overflow.end()) && (oit->first < std::make_pair(i,**it)))
1379  {
1380  //check whether there is enough memory to write to
1381  if (jiit > begin)
1383  "Allocated memory for BCRSMatrix exhausted during compress()!"
1384  "Please increase either the average number of entries per row or the overflow fraction."
1385  );
1386  //copy an element from the overflow area to the insertion position in a and j
1387  *jiit = oit->first.second;
1388  ++jiit;
1389  *aiit = oit->second;
1390  ++aiit;
1391  ++oit;
1392  r[i].setsize(r[i].getsize()+1);
1393  }
1394 
1395  //check whether there is enough memory to write to
1396  if (jiit > begin)
1398  "Allocated memory for BCRSMatrix exhausted during compress()!"
1399  "Please increase either the average number of entries per row or the overflow fraction."
1400  );
1401 
1402  //copy element from array
1403  *jiit = **it;
1404  ++jiit;
1405  B* apos = *it - j_.get() + a;
1406  *aiit = *apos;
1407  ++aiit;
1408  }
1409 
1410  //copy remaining elements from the overflow area
1411  while ((oit!=overflow.end()) && (oit->first.first == i))
1412  {
1413  //check whether there is enough memory to write to
1414  if (jiit > begin)
1416  "Allocated memory for BCRSMatrix exhausted during compress()!"
1417  "Please increase either the average number of entries per row or the overflow fraction."
1418  );
1419 
1420  //copy and element from the overflow area to the insertion position in a and j
1421  *jiit = oit->first.second;
1422  ++jiit;
1423  *aiit = oit->second;
1424  ++aiit;
1425  ++oit;
1426  r[i].setsize(r[i].getsize()+1);
1427  }
1428 
1429  // update maximum row size
1430  if (r[i].getsize()>stats.maximum)
1431  stats.maximum = r[i].getsize();
1432  }
1433 
1434  // overflow area may be cleared
1435  overflow.clear();
1436 
1437  //determine average number of entries and memory usage
1438  std::ptrdiff_t diff = (r[n-1].getindexptr() + r[n-1].getsize() - j_.get());
1439  nnz_ = diff;
1440  stats.avg = (double) (nnz_) / (double) n;
1441  stats.mem_ratio = (double) (nnz_) / (double) allocationSize_;
1442 
1443  //matrix is now built
1444  ready = built;
1445 
1446  return stats;
1447  }
1448 
1449  //===== vector space arithmetic
1450 
1453  {
1454 #ifdef DUNE_ISTL_WITH_CHECKING
1455  if (ready != built)
1456  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1457 #endif
1458 
1459  if (nnz_ > 0)
1460  {
1461  // process 1D array
1462  for (size_type i=0; i<nnz_; i++)
1463  a[i] *= k;
1464  }
1465  else
1466  {
1467  RowIterator endi=end();
1468  for (RowIterator i=begin(); i!=endi; ++i)
1469  {
1470  ColIterator endj = (*i).end();
1471  for (ColIterator j=(*i).begin(); j!=endj; ++j)
1472  (*j) *= k;
1473  }
1474  }
1475 
1476  return *this;
1477  }
1478 
1481  {
1482 #ifdef DUNE_ISTL_WITH_CHECKING
1483  if (ready != built)
1484  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1485 #endif
1486 
1487  if (nnz_ > 0)
1488  {
1489  // process 1D array
1490  for (size_type i=0; i<nnz_; i++)
1491  a[i] /= k;
1492  }
1493  else
1494  {
1495  RowIterator endi=end();
1496  for (RowIterator i=begin(); i!=endi; ++i)
1497  {
1498  ColIterator endj = (*i).end();
1499  for (ColIterator j=(*i).begin(); j!=endj; ++j)
1500  (*j) /= k;
1501  }
1502  }
1503 
1504  return *this;
1505  }
1506 
1507 
1514  {
1515 #ifdef DUNE_ISTL_WITH_CHECKING
1516  if (ready != built || b.ready != built)
1517  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1518  if(N()!=b.N() || M() != b.M())
1519  DUNE_THROW(RangeError, "Matrix sizes do not match!");
1520 #endif
1521  RowIterator endi=end();
1522  ConstRowIterator j=b.begin();
1523  for (RowIterator i=begin(); i!=endi; ++i, ++j) {
1524  i->operator+=(*j);
1525  }
1526 
1527  return *this;
1528  }
1529 
1536  {
1537 #ifdef DUNE_ISTL_WITH_CHECKING
1538  if (ready != built || b.ready != built)
1539  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1540  if(N()!=b.N() || M() != b.M())
1541  DUNE_THROW(RangeError, "Matrix sizes do not match!");
1542 #endif
1543  RowIterator endi=end();
1544  ConstRowIterator j=b.begin();
1545  for (RowIterator i=begin(); i!=endi; ++i, ++j) {
1546  i->operator-=(*j);
1547  }
1548 
1549  return *this;
1550  }
1551 
1561  {
1562 #ifdef DUNE_ISTL_WITH_CHECKING
1563  if (ready != built || b.ready != built)
1564  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1565  if(N()!=b.N() || M() != b.M())
1566  DUNE_THROW(RangeError, "Matrix sizes do not match!");
1567 #endif
1568  RowIterator endi=end();
1569  ConstRowIterator j=b.begin();
1570  for(RowIterator i=begin(); i!=endi; ++i, ++j)
1571  i->axpy(alpha, *j);
1572 
1573  return *this;
1574  }
1575 
1576  //===== linear maps
1577 
1579  template<class X, class Y>
1580  void mv (const X& x, Y& y) const
1581  {
1582 #ifdef DUNE_ISTL_WITH_CHECKING
1583  if (ready != built)
1584  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1585  if (x.N()!=M()) DUNE_THROW(BCRSMatrixError,
1586  "Size mismatch: M: " << N() << "x" << M() << " x: " << x.N());
1587  if (y.N()!=N()) DUNE_THROW(BCRSMatrixError,
1588  "Size mismatch: M: " << N() << "x" << M() << " y: " << y.N());
1589 #endif
1590  ConstRowIterator endi=end();
1591  for (ConstRowIterator i=begin(); i!=endi; ++i)
1592  {
1593  y[i.index()]=0;
1594  ConstColIterator endj = (*i).end();
1595  for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
1596  (*j).umv(x[j.index()],y[i.index()]);
1597  }
1598  }
1599 
1601  template<class X, class Y>
1602  void umv (const X& x, Y& y) const
1603  {
1604 #ifdef DUNE_ISTL_WITH_CHECKING
1605  if (ready != built)
1606  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1607  if (x.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range");
1608  if (y.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range");
1609 #endif
1610  ConstRowIterator endi=end();
1611  for (ConstRowIterator i=begin(); i!=endi; ++i)
1612  {
1613  ConstColIterator endj = (*i).end();
1614  for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
1615  (*j).umv(x[j.index()],y[i.index()]);
1616  }
1617  }
1618 
1620  template<class X, class Y>
1621  void mmv (const X& x, Y& y) const
1622  {
1623 #ifdef DUNE_ISTL_WITH_CHECKING
1624  if (ready != built)
1625  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1626  if (x.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range");
1627  if (y.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range");
1628 #endif
1629  ConstRowIterator endi=end();
1630  for (ConstRowIterator i=begin(); i!=endi; ++i)
1631  {
1632  ConstColIterator endj = (*i).end();
1633  for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
1634  (*j).mmv(x[j.index()],y[i.index()]);
1635  }
1636  }
1637 
1639  template<class X, class Y, class F>
1640  void usmv (F&& alpha, const X& x, Y& y) const
1641  {
1642 #ifdef DUNE_ISTL_WITH_CHECKING
1643  if (ready != built)
1644  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1645  if (x.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range");
1646  if (y.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range");
1647 #endif
1648  ConstRowIterator endi=end();
1649  for (ConstRowIterator i=begin(); i!=endi; ++i)
1650  {
1651  ConstColIterator endj = (*i).end();
1652  for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
1653  (*j).usmv(alpha,x[j.index()],y[i.index()]);
1654  }
1655  }
1656 
1658  template<class X, class Y>
1659  void mtv (const X& x, Y& y) const
1660  {
1661 #ifdef DUNE_ISTL_WITH_CHECKING
1662  if (ready != built)
1663  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1664  if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range");
1665  if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range");
1666 #endif
1667  for(size_type i=0; i<y.N(); ++i)
1668  y[i]=0;
1669  umtv(x,y);
1670  }
1671 
1673  template<class X, class Y>
1674  void umtv (const X& x, Y& y) const
1675  {
1676 #ifdef DUNE_ISTL_WITH_CHECKING
1677  if (ready != built)
1678  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1679  if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range");
1680  if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range");
1681 #endif
1682  ConstRowIterator endi=end();
1683  for (ConstRowIterator i=begin(); i!=endi; ++i)
1684  {
1685  ConstColIterator endj = (*i).end();
1686  for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
1687  (*j).umtv(x[i.index()],y[j.index()]);
1688  }
1689  }
1690 
1692  template<class X, class Y>
1693  void mmtv (const X& x, Y& y) const
1694  {
1695 #ifdef DUNE_ISTL_WITH_CHECKING
1696  if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range");
1697  if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range");
1698 #endif
1699  ConstRowIterator endi=end();
1700  for (ConstRowIterator i=begin(); i!=endi; ++i)
1701  {
1702  ConstColIterator endj = (*i).end();
1703  for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
1704  (*j).mmtv(x[i.index()],y[j.index()]);
1705  }
1706  }
1707 
1709  template<class X, class Y>
1710  void usmtv (const field_type& alpha, const X& x, Y& y) const
1711  {
1712 #ifdef DUNE_ISTL_WITH_CHECKING
1713  if (ready != built)
1714  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1715  if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range");
1716  if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range");
1717 #endif
1718  ConstRowIterator endi=end();
1719  for (ConstRowIterator i=begin(); i!=endi; ++i)
1720  {
1721  ConstColIterator endj = (*i).end();
1722  for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
1723  (*j).usmtv(alpha,x[i.index()],y[j.index()]);
1724  }
1725  }
1726 
1728  template<class X, class Y>
1729  void umhv (const X& x, Y& y) const
1730  {
1731 #ifdef DUNE_ISTL_WITH_CHECKING
1732  if (ready != built)
1733  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1734  if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range");
1735  if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range");
1736 #endif
1737  ConstRowIterator endi=end();
1738  for (ConstRowIterator i=begin(); i!=endi; ++i)
1739  {
1740  ConstColIterator endj = (*i).end();
1741  for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
1742  (*j).umhv(x[i.index()],y[j.index()]);
1743  }
1744  }
1745 
1747  template<class X, class Y>
1748  void mmhv (const X& x, Y& y) const
1749  {
1750 #ifdef DUNE_ISTL_WITH_CHECKING
1751  if (ready != built)
1752  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1753  if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range");
1754  if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range");
1755 #endif
1756  ConstRowIterator endi=end();
1757  for (ConstRowIterator i=begin(); i!=endi; ++i)
1758  {
1759  ConstColIterator endj = (*i).end();
1760  for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
1761  (*j).mmhv(x[i.index()],y[j.index()]);
1762  }
1763  }
1764 
1766  template<class X, class Y>
1767  void usmhv (const field_type& alpha, const X& x, Y& y) const
1768  {
1769 #ifdef DUNE_ISTL_WITH_CHECKING
1770  if (ready != built)
1771  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1772  if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range");
1773  if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range");
1774 #endif
1775  ConstRowIterator endi=end();
1776  for (ConstRowIterator i=begin(); i!=endi; ++i)
1777  {
1778  ConstColIterator endj = (*i).end();
1779  for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
1780  (*j).usmhv(alpha,x[i.index()],y[j.index()]);
1781  }
1782  }
1783 
1784 
1785  //===== norms
1786 
1788  typename FieldTraits<field_type>::real_type frobenius_norm2 () const
1789  {
1790 #ifdef DUNE_ISTL_WITH_CHECKING
1791  if (ready != built)
1792  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1793 #endif
1794 
1795  double sum=0;
1796 
1797  ConstRowIterator endi=end();
1798  for (ConstRowIterator i=begin(); i!=endi; ++i)
1799  {
1800  ConstColIterator endj = (*i).end();
1801  for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
1802  sum += (*j).frobenius_norm2();
1803  }
1804 
1805  return sum;
1806  }
1807 
1809  typename FieldTraits<field_type>::real_type frobenius_norm () const
1810  {
1811  return sqrt(frobenius_norm2());
1812  }
1813 
1815  template <typename ft = field_type,
1816  typename std::enable_if<!has_nan<ft>::value, int>::type = 0>
1817  typename FieldTraits<ft>::real_type infinity_norm() const {
1818  if (ready != built)
1819  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1820 
1821  using real_type = typename FieldTraits<ft>::real_type;
1822  using std::max;
1823 
1824  real_type norm = 0;
1825  for (auto const &x : *this) {
1826  real_type sum = 0;
1827  for (auto const &y : x)
1828  sum += y.infinity_norm();
1829  norm = max(sum, norm);
1830  }
1831  return norm;
1832  }
1833 
1835  template <typename ft = field_type,
1836  typename std::enable_if<!has_nan<ft>::value, int>::type = 0>
1837  typename FieldTraits<ft>::real_type infinity_norm_real() const {
1838  if (ready != built)
1839  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1840 
1841  using real_type = typename FieldTraits<ft>::real_type;
1842  using std::max;
1843 
1844  real_type norm = 0;
1845  for (auto const &x : *this) {
1846  real_type sum = 0;
1847  for (auto const &y : x)
1848  sum += y.infinity_norm_real();
1849  norm = max(sum, norm);
1850  }
1851  return norm;
1852  }
1853 
1855  template <typename ft = field_type,
1856  typename std::enable_if<has_nan<ft>::value, int>::type = 0>
1857  typename FieldTraits<ft>::real_type infinity_norm() const {
1858  if (ready != built)
1859  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1860 
1861  using real_type = typename FieldTraits<ft>::real_type;
1862  using std::max;
1863 
1864  real_type norm = 0;
1865  real_type isNaN = 1;
1866  for (auto const &x : *this) {
1867  real_type sum = 0;
1868  for (auto const &y : x)
1869  sum += y.infinity_norm();
1870  norm = max(sum, norm);
1871  isNaN += sum;
1872  }
1873  isNaN /= isNaN;
1874  return norm * isNaN;
1875  }
1876 
1878  template <typename ft = field_type,
1879  typename std::enable_if<has_nan<ft>::value, int>::type = 0>
1880  typename FieldTraits<ft>::real_type infinity_norm_real() const {
1881  if (ready != built)
1882  DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances");
1883 
1884  using real_type = typename FieldTraits<ft>::real_type;
1885  using std::max;
1886 
1887  real_type norm = 0;
1888  real_type isNaN = 1;
1889  for (auto const &x : *this) {
1890  real_type sum = 0;
1891  for (auto const &y : x)
1892  sum += y.infinity_norm_real();
1893  norm = max(sum, norm);
1894  isNaN += sum;
1895  }
1896  isNaN /= isNaN;
1897  return norm * isNaN;
1898  }
1899 
1900  //===== sizes
1901 
1903  size_type N () const
1904  {
1905  return n;
1906  }
1907 
1909  size_type M () const
1910  {
1911  return m;
1912  }
1913 
1916  {
1917  return nnz_;
1918  }
1919 
1922  {
1923  return ready;
1924  }
1925 
1928  {
1929  return build_mode;
1930  }
1931 
1932  //===== query
1933 
1935  bool exists (size_type i, size_type j) const
1936  {
1937 #ifdef DUNE_ISTL_WITH_CHECKING
1938  if (i<0 || i>=n) DUNE_THROW(BCRSMatrixError,"row index out of range");
1939  if (j<0 || j>=m) DUNE_THROW(BCRSMatrixError,"column index out of range");
1940 #endif
1941  return (r[i].size() && r[i].find(j) != r[i].end());
1942  }
1943 
1944 
1945  protected:
1946  // state information
1947  BuildMode build_mode; // row wise or whole matrix
1948  BuildStage ready; // indicate the stage the matrix building is in
1949 
1950  // The allocator used for memory management
1951  typename A::template rebind<B>::other allocator_;
1952 
1953  typename A::template rebind<row_type>::other rowAllocator_;
1954 
1955  typename A::template rebind<size_type>::other sizeAllocator_;
1956 
1957  // size of the matrix
1958  size_type n; // number of rows
1959  size_type m; // number of columns
1960  size_type nnz_; // number of nonzeroes contained in the matrix
1961  size_type allocationSize_; //allocated size of a and j arrays, except in implicit mode: nnz_==allocationsSize_
1962  // zero means that memory is allocated separately for each row.
1963 
1964  // the rows are dynamically allocated
1965  row_type* r; // [n] the individual rows having pointers into a,j arrays
1966 
1967  // dynamically allocated memory
1968  B* a; // [allocationSize] non-zero entries of the matrix in row-wise ordering
1969  // If a single array of column indices is used, it can be shared
1970  // between different matrices with the same sparsity pattern
1971  std::shared_ptr<size_type> j_; // [allocationSize] column indices of entries
1972 
1973  // additional data is needed in implicit buildmode
1974  size_type avg;
1975  double overflowsize;
1976 
1977  typedef std::map<std::pair<size_type,size_type>, B> OverflowType;
1978  OverflowType overflow;
1979 
1980  void setWindowPointers(ConstRowIterator row)
1981  {
1982  row_type current_row(a,j_.get(),0); // Pointers to current row data
1983  for (size_type i=0; i<n; i++, ++row) {
1984  // set row i
1985  size_type s = row->getsize();
1986 
1987  if (s>0) {
1988  // setup pointers and size
1989  r[i].set(s,current_row.getptr(), current_row.getindexptr());
1990  // update pointer for next row
1991  current_row.setptr(current_row.getptr()+s);
1992  current_row.setindexptr(current_row.getindexptr()+s);
1993  } else{
1994  // empty row
1995  r[i].set(0,nullptr,nullptr);
1996  }
1997  }
1998  }
1999 
2001 
2006  {
2007  size_type* jptr = j_.get();
2008  for (size_type i=0; i<n; ++i, ++row) {
2009  // set row i
2010  size_type s = row->getsize();
2011 
2012  if (s>0) {
2013  // setup pointers and size
2014  r[i].setsize(s);
2015  r[i].setindexptr(jptr);
2016  } else{
2017  // empty row
2018  r[i].set(0,nullptr,nullptr);
2019  }
2020 
2021  // advance position in global array
2022  jptr += s;
2023  }
2024  }
2025 
2027 
2032  {
2033  B* aptr = a;
2034  for (size_type i=0; i<n; ++i) {
2035  // set row i
2036  if (r[i].getsize() > 0) {
2037  // setup pointers and size
2038  r[i].setptr(aptr);
2039  } else{
2040  // empty row
2041  r[i].set(0,nullptr,nullptr);
2042  }
2043 
2044  // advance position in global array
2045  aptr += r[i].getsize();
2046  }
2047  }
2048 
2051  {
2052  setWindowPointers(Mat.begin());
2053 
2054  // copy data
2055  for (size_type i=0; i<n; i++) r[i] = Mat.r[i];
2056 
2057  // finish off
2058  build_mode = row_wise; // dummy
2059  ready = built;
2060  }
2061 
2067  void deallocate(bool deallocateRows=true)
2068  {
2069 
2070  if (notAllocated)
2071  return;
2072 
2073  if (allocationSize_>0)
2074  {
2075  // a,j_ have been allocated as one long vector
2076  j_.reset();
2077  if (a)
2078  {
2079  for(B *aiter=a+(allocationSize_-1), *aend=a-1; aiter!=aend; --aiter)
2080  allocator_.destroy(aiter);
2081  allocator_.deallocate(a,allocationSize_);
2082  a = nullptr;
2083  }
2084  }
2085  else if (r)
2086  {
2087  // check if memory for rows have been allocated individually
2088  for (size_type i=0; i<n; i++)
2089  if (r[i].getsize()>0)
2090  {
2091  for (B *col=r[i].getptr()+(r[i].getsize()-1),
2092  *colend = r[i].getptr()-1; col!=colend; --col) {
2093  allocator_.destroy(col);
2094  }
2095  sizeAllocator_.deallocate(r[i].getindexptr(),1);
2096  allocator_.deallocate(r[i].getptr(),1);
2097  // clear out row data in case we don't want to deallocate the rows
2098  // otherwise we might run into a double free problem here later
2099  r[i].set(0,nullptr,nullptr);
2100  }
2101  }
2102 
2103  // deallocate the rows
2104  if (n>0 && deallocateRows && r) {
2105  for(row_type *riter=r+(n-1), *rend=r-1; riter!=rend; --riter)
2106  rowAllocator_.destroy(riter);
2107  rowAllocator_.deallocate(r,n);
2108  r = nullptr;
2109  }
2110 
2111  // Mark matrix as not built at all.
2112  ready=notAllocated;
2113 
2114  }
2115 
2118  {
2119  typename A::template rebind<size_type>::other& sizeAllocator_;
2120 
2121  public:
2122  Deallocator(typename A::template rebind<size_type>::other& sizeAllocator)
2123  : sizeAllocator_(sizeAllocator)
2124  {}
2125 
2126  void operator()(size_type* p) { sizeAllocator_.deallocate(p,1); }
2127  };
2128 
2129 
2147  void allocate(size_type rows, size_type columns, size_type allocationSize, bool allocateRows, bool allocate_data)
2148  {
2149  // Store size
2150  n = rows;
2151  m = columns;
2152  nnz_ = allocationSize;
2153  allocationSize_ = allocationSize;
2154 
2155  // allocate rows
2156  if(allocateRows) {
2157  if (n>0) {
2158  if (r)
2159  DUNE_THROW(InvalidStateException,"Rows have already been allocated, cannot allocate a second time");
2160  r = rowAllocator_.allocate(rows);
2161  }else{
2162  r = 0;
2163  }
2164  }
2165 
2166  // allocate a and j_ array
2167  if (allocate_data)
2168  allocateData();
2169  if (allocationSize_>0) {
2170  // allocate column indices only if not yet present (enable sharing)
2171  if (!j_.get())
2172  j_.reset(sizeAllocator_.allocate(allocationSize_),Deallocator(sizeAllocator_));
2173  }else{
2174  j_.reset();
2175  for(row_type* ri=r; ri!=r+rows; ++ri)
2176  rowAllocator_.construct(ri, row_type());
2177  }
2178 
2179  // Mark the matrix as not built.
2180  ready = building;
2181  }
2182 
2183  void allocateData()
2184  {
2185  if (a)
2186  DUNE_THROW(InvalidStateException,"Cannot allocate data array (already allocated)");
2187  if (allocationSize_>0) {
2188  a = allocator_.allocate(allocationSize_);
2189  // use placement new to call constructor that allocates
2190  // additional memory.
2191  new (a) B[allocationSize_];
2192  } else {
2193  a = nullptr;
2194  }
2195  }
2196 
2203  {
2204  if (build_mode != implicit)
2205  DUNE_THROW(InvalidStateException,"implicit_allocate() may only be called in implicit build mode");
2206  if (ready != notAllocated)
2207  DUNE_THROW(InvalidStateException,"memory has already been allocated");
2208 
2209  // check to make sure the user has actually set the parameters
2210  if (overflowsize < 0)
2211  DUNE_THROW(InvalidStateException,"You have to set the implicit build mode parameters before starting to build the matrix");
2212  //calculate size of overflow region, add buffer for row sort!
2213  size_type osize = (size_type) (_n*avg)*overflowsize + 4*avg;
2214  allocationSize_ = _n*avg + osize;
2215 
2216  allocate(_n, _m, allocationSize_,true,true);
2217 
2218  //set row pointers correctly
2219  size_type* jptr = j_.get() + osize;
2220  B* aptr = a + osize;
2221  for (size_type i=0; i<n; i++)
2222  {
2223  r[i].set(0,aptr,jptr);
2224  jptr = jptr + avg;
2225  aptr = aptr + avg;
2226  }
2227 
2228  ready = building;
2229  }
2230  };
2231 
2232 
2235 } // end namespace
2236 
2237 #endif
This file implements a vector space as a tensor product of a given vector space. The number of compon...
Error specific to BCRSMatrix.
Definition: istlexception.hh:21
Iterator class for sequential creation of blocks
Definition: bcrsmatrix.hh:929
bool operator==(const CreateIterator &it) const
equality
Definition: bcrsmatrix.hh:1021
size_type index() const
The number of the row that the iterator currently points to.
Definition: bcrsmatrix.hh:1027
bool operator!=(const CreateIterator &it) const
inequality
Definition: bcrsmatrix.hh:1015
CreateIterator(BCRSMatrix &_Mat, size_type _i)
constructor
Definition: bcrsmatrix.hh:932
CreateIterator & operator++()
prefix increment
Definition: bcrsmatrix.hh:946
void insert(size_type j)
put column index in row
Definition: bcrsmatrix.hh:1033
bool contains(size_type j)
return true if column index is in row
Definition: bcrsmatrix.hh:1039
size_type size() const
Get the current row size.
Definition: bcrsmatrix.hh:1048
Class used by shared_ptr to deallocate memory using the proper allocator.
Definition: bcrsmatrix.hh:2118
Iterator access to matrix rows
Definition: bcrsmatrix.hh:538
RealRowIterator()
empty constructor, use with care!
Definition: bcrsmatrix.hh:555
bool equals(const RealRowIterator< ValueType > &other) const
equality
Definition: bcrsmatrix.hh:583
std::remove_const< T >::type ValueType
The unqualified value type.
Definition: bcrsmatrix.hh:542
bool equals(const RealRowIterator< const ValueType > &other) const
equality
Definition: bcrsmatrix.hh:590
RealRowIterator(row_type *_p, size_type _i)
constructor
Definition: bcrsmatrix.hh:550
size_type index() const
return index
Definition: bcrsmatrix.hh:565
A sparse block matrix with compressed row storage.
Definition: bcrsmatrix.hh:423
FieldTraits< field_type >::real_type frobenius_norm() const
frobenius norm: sqrt(sum over squared values of entries)
Definition: bcrsmatrix.hh:1809
bool exists(size_type i, size_type j) const
return true if (i,j) is in pattern
Definition: bcrsmatrix.hh:1935
BuildStage buildStage() const
The current build stage of the matrix.
Definition: bcrsmatrix.hh:1921
Iterator begin()
Get iterator to first row.
Definition: bcrsmatrix.hh:634
friend class CreateIterator
allow CreateIterator to access internal data
Definition: bcrsmatrix.hh:1063
void copyWindowStructure(const BCRSMatrix &Mat)
Copy the window structure from another matrix.
Definition: bcrsmatrix.hh:2050
void mmhv(const X &x, Y &y) const
y -= A^H x
Definition: bcrsmatrix.hh:1748
void usmhv(const field_type &alpha, const X &x, Y &y) const
y += alpha A^H x
Definition: bcrsmatrix.hh:1767
void umtv(const X &x, Y &y) const
y += A^T x
Definition: bcrsmatrix.hh:1674
RealRowIterator< const row_type > const_iterator
The const iterator over the matrix rows.
Definition: bcrsmatrix.hh:666
BCRSMatrix(size_type _n, size_type _m, size_type _avg, double _overflowsize, BuildMode bm)
construct matrix with a known average number of entries per row
Definition: bcrsmatrix.hh:743
void allocate(size_type rows, size_type columns, size_type allocationSize, bool allocateRows, bool allocate_data)
Allocate memory for the matrix structure.
Definition: bcrsmatrix.hh:2147
B::field_type field_type
export the type representing the field
Definition: bcrsmatrix.hh:445
~BCRSMatrix()
destructor
Definition: bcrsmatrix.hh:791
BCRSMatrix & operator=(const BCRSMatrix &Mat)
assignment
Definition: bcrsmatrix.hh:878
void deallocate(bool deallocateRows=true)
deallocate memory of the matrix.
Definition: bcrsmatrix.hh:2067
Iterator RowIterator
rename the iterators for easier access
Definition: bcrsmatrix.hh:660
BCRSMatrix()
an empty matrix
Definition: bcrsmatrix.hh:708
void endrowsizes()
indicate that size of all rows is defined
Definition: bcrsmatrix.hh:1118
void incrementrowsize(size_type i, size_type s=1)
increment size of row i by s (1 by default)
Definition: bcrsmatrix.hh:1107
void mtv(const X &x, Y &y) const
y = A^T x
Definition: bcrsmatrix.hh:1659
void umhv(const X &x, Y &y) const
y += A^H x
Definition: bcrsmatrix.hh:1729
size_type nonzeroes() const
number of blocks that are stored (the number of blocks that possibly are nonzero)
Definition: bcrsmatrix.hh:1915
FieldTraits< ft >::real_type infinity_norm_real() const
simplified infinity norm (uses Manhattan norm for complex values)
Definition: bcrsmatrix.hh:1837
ConstIterator ConstRowIterator
rename the const row iterator for easier access
Definition: bcrsmatrix.hh:697
void setrowsize(size_type i, size_type s)
Set number of indices in row i to s.
Definition: bcrsmatrix.hh:1086
RealRowIterator< row_type > iterator
The iterator over the (mutable matrix rows.
Definition: bcrsmatrix.hh:630
void usmtv(const field_type &alpha, const X &x, Y &y) const
y += alpha A^T x
Definition: bcrsmatrix.hh:1710
ConstIterator beforeBegin() const
Definition: bcrsmatrix.hh:691
Iterator beforeBegin()
Definition: bcrsmatrix.hh:654
@ blocklevel
The number of blocklevels the matrix contains.
Definition: bcrsmatrix.hh:465
BuildMode
we support two modes
Definition: bcrsmatrix.hh:469
@ implicit
Build entries randomly with an educated guess for the number of entries per row.
Definition: bcrsmatrix.hh:498
@ unknown
Build mode not set!
Definition: bcrsmatrix.hh:502
@ random
Build entries randomly.
Definition: bcrsmatrix.hh:489
@ row_wise
Build in a row-wise manner.
Definition: bcrsmatrix.hh:480
BCRSMatrix & operator/=(const field_type &k)
vector space division by scalar
Definition: bcrsmatrix.hh:1480
FieldTraits< field_type >::real_type frobenius_norm2() const
square of frobenius norm, need for block recursion
Definition: bcrsmatrix.hh:1788
BCRSMatrix(size_type _n, size_type _m, size_type _nnz, BuildMode bm)
matrix with known number of nonzeroes
Definition: bcrsmatrix.hh:715
::Dune::CompressionStatistics< size_type > CompressionStatistics
The type for the statistics object returned by compress()
Definition: bcrsmatrix.hh:460
BCRSMatrix(const BCRSMatrix &Mat)
copy constructor
Definition: bcrsmatrix.hh:764
Iterator end()
Get iterator to one beyond last row.
Definition: bcrsmatrix.hh:640
void setIndices(size_type row, It begin, It end)
Set all column indices for row from the given iterator range.
Definition: bcrsmatrix.hh:1203
void addindex(size_type row, size_type col)
add index (row,col) to the matrix
Definition: bcrsmatrix.hh:1160
row_type::Iterator ColIterator
Iterator for the entries of each row.
Definition: bcrsmatrix.hh:663
FieldTraits< ft >::real_type infinity_norm() const
infinity norm (row sum norm, how to generalize for blocks?)
Definition: bcrsmatrix.hh:1817
A::size_type size_type
The type for the index access and the size.
Definition: bcrsmatrix.hh:457
row_type & operator[](size_type i)
random access to the rows
Definition: bcrsmatrix.hh:508
CreateIterator createend()
get create iterator pointing to one after the last block
Definition: bcrsmatrix.hh:1072
BCRSMatrix & axpy(field_type alpha, const BCRSMatrix &b)
Add the scaled entries of another matrix to this one.
Definition: bcrsmatrix.hh:1560
BCRSMatrix & operator+=(const BCRSMatrix &b)
Add the entries of another matrix to this one.
Definition: bcrsmatrix.hh:1513
Iterator beforeEnd()
Definition: bcrsmatrix.hh:647
row_type::ConstIterator ConstColIterator
Const iterator to the entries of a row.
Definition: bcrsmatrix.hh:700
void usmv(F &&alpha, const X &x, Y &y) const
y += alpha A x
Definition: bcrsmatrix.hh:1640
CompressedBlockVectorWindow< B, A > row_type
implement row_type with compressed vector
Definition: bcrsmatrix.hh:454
size_type getrowsize(size_type i) const
get current number of indices in row i
Definition: bcrsmatrix.hh:1097
size_type M() const
number of columns (counted in blocks)
Definition: bcrsmatrix.hh:1909
CreateIterator createbegin()
get initial create iterator
Definition: bcrsmatrix.hh:1066
BuildStage
Definition: bcrsmatrix.hh:426
@ rowSizesBuilt
The row sizes of the matrix are known.
Definition: bcrsmatrix.hh:437
@ built
The matrix structure is fully built.
Definition: bcrsmatrix.hh:439
@ notbuilt
Matrix is not built at all, no memory has been allocated, build mode and size can still be set.
Definition: bcrsmatrix.hh:428
@ notAllocated
Matrix is not built at all, no memory has been allocated, build mode and size can still be set.
Definition: bcrsmatrix.hh:430
@ building
Matrix is currently being built, some memory has been allocated, build mode and size are fixed.
Definition: bcrsmatrix.hh:432
BuildMode buildMode() const
The currently selected build mode of the matrix.
Definition: bcrsmatrix.hh:1927
void mmv(const X &x, Y &y) const
y -= A x
Definition: bcrsmatrix.hh:1621
void mv(const X &x, Y &y) const
y = A x
Definition: bcrsmatrix.hh:1580
B block_type
export the type representing the components
Definition: bcrsmatrix.hh:448
void mmtv(const X &x, Y &y) const
y -= A^T x
Definition: bcrsmatrix.hh:1693
void umv(const X &x, Y &y) const
y += A x
Definition: bcrsmatrix.hh:1602
void implicit_allocate(size_type _n, size_type _m)
organizes allocation implicit mode calculates correct array size to be allocated and sets the the win...
Definition: bcrsmatrix.hh:2202
BCRSMatrix(size_type _n, size_type _m, BuildMode bm)
matrix with unknown number of nonzeroes
Definition: bcrsmatrix.hh:724
void endindices()
indicate that all indices are defined, check consistency
Definition: bcrsmatrix.hh:1217
BCRSMatrix & operator-=(const BCRSMatrix &b)
Subtract the entries of another matrix from this one.
Definition: bcrsmatrix.hh:1535
BCRSMatrix & operator*=(const field_type &k)
vector space multiplication with scalar
Definition: bcrsmatrix.hh:1452
CompressionStatistics compress()
Finishes the buildstage in implicit mode.
Definition: bcrsmatrix.hh:1328
B & entry(size_type row, size_type col)
Returns reference to entry (row,col) of the matrix.
Definition: bcrsmatrix.hh:1264
void setDataPointers()
Set data pointers for all rows.
Definition: bcrsmatrix.hh:2031
size_type N() const
number of rows (counted in blocks)
Definition: bcrsmatrix.hh:1903
void setBuildMode(BuildMode bm)
Sets the build mode of the matrix.
Definition: bcrsmatrix.hh:800
void setSize(size_type rows, size_type columns, size_type nnz=0)
Set the size of the matrix.
Definition: bcrsmatrix.hh:828
void setColumnPointers(ConstRowIterator row)
Copy row sizes from iterator range starting at row and set column index pointers for all rows.
Definition: bcrsmatrix.hh:2005
ConstIterator end() const
Get const iterator to one beyond last row.
Definition: bcrsmatrix.hh:677
ConstIterator begin() const
Get const iterator to first row.
Definition: bcrsmatrix.hh:671
void setImplicitBuildModeParameters(size_type _avg, double _overflow)
Set parameters needed for creation in implicit build mode.
Definition: bcrsmatrix.hh:856
A allocator_type
export the allocator type
Definition: bcrsmatrix.hh:451
ConstIterator beforeEnd() const
Definition: bcrsmatrix.hh:684
void set(size_type _n, B *_p, size_type *_j)
set size and pointer
Definition: bvector.hh:1104
B * getptr()
get pointer
Definition: bvector.hh:1130
void setsize(size_type _n)
set size only
Definition: bvector.hh:1112
void setptr(B *_p)
set pointer only
Definition: bvector.hh:1118
size_type getsize() const
get size
Definition: bvector.hh:1153
void setindexptr(size_type *_j)
set pointer only
Definition: bvector.hh:1124
size_type * getindexptr()
get pointer
Definition: bvector.hh:1136
Proxy row object for entry access.
Definition: bcrsmatrix.hh:130
block_type & operator[](size_type j) const
Returns entry in column j.
Definition: bcrsmatrix.hh:135
A wrapper for uniform access to the BCRSMatrix during and after the build stage in implicit build mod...
Definition: bcrsmatrix.hh:110
Matrix::block_type block_type
The block_type of the underlying matrix.
Definition: bcrsmatrix.hh:118
ImplicitMatrixBuilder(Matrix &m)
Creates an ImplicitMatrixBuilder for matrix m.
Definition: bcrsmatrix.hh:163
M_ Matrix
The underlying matrix.
Definition: bcrsmatrix.hh:115
ImplicitMatrixBuilder(Matrix &m, size_type rows, size_type cols, size_type avg_cols_per_row, double overflow_fraction)
Sets up matrix m for implicit construction using the given parameters and creates an ImplicitBmatrixu...
Definition: bcrsmatrix.hh:187
size_type M() const
The number of columns in the matrix.
Definition: bcrsmatrix.hh:210
Matrix::size_type size_type
The size_type of the underlying matrix.
Definition: bcrsmatrix.hh:121
row_object operator[](size_type i) const
Returns a proxy for entries in row i.
Definition: bcrsmatrix.hh:198
size_type N() const
The number of rows in the matrix.
Definition: bcrsmatrix.hh:204
The overflow error used during implicit BCRSMatrix construction was exhausted.
Definition: istlexception.hh:34
Default exception if a function was called while the object is not in a valid state for that function...
Definition: exceptions.hh:279
A generic dynamic dense matrix.
Definition: matrix.hh:555
A::size_type size_type
Type for indices and sizes.
Definition: matrix.hh:571
T block_type
Export the type representing the components.
Definition: matrix.hh:562
Base class for stl conformant forward iterators.
Definition: iteratorfacades.hh:433
Default exception class for range errors.
Definition: exceptions.hh:252
iterator class for sequential access
Definition: basearray.hh:565
size_type size() const
number of blocks in the array (are of size 1 here)
Definition: basearray.hh:735
Type traits to determine the type of reals (when working with complex numbers)
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
constexpr decltype(auto) elementAt(Container &&c, Index &&i)
Get element at given position from container.
Definition: hybridutilities.hh:138
DWarnType dwarn(std::cerr)
Stream for warnings indicating problems.
Definition: stdstreams.hh:159
This file implements iterator facade classes for writing stl conformant iterators.
Some handy generic functions for ISTL matrices.
Dune namespace.
Definition: alignment.hh:11
Standard Dune debug streams.
Statistics about compression achieved in implicit mode.
Definition: bcrsmatrix.hh:81
size_type overflow_total
total number of elements written to the overflow area during construction.
Definition: bcrsmatrix.hh:87
size_type maximum
maximum number of non-zeroes per row.
Definition: bcrsmatrix.hh:85
double avg
average number of non-zeroes per row.
Definition: bcrsmatrix.hh:83
double mem_ratio
fraction of wasted memory resulting from non-used overflow area.
Definition: bcrsmatrix.hh:92
Traits for type conversions and type information.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 9, 22:29, 2024)