Dune Core Modules (2.7.1)

aggregates.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 #ifndef DUNE_AMG_AGGREGATES_HH
4 #define DUNE_AMG_AGGREGATES_HH
5 
6 
7 #include "parameters.hh"
8 #include "graph.hh"
9 #include "properties.hh"
10 #include "combinedfunctor.hh"
11 
12 #include <dune/common/timer.hh>
15 #include <dune/common/sllist.hh>
16 #include <dune/common/unused.hh>
17 #include <dune/common/ftraits.hh>
19 
20 #include <utility>
21 #include <set>
22 #include <algorithm>
23 #include <complex>
24 #include <limits>
25 #include <ostream>
26 #include <tuple>
27 
28 namespace Dune
29 {
30  namespace Amg
31  {
32 
46  template<class T>
47  class AggregationCriterion : public T
48  {
49 
50  public:
54  typedef T DependencyPolicy;
55 
66  : T()
67  {}
68 
69  AggregationCriterion(const Parameters& parms)
70  : T(parms)
71  {}
81  void setDefaultValuesIsotropic(std::size_t dim, std::size_t diameter=2)
82  {
83  this->setMaxDistance(diameter-1);
84  std::size_t csize=1;
85 
86  for(; dim>0; dim--) {
87  csize*=diameter;
88  this->setMaxDistance(this->maxDistance()+diameter-1);
89  }
90  this->setMinAggregateSize(csize);
91  this->setMaxAggregateSize(static_cast<std::size_t>(csize*1.5));
92  }
93 
104  void setDefaultValuesAnisotropic(std::size_t dim,std::size_t diameter=2)
105  {
106  setDefaultValuesIsotropic(dim, diameter);
107  this->setMaxDistance(this->maxDistance()+dim-1);
108  }
109  };
110 
111  template<class T>
112  std::ostream& operator<<(std::ostream& os, const AggregationCriterion<T>& criterion)
113  {
114  os<<"{ maxdistance="<<criterion.maxDistance()<<" minAggregateSize="
115  <<criterion.minAggregateSize()<< " maxAggregateSize="<<criterion.maxAggregateSize()
116  <<" connectivity="<<criterion.maxConnectivity()<<" debugLevel="<<criterion.debugLevel()<<"}";
117  return os;
118  }
119 
131  template<class M, class N>
133  {
134  public:
138  typedef M Matrix;
139 
143  typedef N Norm;
144 
148  typedef typename Matrix::row_type Row;
149 
154 
155  void init(const Matrix* matrix);
156 
157  void initRow(const Row& row, int index);
158 
159  void examine(const ColIter& col);
160 
161  template<class G>
162  void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
163 
164  bool isIsolated();
165 
166 
168  : Parameters(parms)
169  {}
171  : Parameters()
172  {}
173 
174  protected:
176  const Matrix* matrix_;
178  typedef typename Matrix::field_type field_type;
179  typedef typename FieldTraits<field_type>::real_type real_type;
180  real_type maxValue_;
184  int row_;
186  real_type diagonal_;
187  std::vector<real_type> vals_;
188  typename std::vector<real_type>::iterator valIter_;
189 
190  };
191 
192 
193  template<class M, class N>
194  inline void SymmetricMatrixDependency<M,N>::init(const Matrix* matrix)
195  {
196  matrix_ = matrix;
197  }
198 
199  template<class M, class N>
200  inline void SymmetricMatrixDependency<M,N>::initRow(const Row& row, int index)
201  {
202  using std::min;
203  vals_.assign(row.size(), 0.0);
204  assert(vals_.size()==row.size());
205  valIter_=vals_.begin();
206 
208  diagonal_=norm_(row[index]);
209  row_ = index;
210  }
211 
212  template<class M, class N>
213  inline void SymmetricMatrixDependency<M,N>::examine(const ColIter& col)
214  {
215  using std::max;
216  // skip positive offdiagonals if norm preserves sign of them.
217  real_type eij = norm_(*col);
218  if(!N::is_sign_preserving || eij<0) // || eji<0)
219  {
220  *valIter_ = eij/diagonal_*eij/norm_(matrix_->operator[](col.index())[col.index()]);
221  maxValue_ = max(maxValue_, *valIter_);
222  }else
223  *valIter_ =0;
224  ++valIter_;
225  }
226 
227  template<class M, class N>
228  template<class G>
229  inline void SymmetricMatrixDependency<M,N>::examine(G&, const typename G::EdgeIterator& edge, const ColIter&)
230  {
231  if(*valIter_ > alpha() * maxValue_) {
232  edge.properties().setDepends();
233  edge.properties().setInfluences();
234  }
235  ++valIter_;
236  }
237 
238  template<class M, class N>
239  inline bool SymmetricMatrixDependency<M,N>::isIsolated()
240  {
241  if(diagonal_==0)
242  DUNE_THROW(Dune::ISTLError, "No diagonal entry for row "<<row_<<".");
243  valIter_=vals_.begin();
244  return maxValue_ < beta();
245  }
246 
250  template<class M, class N>
251  class Dependency : public Parameters
252  {
253  public:
257  typedef M Matrix;
258 
262  typedef N Norm;
263 
267  typedef typename Matrix::row_type Row;
268 
273 
274  void init(const Matrix* matrix);
275 
276  void initRow(const Row& row, int index);
277 
278  void examine(const ColIter& col);
279 
280  template<class G>
281  void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
282 
283  bool isIsolated();
284 
285  Dependency(const Parameters& parms)
286  : Parameters(parms)
287  {}
288 
289  Dependency()
290  : Parameters()
291  {}
292 
293  protected:
295  const Matrix* matrix_;
297  typedef typename Matrix::field_type field_type;
298  typedef typename FieldTraits<field_type>::real_type real_type;
299  real_type maxValue_;
303  int row_;
305  real_type diagonal_;
306  };
307 
311  template<class M, class N>
313  {
314  public:
318  typedef M Matrix;
319 
323  typedef N Norm;
324 
328  typedef typename Matrix::row_type Row;
329 
334 
335  void init(const Matrix* matrix);
336 
337  void initRow(const Row& row, int index);
338 
339  void examine(const ColIter& col);
340 
341  template<class G>
342  void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
343 
344  bool isIsolated();
345 
346 
347  SymmetricDependency(const Parameters& parms)
348  : Parameters(parms)
349  {}
351  : Parameters()
352  {}
353 
354  protected:
356  const Matrix* matrix_;
358  typedef typename Matrix::field_type field_type;
359  typedef typename FieldTraits<field_type>::real_type real_type;
360  real_type maxValue_;
364  int row_;
366  real_type diagonal_;
367  };
368 
373  template<int N>
374  class Diagonal
375  {
376  public:
377  enum { /* @brief We preserve the sign.*/
378  is_sign_preserving = true
379  };
380 
385  template<class M>
386  typename FieldTraits<typename M::field_type>::real_type operator()(const M& m,
387  typename std::enable_if_t<!Dune::IsNumber<M>::value>* sfinae = nullptr) const
388  {
389  typedef typename M::field_type field_type;
390  typedef typename FieldTraits<field_type>::real_type real_type;
391  static_assert( std::is_convertible<field_type, real_type >::value,
392  "use of diagonal norm in AMG not implemented for complex field_type");
393  return m[N][N];
394  // possible implementation for complex types: return signed_abs(m[N][N]);
395  }
396 
401  template<class M>
402  auto operator()(const M& m,
403  typename std::enable_if_t<Dune::IsNumber<M>::value>* sfinae = nullptr) const
404  {
405  typedef typename FieldTraits<M>::real_type real_type;
406  static_assert( std::is_convertible<M, real_type >::value,
407  "use of diagonal norm in AMG not implemented for complex field_type");
408  return m;
409  // possible implementation for complex types: return signed_abs(m[N][N]);
410  }
411 
412  private:
413 
415  template<typename T>
416  static T signed_abs(const T & v)
417  {
418  return v;
419  }
420 
422  template<typename T>
423  static T signed_abs(const std::complex<T> & v)
424  {
425  // return sign * abs_value
426  // in case of complex numbers this extends to using the csgn function to determine the sign
427  return csgn(v) * std::abs(v);
428  }
429 
431  template<typename T>
432  static T csgn(const T & v)
433  {
434  return (T(0) < v) - (v < T(0));
435  }
436 
438  template<typename T>
439  static T csgn(std::complex<T> a)
440  {
441  return csgn(a.real())+(a.real() == 0.0)*csgn(a.imag());
442  }
443 
444  };
445 
450  class FirstDiagonal : public Diagonal<0>
451  {};
452 
458  struct RowSum
459  {
460 
461  enum { /* @brief We preserve the sign.*/
462  is_sign_preserving = false
463  };
468  template<class M>
469  typename FieldTraits<typename M::field_type>::real_type operator()(const M& m) const
470  {
471  return m.infinity_norm();
472  }
473  };
474 
475  struct FrobeniusNorm
476  {
477 
478  enum { /* @brief We preserve the sign.*/
479  is_sign_preserving = false
480  };
485  template<class M>
486  typename FieldTraits<typename M::field_type>::real_type operator()(const M& m) const
487  {
488  return m.frobenius_norm();
489  }
490  };
491  struct AlwaysOneNorm
492  {
493 
494  enum { /* @brief We preserve the sign.*/
495  is_sign_preserving = false
496  };
501  template<class M>
502  typename FieldTraits<typename M::field_type>::real_type operator()(const M& m) const
503  {
504  return 1;
505  }
506  };
513  template<class M, class Norm>
514  class SymmetricCriterion : public AggregationCriterion<SymmetricDependency<M,Norm> >
515  {
516  public:
517  SymmetricCriterion(const Parameters& parms)
519  {}
521  {}
522  };
523 
524 
533  template<class M, class Norm>
534  class UnSymmetricCriterion : public AggregationCriterion<Dependency<M,Norm> >
535  {
536  public:
537  UnSymmetricCriterion(const Parameters& parms)
539  {}
541  {}
542  };
543  // forward declaration
544  template<class G> class Aggregator;
545 
546 
554  template<class V>
556  {
557  public:
558 
562  static const V UNAGGREGATED;
563 
567  static const V ISOLATED;
571  typedef V VertexDescriptor;
572 
577 
583 
589 
594  {
595  public:
596  template<class EdgeIterator>
597  void operator()(const EdgeIterator& edge) const
598  {
599  DUNE_UNUSED_PARAMETER(edge);
600  }
601  };
602 
603 
608 
614  AggregatesMap(std::size_t noVertices);
615 
620 
632  template<class M, class G, class C>
633  std::tuple<int,int,int,int> buildAggregates(const M& matrix, G& graph, const C& criterion,
634  bool finestLevel);
635 
653  template<bool reset, class G, class F, class VM>
654  std::size_t breadthFirstSearch(const VertexDescriptor& start,
655  const AggregateDescriptor& aggregate,
656  const G& graph,
657  F& aggregateVisitor,
658  VM& visitedMap) const;
659 
683  template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
684  std::size_t breadthFirstSearch(const VertexDescriptor& start,
685  const AggregateDescriptor& aggregate,
686  const G& graph, L& visited, F1& aggregateVisitor,
687  F2& nonAggregateVisitor,
688  VM& visitedMap) const;
689 
695  void allocate(std::size_t noVertices);
696 
700  std::size_t noVertices() const;
701 
705  void free();
706 
713 
720 
721  typedef const AggregateDescriptor* const_iterator;
722 
723  const_iterator begin() const
724  {
725  return aggregates_;
726  }
727 
728  const_iterator end() const
729  {
730  return aggregates_+noVertices();
731  }
732 
733  typedef AggregateDescriptor* iterator;
734 
735  iterator begin()
736  {
737  return aggregates_;
738  }
739 
740  iterator end()
741  {
742  return aggregates_+noVertices();
743  }
744  private:
746  AggregatesMap(const AggregatesMap<V>&) = delete;
748  AggregatesMap<V>& operator=(const AggregatesMap<V>&) = delete;
749 
753  AggregateDescriptor* aggregates_;
754 
758  std::size_t noVertices_;
759  };
760 
764  template<class G, class C>
765  void buildDependency(G& graph,
766  const typename C::Matrix& matrix,
767  C criterion,
768  bool finestLevel);
769 
774  template<class G, class S>
775  class Aggregate
776  {
777 
778  public:
779 
780  /***
781  * @brief The type of the matrix graph we work with.
782  */
783  typedef G MatrixGraph;
788 
794 
799  typedef S VertexSet;
800 
802  typedef typename VertexSet::const_iterator const_iterator;
803 
807  typedef std::size_t* SphereMap;
808 
817  Aggregate(MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
818  VertexSet& connectivity, std::vector<Vertex>& front_);
819 
820  void invalidate()
821  {
822  --id_;
823  }
824 
831  void reconstruct(const Vertex& vertex);
832 
836  void seed(const Vertex& vertex);
837 
841  void add(const Vertex& vertex);
842 
843  void add(std::vector<Vertex>& vertex);
847  void clear();
848 
852  typename VertexSet::size_type size();
856  typename VertexSet::size_type connectSize();
857 
861  int id();
862 
865 
868 
869  private:
873  VertexSet vertices_;
874 
879  int id_;
880 
884  MatrixGraph& graph_;
885 
889  AggregatesMap<Vertex>& aggregates_;
890 
894  VertexSet& connected_;
895 
899  std::vector<Vertex>& front_;
900  };
901 
905  template<class G>
907  {
908  public:
909 
913  typedef G MatrixGraph;
914 
919 
922 
927 
932 
949  template<class M, class C>
950  std::tuple<int,int,int,int> build(const M& m, G& graph,
951  AggregatesMap<Vertex>& aggregates, const C& c,
952  bool finestLevel);
953  private:
959 
964 
968  typedef std::set<Vertex,std::less<Vertex>,Allocator> VertexSet;
969 
973  typedef std::size_t* SphereMap;
974 
978  MatrixGraph* graph_;
979 
984 
988  std::vector<Vertex> front_;
989 
993  VertexSet connected_;
994 
998  int size_;
999 
1003  class Stack
1004  {
1005  public:
1006  static const Vertex NullEntry;
1007 
1008  Stack(const MatrixGraph& graph,
1009  const Aggregator<G>& aggregatesBuilder,
1010  const AggregatesMap<Vertex>& aggregates);
1011  ~Stack();
1012  Vertex pop();
1013  private:
1014  enum { N = 1300000 };
1015 
1017  const MatrixGraph& graph_;
1019  const Aggregator<G>& aggregatesBuilder_;
1021  const AggregatesMap<Vertex>& aggregates_;
1023  int size_;
1024  Vertex maxSize_;
1026  typename MatrixGraph::ConstVertexIterator begin_;
1027  typename MatrixGraph::ConstVertexIterator end_;
1028 
1030  Vertex* vals_;
1031 
1032  };
1033 
1034  friend class Stack;
1035 
1046  template<class V>
1047  void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate,
1048  const AggregatesMap<Vertex>& aggregates,
1049  V& visitor) const;
1050 
1055  template<class V>
1056  class AggregateVisitor
1057  {
1058  public:
1062  typedef V Visitor;
1070  AggregateVisitor(const AggregatesMap<Vertex>& aggregates, const AggregateDescriptor& aggregate,
1071  Visitor& visitor);
1072 
1079  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1080 
1081  private:
1083  const AggregatesMap<Vertex>& aggregates_;
1085  AggregateDescriptor aggregate_;
1087  Visitor* visitor_;
1088  };
1089 
1093  class Counter
1094  {
1095  public:
1099  int value();
1100 
1101  protected:
1103  void increment();
1105  void decrement();
1106 
1107  private:
1108  int count_;
1109  };
1110 
1111 
1116  class FrontNeighbourCounter : public Counter
1117  {
1118  public:
1124 
1125  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1126 
1127  private:
1128  const MatrixGraph& graph_;
1129  };
1130 
1135  int noFrontNeighbours(const Vertex& vertex) const;
1136 
1140  class TwoWayCounter : public Counter
1141  {
1142  public:
1143  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1144  };
1145 
1157  int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
1158  const AggregatesMap<Vertex>& aggregates) const;
1159 
1163  class OneWayCounter : public Counter
1164  {
1165  public:
1166  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1167  };
1168 
1180  int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
1181  const AggregatesMap<Vertex>& aggregates) const;
1182 
1189  class ConnectivityCounter : public Counter
1190  {
1191  public:
1198  ConnectivityCounter(const VertexSet& connected, const AggregatesMap<Vertex>& aggregates);
1199 
1200  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1201 
1202  private:
1204  const VertexSet& connected_;
1206  const AggregatesMap<Vertex>& aggregates_;
1207 
1208  };
1209 
1221  double connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1229  bool connected(const Vertex& vertex, const AggregateDescriptor& aggregate,
1230  const AggregatesMap<Vertex>& aggregates) const;
1231 
1239  bool connected(const Vertex& vertex, const SLList<AggregateDescriptor>& aggregateList,
1240  const AggregatesMap<Vertex>& aggregates) const;
1241 
1249  class DependencyCounter : public Counter
1250  {
1251  public:
1256 
1257  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1258  };
1259 
1266  class FrontMarker
1267  {
1268  public:
1275  FrontMarker(std::vector<Vertex>& front, MatrixGraph& graph);
1276 
1277  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1278 
1279  private:
1281  std::vector<Vertex>& front_;
1283  MatrixGraph& graph_;
1284  };
1285 
1289  void unmarkFront();
1290 
1305  int unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1306 
1320  std::pair<int,int> neighbours(const Vertex& vertex,
1321  const AggregateDescriptor& aggregate,
1322  const AggregatesMap<Vertex>& aggregates) const;
1339  int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
1340 
1348  bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
1349 
1357  std::size_t distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates);
1358 
1367  Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1368 
1377  void nonisoNeighbourAggregate(const Vertex& vertex,
1378  const AggregatesMap<Vertex>& aggregates,
1379  SLList<Vertex>& neighbours) const;
1380 
1388  template<class C>
1389  void growAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
1390  template<class C>
1391  void growIsolatedAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
1392  };
1393 
1394 #ifndef DOXYGEN
1395 
1396  template<class M, class N>
1397  inline void SymmetricDependency<M,N>::init(const Matrix* matrix)
1398  {
1399  matrix_ = matrix;
1400  }
1401 
1402  template<class M, class N>
1403  inline void SymmetricDependency<M,N>::initRow(const Row& row, int index)
1404  {
1405  using std::min;
1406  DUNE_UNUSED_PARAMETER(row);
1408  row_ = index;
1409  diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1410  }
1411 
1412  template<class M, class N>
1413  inline void SymmetricDependency<M,N>::examine(const ColIter& col)
1414  {
1415  using std::max;
1416  real_type eij = norm_(*col);
1417  typename Matrix::ConstColIterator opposite_entry =
1418  matrix_->operator[](col.index()).find(row_);
1419  if ( opposite_entry == matrix_->operator[](col.index()).end() )
1420  {
1421  // Consider this a weak connection we disregard.
1422  return;
1423  }
1424  real_type eji = norm_(*opposite_entry);
1425 
1426  // skip positive offdiagonals if norm preserves sign of them.
1427  if(!N::is_sign_preserving || eij<0 || eji<0)
1428  maxValue_ = max(maxValue_,
1429  eij /diagonal_ * eji/
1430  norm_(matrix_->operator[](col.index())[col.index()]));
1431  }
1432 
1433  template<class M, class N>
1434  template<class G>
1435  inline void SymmetricDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
1436  {
1437  real_type eij = norm_(*col);
1438  typename Matrix::ConstColIterator opposite_entry =
1439  matrix_->operator[](col.index()).find(row_);
1440 
1441  if ( opposite_entry == matrix_->operator[](col.index()).end() )
1442  {
1443  // Consider this as a weak connection we disregard.
1444  return;
1445  }
1446  real_type eji = norm_(*opposite_entry);
1447  // skip positve offdiagonals if norm preserves sign of them.
1448  if(!N::is_sign_preserving || (eij<0 || eji<0))
1449  if(eji / norm_(matrix_->operator[](edge.target())[edge.target()]) *
1450  eij/ diagonal_ > alpha() * maxValue_) {
1451  edge.properties().setDepends();
1452  edge.properties().setInfluences();
1453  typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
1454  other.setInfluences();
1455  other.setDepends();
1456  }
1457  }
1458 
1459  template<class M, class N>
1460  inline bool SymmetricDependency<M,N>::isIsolated()
1461  {
1462  return maxValue_ < beta();
1463  }
1464 
1465 
1466  template<class M, class N>
1467  inline void Dependency<M,N>::init(const Matrix* matrix)
1468  {
1469  matrix_ = matrix;
1470  }
1471 
1472  template<class M, class N>
1473  inline void Dependency<M,N>::initRow(const Row& row, int index)
1474  {
1475  using std::min;
1476  DUNE_UNUSED_PARAMETER(row);
1478  row_ = index;
1479  diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1480  }
1481 
1482  template<class M, class N>
1483  inline void Dependency<M,N>::examine(const ColIter& col)
1484  {
1485  using std::max;
1486  maxValue_ = max(maxValue_, -norm_(*col));
1487  }
1488 
1489  template<class M, class N>
1490  template<class G>
1491  inline void Dependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
1492  {
1493  if(-norm_(*col) >= maxValue_ * alpha()) {
1494  edge.properties().setDepends();
1495  typedef typename G::EdgeDescriptor ED;
1496  ED e= graph.findEdge(edge.target(), edge.source());
1498  {
1499  typename G::EdgeProperties& other = graph.getEdgeProperties(e);
1500  other.setInfluences();
1501  }
1502  }
1503  }
1504 
1505  template<class M, class N>
1506  inline bool Dependency<M,N>::isIsolated()
1507  {
1508  return maxValue_ < beta() * diagonal_;
1509  }
1510 
1511  template<class G,class S>
1512  Aggregate<G,S>::Aggregate(MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
1513  VertexSet& connected, std::vector<Vertex>& front)
1514  : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
1515  connected_(connected), front_(front)
1516  {}
1517 
1518  template<class G,class S>
1520  {
1521  /*
1522  vertices_.push_back(vertex);
1523  typedef typename VertexList::const_iterator iterator;
1524  iterator begin = vertices_.begin();
1525  iterator end = vertices_.end();*/
1526  throw "Not yet implemented";
1527 
1528  // while(begin!=end){
1529  //for();
1530  // }
1531 
1532  }
1533 
1534  template<class G,class S>
1535  inline void Aggregate<G,S>::seed(const Vertex& vertex)
1536  {
1537  dvverb<<"Connected cleared"<<std::endl;
1538  connected_.clear();
1539  vertices_.clear();
1540  connected_.insert(vertex);
1541  dvverb << " Inserting "<<vertex<<" size="<<connected_.size();
1542  ++id_ ;
1543  add(vertex);
1544  }
1545 
1546 
1547  template<class G,class S>
1548  inline void Aggregate<G,S>::add(const Vertex& vertex)
1549  {
1550  vertices_.insert(vertex);
1551  aggregates_[vertex]=id_;
1552  if(front_.size())
1553  front_.erase(std::lower_bound(front_.begin(), front_.end(), vertex));
1554 
1555 
1556  typedef typename MatrixGraph::ConstEdgeIterator iterator;
1557  const iterator end = graph_.endEdges(vertex);
1558  for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge) {
1559  dvverb << " Inserting "<<aggregates_[edge.target()];
1560  connected_.insert(aggregates_[edge.target()]);
1561  dvverb <<" size="<<connected_.size();
1562  if(aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED &&
1563  !graph_.getVertexProperties(edge.target()).front())
1564  {
1565  front_.push_back(edge.target());
1566  graph_.getVertexProperties(edge.target()).setFront();
1567  }
1568  }
1569  dvverb <<std::endl;
1570  std::sort(front_.begin(), front_.end());
1571  }
1572 
1573  template<class G,class S>
1574  inline void Aggregate<G,S>::add(std::vector<Vertex>& vertices)
1575  {
1576 #ifndef NDEBUG
1577  std::size_t oldsize = vertices_.size();
1578 #endif
1579  typedef typename std::vector<Vertex>::iterator Iterator;
1580 
1581  typedef typename VertexSet::iterator SIterator;
1582 
1583  SIterator pos=vertices_.begin();
1584  std::vector<Vertex> newFront;
1585  newFront.reserve(front_.capacity());
1586 
1587  std::set_difference(front_.begin(), front_.end(), vertices.begin(), vertices.end(),
1588  std::back_inserter(newFront));
1589  front_=newFront;
1590 
1591  for(Iterator vertex=vertices.begin(); vertex != vertices.end(); ++vertex)
1592  {
1593  pos=vertices_.insert(pos,*vertex);
1594  vertices_.insert(*vertex);
1595  graph_.getVertexProperties(*vertex).resetFront(); // Not a front node any more.
1596  aggregates_[*vertex]=id_;
1597 
1598  typedef typename MatrixGraph::ConstEdgeIterator iterator;
1599  const iterator end = graph_.endEdges(*vertex);
1600  for(iterator edge = graph_.beginEdges(*vertex); edge != end; ++edge) {
1601  dvverb << " Inserting "<<aggregates_[edge.target()];
1602  connected_.insert(aggregates_[edge.target()]);
1603  if(aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED &&
1604  !graph_.getVertexProperties(edge.target()).front())
1605  {
1606  front_.push_back(edge.target());
1607  graph_.getVertexProperties(edge.target()).setFront();
1608  }
1609  dvverb <<" size="<<connected_.size();
1610  }
1611  dvverb <<std::endl;
1612  }
1613  std::sort(front_.begin(), front_.end());
1614  assert(oldsize+vertices.size()==vertices_.size());
1615  }
1616  template<class G,class S>
1617  inline void Aggregate<G,S>::clear()
1618  {
1619  vertices_.clear();
1620  connected_.clear();
1621  id_=-1;
1622  }
1623 
1624  template<class G,class S>
1625  inline typename Aggregate<G,S>::VertexSet::size_type
1627  {
1628  return vertices_.size();
1629  }
1630 
1631  template<class G,class S>
1632  inline typename Aggregate<G,S>::VertexSet::size_type
1634  {
1635  return connected_.size();
1636  }
1637 
1638  template<class G,class S>
1639  inline int Aggregate<G,S>::id()
1640  {
1641  return id_;
1642  }
1643 
1644  template<class G,class S>
1646  {
1647  return vertices_.begin();
1648  }
1649 
1650  template<class G,class S>
1651  inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::end() const
1652  {
1653  return vertices_.end();
1654  }
1655 
1656  template<class V>
1658 
1659  template<class V>
1661 
1662  template<class V>
1664  : aggregates_(0)
1665  {}
1666 
1667  template<class V>
1669  {
1670  if(aggregates_!=0)
1671  delete[] aggregates_;
1672  }
1673 
1674 
1675  template<class V>
1676  inline AggregatesMap<V>::AggregatesMap(std::size_t noVertices)
1677  {
1678  allocate(noVertices);
1679  }
1680 
1681  template<class V>
1682  inline std::size_t AggregatesMap<V>::noVertices() const
1683  {
1684  return noVertices_;
1685  }
1686 
1687  template<class V>
1688  inline void AggregatesMap<V>::allocate(std::size_t noVertices)
1689  {
1690  aggregates_ = new AggregateDescriptor[noVertices];
1691  noVertices_ = noVertices;
1692 
1693  for(std::size_t i=0; i < noVertices; i++)
1694  aggregates_[i]=UNAGGREGATED;
1695  }
1696 
1697  template<class V>
1698  inline void AggregatesMap<V>::free()
1699  {
1700  assert(aggregates_ != 0);
1701  delete[] aggregates_;
1702  aggregates_=0;
1703  }
1704 
1705  template<class V>
1706  inline typename AggregatesMap<V>::AggregateDescriptor&
1707  AggregatesMap<V>::operator[](const VertexDescriptor& v)
1708  {
1709  return aggregates_[v];
1710  }
1711 
1712  template<class V>
1713  inline const typename AggregatesMap<V>::AggregateDescriptor&
1714  AggregatesMap<V>::operator[](const VertexDescriptor& v) const
1715  {
1716  return aggregates_[v];
1717  }
1718 
1719  template<class V>
1720  template<bool reset, class G, class F,class VM>
1721  inline std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
1722  const AggregateDescriptor& aggregate,
1723  const G& graph, F& aggregateVisitor,
1724  VM& visitedMap) const
1725  {
1726  VertexList vlist;
1727 
1728  DummyEdgeVisitor dummy;
1729  return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap);
1730  }
1731 
1732  template<class V>
1733  template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
1734  std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
1735  const AggregateDescriptor& aggregate,
1736  const G& graph,
1737  L& visited,
1738  F1& aggregateVisitor,
1739  F2& nonAggregateVisitor,
1740  VM& visitedMap) const
1741  {
1742  typedef typename L::const_iterator ListIterator;
1743  int visitedSpheres = 0;
1744 
1745  visited.push_back(start);
1746  put(visitedMap, start, true);
1747 
1748  ListIterator current = visited.begin();
1749  ListIterator end = visited.end();
1750  std::size_t i=0, size=visited.size();
1751 
1752  // visit the neighbours of all vertices of the
1753  // current sphere.
1754  while(current != end) {
1755 
1756  for(; i<size; ++current, ++i) {
1757  typedef typename G::ConstEdgeIterator EdgeIterator;
1758  const EdgeIterator endEdge = graph.endEdges(*current);
1759 
1760  for(EdgeIterator edge = graph.beginEdges(*current);
1761  edge != endEdge; ++edge) {
1762 
1763  if(aggregates_[edge.target()]==aggregate) {
1764  if(!get(visitedMap, edge.target())) {
1765  put(visitedMap, edge.target(), true);
1766  visited.push_back(edge.target());
1767  aggregateVisitor(edge);
1768  }
1769  }else
1770  nonAggregateVisitor(edge);
1771  }
1772  }
1773  end = visited.end();
1774  size = visited.size();
1775  if(current != end)
1776  visitedSpheres++;
1777  }
1778 
1779  if(reset)
1780  for(current = visited.begin(); current != end; ++current)
1781  put(visitedMap, *current, false);
1782 
1783 
1784  if(remove)
1785  visited.clear();
1786 
1787  return visitedSpheres;
1788  }
1789 
1790  template<class G>
1792  : graph_(0), aggregate_(0), front_(), connected_(), size_(-1)
1793  {}
1794 
1795  template<class G>
1797  {
1798  size_=-1;
1799  }
1800 
1801  template<class G, class C>
1802  void buildDependency(G& graph,
1803  const typename C::Matrix& matrix,
1804  C criterion, bool firstlevel)
1805  {
1806  // assert(graph.isBuilt());
1807  typedef typename C::Matrix Matrix;
1808  typedef typename G::VertexIterator VertexIterator;
1809 
1810  criterion.init(&matrix);
1811 
1812  for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex) {
1813  typedef typename Matrix::row_type Row;
1814 
1815  const Row& row = matrix[*vertex];
1816 
1817  // Tell the criterion what row we will examine now
1818  // This might for example be used for calculating the
1819  // maximum offdiagonal value
1820  criterion.initRow(row, *vertex);
1821 
1822  // On a first path all columns are examined. After this
1823  // the calculator should know whether the vertex is isolated.
1824  typedef typename Matrix::ConstColIterator ColIterator;
1825  ColIterator end = row.end();
1826  typename FieldTraits<typename Matrix::field_type>::real_type absoffdiag=0.;
1827 
1828  using std::max;
1829  if(firstlevel) {
1830  for(ColIterator col = row.begin(); col != end; ++col)
1831  if(col.index()!=*vertex) {
1832  criterion.examine(col);
1833  absoffdiag = max(absoffdiag, Impl::asMatrix(*col).frobenius_norm());
1834  }
1835 
1836  if(absoffdiag==0)
1837  vertex.properties().setExcludedBorder();
1838  }
1839  else
1840  for(ColIterator col = row.begin(); col != end; ++col)
1841  if(col.index()!=*vertex)
1842  criterion.examine(col);
1843 
1844  // reset the vertex properties
1845  //vertex.properties().reset();
1846 
1847  // Check whether the vertex is isolated.
1848  if(criterion.isIsolated()) {
1849  //std::cout<<"ISOLATED: "<<*vertex<<std::endl;
1850  vertex.properties().setIsolated();
1851  }else{
1852  // Examine all the edges beginning at this vertex.
1853  typedef typename G::EdgeIterator EdgeIterator;
1854  typedef typename Matrix::ConstColIterator ColIterator;
1855  EdgeIterator eEnd = vertex.end();
1856  ColIterator col = matrix[*vertex].begin();
1857 
1858  for(EdgeIterator edge = vertex.begin(); edge!= eEnd; ++edge, ++col) {
1859  // Move to the right column.
1860  while(col.index()!=edge.target())
1861  ++col;
1862  criterion.examine(graph, edge, col);
1863  }
1864  }
1865 
1866  }
1867  }
1868 
1869 
1870  template<class G>
1871  template<class V>
1872  inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates,
1873  const AggregateDescriptor& aggregate, V& visitor)
1874  : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
1875  {}
1876 
1877  template<class G>
1878  template<class V>
1879  inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1880  {
1881  if(aggregates_[edge.target()]==aggregate_)
1882  visitor_->operator()(edge);
1883  }
1884 
1885  template<class G>
1886  template<class V>
1887  inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
1888  const AggregateDescriptor& aggregate,
1889  const AggregatesMap<Vertex>& aggregates,
1890  V& visitor) const
1891  {
1892  // Only evaluates for edge pointing to the aggregate
1893  AggregateVisitor<V> v(aggregates, aggregate, visitor);
1894  visitNeighbours(*graph_, vertex, v);
1895  }
1896 
1897 
1898  template<class G>
1899  inline Aggregator<G>::Counter::Counter()
1900  : count_(0)
1901  {}
1902 
1903  template<class G>
1904  inline void Aggregator<G>::Counter::increment()
1905  {
1906  ++count_;
1907  }
1908 
1909  template<class G>
1910  inline void Aggregator<G>::Counter::decrement()
1911  {
1912  --count_;
1913  }
1914  template<class G>
1915  inline int Aggregator<G>::Counter::value()
1916  {
1917  return count_;
1918  }
1919 
1920  template<class G>
1921  inline void Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1922  {
1923  if(edge.properties().isTwoWay())
1924  Counter::increment();
1925  }
1926 
1927  template<class G>
1928  int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
1929  const AggregatesMap<Vertex>& aggregates) const
1930  {
1931  TwoWayCounter counter;
1932  visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
1933  return counter.value();
1934  }
1935 
1936  template<class G>
1937  int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
1938  const AggregatesMap<Vertex>& aggregates) const
1939  {
1940  OneWayCounter counter;
1941  visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
1942  return counter.value();
1943  }
1944 
1945  template<class G>
1946  inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1947  {
1948  if(edge.properties().isOneWay())
1949  Counter::increment();
1950  }
1951 
1952  template<class G>
1953  inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
1954  const AggregatesMap<Vertex>& aggregates)
1955  : Counter(), connected_(connected), aggregates_(aggregates)
1956  {}
1957 
1958 
1959  template<class G>
1960  inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1961  {
1962  if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
1963  // Would be a new connection
1964  Counter::increment();
1965  else{
1966  Counter::increment();
1967  Counter::increment();
1968  }
1969  }
1970 
1971  template<class G>
1972  inline double Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
1973  {
1974  ConnectivityCounter counter(connected_, aggregates);
1975  double noNeighbours=visitNeighbours(*graph_, vertex, counter);
1976  return (double)counter.value()/noNeighbours;
1977  }
1978 
1979  template<class G>
1980  inline Aggregator<G>::DependencyCounter::DependencyCounter()
1981  : Counter()
1982  {}
1983 
1984  template<class G>
1985  inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1986  {
1987  if(edge.properties().depends())
1988  Counter::increment();
1989  if(edge.properties().influences())
1990  Counter::increment();
1991  }
1992 
1993  template<class G>
1994  int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
1995  {
1996  return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
1997  }
1998 
1999  template<class G>
2000  std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
2001  const AggregateDescriptor& aggregate,
2002  const AggregatesMap<Vertex>& aggregates) const
2003  {
2004  DependencyCounter unused, aggregated;
2005  typedef AggregateVisitor<DependencyCounter> Counter;
2006  typedef std::tuple<Counter,Counter> CounterTuple;
2007  CombinedFunctor<CounterTuple> visitors(CounterTuple(Counter(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), Counter(aggregates, aggregate, aggregated)));
2008  visitNeighbours(*graph_, vertex, visitors);
2009  return std::make_pair(unused.value(), aggregated.value());
2010  }
2011 
2012 
2013  template<class G>
2014  int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
2015  {
2016  DependencyCounter counter;
2017  visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
2018  return counter.value();
2019  }
2020 
2021  template<class G>
2022  std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
2023  {
2024  return 0;
2025  typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
2026  VertexList vlist;
2027  typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
2028  return aggregates.template breadthFirstSearch<true,true>(vertex,
2029  aggregate_->id(), *graph_,
2030  vlist, dummy, dummy, visitedMap);
2031  }
2032 
2033  template<class G>
2034  inline Aggregator<G>::FrontMarker::FrontMarker(std::vector<Vertex>& front, MatrixGraph& graph)
2035  : front_(front), graph_(graph)
2036  {}
2037 
2038  template<class G>
2039  inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
2040  {
2041  Vertex target = edge.target();
2042 
2043  if(!graph_.getVertexProperties(target).front()) {
2044  front_.push_back(target);
2045  graph_.getVertexProperties(target).setFront();
2046  }
2047  }
2048 
2049  template<class G>
2050  inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
2051  {
2052  // Todo
2053  Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
2054  return true;
2055  //Situation 1: front node depends on two nodes. Then these
2056  // have to be strongly connected to each other
2057 
2058  // Iterate over all all neighbours of front node
2059  typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2060  Iterator vend = graph_->endEdges(vertex);
2061  for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge) {
2062  // if(edge.properties().depends() && !edge.properties().influences()
2063  if(edge.properties().isStrong()
2064  && aggregates[edge.target()]==aggregate)
2065  {
2066  // Search for another link to the aggregate
2067  Iterator edge1 = edge;
2068  for(++edge1; edge1 != vend; ++edge1) {
2069  //if(edge1.properties().depends() && !edge1.properties().influences()
2070  if(edge1.properties().isStrong()
2071  && aggregates[edge.target()]==aggregate)
2072  {
2073  //Search for an edge connecting the two vertices that is
2074  //strong
2075  bool found=false;
2076  Iterator v2end = graph_->endEdges(edge.target());
2077  for(Iterator edge2 = graph_->beginEdges(edge.target()); edge2 != v2end; ++edge2) {
2078  if(edge2.target()==edge1.target() &&
2079  edge2.properties().isStrong()) {
2080  found =true;
2081  break;
2082  }
2083  }
2084  if(found)
2085  {
2086  return true;
2087  }
2088  }
2089  }
2090  }
2091  }
2092 
2093  // Situation 2: cluster node depends on front node and other cluster node
2095  vend = graph_->endEdges(vertex);
2096  for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge) {
2097  //if(!edge.properties().depends() && edge.properties().influences()
2098  if(edge.properties().isStrong()
2099  && aggregates[edge.target()]==aggregate)
2100  {
2101  // Search for a link from target that stays within the aggregate
2102  Iterator v1end = graph_->endEdges(edge.target());
2103 
2104  for(Iterator edge1=graph_->beginEdges(edge.target()); edge1 != v1end; ++edge1) {
2105  //if(edge1.properties().depends() && !edge1.properties().influences()
2106  if(edge1.properties().isStrong()
2107  && aggregates[edge1.target()]==aggregate)
2108  {
2109  bool found=false;
2110  // Check if front node is also connected to this one
2111  Iterator v2end = graph_->endEdges(vertex);
2112  for(Iterator edge2 = graph_->beginEdges(vertex); edge2 != v2end; ++edge2) {
2113  if(edge2.target()==edge1.target()) {
2114  if(edge2.properties().isStrong())
2115  found=true;
2116  break;
2117  }
2118  }
2119  if(found)
2120  {
2121  return true;
2122  }
2123  }
2124  }
2125  }
2126  }
2127  return false;
2128  }
2129 
2130  template<class G>
2131  void Aggregator<G>::unmarkFront()
2132  {
2133  typedef typename std::vector<Vertex>::const_iterator Iterator;
2134 
2135  for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
2136  graph_->getVertexProperties(*vertex).resetFront();
2137 
2138  front_.clear();
2139  }
2140 
2141  template<class G>
2142  inline void
2143  Aggregator<G>::nonisoNeighbourAggregate(const Vertex& vertex,
2144  const AggregatesMap<Vertex>& aggregates,
2145  SLList<Vertex>& neighbours) const
2146  {
2147  typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2148  Iterator end=graph_->beginEdges(vertex);
2149  neighbours.clear();
2150 
2151  for(Iterator edge=graph_->beginEdges(vertex); edge!=end; ++edge)
2152  {
2153  if(aggregates[edge.target()]!=AggregatesMap<Vertex>::UNAGGREGATED && graph_->getVertexProperties(edge.target()).isolated())
2154  neighbours.push_back(aggregates[edge.target()]);
2155  }
2156  }
2157 
2158  template<class G>
2159  inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
2160  {
2161  typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2162 
2163  Iterator end = graph_->endEdges(vertex);
2164  for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge) {
2165  if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
2166  graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()) {
2167  if( graph_->getVertexProperties(vertex).isolated() ||
2168  ((edge.properties().depends() || edge.properties().influences())
2169  && admissible(vertex, aggregates[edge.target()], aggregates)))
2170  return edge.target();
2171  }
2172  }
2174  }
2175 
2176  template<class G>
2177  Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph)
2178  : Counter(), graph_(graph)
2179  {}
2180 
2181  template<class G>
2182  void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
2183  {
2184  if(graph_.getVertexProperties(edge.target()).front())
2185  Counter::increment();
2186  }
2187 
2188  template<class G>
2189  int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
2190  {
2191  FrontNeighbourCounter counter(*graph_);
2192  visitNeighbours(*graph_, vertex, counter);
2193  return counter.value();
2194  }
2195  template<class G>
2196  inline bool Aggregator<G>::connected(const Vertex& vertex,
2197  const AggregateDescriptor& aggregate,
2198  const AggregatesMap<Vertex>& aggregates) const
2199  {
2200  typedef typename G::ConstEdgeIterator iterator;
2201  const iterator end = graph_->endEdges(vertex);
2202  for(iterator edge = graph_->beginEdges(vertex); edge != end; ++edge)
2203  if(aggregates[edge.target()]==aggregate)
2204  return true;
2205  return false;
2206  }
2207  template<class G>
2208  inline bool Aggregator<G>::connected(const Vertex& vertex,
2209  const SLList<AggregateDescriptor>& aggregateList,
2210  const AggregatesMap<Vertex>& aggregates) const
2211  {
2212  typedef typename SLList<AggregateDescriptor>::const_iterator Iter;
2213  for(Iter i=aggregateList.begin(); i!=aggregateList.end(); ++i)
2214  if(connected(vertex, *i, aggregates))
2215  return true;
2216  return false;
2217  }
2218 
2219  template<class G>
2220  template<class C>
2221  void Aggregator<G>::growIsolatedAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
2222  {
2223  SLList<Vertex> connectedAggregates;
2224  nonisoNeighbourAggregate(seed, aggregates,connectedAggregates);
2225 
2226  while(aggregate_->size()< c.minAggregateSize() && aggregate_->connectSize() < c.maxConnectivity()) {
2227  double maxCon=-1;
2228  std::size_t maxFrontNeighbours=0;
2229 
2231 
2232  typedef typename std::vector<Vertex>::const_iterator Iterator;
2233 
2234  for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2235  if(distance(*vertex, aggregates)>c.maxDistance())
2236  continue; // distance of proposes aggregate too big
2237 
2238  if(connectedAggregates.size()>0) {
2239  // there is already a neighbour cluster
2240  // front node must be connected to same neighbour cluster
2241 
2242  if(!connected(*vertex, connectedAggregates, aggregates))
2243  continue;
2244  }
2245 
2246  double con = connectivity(*vertex, aggregates);
2247 
2248  if(con == maxCon) {
2249  std::size_t frontNeighbours = noFrontNeighbours(*vertex);
2250 
2251  if(frontNeighbours >= maxFrontNeighbours) {
2252  maxFrontNeighbours = frontNeighbours;
2253  candidate = *vertex;
2254  }
2255  }else if(con > maxCon) {
2256  maxCon = con;
2257  maxFrontNeighbours = noFrontNeighbours(*vertex);
2258  candidate = *vertex;
2259  }
2260  }
2261 
2263  break;
2264 
2265  aggregate_->add(candidate);
2266  }
2267  }
2268 
2269  template<class G>
2270  template<class C>
2271  void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
2272  {
2273  using std::min;
2274 
2275  std::size_t distance_ =0;
2276  while(aggregate_->size() < c.minAggregateSize()&& distance_<c.maxDistance()) {
2277  int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1;
2278  double maxCon=-1;
2279 
2280  std::vector<Vertex> candidates;
2281  candidates.reserve(30);
2282 
2283  typedef typename std::vector<Vertex>::const_iterator Iterator;
2284 
2285  for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2286  // Only nonisolated nodes are considered
2287  if(graph_->getVertexProperties(*vertex).isolated())
2288  continue;
2289 
2290  int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
2291 
2292  /* The case of two way connections. */
2293  if( maxTwoCons == twoWayCons && twoWayCons > 0) {
2294  double con = connectivity(*vertex, aggregates);
2295 
2296  if(con == maxCon) {
2297  int neighbours = noFrontNeighbours(*vertex);
2298 
2299  if(neighbours > maxNeighbours) {
2300  maxNeighbours = neighbours;
2301  candidates.clear();
2302  candidates.push_back(*vertex);
2303  }else{
2304  candidates.push_back(*vertex);
2305  }
2306  }else if( con > maxCon) {
2307  maxCon = con;
2308  maxNeighbours = noFrontNeighbours(*vertex);
2309  candidates.clear();
2310  candidates.push_back(*vertex);
2311  }
2312  }else if(twoWayCons > maxTwoCons) {
2313  maxTwoCons = twoWayCons;
2314  maxCon = connectivity(*vertex, aggregates);
2315  maxNeighbours = noFrontNeighbours(*vertex);
2316  candidates.clear();
2317  candidates.push_back(*vertex);
2318 
2319  // two way connections precede
2320  maxOneCons = std::numeric_limits<int>::max();
2321  }
2322 
2323  if(twoWayCons > 0)
2324  {
2325  continue; // THis is a two-way node, skip tests for one way nodes
2326  }
2327 
2328  /* The one way case */
2329  int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
2330 
2331  if(oneWayCons==0)
2332  continue; // No strong connections, skip the tests.
2333 
2334  if(!admissible(*vertex, aggregate_->id(), aggregates))
2335  continue;
2336 
2337  if( maxOneCons == oneWayCons && oneWayCons > 0) {
2338  double con = connectivity(*vertex, aggregates);
2339 
2340  if(con == maxCon) {
2341  int neighbours = noFrontNeighbours(*vertex);
2342 
2343  if(neighbours > maxNeighbours) {
2344  maxNeighbours = neighbours;
2345  candidates.clear();
2346  candidates.push_back(*vertex);
2347  }else{
2348  if(neighbours==maxNeighbours)
2349  {
2350  candidates.push_back(*vertex);
2351  }
2352  }
2353  }else if( con > maxCon) {
2354  maxCon = con;
2355  maxNeighbours = noFrontNeighbours(*vertex);
2356  candidates.clear();
2357  candidates.push_back(*vertex);
2358  }
2359  }else if(oneWayCons > maxOneCons) {
2360  maxOneCons = oneWayCons;
2361  maxCon = connectivity(*vertex, aggregates);
2362  maxNeighbours = noFrontNeighbours(*vertex);
2363  candidates.clear();
2364  candidates.push_back(*vertex);
2365  }
2366  }
2367 
2368 
2369  if(!candidates.size())
2370  break; // No more candidates found
2371  distance_=distance(seed, aggregates);
2372  candidates.resize(min(candidates.size(), c.maxAggregateSize()-
2373  aggregate_->size()));
2374  aggregate_->add(candidates);
2375  }
2376  }
2377 
2378  template<typename V>
2379  template<typename M, typename G, typename C>
2380  std::tuple<int,int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion,
2381  bool finestLevel)
2382  {
2383  Aggregator<G> aggregator;
2384  return aggregator.build(matrix, graph, *this, criterion, finestLevel);
2385  }
2386 
2387  template<class G>
2388  template<class M, class C>
2389  std::tuple<int,int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c,
2390  bool finestLevel)
2391  {
2392  using std::max;
2393  using std::min;
2394  // Stack for fast vertex access
2395  Stack stack_(graph, *this, aggregates);
2396 
2397  graph_ = &graph;
2398 
2399  aggregate_ = new Aggregate<G,VertexSet>(graph, aggregates, connected_, front_);
2400 
2401  Timer watch;
2402  watch.reset();
2403 
2404  buildDependency(graph, m, c, finestLevel);
2405 
2406  dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
2407  int noAggregates, conAggregates, isoAggregates, oneAggregates;
2408  std::size_t maxA=0, minA=1000000, avg=0;
2409  int skippedAggregates;
2410  noAggregates = conAggregates = isoAggregates = oneAggregates =
2411  skippedAggregates = 0;
2412 
2413  while(true) {
2414  Vertex seed = stack_.pop();
2415 
2416  if(seed == Stack::NullEntry)
2417  // No more unaggregated vertices. We are finished!
2418  break;
2419 
2420  // Debugging output
2421  if((noAggregates+1)%10000 == 0)
2422  Dune::dverb<<"c";
2423  unmarkFront();
2424 
2425  if(graph.getVertexProperties(seed).excludedBorder()) {
2426  aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
2427  ++skippedAggregates;
2428  continue;
2429  }
2430 
2431  if(graph.getVertexProperties(seed).isolated()) {
2432  if(c.skipIsolated()) {
2433  // isolated vertices are not aggregated but skipped on the coarser levels.
2434  aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
2435  ++skippedAggregates;
2436  // skip rest as no agglomeration is done.
2437  continue;
2438  }else{
2439  aggregate_->seed(seed);
2440  growIsolatedAggregate(seed, aggregates, c);
2441  }
2442  }else{
2443  aggregate_->seed(seed);
2444  growAggregate(seed, aggregates, c);
2445  }
2446 
2447  /* The rounding step. */
2448  while(!(graph.getVertexProperties(seed).isolated()) && aggregate_->size() < c.maxAggregateSize()) {
2449 
2450  std::vector<Vertex> candidates;
2451  candidates.reserve(30);
2452 
2453  typedef typename std::vector<Vertex>::const_iterator Iterator;
2454 
2455  for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2456 
2457  if(graph.getVertexProperties(*vertex).isolated())
2458  continue; // No isolated nodes here
2459 
2460  if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 &&
2461  (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 ||
2462  !admissible( *vertex, aggregate_->id(), aggregates) ))
2463  continue;
2464 
2465  std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
2466  aggregates);
2467 
2468  //if(aggregateNeighbours(*vertex, aggregate_->id(), aggregates) <= unusedNeighbours(*vertex, aggregates))
2469  // continue;
2470 
2471  if(neighbourPair.first >= neighbourPair.second)
2472  continue;
2473 
2474  if(distance(*vertex, aggregates) > c.maxDistance())
2475  continue; // Distance too far
2476  candidates.push_back(*vertex);
2477  break;
2478  }
2479 
2480  if(!candidates.size()) break; // no more candidates found.
2481 
2482  candidates.resize(min(candidates.size(), c.maxAggregateSize()-
2483  aggregate_->size()));
2484  aggregate_->add(candidates);
2485 
2486  }
2487 
2488  // try to merge aggregates consisting of only one nonisolated vertex with other aggregates
2489  if(aggregate_->size()==1 && c.maxAggregateSize()>1) {
2490  if(!graph.getVertexProperties(seed).isolated()) {
2491  Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
2492 
2493  if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED) {
2494  // assign vertex to the neighbouring cluster
2495  aggregates[seed] = aggregates[mergedNeighbour];
2496  aggregate_->invalidate();
2497  }else{
2498  ++avg;
2499  minA=min(minA,static_cast<std::size_t>(1));
2500  maxA=max(maxA,static_cast<std::size_t>(1));
2501  ++oneAggregates;
2502  ++conAggregates;
2503  }
2504  }else{
2505  ++avg;
2506  minA=min(minA,static_cast<std::size_t>(1));
2507  maxA=max(maxA,static_cast<std::size_t>(1));
2508  ++oneAggregates;
2509  ++isoAggregates;
2510  }
2511  ++avg;
2512  }else{
2513  avg+=aggregate_->size();
2514  minA=min(minA,aggregate_->size());
2515  maxA=max(maxA,aggregate_->size());
2516  if(graph.getVertexProperties(seed).isolated())
2517  ++isoAggregates;
2518  else
2519  ++conAggregates;
2520  }
2521 
2522  }
2523 
2524  Dune::dinfo<<"connected aggregates: "<<conAggregates;
2525  Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
2526  if(conAggregates+isoAggregates>0)
2527  Dune::dinfo<<" one node aggregates: "<<oneAggregates<<" min size="
2528  <<minA<<" max size="<<maxA
2529  <<" avg="<<avg/(conAggregates+isoAggregates)<<std::endl;
2530 
2531  delete aggregate_;
2532  return std::make_tuple(conAggregates+isoAggregates,isoAggregates,
2533  oneAggregates,skippedAggregates);
2534  }
2535 
2536 
2537  template<class G>
2538  Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
2539  const AggregatesMap<Vertex>& aggregates)
2540  : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), begin_(graph.begin()), end_(graph.end())
2541  {
2542  //vals_ = new Vertex[N];
2543  }
2544 
2545  template<class G>
2546  Aggregator<G>::Stack::~Stack()
2547  {
2548  //Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
2549  //delete[] vals_;
2550  }
2551 
2552  template<class G>
2553  const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry
2555 
2556  template<class G>
2557  inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
2558  {
2559  for(; begin_!=end_ && aggregates_[*begin_] != AggregatesMap<Vertex>::UNAGGREGATED; ++begin_) ;
2560 
2561  if(begin_!=end_)
2562  {
2563  typename G::VertexDescriptor current=*begin_;
2564  ++begin_;
2565  return current;
2566  }else
2567  return NullEntry;
2568  }
2569 
2570 #endif // DOXYGEN
2571 
2572  template<class V>
2573  void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m, std::ostream& os)
2574  {
2575  using std::max;
2576 
2577  std::ios_base::fmtflags oldOpts=os.flags();
2578 
2579  os.setf(std::ios_base::right, std::ios_base::adjustfield);
2580 
2581  V maxVal=0;
2582  int width=1;
2583 
2584  for(int i=0; i< n*m; i++)
2585  maxVal=max(maxVal, aggregates[i]);
2586 
2587  for(int i=10; i < 1000000; i*=10)
2588  if(maxVal/i>0)
2589  width++;
2590  else
2591  break;
2592 
2593  for(int j=0, entry=0; j < m; j++) {
2594  for(int i=0; i<n; i++, entry++) {
2595  os.width(width);
2596  os<<aggregates[entry]<<" ";
2597  }
2598 
2599  os<<std::endl;
2600  }
2601  os<<std::endl;
2602  os.flags(oldOpts);
2603  }
2604 
2605 
2606  } // namespace Amg
2607 
2608 } // namespace Dune
2609 
2610 
2611 #endif
A class for temporarily storing the vertices of an aggregate in.
Definition: aggregates.hh:776
A Dummy visitor that does nothing for each visited edge.
Definition: aggregates.hh:594
Class providing information about the mapping of the vertices onto aggregates.
Definition: aggregates.hh:556
Base class of all aggregation criterions.
Definition: aggregates.hh:48
Class for building the aggregates.
Definition: aggregates.hh:907
Dependency policy for symmetric matrices.
Definition: aggregates.hh:252
Norm that uses only the [N][N] entry of the block to determine couplings.
Definition: aggregates.hh:375
Norm that uses only the [0][0] entry of the block to determine couplings.
Definition: aggregates.hh:451
Iterator over all edges starting from a vertex.
Definition: graph.hh:93
The vertex iterator type of the graph.
Definition: graph.hh:207
The (undirected) graph of a matrix.
Definition: graph.hh:49
M::size_type VertexDescriptor
The vertex descriptor.
Definition: graph.hh:71
EdgeIteratorT< const MatrixGraph< Matrix > > ConstEdgeIterator
The constant edge iterator type.
Definition: graph.hh:296
All parameters for AMG.
Definition: parameters.hh:391
Criterion taking advantage of symmetric matrices.
Definition: aggregates.hh:515
Dependency policy for symmetric matrices.
Definition: aggregates.hh:313
Dependency policy for symmetric matrices.
Definition: aggregates.hh:133
Criterion suitable for unsymmetric matrices.
Definition: aggregates.hh:535
derive error class from the base class in common
Definition: istlexception.hh:16
A generic dynamic dense matrix.
Definition: matrix.hh:558
typename Imp::BlockTraits< T >::field_type field_type
Export the type representing the underlying field.
Definition: matrix.hh:562
row_type::const_iterator ConstColIterator
Const iterator for the entries of each row.
Definition: matrix.hh:586
MatrixImp::DenseMatrixBase< T, A >::window_type row_type
The type implementing a matrix row.
Definition: matrix.hh:571
An allocator managing a pool of objects for reuse.
Definition: poolallocator.hh:223
A single linked list.
Definition: sllist.hh:42
Type traits to determine the type of reals (when working with complex numbers)
Provides classes for building the matrix graph.
SLListConstIterator< T, A > const_iterator
The constant iterator of the list.
Definition: sllist.hh:72
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentionally unused function parameters with.
Definition: unused.hh:25
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
constexpr GeometryType vertex
GeometryType representing a vertex.
Definition: type.hh:797
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:272
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:153
std::size_t breadthFirstSearch(const VertexDescriptor &start, const AggregateDescriptor &aggregate, const G &graph, L &visited, F1 &aggregateVisitor, F2 &nonAggregateVisitor, VM &visitedMap) const
Breadth first search within an aggregate.
PoolAllocator< VertexDescriptor, 100 > Allocator
The allocator we use for our lists and the set.
Definition: aggregates.hh:582
int id()
Get the id identifying the aggregate.
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:301
MatrixGraph::VertexDescriptor Vertex
The vertex identifier.
Definition: aggregates.hh:918
AggregationCriterion()
Constructor.
Definition: aggregates.hh:65
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:356
auto operator()(const M &m, typename std::enable_if_t< Dune::IsNumber< M >::value > *sfinae=nullptr) const
Compute the norm of a scalar.
Definition: aggregates.hh:402
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:257
G MatrixGraph
The matrix graph type used.
Definition: aggregates.hh:913
FieldTraits< typename M::field_type >::real_type operator()(const M &m) const
compute the norm of a matrix.
Definition: aggregates.hh:486
const AggregateDescriptor & operator[](const VertexDescriptor &v) const
Get the aggregate a vertex belongs to.
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:362
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:318
real_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:186
N Norm
The norm to use for examining the matrix entries.
Definition: aggregates.hh:262
std::tuple< int, int, int, int > build(const M &m, G &graph, AggregatesMap< Vertex > &aggregates, const C &c, bool finestLevel)
Build the aggregates.
int row_
index of the currently evaluated row.
Definition: aggregates.hh:184
FrontNeighbourCounter(const MatrixGraph &front)
Constructor.
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:328
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:295
AggregateVisitor(const AggregatesMap< Vertex > &aggregates, const AggregateDescriptor &aggregate, Visitor &visitor)
Constructor.
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:333
~AggregatesMap()
Destructor.
Matrix::field_type field_type
The current max value.
Definition: aggregates.hh:178
void decrement()
Decrement counter.
Aggregate(MatrixGraph &graph, AggregatesMap< Vertex > &aggregates, VertexSet &connectivity, std::vector< Vertex > &front_)
Constructor.
V Visitor
The type of the adapted visitor.
Definition: aggregates.hh:1062
std::size_t * SphereMap
Type of the mapping of aggregate members onto distance spheres.
Definition: aggregates.hh:807
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:267
VertexSet::size_type connectSize()
Get tne number of connections to other aggregates.
FieldTraits< typename M::field_type >::real_type operator()(const M &m) const
compute the norm of a matrix.
Definition: aggregates.hh:502
N Norm
The norm to use for examining the matrix entries.
Definition: aggregates.hh:323
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:182
VertexSet::const_iterator const_iterator
Const iterator over a vertex list.
Definition: aggregates.hh:802
MatrixGraph::VertexDescriptor AggregateDescriptor
The type of the aggregate descriptor.
Definition: aggregates.hh:921
real_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:366
~Aggregator()
Destructor.
AggregateDescriptor & operator[](const VertexDescriptor &v)
Get the aggregate a vertex belongs to.
void add(const Vertex &vertex)
Add a vertex to the aggregate.
T DependencyPolicy
The policy for calculating the dependency graph.
Definition: aggregates.hh:54
Aggregator()
Constructor.
void operator()(const typename MatrixGraph::ConstEdgeIterator &edge)
Examine an edge.
FrontMarker(std::vector< Vertex > &front, MatrixGraph &graph)
Constructor.
int visitNeighbours(const G &graph, const typename G::VertexDescriptor &vertex, V &visitor)
Visit all neighbour vertices of a vertex in a graph.
void setDefaultValuesIsotropic(std::size_t dim, std::size_t diameter=2)
Sets reasonable default values for an isotropic problem.
Definition: aggregates.hh:81
V AggregateDescriptor
The aggregate descriptor type.
Definition: aggregates.hh:576
static const V ISOLATED
Identifier of isolated vertices.
Definition: aggregates.hh:567
int row_
index of the currently evaluated row.
Definition: aggregates.hh:364
real_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:305
std::size_t noVertices() const
Get the number of vertices.
void setDefaultValuesAnisotropic(std::size_t dim, std::size_t diameter=2)
Sets reasonable default values for an aisotropic problem.
Definition: aggregates.hh:104
AggregatesMap(std::size_t noVertices)
Constructs with allocating memory.
FieldTraits< typename M::field_type >::real_type operator()(const M &m, typename std::enable_if_t<!Dune::IsNumber< M >::value > *sfinae=nullptr) const
compute the norm of a matrix.
Definition: aggregates.hh:386
Matrix::field_type field_type
The current max value.
Definition: aggregates.hh:358
AggregatesMap()
Constructs without allocating memory.
int value()
Access the current count.
std::tuple< int, int, int, int > buildAggregates(const M &matrix, G &graph, const C &criterion, bool finestLevel)
Build the aggregates.
SLList< VertexDescriptor, Allocator > VertexList
The type of a single linked list of vertex descriptors.
Definition: aggregates.hh:588
ConnectivityCounter(const VertexSet &connected, const AggregatesMap< Vertex > &aggregates)
Constructor.
VertexSet::size_type size()
Get the size of the aggregate.
const_iterator end() const
get an iterator over the vertices of the aggregate.
FieldTraits< typename M::field_type >::real_type operator()(const M &m) const
compute the norm of a matrix.
Definition: aggregates.hh:469
int row_
index of the currently evaluated row.
Definition: aggregates.hh:303
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:138
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:176
S VertexSet
The type of a single linked list of vertex descriptors.
Definition: aggregates.hh:799
static const V UNAGGREGATED
Identifier of not yet aggregated vertices.
Definition: aggregates.hh:562
std::size_t breadthFirstSearch(const VertexDescriptor &start, const AggregateDescriptor &aggregate, const G &graph, F &aggregateVisitor, VM &visitedMap) const
Breadth first search within an aggregate.
Matrix::field_type field_type
The current max value.
Definition: aggregates.hh:297
void allocate(std::size_t noVertices)
Allocate memory for holding the information.
N Norm
The norm to use for examining the matrix entries.
Definition: aggregates.hh:143
void reconstruct(const Vertex &vertex)
Reconstruct the aggregat from an seed node.
const_iterator begin() const
get an iterator over the vertices of the aggregate.
MatrixGraph::VertexDescriptor Vertex
The vertex descriptor type.
Definition: aggregates.hh:787
void seed(const Vertex &vertex)
Initialize the aggregate with one vertex.
void clear()
Clear the aggregate.
void free()
Free the allocated memory.
void increment()
Increment counter.
void buildDependency(G &graph, const typename C::Matrix &matrix, C criterion, bool finestLevel)
Build the dependency of the matrix graph.
V VertexDescriptor
The vertex descriptor type.
Definition: aggregates.hh:571
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:148
PoolAllocator< Vertex, 100 > Allocator
The allocator we use for our lists and the set.
Definition: aggregates.hh:793
auto min(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::min()
Definition: defaults.hh:87
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:79
DVVerbType dvverb(std::cout)
stream for very verbose output.
Definition: stdstreams.hh:93
DInfoType dinfo(std::cout)
Stream for informative output.
Definition: stdstreams.hh:138
DVerbType dverb(std::cout)
Singleton of verbose debug stream.
Definition: stdstreams.hh:114
constexpr Front front
PartitionSet for the front partition.
Definition: partitionset.hh:279
Dune namespace.
Definition: alignedallocator.hh:14
Parameter classes for customizing AMG.
An stl-compliant pool allocator.
Provides classes for handling internal properties in a graph.
Implements a scalar matrix view wrapper around an existing scalar.
Implements a singly linked list together with the necessary iterators.
Standard Dune debug streams.
Functor using the row sum (infinity) norm to determine strong couplings.
Definition: aggregates.hh:459
Whether this type acts as a scalar in the context of (hierarchically blocked) containers.
Definition: typetraits.hh:163
A simple timing class.
Definition of the DUNE_UNUSED macro for the case that config.h is not available.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)