Dune Core Modules (2.9.0)

aggregates.hh
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) DUNE Project contributors, see file LICENSE.md in module root
2 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4 // vi: set et ts=4 sw=2 sts=2:
5 #ifndef DUNE_AMG_AGGREGATES_HH
6 #define DUNE_AMG_AGGREGATES_HH
7 
8 
9 #include "parameters.hh"
10 #include "graph.hh"
11 #include "properties.hh"
12 #include "combinedfunctor.hh"
13 
14 #include <dune/common/timer.hh>
17 #include <dune/common/sllist.hh>
18 #include <dune/common/ftraits.hh>
20 
21 #include <utility>
22 #include <set>
23 #include <algorithm>
24 #include <complex>
25 #include <limits>
26 #include <ostream>
27 #include <tuple>
28 
29 namespace Dune
30 {
31  namespace Amg
32  {
33 
47  template<class T>
48  class AggregationCriterion : public T
49  {
50 
51  public:
55  typedef T DependencyPolicy;
56 
67  : T()
68  {}
69 
70  AggregationCriterion(const Parameters& parms)
71  : T(parms)
72  {}
82  void setDefaultValuesIsotropic(std::size_t dim, std::size_t diameter=2)
83  {
84  this->setMaxDistance(diameter-1);
85  std::size_t csize=1;
86 
87  for(; dim>0; dim--) {
88  csize*=diameter;
89  this->setMaxDistance(this->maxDistance()+diameter-1);
90  }
91  this->setMinAggregateSize(csize);
92  this->setMaxAggregateSize(static_cast<std::size_t>(csize*1.5));
93  }
94 
105  void setDefaultValuesAnisotropic(std::size_t dim,std::size_t diameter=2)
106  {
107  setDefaultValuesIsotropic(dim, diameter);
108  this->setMaxDistance(this->maxDistance()+dim-1);
109  }
110  };
111 
112  template<class T>
113  std::ostream& operator<<(std::ostream& os, const AggregationCriterion<T>& criterion)
114  {
115  os<<"{ maxdistance="<<criterion.maxDistance()<<" minAggregateSize="
116  <<criterion.minAggregateSize()<< " maxAggregateSize="<<criterion.maxAggregateSize()
117  <<" connectivity="<<criterion.maxConnectivity()<<" debugLevel="<<criterion.debugLevel()<<"}";
118  return os;
119  }
120 
132  template<class M, class N>
134  {
135  public:
139  typedef M Matrix;
140 
144  typedef N Norm;
145 
149  typedef typename Matrix::row_type Row;
150 
155 
156  void init(const Matrix* matrix);
157 
158  void initRow(const Row& row, int index);
159 
160  void examine(const ColIter& col);
161 
162  template<class G>
163  void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
164 
165  bool isIsolated();
166 
167 
169  : Parameters(parms)
170  {}
172  : Parameters()
173  {}
174 
175  protected:
177  const Matrix* matrix_;
179  typedef typename Matrix::field_type field_type;
180  typedef typename FieldTraits<field_type>::real_type real_type;
181  real_type maxValue_;
185  int row_;
187  real_type diagonal_;
188  std::vector<real_type> vals_;
189  typename std::vector<real_type>::iterator valIter_;
190 
191  };
192 
193 
194  template<class M, class N>
195  inline void SymmetricMatrixDependency<M,N>::init(const Matrix* matrix)
196  {
197  matrix_ = matrix;
198  }
199 
200  template<class M, class N>
201  inline void SymmetricMatrixDependency<M,N>::initRow(const Row& row, int index)
202  {
203  using std::min;
204  vals_.assign(row.size(), 0.0);
205  assert(vals_.size()==row.size());
206  valIter_=vals_.begin();
207 
209  diagonal_=norm_(row[index]);
210  row_ = index;
211  }
212 
213  template<class M, class N>
214  inline void SymmetricMatrixDependency<M,N>::examine(const ColIter& col)
215  {
216  using std::max;
217  // skip positive offdiagonals if norm preserves sign of them.
218  real_type eij = norm_(*col);
219  if(!N::is_sign_preserving || eij<0) // || eji<0)
220  {
221  *valIter_ = eij/diagonal_*eij/norm_(matrix_->operator[](col.index())[col.index()]);
222  maxValue_ = max(maxValue_, *valIter_);
223  }else
224  *valIter_ =0;
225  ++valIter_;
226  }
227 
228  template<class M, class N>
229  template<class G>
230  inline void SymmetricMatrixDependency<M,N>::examine(G&, const typename G::EdgeIterator& edge, const ColIter&)
231  {
232  if(*valIter_ > alpha() * maxValue_) {
233  edge.properties().setDepends();
234  edge.properties().setInfluences();
235  }
236  ++valIter_;
237  }
238 
239  template<class M, class N>
240  inline bool SymmetricMatrixDependency<M,N>::isIsolated()
241  {
242  if(diagonal_==0)
243  DUNE_THROW(Dune::ISTLError, "No diagonal entry for row "<<row_<<".");
244  valIter_=vals_.begin();
245  return maxValue_ < beta();
246  }
247 
251  template<class M, class N>
252  class Dependency : public Parameters
253  {
254  public:
258  typedef M Matrix;
259 
263  typedef N Norm;
264 
268  typedef typename Matrix::row_type Row;
269 
274 
275  void init(const Matrix* matrix);
276 
277  void initRow(const Row& row, int index);
278 
279  void examine(const ColIter& col);
280 
281  template<class G>
282  void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
283 
284  bool isIsolated();
285 
286  Dependency(const Parameters& parms)
287  : Parameters(parms)
288  {}
289 
290  Dependency()
291  : Parameters()
292  {}
293 
294  protected:
296  const Matrix* matrix_;
298  typedef typename Matrix::field_type field_type;
299  typedef typename FieldTraits<field_type>::real_type real_type;
300  real_type maxValue_;
304  int row_;
306  real_type diagonal_;
307  };
308 
312  template<class M, class N>
314  {
315  public:
319  typedef M Matrix;
320 
324  typedef N Norm;
325 
329  typedef typename Matrix::row_type Row;
330 
335 
336  void init(const Matrix* matrix);
337 
338  void initRow(const Row& row, int index);
339 
340  void examine(const ColIter& col);
341 
342  template<class G>
343  void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
344 
345  bool isIsolated();
346 
347 
348  SymmetricDependency(const Parameters& parms)
349  : Parameters(parms)
350  {}
352  : Parameters()
353  {}
354 
355  protected:
357  const Matrix* matrix_;
359  typedef typename Matrix::field_type field_type;
360  typedef typename FieldTraits<field_type>::real_type real_type;
361  real_type maxValue_;
365  int row_;
367  real_type diagonal_;
368  private:
369  void initRow(const Row& row, int index, const std::true_type&);
370  void initRow(const Row& row, int index, const std::false_type&);
371  };
372 
377  template<int N>
378  class Diagonal
379  {
380  public:
381  enum { /* @brief We preserve the sign.*/
382  is_sign_preserving = true
383  };
384 
389  template<class M>
390  typename FieldTraits<typename M::field_type>::real_type operator()(const M& m,
391  [[maybe_unused]] typename std::enable_if_t<!Dune::IsNumber<M>::value>* sfinae = nullptr) const
392  {
393  typedef typename M::field_type field_type;
394  typedef typename FieldTraits<field_type>::real_type real_type;
395  static_assert( std::is_convertible<field_type, real_type >::value,
396  "use of diagonal norm in AMG not implemented for complex field_type");
397  return m[N][N];
398  // possible implementation for complex types: return signed_abs(m[N][N]);
399  }
400 
405  template<class M>
406  auto operator()(const M& m,
407  typename std::enable_if_t<Dune::IsNumber<M>::value>* sfinae = nullptr) const
408  {
409  typedef typename FieldTraits<M>::real_type real_type;
410  static_assert( std::is_convertible<M, real_type >::value,
411  "use of diagonal norm in AMG not implemented for complex field_type");
412  return m;
413  // possible implementation for complex types: return signed_abs(m[N][N]);
414  }
415 
416  private:
417 
419  template<typename T>
420  static T signed_abs(const T & v)
421  {
422  return v;
423  }
424 
426  template<typename T>
427  static T signed_abs(const std::complex<T> & v)
428  {
429  // return sign * abs_value
430  // in case of complex numbers this extends to using the csgn function to determine the sign
431  return csgn(v) * std::abs(v);
432  }
433 
435  template<typename T>
436  static T csgn(const T & v)
437  {
438  return (T(0) < v) - (v < T(0));
439  }
440 
442  template<typename T>
443  static T csgn(std::complex<T> a)
444  {
445  return csgn(a.real())+(a.real() == 0.0)*csgn(a.imag());
446  }
447 
448  };
449 
454  class FirstDiagonal : public Diagonal<0>
455  {};
456 
462  struct RowSum
463  {
464 
465  enum { /* @brief We preserve the sign.*/
466  is_sign_preserving = false
467  };
472  template<class M>
473  typename FieldTraits<typename M::field_type>::real_type operator()(const M& m) const
474  {
475  return m.infinity_norm();
476  }
477  };
478 
479  struct FrobeniusNorm
480  {
481 
482  enum { /* @brief We preserve the sign.*/
483  is_sign_preserving = false
484  };
489  template<class M>
490  typename FieldTraits<typename M::field_type>::real_type operator()(const M& m) const
491  {
492  return m.frobenius_norm();
493  }
494  };
495  struct AlwaysOneNorm
496  {
497 
498  enum { /* @brief We preserve the sign.*/
499  is_sign_preserving = false
500  };
505  template<class M>
506  typename FieldTraits<typename M::field_type>::real_type operator()(const M& m) const
507  {
508  return 1;
509  }
510  };
517  template<class M, class Norm>
518  class SymmetricCriterion : public AggregationCriterion<SymmetricDependency<M,Norm> >
519  {
520  public:
521  SymmetricCriterion(const Parameters& parms)
523  {}
525  {}
526  };
527 
528 
537  template<class M, class Norm>
538  class UnSymmetricCriterion : public AggregationCriterion<Dependency<M,Norm> >
539  {
540  public:
541  UnSymmetricCriterion(const Parameters& parms)
543  {}
545  {}
546  };
547  // forward declaration
548  template<class G> class Aggregator;
549 
550 
558  template<class V>
560  {
561  public:
562 
566  static const V UNAGGREGATED;
567 
571  static const V ISOLATED;
575  typedef V VertexDescriptor;
576 
581 
587 
593 
598  {
599  public:
600  template<class EdgeIterator>
601  void operator()([[maybe_unused]] const EdgeIterator& edge) const
602  {}
603  };
604 
605 
610 
616  AggregatesMap(std::size_t noVertices);
617 
622 
634  template<class M, class G, class C>
635  std::tuple<int,int,int,int> buildAggregates(const M& matrix, G& graph, const C& criterion,
636  bool finestLevel);
637 
655  template<bool reset, class G, class F, class VM>
656  std::size_t breadthFirstSearch(const VertexDescriptor& start,
657  const AggregateDescriptor& aggregate,
658  const G& graph,
659  F& aggregateVisitor,
660  VM& visitedMap) const;
661 
685  template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
686  std::size_t breadthFirstSearch(const VertexDescriptor& start,
687  const AggregateDescriptor& aggregate,
688  const G& graph, L& visited, F1& aggregateVisitor,
689  F2& nonAggregateVisitor,
690  VM& visitedMap) const;
691 
697  void allocate(std::size_t noVertices);
698 
702  std::size_t noVertices() const;
703 
707  void free();
708 
715 
722 
723  typedef const AggregateDescriptor* const_iterator;
724 
725  const_iterator begin() const
726  {
727  return aggregates_;
728  }
729 
730  const_iterator end() const
731  {
732  return aggregates_+noVertices();
733  }
734 
735  typedef AggregateDescriptor* iterator;
736 
737  iterator begin()
738  {
739  return aggregates_;
740  }
741 
742  iterator end()
743  {
744  return aggregates_+noVertices();
745  }
746  private:
748  AggregatesMap(const AggregatesMap<V>&) = delete;
750  AggregatesMap<V>& operator=(const AggregatesMap<V>&) = delete;
751 
755  AggregateDescriptor* aggregates_;
756 
760  std::size_t noVertices_;
761  };
762 
766  template<class G, class C>
767  void buildDependency(G& graph,
768  const typename C::Matrix& matrix,
769  C criterion,
770  bool finestLevel);
771 
776  template<class G, class S>
777  class Aggregate
778  {
779 
780  public:
781 
782  /***
783  * @brief The type of the matrix graph we work with.
784  */
785  typedef G MatrixGraph;
790 
796 
801  typedef S VertexSet;
802 
804  typedef typename VertexSet::const_iterator const_iterator;
805 
809  typedef std::size_t* SphereMap;
810 
819  Aggregate(MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
820  VertexSet& connectivity, std::vector<Vertex>& front_);
821 
822  void invalidate()
823  {
824  --id_;
825  }
826 
833  void reconstruct(const Vertex& vertex);
834 
838  void seed(const Vertex& vertex);
839 
843  void add(const Vertex& vertex);
844 
845  void add(std::vector<Vertex>& vertex);
849  void clear();
850 
854  typename VertexSet::size_type size();
858  typename VertexSet::size_type connectSize();
859 
863  int id();
864 
867 
870 
871  private:
875  VertexSet vertices_;
876 
881  int id_;
882 
886  MatrixGraph& graph_;
887 
891  AggregatesMap<Vertex>& aggregates_;
892 
896  VertexSet& connected_;
897 
901  std::vector<Vertex>& front_;
902  };
903 
907  template<class G>
909  {
910  public:
911 
915  typedef G MatrixGraph;
916 
921 
924 
929 
934 
951  template<class M, class C>
952  std::tuple<int,int,int,int> build(const M& m, G& graph,
953  AggregatesMap<Vertex>& aggregates, const C& c,
954  bool finestLevel);
955  private:
961 
966 
970  typedef std::set<Vertex,std::less<Vertex>,Allocator> VertexSet;
971 
975  typedef std::size_t* SphereMap;
976 
980  MatrixGraph* graph_;
981 
986 
990  std::vector<Vertex> front_;
991 
995  VertexSet connected_;
996 
1000  int size_;
1001 
1005  class Stack
1006  {
1007  public:
1008  static const Vertex NullEntry;
1009 
1010  Stack(const MatrixGraph& graph,
1011  const Aggregator<G>& aggregatesBuilder,
1012  const AggregatesMap<Vertex>& aggregates);
1013  ~Stack();
1014  Vertex pop();
1015  private:
1016  enum { N = 1300000 };
1017 
1019  const MatrixGraph& graph_;
1021  const Aggregator<G>& aggregatesBuilder_;
1023  const AggregatesMap<Vertex>& aggregates_;
1025  int size_;
1026  Vertex maxSize_;
1028  typename MatrixGraph::ConstVertexIterator begin_;
1029  typename MatrixGraph::ConstVertexIterator end_;
1030 
1032  Vertex* vals_;
1033 
1034  };
1035 
1036  friend class Stack;
1037 
1048  template<class V>
1049  void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate,
1050  const AggregatesMap<Vertex>& aggregates,
1051  V& visitor) const;
1052 
1057  template<class V>
1058  class AggregateVisitor
1059  {
1060  public:
1064  typedef V Visitor;
1072  AggregateVisitor(const AggregatesMap<Vertex>& aggregates, const AggregateDescriptor& aggregate,
1073  Visitor& visitor);
1074 
1081  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1082 
1083  private:
1085  const AggregatesMap<Vertex>& aggregates_;
1087  AggregateDescriptor aggregate_;
1089  Visitor* visitor_;
1090  };
1091 
1095  class Counter
1096  {
1097  public:
1101  int value();
1102 
1103  protected:
1105  void increment();
1107  void decrement();
1108 
1109  private:
1110  int count_;
1111  };
1112 
1113 
1118  class FrontNeighbourCounter : public Counter
1119  {
1120  public:
1126 
1127  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1128 
1129  private:
1130  const MatrixGraph& graph_;
1131  };
1132 
1137  int noFrontNeighbours(const Vertex& vertex) const;
1138 
1142  class TwoWayCounter : public Counter
1143  {
1144  public:
1145  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1146  };
1147 
1159  int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
1160  const AggregatesMap<Vertex>& aggregates) const;
1161 
1165  class OneWayCounter : public Counter
1166  {
1167  public:
1168  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1169  };
1170 
1182  int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
1183  const AggregatesMap<Vertex>& aggregates) const;
1184 
1191  class ConnectivityCounter : public Counter
1192  {
1193  public:
1200  ConnectivityCounter(const VertexSet& connected, const AggregatesMap<Vertex>& aggregates);
1201 
1202  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1203 
1204  private:
1206  const VertexSet& connected_;
1208  const AggregatesMap<Vertex>& aggregates_;
1209 
1210  };
1211 
1223  double connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1231  bool connected(const Vertex& vertex, const AggregateDescriptor& aggregate,
1232  const AggregatesMap<Vertex>& aggregates) const;
1233 
1241  bool connected(const Vertex& vertex, const SLList<AggregateDescriptor>& aggregateList,
1242  const AggregatesMap<Vertex>& aggregates) const;
1243 
1251  class DependencyCounter : public Counter
1252  {
1253  public:
1258 
1259  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1260  };
1261 
1268  class FrontMarker
1269  {
1270  public:
1277  FrontMarker(std::vector<Vertex>& front, MatrixGraph& graph);
1278 
1279  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1280 
1281  private:
1283  std::vector<Vertex>& front_;
1285  MatrixGraph& graph_;
1286  };
1287 
1291  void unmarkFront();
1292 
1307  int unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1308 
1322  std::pair<int,int> neighbours(const Vertex& vertex,
1323  const AggregateDescriptor& aggregate,
1324  const AggregatesMap<Vertex>& aggregates) const;
1341  int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
1342 
1350  bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
1351 
1359  std::size_t distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates);
1360 
1369  Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1370 
1379  void nonisoNeighbourAggregate(const Vertex& vertex,
1380  const AggregatesMap<Vertex>& aggregates,
1381  SLList<Vertex>& neighbours) const;
1382 
1390  template<class C>
1391  void growAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
1392  template<class C>
1393  void growIsolatedAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
1394  };
1395 
1396 #ifndef DOXYGEN
1397 
1398  template<class M, class N>
1399  inline void SymmetricDependency<M,N>::init(const Matrix* matrix)
1400  {
1401  matrix_ = matrix;
1402  }
1403 
1404  template<class M, class N>
1405  inline void SymmetricDependency<M,N>::initRow(const Row& row, int index)
1406  {
1407  initRow(row, index, std::is_convertible<field_type, real_type>());
1408  }
1409 
1410  template<class M, class N>
1411  inline void SymmetricDependency<M,N>::initRow(const Row& row, int index, const std::false_type&)
1412  {
1413  DUNE_THROW(InvalidStateException, "field_type needs to convertible to real_type");
1414  }
1415 
1416  template<class M, class N>
1417  inline void SymmetricDependency<M,N>::initRow([[maybe_unused]] const Row& row, int index, const std::true_type&)
1418  {
1419  using std::min;
1421  row_ = index;
1422  diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1423  }
1424 
1425  template<class M, class N>
1426  inline void SymmetricDependency<M,N>::examine(const ColIter& col)
1427  {
1428  using std::max;
1429  real_type eij = norm_(*col);
1430  typename Matrix::ConstColIterator opposite_entry =
1431  matrix_->operator[](col.index()).find(row_);
1432  if ( opposite_entry == matrix_->operator[](col.index()).end() )
1433  {
1434  // Consider this a weak connection we disregard.
1435  return;
1436  }
1437  real_type eji = norm_(*opposite_entry);
1438 
1439  // skip positive offdiagonals if norm preserves sign of them.
1440  if(!N::is_sign_preserving || eij<0 || eji<0)
1441  maxValue_ = max(maxValue_,
1442  eij /diagonal_ * eji/
1443  norm_(matrix_->operator[](col.index())[col.index()]));
1444  }
1445 
1446  template<class M, class N>
1447  template<class G>
1448  inline void SymmetricDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
1449  {
1450  real_type eij = norm_(*col);
1451  typename Matrix::ConstColIterator opposite_entry =
1452  matrix_->operator[](col.index()).find(row_);
1453 
1454  if ( opposite_entry == matrix_->operator[](col.index()).end() )
1455  {
1456  // Consider this as a weak connection we disregard.
1457  return;
1458  }
1459  real_type eji = norm_(*opposite_entry);
1460  // skip positve offdiagonals if norm preserves sign of them.
1461  if(!N::is_sign_preserving || (eij<0 || eji<0))
1462  if(eji / norm_(matrix_->operator[](edge.target())[edge.target()]) *
1463  eij/ diagonal_ > alpha() * maxValue_) {
1464  edge.properties().setDepends();
1465  edge.properties().setInfluences();
1466  typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
1467  other.setInfluences();
1468  other.setDepends();
1469  }
1470  }
1471 
1472  template<class M, class N>
1473  inline bool SymmetricDependency<M,N>::isIsolated()
1474  {
1475  return maxValue_ < beta();
1476  }
1477 
1478 
1479  template<class M, class N>
1480  inline void Dependency<M,N>::init(const Matrix* matrix)
1481  {
1482  matrix_ = matrix;
1483  }
1484 
1485  template<class M, class N>
1486  inline void Dependency<M,N>::initRow([[maybe_unused]] const Row& row, int index)
1487  {
1488  using std::min;
1490  row_ = index;
1491  diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1492  }
1493 
1494  template<class M, class N>
1495  inline void Dependency<M,N>::examine(const ColIter& col)
1496  {
1497  using std::max;
1498  maxValue_ = max(maxValue_, -norm_(*col));
1499  }
1500 
1501  template<class M, class N>
1502  template<class G>
1503  inline void Dependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
1504  {
1505  if(-norm_(*col) >= maxValue_ * alpha()) {
1506  edge.properties().setDepends();
1507  typedef typename G::EdgeDescriptor ED;
1508  ED e= graph.findEdge(edge.target(), edge.source());
1510  {
1511  typename G::EdgeProperties& other = graph.getEdgeProperties(e);
1512  other.setInfluences();
1513  }
1514  }
1515  }
1516 
1517  template<class M, class N>
1518  inline bool Dependency<M,N>::isIsolated()
1519  {
1520  return maxValue_ < beta() * diagonal_;
1521  }
1522 
1523  template<class G,class S>
1524  Aggregate<G,S>::Aggregate(MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
1525  VertexSet& connected, std::vector<Vertex>& front)
1526  : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
1527  connected_(connected), front_(front)
1528  {}
1529 
1530  template<class G,class S>
1532  {
1533  /*
1534  vertices_.push_back(vertex);
1535  typedef typename VertexList::const_iterator iterator;
1536  iterator begin = vertices_.begin();
1537  iterator end = vertices_.end();*/
1538  throw "Not yet implemented";
1539 
1540  // while(begin!=end){
1541  //for();
1542  // }
1543 
1544  }
1545 
1546  template<class G,class S>
1547  inline void Aggregate<G,S>::seed(const Vertex& vertex)
1548  {
1549  dvverb<<"Connected cleared"<<std::endl;
1550  connected_.clear();
1551  vertices_.clear();
1552  connected_.insert(vertex);
1553  dvverb << " Inserting "<<vertex<<" size="<<connected_.size();
1554  ++id_ ;
1555  add(vertex);
1556  }
1557 
1558 
1559  template<class G,class S>
1560  inline void Aggregate<G,S>::add(const Vertex& vertex)
1561  {
1562  vertices_.insert(vertex);
1563  aggregates_[vertex]=id_;
1564  if(front_.size())
1565  front_.erase(std::lower_bound(front_.begin(), front_.end(), vertex));
1566 
1567 
1568  typedef typename MatrixGraph::ConstEdgeIterator iterator;
1569  const iterator end = graph_.endEdges(vertex);
1570  for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge) {
1571  dvverb << " Inserting "<<aggregates_[edge.target()];
1572  connected_.insert(aggregates_[edge.target()]);
1573  dvverb <<" size="<<connected_.size();
1574  if(aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED &&
1575  !graph_.getVertexProperties(edge.target()).front())
1576  {
1577  front_.push_back(edge.target());
1578  graph_.getVertexProperties(edge.target()).setFront();
1579  }
1580  }
1581  dvverb <<std::endl;
1582  std::sort(front_.begin(), front_.end());
1583  }
1584 
1585  template<class G,class S>
1586  inline void Aggregate<G,S>::add(std::vector<Vertex>& vertices)
1587  {
1588 #ifndef NDEBUG
1589  std::size_t oldsize = vertices_.size();
1590 #endif
1591  typedef typename std::vector<Vertex>::iterator Iterator;
1592 
1593  typedef typename VertexSet::iterator SIterator;
1594 
1595  SIterator pos=vertices_.begin();
1596  std::vector<Vertex> newFront;
1597  newFront.reserve(front_.capacity());
1598 
1599  std::set_difference(front_.begin(), front_.end(), vertices.begin(), vertices.end(),
1600  std::back_inserter(newFront));
1601  front_=newFront;
1602 
1603  for(Iterator vertex=vertices.begin(); vertex != vertices.end(); ++vertex)
1604  {
1605  pos=vertices_.insert(pos,*vertex);
1606  vertices_.insert(*vertex);
1607  graph_.getVertexProperties(*vertex).resetFront(); // Not a front node any more.
1608  aggregates_[*vertex]=id_;
1609 
1610  typedef typename MatrixGraph::ConstEdgeIterator iterator;
1611  const iterator end = graph_.endEdges(*vertex);
1612  for(iterator edge = graph_.beginEdges(*vertex); edge != end; ++edge) {
1613  dvverb << " Inserting "<<aggregates_[edge.target()];
1614  connected_.insert(aggregates_[edge.target()]);
1615  if(aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED &&
1616  !graph_.getVertexProperties(edge.target()).front())
1617  {
1618  front_.push_back(edge.target());
1619  graph_.getVertexProperties(edge.target()).setFront();
1620  }
1621  dvverb <<" size="<<connected_.size();
1622  }
1623  dvverb <<std::endl;
1624  }
1625  std::sort(front_.begin(), front_.end());
1626  assert(oldsize+vertices.size()==vertices_.size());
1627  }
1628  template<class G,class S>
1629  inline void Aggregate<G,S>::clear()
1630  {
1631  vertices_.clear();
1632  connected_.clear();
1633  id_=-1;
1634  }
1635 
1636  template<class G,class S>
1637  inline typename Aggregate<G,S>::VertexSet::size_type
1639  {
1640  return vertices_.size();
1641  }
1642 
1643  template<class G,class S>
1644  inline typename Aggregate<G,S>::VertexSet::size_type
1646  {
1647  return connected_.size();
1648  }
1649 
1650  template<class G,class S>
1651  inline int Aggregate<G,S>::id()
1652  {
1653  return id_;
1654  }
1655 
1656  template<class G,class S>
1658  {
1659  return vertices_.begin();
1660  }
1661 
1662  template<class G,class S>
1663  inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::end() const
1664  {
1665  return vertices_.end();
1666  }
1667 
1668  template<class V>
1670 
1671  template<class V>
1673 
1674  template<class V>
1676  : aggregates_(0)
1677  {}
1678 
1679  template<class V>
1681  {
1682  if(aggregates_!=0)
1683  delete[] aggregates_;
1684  }
1685 
1686 
1687  template<class V>
1688  inline AggregatesMap<V>::AggregatesMap(std::size_t noVertices)
1689  {
1690  allocate(noVertices);
1691  }
1692 
1693  template<class V>
1694  inline std::size_t AggregatesMap<V>::noVertices() const
1695  {
1696  return noVertices_;
1697  }
1698 
1699  template<class V>
1700  inline void AggregatesMap<V>::allocate(std::size_t noVertices)
1701  {
1702  aggregates_ = new AggregateDescriptor[noVertices];
1703  noVertices_ = noVertices;
1704 
1705  for(std::size_t i=0; i < noVertices; i++)
1706  aggregates_[i]=UNAGGREGATED;
1707  }
1708 
1709  template<class V>
1710  inline void AggregatesMap<V>::free()
1711  {
1712  assert(aggregates_ != 0);
1713  delete[] aggregates_;
1714  aggregates_=0;
1715  }
1716 
1717  template<class V>
1718  inline typename AggregatesMap<V>::AggregateDescriptor&
1719  AggregatesMap<V>::operator[](const VertexDescriptor& v)
1720  {
1721  return aggregates_[v];
1722  }
1723 
1724  template<class V>
1725  inline const typename AggregatesMap<V>::AggregateDescriptor&
1726  AggregatesMap<V>::operator[](const VertexDescriptor& v) const
1727  {
1728  return aggregates_[v];
1729  }
1730 
1731  template<class V>
1732  template<bool reset, class G, class F,class VM>
1733  inline std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
1734  const AggregateDescriptor& aggregate,
1735  const G& graph, F& aggregateVisitor,
1736  VM& visitedMap) const
1737  {
1738  VertexList vlist;
1739 
1740  DummyEdgeVisitor dummy;
1741  return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap);
1742  }
1743 
1744  template<class V>
1745  template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
1746  std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
1747  const AggregateDescriptor& aggregate,
1748  const G& graph,
1749  L& visited,
1750  F1& aggregateVisitor,
1751  F2& nonAggregateVisitor,
1752  VM& visitedMap) const
1753  {
1754  typedef typename L::const_iterator ListIterator;
1755  int visitedSpheres = 0;
1756 
1757  visited.push_back(start);
1758  put(visitedMap, start, true);
1759 
1760  ListIterator current = visited.begin();
1761  ListIterator end = visited.end();
1762  std::size_t i=0, size=visited.size();
1763 
1764  // visit the neighbours of all vertices of the
1765  // current sphere.
1766  while(current != end) {
1767 
1768  for(; i<size; ++current, ++i) {
1769  typedef typename G::ConstEdgeIterator EdgeIterator;
1770  const EdgeIterator endEdge = graph.endEdges(*current);
1771 
1772  for(EdgeIterator edge = graph.beginEdges(*current);
1773  edge != endEdge; ++edge) {
1774 
1775  if(aggregates_[edge.target()]==aggregate) {
1776  if(!get(visitedMap, edge.target())) {
1777  put(visitedMap, edge.target(), true);
1778  visited.push_back(edge.target());
1779  aggregateVisitor(edge);
1780  }
1781  }else
1782  nonAggregateVisitor(edge);
1783  }
1784  }
1785  end = visited.end();
1786  size = visited.size();
1787  if(current != end)
1788  visitedSpheres++;
1789  }
1790 
1791  if(reset)
1792  for(current = visited.begin(); current != end; ++current)
1793  put(visitedMap, *current, false);
1794 
1795 
1796  if(remove)
1797  visited.clear();
1798 
1799  return visitedSpheres;
1800  }
1801 
1802  template<class G>
1804  : graph_(0), aggregate_(0), front_(), connected_(), size_(-1)
1805  {}
1806 
1807  template<class G>
1809  {
1810  size_=-1;
1811  }
1812 
1813  template<class G, class C>
1814  void buildDependency(G& graph,
1815  const typename C::Matrix& matrix,
1816  C criterion, bool firstlevel)
1817  {
1818  // assert(graph.isBuilt());
1819  typedef typename C::Matrix Matrix;
1820  typedef typename G::VertexIterator VertexIterator;
1821 
1822  criterion.init(&matrix);
1823 
1824  for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex) {
1825  typedef typename Matrix::row_type Row;
1826 
1827  const Row& row = matrix[*vertex];
1828 
1829  // Tell the criterion what row we will examine now
1830  // This might for example be used for calculating the
1831  // maximum offdiagonal value
1832  criterion.initRow(row, *vertex);
1833 
1834  // On a first path all columns are examined. After this
1835  // the calculator should know whether the vertex is isolated.
1836  typedef typename Matrix::ConstColIterator ColIterator;
1837  ColIterator end = row.end();
1838  typename FieldTraits<typename Matrix::field_type>::real_type absoffdiag=0.;
1839 
1840  using std::max;
1841  if(firstlevel) {
1842  for(ColIterator col = row.begin(); col != end; ++col)
1843  if(col.index()!=*vertex) {
1844  criterion.examine(col);
1845  absoffdiag = max(absoffdiag, Impl::asMatrix(*col).frobenius_norm());
1846  }
1847 
1848  if(absoffdiag==0)
1849  vertex.properties().setExcludedBorder();
1850  }
1851  else
1852  for(ColIterator col = row.begin(); col != end; ++col)
1853  if(col.index()!=*vertex)
1854  criterion.examine(col);
1855 
1856  // reset the vertex properties
1857  //vertex.properties().reset();
1858 
1859  // Check whether the vertex is isolated.
1860  if(criterion.isIsolated()) {
1861  //std::cout<<"ISOLATED: "<<*vertex<<std::endl;
1862  vertex.properties().setIsolated();
1863  }else{
1864  // Examine all the edges beginning at this vertex.
1865  auto eEnd = vertex.end();
1866  auto col = matrix[*vertex].begin();
1867 
1868  for(auto edge = vertex.begin(); edge!= eEnd; ++edge, ++col) {
1869  // Move to the right column.
1870  while(col.index()!=edge.target())
1871  ++col;
1872  criterion.examine(graph, edge, col);
1873  }
1874  }
1875 
1876  }
1877  }
1878 
1879 
1880  template<class G>
1881  template<class V>
1882  inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates,
1883  const AggregateDescriptor& aggregate, V& visitor)
1884  : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
1885  {}
1886 
1887  template<class G>
1888  template<class V>
1889  inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1890  {
1891  if(aggregates_[edge.target()]==aggregate_)
1892  visitor_->operator()(edge);
1893  }
1894 
1895  template<class G>
1896  template<class V>
1897  inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
1898  const AggregateDescriptor& aggregate,
1899  const AggregatesMap<Vertex>& aggregates,
1900  V& visitor) const
1901  {
1902  // Only evaluates for edge pointing to the aggregate
1903  AggregateVisitor<V> v(aggregates, aggregate, visitor);
1904  visitNeighbours(*graph_, vertex, v);
1905  }
1906 
1907 
1908  template<class G>
1909  inline Aggregator<G>::Counter::Counter()
1910  : count_(0)
1911  {}
1912 
1913  template<class G>
1914  inline void Aggregator<G>::Counter::increment()
1915  {
1916  ++count_;
1917  }
1918 
1919  template<class G>
1920  inline void Aggregator<G>::Counter::decrement()
1921  {
1922  --count_;
1923  }
1924  template<class G>
1925  inline int Aggregator<G>::Counter::value()
1926  {
1927  return count_;
1928  }
1929 
1930  template<class G>
1931  inline void Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1932  {
1933  if(edge.properties().isTwoWay())
1934  Counter::increment();
1935  }
1936 
1937  template<class G>
1938  int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
1939  const AggregatesMap<Vertex>& aggregates) const
1940  {
1941  TwoWayCounter counter;
1942  visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
1943  return counter.value();
1944  }
1945 
1946  template<class G>
1947  int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
1948  const AggregatesMap<Vertex>& aggregates) const
1949  {
1950  OneWayCounter counter;
1951  visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
1952  return counter.value();
1953  }
1954 
1955  template<class G>
1956  inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1957  {
1958  if(edge.properties().isOneWay())
1959  Counter::increment();
1960  }
1961 
1962  template<class G>
1963  inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
1964  const AggregatesMap<Vertex>& aggregates)
1965  : Counter(), connected_(connected), aggregates_(aggregates)
1966  {}
1967 
1968 
1969  template<class G>
1970  inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1971  {
1972  if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
1973  // Would be a new connection
1974  Counter::increment();
1975  else{
1976  Counter::increment();
1977  Counter::increment();
1978  }
1979  }
1980 
1981  template<class G>
1982  inline double Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
1983  {
1984  ConnectivityCounter counter(connected_, aggregates);
1985  double noNeighbours=visitNeighbours(*graph_, vertex, counter);
1986  return (double)counter.value()/noNeighbours;
1987  }
1988 
1989  template<class G>
1990  inline Aggregator<G>::DependencyCounter::DependencyCounter()
1991  : Counter()
1992  {}
1993 
1994  template<class G>
1995  inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1996  {
1997  if(edge.properties().depends())
1998  Counter::increment();
1999  if(edge.properties().influences())
2000  Counter::increment();
2001  }
2002 
2003  template<class G>
2004  int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
2005  {
2006  return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
2007  }
2008 
2009  template<class G>
2010  std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
2011  const AggregateDescriptor& aggregate,
2012  const AggregatesMap<Vertex>& aggregates) const
2013  {
2014  DependencyCounter unused, aggregated;
2015  typedef AggregateVisitor<DependencyCounter> CounterT;
2016  typedef std::tuple<CounterT,CounterT> CounterTuple;
2017  CombinedFunctor<CounterTuple> visitors(CounterTuple(CounterT(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), CounterT(aggregates, aggregate, aggregated)));
2018  visitNeighbours(*graph_, vertex, visitors);
2019  return std::make_pair(unused.value(), aggregated.value());
2020  }
2021 
2022 
2023  template<class G>
2024  int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
2025  {
2026  DependencyCounter counter;
2027  visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
2028  return counter.value();
2029  }
2030 
2031  template<class G>
2032  std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
2033  {
2034  return 0;
2035  typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
2036  VertexList vlist;
2037  typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
2038  return aggregates.template breadthFirstSearch<true,true>(vertex,
2039  aggregate_->id(), *graph_,
2040  vlist, dummy, dummy, visitedMap);
2041  }
2042 
2043  template<class G>
2044  inline Aggregator<G>::FrontMarker::FrontMarker(std::vector<Vertex>& front, MatrixGraph& graph)
2045  : front_(front), graph_(graph)
2046  {}
2047 
2048  template<class G>
2049  inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
2050  {
2051  Vertex target = edge.target();
2052 
2053  if(!graph_.getVertexProperties(target).front()) {
2054  front_.push_back(target);
2055  graph_.getVertexProperties(target).setFront();
2056  }
2057  }
2058 
2059  template<class G>
2060  inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
2061  {
2062  // Todo
2063  Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
2064  return true;
2065  //Situation 1: front node depends on two nodes. Then these
2066  // have to be strongly connected to each other
2067 
2068  // Iterate over all all neighbours of front node
2069  typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2070  Iterator vend = graph_->endEdges(vertex);
2071  for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge) {
2072  // if(edge.properties().depends() && !edge.properties().influences()
2073  if(edge.properties().isStrong()
2074  && aggregates[edge.target()]==aggregate)
2075  {
2076  // Search for another link to the aggregate
2077  Iterator edge1 = edge;
2078  for(++edge1; edge1 != vend; ++edge1) {
2079  //if(edge1.properties().depends() && !edge1.properties().influences()
2080  if(edge1.properties().isStrong()
2081  && aggregates[edge.target()]==aggregate)
2082  {
2083  //Search for an edge connecting the two vertices that is
2084  //strong
2085  bool found=false;
2086  Iterator v2end = graph_->endEdges(edge.target());
2087  for(Iterator edge2 = graph_->beginEdges(edge.target()); edge2 != v2end; ++edge2) {
2088  if(edge2.target()==edge1.target() &&
2089  edge2.properties().isStrong()) {
2090  found =true;
2091  break;
2092  }
2093  }
2094  if(found)
2095  {
2096  return true;
2097  }
2098  }
2099  }
2100  }
2101  }
2102 
2103  // Situation 2: cluster node depends on front node and other cluster node
2105  vend = graph_->endEdges(vertex);
2106  for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge) {
2107  //if(!edge.properties().depends() && edge.properties().influences()
2108  if(edge.properties().isStrong()
2109  && aggregates[edge.target()]==aggregate)
2110  {
2111  // Search for a link from target that stays within the aggregate
2112  Iterator v1end = graph_->endEdges(edge.target());
2113 
2114  for(Iterator edge1=graph_->beginEdges(edge.target()); edge1 != v1end; ++edge1) {
2115  //if(edge1.properties().depends() && !edge1.properties().influences()
2116  if(edge1.properties().isStrong()
2117  && aggregates[edge1.target()]==aggregate)
2118  {
2119  bool found=false;
2120  // Check if front node is also connected to this one
2121  Iterator v2end = graph_->endEdges(vertex);
2122  for(Iterator edge2 = graph_->beginEdges(vertex); edge2 != v2end; ++edge2) {
2123  if(edge2.target()==edge1.target()) {
2124  if(edge2.properties().isStrong())
2125  found=true;
2126  break;
2127  }
2128  }
2129  if(found)
2130  {
2131  return true;
2132  }
2133  }
2134  }
2135  }
2136  }
2137  return false;
2138  }
2139 
2140  template<class G>
2141  void Aggregator<G>::unmarkFront()
2142  {
2143  typedef typename std::vector<Vertex>::const_iterator Iterator;
2144 
2145  for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
2146  graph_->getVertexProperties(*vertex).resetFront();
2147 
2148  front_.clear();
2149  }
2150 
2151  template<class G>
2152  inline void
2153  Aggregator<G>::nonisoNeighbourAggregate(const Vertex& vertex,
2154  const AggregatesMap<Vertex>& aggregates,
2155  SLList<Vertex>& neighbours) const
2156  {
2157  typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2158  Iterator end=graph_->beginEdges(vertex);
2159  neighbours.clear();
2160 
2161  for(Iterator edge=graph_->beginEdges(vertex); edge!=end; ++edge)
2162  {
2163  if(aggregates[edge.target()]!=AggregatesMap<Vertex>::UNAGGREGATED && graph_->getVertexProperties(edge.target()).isolated())
2164  neighbours.push_back(aggregates[edge.target()]);
2165  }
2166  }
2167 
2168  template<class G>
2169  inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
2170  {
2171  typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2172 
2173  Iterator end = graph_->endEdges(vertex);
2174  for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge) {
2175  if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
2176  graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()) {
2177  if( graph_->getVertexProperties(vertex).isolated() ||
2178  ((edge.properties().depends() || edge.properties().influences())
2179  && admissible(vertex, aggregates[edge.target()], aggregates)))
2180  return edge.target();
2181  }
2182  }
2184  }
2185 
2186  template<class G>
2187  Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph)
2188  : Counter(), graph_(graph)
2189  {}
2190 
2191  template<class G>
2192  void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
2193  {
2194  if(graph_.getVertexProperties(edge.target()).front())
2195  Counter::increment();
2196  }
2197 
2198  template<class G>
2199  int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
2200  {
2201  FrontNeighbourCounter counter(*graph_);
2202  visitNeighbours(*graph_, vertex, counter);
2203  return counter.value();
2204  }
2205  template<class G>
2206  inline bool Aggregator<G>::connected(const Vertex& vertex,
2207  const AggregateDescriptor& aggregate,
2208  const AggregatesMap<Vertex>& aggregates) const
2209  {
2210  typedef typename G::ConstEdgeIterator iterator;
2211  const iterator end = graph_->endEdges(vertex);
2212  for(iterator edge = graph_->beginEdges(vertex); edge != end; ++edge)
2213  if(aggregates[edge.target()]==aggregate)
2214  return true;
2215  return false;
2216  }
2217  template<class G>
2218  inline bool Aggregator<G>::connected(const Vertex& vertex,
2219  const SLList<AggregateDescriptor>& aggregateList,
2220  const AggregatesMap<Vertex>& aggregates) const
2221  {
2222  typedef typename SLList<AggregateDescriptor>::const_iterator Iter;
2223  for(Iter i=aggregateList.begin(); i!=aggregateList.end(); ++i)
2224  if(connected(vertex, *i, aggregates))
2225  return true;
2226  return false;
2227  }
2228 
2229  template<class G>
2230  template<class C>
2231  void Aggregator<G>::growIsolatedAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
2232  {
2233  SLList<Vertex> connectedAggregates;
2234  nonisoNeighbourAggregate(seed, aggregates,connectedAggregates);
2235 
2236  while(aggregate_->size()< c.minAggregateSize() && aggregate_->connectSize() < c.maxConnectivity()) {
2237  double maxCon=-1;
2238  std::size_t maxFrontNeighbours=0;
2239 
2241 
2242  typedef typename std::vector<Vertex>::const_iterator Iterator;
2243 
2244  for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2245  if(distance(*vertex, aggregates)>c.maxDistance())
2246  continue; // distance of proposes aggregate too big
2247 
2248  if(connectedAggregates.size()>0) {
2249  // there is already a neighbour cluster
2250  // front node must be connected to same neighbour cluster
2251 
2252  if(!connected(*vertex, connectedAggregates, aggregates))
2253  continue;
2254  }
2255 
2256  double con = connectivity(*vertex, aggregates);
2257 
2258  if(con == maxCon) {
2259  std::size_t frontNeighbours = noFrontNeighbours(*vertex);
2260 
2261  if(frontNeighbours >= maxFrontNeighbours) {
2262  maxFrontNeighbours = frontNeighbours;
2263  candidate = *vertex;
2264  }
2265  }else if(con > maxCon) {
2266  maxCon = con;
2267  maxFrontNeighbours = noFrontNeighbours(*vertex);
2268  candidate = *vertex;
2269  }
2270  }
2271 
2273  break;
2274 
2275  aggregate_->add(candidate);
2276  }
2277  }
2278 
2279  template<class G>
2280  template<class C>
2281  void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
2282  {
2283  using std::min;
2284 
2285  std::size_t distance_ =0;
2286  while(aggregate_->size() < c.minAggregateSize()&& distance_<c.maxDistance()) {
2287  int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1;
2288  double maxCon=-1;
2289 
2290  std::vector<Vertex> candidates;
2291  candidates.reserve(30);
2292 
2293  typedef typename std::vector<Vertex>::const_iterator Iterator;
2294 
2295  for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2296  // Only nonisolated nodes are considered
2297  if(graph_->getVertexProperties(*vertex).isolated())
2298  continue;
2299 
2300  int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
2301 
2302  /* The case of two way connections. */
2303  if( maxTwoCons == twoWayCons && twoWayCons > 0) {
2304  double con = connectivity(*vertex, aggregates);
2305 
2306  if(con == maxCon) {
2307  int neighbours = noFrontNeighbours(*vertex);
2308 
2309  if(neighbours > maxNeighbours) {
2310  maxNeighbours = neighbours;
2311  candidates.clear();
2312  candidates.push_back(*vertex);
2313  }else{
2314  candidates.push_back(*vertex);
2315  }
2316  }else if( con > maxCon) {
2317  maxCon = con;
2318  maxNeighbours = noFrontNeighbours(*vertex);
2319  candidates.clear();
2320  candidates.push_back(*vertex);
2321  }
2322  }else if(twoWayCons > maxTwoCons) {
2323  maxTwoCons = twoWayCons;
2324  maxCon = connectivity(*vertex, aggregates);
2325  maxNeighbours = noFrontNeighbours(*vertex);
2326  candidates.clear();
2327  candidates.push_back(*vertex);
2328 
2329  // two way connections precede
2330  maxOneCons = std::numeric_limits<int>::max();
2331  }
2332 
2333  if(twoWayCons > 0)
2334  {
2335  continue; // THis is a two-way node, skip tests for one way nodes
2336  }
2337 
2338  /* The one way case */
2339  int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
2340 
2341  if(oneWayCons==0)
2342  continue; // No strong connections, skip the tests.
2343 
2344  if(!admissible(*vertex, aggregate_->id(), aggregates))
2345  continue;
2346 
2347  if( maxOneCons == oneWayCons && oneWayCons > 0) {
2348  double con = connectivity(*vertex, aggregates);
2349 
2350  if(con == maxCon) {
2351  int neighbours = noFrontNeighbours(*vertex);
2352 
2353  if(neighbours > maxNeighbours) {
2354  maxNeighbours = neighbours;
2355  candidates.clear();
2356  candidates.push_back(*vertex);
2357  }else{
2358  if(neighbours==maxNeighbours)
2359  {
2360  candidates.push_back(*vertex);
2361  }
2362  }
2363  }else if( con > maxCon) {
2364  maxCon = con;
2365  maxNeighbours = noFrontNeighbours(*vertex);
2366  candidates.clear();
2367  candidates.push_back(*vertex);
2368  }
2369  }else if(oneWayCons > maxOneCons) {
2370  maxOneCons = oneWayCons;
2371  maxCon = connectivity(*vertex, aggregates);
2372  maxNeighbours = noFrontNeighbours(*vertex);
2373  candidates.clear();
2374  candidates.push_back(*vertex);
2375  }
2376  }
2377 
2378 
2379  if(!candidates.size())
2380  break; // No more candidates found
2381  distance_=distance(seed, aggregates);
2382  candidates.resize(min(candidates.size(), c.maxAggregateSize()-
2383  aggregate_->size()));
2384  aggregate_->add(candidates);
2385  }
2386  }
2387 
2388  template<typename V>
2389  template<typename M, typename G, typename C>
2390  std::tuple<int,int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion,
2391  bool finestLevel)
2392  {
2393  Aggregator<G> aggregator;
2394  return aggregator.build(matrix, graph, *this, criterion, finestLevel);
2395  }
2396 
2397  template<class G>
2398  template<class M, class C>
2399  std::tuple<int,int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c,
2400  bool finestLevel)
2401  {
2402  using std::max;
2403  using std::min;
2404  // Stack for fast vertex access
2405  Stack stack_(graph, *this, aggregates);
2406 
2407  graph_ = &graph;
2408 
2409  aggregate_ = new Aggregate<G,VertexSet>(graph, aggregates, connected_, front_);
2410 
2411  Timer watch;
2412  watch.reset();
2413 
2414  buildDependency(graph, m, c, finestLevel);
2415 
2416  dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
2417  int noAggregates, conAggregates, isoAggregates, oneAggregates;
2418  std::size_t maxA=0, minA=1000000, avg=0;
2419  int skippedAggregates;
2420  noAggregates = conAggregates = isoAggregates = oneAggregates =
2421  skippedAggregates = 0;
2422 
2423  while(true) {
2424  Vertex seed = stack_.pop();
2425 
2426  if(seed == Stack::NullEntry)
2427  // No more unaggregated vertices. We are finished!
2428  break;
2429 
2430  // Debugging output
2431  if((noAggregates+1)%10000 == 0)
2432  Dune::dverb<<"c";
2433  unmarkFront();
2434 
2435  if(graph.getVertexProperties(seed).excludedBorder()) {
2436  aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
2437  ++skippedAggregates;
2438  continue;
2439  }
2440 
2441  if(graph.getVertexProperties(seed).isolated()) {
2442  if(c.skipIsolated()) {
2443  // isolated vertices are not aggregated but skipped on the coarser levels.
2444  aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
2445  ++skippedAggregates;
2446  // skip rest as no agglomeration is done.
2447  continue;
2448  }else{
2449  aggregate_->seed(seed);
2450  growIsolatedAggregate(seed, aggregates, c);
2451  }
2452  }else{
2453  aggregate_->seed(seed);
2454  growAggregate(seed, aggregates, c);
2455  }
2456 
2457  /* The rounding step. */
2458  while(!(graph.getVertexProperties(seed).isolated()) && aggregate_->size() < c.maxAggregateSize()) {
2459 
2460  std::vector<Vertex> candidates;
2461  candidates.reserve(30);
2462 
2463  typedef typename std::vector<Vertex>::const_iterator Iterator;
2464 
2465  for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2466 
2467  if(graph.getVertexProperties(*vertex).isolated())
2468  continue; // No isolated nodes here
2469 
2470  if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 &&
2471  (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 ||
2472  !admissible( *vertex, aggregate_->id(), aggregates) ))
2473  continue;
2474 
2475  std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
2476  aggregates);
2477 
2478  //if(aggregateNeighbours(*vertex, aggregate_->id(), aggregates) <= unusedNeighbours(*vertex, aggregates))
2479  // continue;
2480 
2481  if(neighbourPair.first >= neighbourPair.second)
2482  continue;
2483 
2484  if(distance(*vertex, aggregates) > c.maxDistance())
2485  continue; // Distance too far
2486  candidates.push_back(*vertex);
2487  break;
2488  }
2489 
2490  if(!candidates.size()) break; // no more candidates found.
2491 
2492  candidates.resize(min(candidates.size(), c.maxAggregateSize()-
2493  aggregate_->size()));
2494  aggregate_->add(candidates);
2495 
2496  }
2497 
2498  // try to merge aggregates consisting of only one nonisolated vertex with other aggregates
2499  if(aggregate_->size()==1 && c.maxAggregateSize()>1) {
2500  if(!graph.getVertexProperties(seed).isolated()) {
2501  Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
2502 
2503  if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED) {
2504  // assign vertex to the neighbouring cluster
2505  aggregates[seed] = aggregates[mergedNeighbour];
2506  aggregate_->invalidate();
2507  }else{
2508  ++avg;
2509  minA=min(minA,static_cast<std::size_t>(1));
2510  maxA=max(maxA,static_cast<std::size_t>(1));
2511  ++oneAggregates;
2512  ++conAggregates;
2513  }
2514  }else{
2515  ++avg;
2516  minA=min(minA,static_cast<std::size_t>(1));
2517  maxA=max(maxA,static_cast<std::size_t>(1));
2518  ++oneAggregates;
2519  ++isoAggregates;
2520  }
2521  ++avg;
2522  }else{
2523  avg+=aggregate_->size();
2524  minA=min(minA,aggregate_->size());
2525  maxA=max(maxA,aggregate_->size());
2526  if(graph.getVertexProperties(seed).isolated())
2527  ++isoAggregates;
2528  else
2529  ++conAggregates;
2530  }
2531 
2532  }
2533 
2534  Dune::dinfo<<"connected aggregates: "<<conAggregates;
2535  Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
2536  if(conAggregates+isoAggregates>0)
2537  Dune::dinfo<<" one node aggregates: "<<oneAggregates<<" min size="
2538  <<minA<<" max size="<<maxA
2539  <<" avg="<<avg/(conAggregates+isoAggregates)<<std::endl;
2540 
2541  delete aggregate_;
2542  return std::make_tuple(conAggregates+isoAggregates,isoAggregates,
2543  oneAggregates,skippedAggregates);
2544  }
2545 
2546 
2547  template<class G>
2548  Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
2549  const AggregatesMap<Vertex>& aggregates)
2550  : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), begin_(graph.begin()), end_(graph.end())
2551  {
2552  //vals_ = new Vertex[N];
2553  }
2554 
2555  template<class G>
2556  Aggregator<G>::Stack::~Stack()
2557  {
2558  //Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
2559  //delete[] vals_;
2560  }
2561 
2562  template<class G>
2563  const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry
2565 
2566  template<class G>
2567  inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
2568  {
2569  for(; begin_!=end_ && aggregates_[*begin_] != AggregatesMap<Vertex>::UNAGGREGATED; ++begin_) ;
2570 
2571  if(begin_!=end_)
2572  {
2573  typename G::VertexDescriptor current=*begin_;
2574  ++begin_;
2575  return current;
2576  }else
2577  return NullEntry;
2578  }
2579 
2580 #endif // DOXYGEN
2581 
2582  template<class V>
2583  void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m, std::ostream& os)
2584  {
2585  using std::max;
2586 
2587  std::ios_base::fmtflags oldOpts=os.flags();
2588 
2589  os.setf(std::ios_base::right, std::ios_base::adjustfield);
2590 
2591  V maxVal=0;
2592  int width=1;
2593 
2594  for(int i=0; i< n*m; i++)
2595  maxVal=max(maxVal, aggregates[i]);
2596 
2597  for(int i=10; i < 1000000; i*=10)
2598  if(maxVal/i>0)
2599  width++;
2600  else
2601  break;
2602 
2603  for(int j=0, entry=0; j < m; j++) {
2604  for(int i=0; i<n; i++, entry++) {
2605  os.width(width);
2606  os<<aggregates[entry]<<" ";
2607  }
2608 
2609  os<<std::endl;
2610  }
2611  os<<std::endl;
2612  os.flags(oldOpts);
2613  }
2614 
2615 
2616  } // namespace Amg
2617 
2618 } // namespace Dune
2619 
2620 
2621 #endif
A class for temporarily storing the vertices of an aggregate in.
Definition: aggregates.hh:778
A Dummy visitor that does nothing for each visited edge.
Definition: aggregates.hh:598
Class providing information about the mapping of the vertices onto aggregates.
Definition: aggregates.hh:560
Base class of all aggregation criterions.
Definition: aggregates.hh:49
Class for building the aggregates.
Definition: aggregates.hh:909
Dependency policy for symmetric matrices.
Definition: aggregates.hh:253
Norm that uses only the [N][N] entry of the block to determine couplings.
Definition: aggregates.hh:379
Norm that uses only the [0][0] entry of the block to determine couplings.
Definition: aggregates.hh:455
Iterator over all edges starting from a vertex.
Definition: graph.hh:95
The vertex iterator type of the graph.
Definition: graph.hh:209
The (undirected) graph of a matrix.
Definition: graph.hh:51
M::size_type VertexDescriptor
The vertex descriptor.
Definition: graph.hh:73
EdgeIteratorT< const MatrixGraph< Matrix > > ConstEdgeIterator
The constant edge iterator type.
Definition: graph.hh:298
All parameters for AMG.
Definition: parameters.hh:393
Criterion taking advantage of symmetric matrices.
Definition: aggregates.hh:519
Dependency policy for symmetric matrices.
Definition: aggregates.hh:314
Dependency policy for symmetric matrices.
Definition: aggregates.hh:134
Criterion suitable for unsymmetric matrices.
Definition: aggregates.hh:539
derive error class from the base class in common
Definition: istlexception.hh:19
A generic dynamic dense matrix.
Definition: matrix.hh:561
typename Imp::BlockTraits< T >::field_type field_type
Export the type representing the underlying field.
Definition: matrix.hh:565
row_type::const_iterator ConstColIterator
Const iterator for the entries of each row.
Definition: matrix.hh:589
MatrixImp::DenseMatrixBase< T, A >::window_type row_type
The type implementing a matrix row.
Definition: matrix.hh:574
An allocator managing a pool of objects for reuse.
Definition: poolallocator.hh:223
A single linked list.
Definition: sllist.hh:44
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:74
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr GeometryType vertex
GeometryType representing a vertex.
Definition: type.hh:506
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:273
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:154
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:586
int id()
Get the id identifying the aggregate.
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:302
MatrixGraph::VertexDescriptor Vertex
The vertex identifier.
Definition: aggregates.hh:920
AggregationCriterion()
Constructor.
Definition: aggregates.hh:66
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:357
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:406
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:258
G MatrixGraph
The matrix graph type used.
Definition: aggregates.hh:915
FieldTraits< typename M::field_type >::real_type operator()(const M &m) const
compute the norm of a matrix.
Definition: aggregates.hh:490
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:363
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:319
real_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:187
N Norm
The norm to use for examining the matrix entries.
Definition: aggregates.hh:263
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:185
FrontNeighbourCounter(const MatrixGraph &front)
Constructor.
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:329
FieldTraits< typename M::field_type >::real_type operator()(const M &m, [[maybe_unused]] typename std::enable_if_t<!Dune::IsNumber< M >::value > *sfinae=nullptr) const
compute the norm of a matrix.
Definition: aggregates.hh:390
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:296
AggregateVisitor(const AggregatesMap< Vertex > &aggregates, const AggregateDescriptor &aggregate, Visitor &visitor)
Constructor.
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:334
~AggregatesMap()
Destructor.
Matrix::field_type field_type
The current max value.
Definition: aggregates.hh:179
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:1064
std::size_t * SphereMap
Type of the mapping of aggregate members onto distance spheres.
Definition: aggregates.hh:809
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:268
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:506
N Norm
The norm to use for examining the matrix entries.
Definition: aggregates.hh:324
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:183
VertexSet::const_iterator const_iterator
Const iterator over a vertex list.
Definition: aggregates.hh:804
MatrixGraph::VertexDescriptor AggregateDescriptor
The type of the aggregate descriptor.
Definition: aggregates.hh:923
real_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:367
~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:55
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:82
V AggregateDescriptor
The aggregate descriptor type.
Definition: aggregates.hh:580
static const V ISOLATED
Identifier of isolated vertices.
Definition: aggregates.hh:571
int row_
index of the currently evaluated row.
Definition: aggregates.hh:365
real_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:306
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:105
AggregatesMap(std::size_t noVertices)
Constructs with allocating memory.
Matrix::field_type field_type
The current max value.
Definition: aggregates.hh:359
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:592
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:473
int row_
index of the currently evaluated row.
Definition: aggregates.hh:304
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:139
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:177
S VertexSet
The type of a single linked list of vertex descriptors.
Definition: aggregates.hh:801
static const V UNAGGREGATED
Identifier of not yet aggregated vertices.
Definition: aggregates.hh:566
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:298
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:144
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:789
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:575
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:149
PoolAllocator< Vertex, 100 > Allocator
The allocator we use for our lists and the set.
Definition: aggregates.hh:795
auto min(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::min()
Definition: defaults.hh:89
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:81
DVVerbType dvverb(std::cout)
stream for very verbose output.
Definition: stdstreams.hh:95
DInfoType dinfo(std::cout)
Stream for informative output.
Definition: stdstreams.hh:140
DVerbType dverb(std::cout)
Singleton of verbose debug stream.
Definition: stdstreams.hh:116
constexpr auto front(const HybridTreePath< T... > &tp) -> decltype(treePathEntry< 0 >(tp))
Returns a copy of the first element of the HybridTreePath.
Definition: treepath.hh:270
Dune namespace.
Definition: alignedallocator.hh:13
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:463
Whether this type acts as a scalar in the context of (hierarchically blocked) containers.
Definition: typetraits.hh:194
A simple timing class.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (Apr 29, 22:29, 2024)