dune-istl  2.11
aggregates.hh
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright © 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>
15 #include <dune/common/stdstreams.hh>
16 #include <dune/common/poolallocator.hh>
17 #include <dune/common/sllist.hh>
18 #include <dune/common/ftraits.hh>
19 #include <dune/common/scalarmatrixview.hh>
20 #include <dune/common/typetraits.hh>
21 
22 #include <utility>
23 #include <set>
24 #include <algorithm>
25 #include <complex>
26 #include <limits>
27 #include <ostream>
28 #include <tuple>
29 #include <cmath>
30 
31 namespace Dune
32 {
33  namespace Amg
34  {
35 
49  template<class T>
50  class AggregationCriterion : public T
51  {
52 
53  public:
57  typedef T DependencyPolicy;
58 
69  : T()
70  {}
71 
73  : T(parms)
74  {}
84  void setDefaultValuesIsotropic(std::size_t dim, std::size_t diameter=2)
85  {
86  this->setMaxDistance(diameter-1);
87  std::size_t csize=1;
88 
89  for(; dim>0; dim--) {
90  csize*=diameter;
91  this->setMaxDistance(this->maxDistance()+diameter-1);
92  }
93  this->setMinAggregateSize(csize);
94  this->setMaxAggregateSize(static_cast<std::size_t>(csize*1.5));
95  }
96 
107  void setDefaultValuesAnisotropic(std::size_t dim,std::size_t diameter=2)
108  {
109  setDefaultValuesIsotropic(dim, diameter);
110  this->setMaxDistance(this->maxDistance()+dim-1);
111  }
112  };
113 
114  template<class T>
115  std::ostream& operator<<(std::ostream& os, const AggregationCriterion<T>& criterion)
116  {
117  os<<"{ maxdistance="<<criterion.maxDistance()<<" minAggregateSize="
118  <<criterion.minAggregateSize()<< " maxAggregateSize="<<criterion.maxAggregateSize()
119  <<" connectivity="<<criterion.maxConnectivity()<<" debugLevel="<<criterion.debugLevel()<<"}";
120  return os;
121  }
122 
134  template<class M, class N>
136  {
137  public:
141  typedef M Matrix;
142 
146  typedef N Norm;
147 
151  typedef typename Matrix::row_type Row;
152 
157 
158  void init(const Matrix* matrix);
159 
160  void initRow(const Row& row, int index);
161 
162  void examine(const ColIter& col);
163 
164  template<class G>
165  void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
166 
167  bool isIsolated();
168 
169 
171  : Parameters(parms)
172  {}
174  : Parameters()
175  {}
176 
177  protected:
179  const Matrix* matrix_;
181  typedef typename Matrix::field_type field_type;
182  typedef typename FieldTraits<field_type>::real_type real_type;
187  int row_;
190  std::vector<real_type> vals_;
191  typename std::vector<real_type>::iterator valIter_;
192 
193  };
194 
195 
196  template<class M, class N>
197  inline void SymmetricMatrixDependency<M,N>::init(const Matrix* matrix)
198  {
199  matrix_ = matrix;
200  }
201 
202  template<class M, class N>
203  inline void SymmetricMatrixDependency<M,N>::initRow(const Row& row, int index)
204  {
205  using std::min;
206  vals_.assign(row.size(), 0.0);
207  assert(vals_.size()==row.size());
208  valIter_=vals_.begin();
209 
210  maxValue_ = min(- std::numeric_limits<real_type>::max(), std::numeric_limits<real_type>::min());
211  diagonal_=norm_(row[index]);
212  row_ = index;
213  }
214 
215  template<class M, class N>
217  {
218  using std::max;
219  // skip positive offdiagonals if norm preserves sign of them.
220  real_type eij = norm_(*col);
221  if(!N::is_sign_preserving || eij<0) // || eji<0)
222  {
223  *valIter_ = eij/diagonal_*eij/norm_(matrix_->operator[](col.index())[col.index()]);
224  maxValue_ = max(maxValue_, *valIter_);
225  }else
226  *valIter_ =0;
227  ++valIter_;
228  }
229 
230  template<class M, class N>
231  template<class G>
232  inline void SymmetricMatrixDependency<M,N>::examine(G&, const typename G::EdgeIterator& edge, const ColIter&)
233  {
234  if(*valIter_ > alpha() * maxValue_) {
235  edge.properties().setDepends();
236  edge.properties().setInfluences();
237  }
238  ++valIter_;
239  }
240 
241  template<class M, class N>
243  {
244  if(diagonal_==0)
245  DUNE_THROW(Dune::ISTLError, "No diagonal entry for row "<<row_<<".");
246  valIter_=vals_.begin();
247  return maxValue_ < beta();
248  }
249 
253  template<class M, class N>
254  class Dependency : public Parameters
255  {
256  public:
260  typedef M Matrix;
261 
265  typedef N Norm;
266 
270  typedef typename Matrix::row_type Row;
271 
276 
277  void init(const Matrix* matrix);
278 
279  void initRow(const Row& row, int index);
280 
281  void examine(const ColIter& col);
282 
283  template<class G>
284  void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
285 
286  bool isIsolated();
287 
288  Dependency(const Parameters& parms)
289  : Parameters(parms)
290  {}
291 
293  : Parameters()
294  {}
295 
296  protected:
298  const Matrix* matrix_;
300  typedef typename Matrix::field_type field_type;
301  typedef typename FieldTraits<field_type>::real_type real_type;
306  int row_;
309  };
310 
314  template<class M, class N>
316  {
317  public:
321  typedef M Matrix;
322 
326  typedef N Norm;
327 
331  typedef typename Matrix::row_type Row;
332 
337 
338  void init(const Matrix* matrix);
339 
340  void initRow(const Row& row, int index);
341 
342  void examine(const ColIter& col);
343 
344  template<class G>
345  void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
346 
347  bool isIsolated();
348 
349 
351  : Parameters(parms)
352  {}
354  : Parameters()
355  {}
356 
357  protected:
359  const Matrix* matrix_;
361  typedef typename Matrix::field_type field_type;
362  typedef typename FieldTraits<field_type>::real_type real_type;
367  int row_;
370  private:
371  void initRow(const Row& row, int index, const std::true_type&);
372  void initRow(const Row& row, int index, const std::false_type&);
373  };
374 
379  template<int N>
380  class Diagonal
381  {
382  public:
383  enum { /* @brief We preserve the sign.*/
385  };
386 
391  template<class M>
392  typename FieldTraits<typename M::field_type>::real_type operator()(const M& m,
393  [[maybe_unused]] typename std::enable_if_t<!Dune::IsNumber<M>::value>* sfinae = nullptr) const
394  {
395  typedef typename M::field_type field_type;
396  typedef typename FieldTraits<field_type>::real_type real_type;
397  static_assert( std::is_convertible<field_type, real_type >::value,
398  "use of diagonal norm in AMG not implemented for complex field_type");
399  return m[N][N];
400  // possible implementation for complex types: return signed_abs(m[N][N]);
401  }
402 
407  template<class M>
408  auto operator()(const M& m,
409  typename std::enable_if_t<Dune::IsNumber<M>::value>* /*sfinae*/ = nullptr) const
410  {
411  typedef typename FieldTraits<M>::real_type real_type;
412  static_assert( std::is_convertible<M, real_type >::value,
413  "use of diagonal norm in AMG not implemented for complex field_type");
414  return m;
415  // possible implementation for complex types: return signed_abs(m[N][N]);
416  }
417 
418  private:
419 
421  template<typename T>
422  static T signed_abs(const T & v)
423  {
424  return v;
425  }
426 
428  template<typename T>
429  static T signed_abs(const std::complex<T> & v)
430  {
431  // return sign * abs_value
432  // in case of complex numbers this extends to using the csgn function to determine the sign
433  return csgn(v) * std::abs(v);
434  }
435 
437  template<typename T>
438  static T csgn(const T & v)
439  {
440  return (T(0) < v) - (v < T(0));
441  }
442 
444  template<typename T>
445  static T csgn(std::complex<T> a)
446  {
447  return csgn(a.real())+(a.real() == 0.0)*csgn(a.imag());
448  }
449 
450  };
451 
456  class FirstDiagonal : public Diagonal<0>
457  {};
458 
464  struct RowSum
465  {
466 
467  enum { /* @brief We preserve the sign.*/
469  };
474  template<class M>
475  auto operator()(const M& m) const
476  {
477  using std::abs;
478  if constexpr(Dune::IsNumber<M>::value)
479  return abs(m);
480  else
481  return m.infinity_norm();
482  }
483  };
484 
486  {
487 
488  enum { /* @brief We preserve the sign.*/
490  };
495  template<class M>
496  typename FieldTraits<typename M::field_type>::real_type operator()(const M& m) const
497  {
498  return m.frobenius_norm();
499  }
500  };
502  {
503 
504  enum { /* @brief We preserve the sign.*/
506  };
511  template<class M>
512  typename FieldTraits<typename M::field_type>::real_type operator()(const M& /*m*/) const
513  {
514  return 1;
515  }
516  };
523  template<class M, class Norm>
524  class SymmetricCriterion : public AggregationCriterion<SymmetricDependency<M,Norm> >
525  {
526  public:
529  {}
531  {}
532  };
533 
534 
543  template<class M, class Norm>
544  class UnSymmetricCriterion : public AggregationCriterion<Dependency<M,Norm> >
545  {
546  public:
548  : AggregationCriterion<Dependency<M,Norm> >(parms)
549  {}
551  {}
552  };
553  // forward declaration
554  template<class G> class Aggregator;
555 
556 
564  template<class V>
566  {
567  public:
568 
572  static const V UNAGGREGATED;
573 
577  static const V ISOLATED;
581  typedef V VertexDescriptor;
582 
587 
592  typedef PoolAllocator<VertexDescriptor,100> Allocator;
593 
598  typedef SLList<VertexDescriptor,Allocator> VertexList;
599 
604  {
605  public:
606  template<class EdgeIterator>
607  void operator()([[maybe_unused]] const EdgeIterator& edge) const
608  {}
609  };
610 
611 
615  AggregatesMap();
616 
622  AggregatesMap(std::size_t noVertices);
623 
627  ~AggregatesMap();
628 
640  template<class M, class G, class C>
641  std::tuple<int,int,int,int> buildAggregates(const M& matrix, G& graph, const C& criterion,
642  bool finestLevel);
643 
661  template<bool reset, class G, class F, class VM>
662  std::size_t breadthFirstSearch(const VertexDescriptor& start,
663  const AggregateDescriptor& aggregate,
664  const G& graph,
665  F& aggregateVisitor,
666  VM& visitedMap) const;
667 
691  template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
692  std::size_t breadthFirstSearch(const VertexDescriptor& start,
693  const AggregateDescriptor& aggregate,
694  const G& graph, L& visited, F1& aggregateVisitor,
695  F2& nonAggregateVisitor,
696  VM& visitedMap) const;
697 
703  void allocate(std::size_t noVertices);
704 
708  std::size_t noVertices() const;
709 
713  void free();
714 
721 
727  const AggregateDescriptor& operator[](const VertexDescriptor& v) const;
728 
730 
732  {
733  return aggregates_;
734  }
735 
737  {
738  return aggregates_+noVertices();
739  }
740 
742 
744  {
745  return aggregates_;
746  }
747 
749  {
750  return aggregates_+noVertices();
751  }
752  private:
754  AggregatesMap(const AggregatesMap<V>&) = delete;
756  AggregatesMap<V>& operator=(const AggregatesMap<V>&) = delete;
757 
761  AggregateDescriptor* aggregates_;
762 
766  std::size_t noVertices_;
767  };
768 
772  template<class G, class C>
773  void buildDependency(G& graph,
774  const typename C::Matrix& matrix,
775  C criterion,
776  bool finestLevel);
777 
782  template<class G, class S>
783  class Aggregate
784  {
785 
786  public:
787 
788  /***
789  * @brief The type of the matrix graph we work with.
790  */
791  typedef G MatrixGraph;
796 
801  typedef PoolAllocator<Vertex,100> Allocator;
802 
807  typedef S VertexSet;
808 
812  using size_type = typename VertexSet::size_type;
813 
815  typedef typename VertexSet::const_iterator const_iterator;
816 
820  typedef std::size_t* SphereMap;
821 
830  Aggregate(MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
831  VertexSet& connectivity, std::vector<Vertex>& front_);
832 
833  void invalidate()
834  {
835  --id_;
836  }
837 
844  void reconstruct(const Vertex& vertex);
845 
849  void seed(const Vertex& vertex);
850 
854  void add(const Vertex& vertex);
855 
856  void add(std::vector<Vertex>& vertex);
860  void clear();
861 
865  size_type size();
870 
874  int id();
875 
877  const_iterator begin() const;
878 
880  const_iterator end() const;
881 
882  private:
886  VertexSet vertices_;
887 
892  int id_;
893 
897  MatrixGraph& graph_;
898 
902  AggregatesMap<Vertex>& aggregates_;
903 
907  VertexSet& connected_;
908 
912  std::vector<Vertex>& front_;
913  };
914 
918  template<class G>
919  class Aggregator
920  {
921  public:
922 
926  typedef G MatrixGraph;
927 
932 
935 
939  Aggregator();
940 
944  ~Aggregator();
945 
962  template<class M, class C>
963  std::tuple<int,int,int,int> build(const M& m, G& graph,
964  AggregatesMap<Vertex>& aggregates, const C& c,
965  bool finestLevel);
966  private:
971  typedef PoolAllocator<Vertex,100> Allocator;
972 
976  typedef SLList<Vertex,Allocator> VertexList;
977 
981  typedef std::set<Vertex,std::less<Vertex>,Allocator> VertexSet;
982 
986  typedef std::size_t* SphereMap;
987 
991  MatrixGraph* graph_;
992 
997 
1001  std::vector<Vertex> front_;
1002 
1006  VertexSet connected_;
1007 
1011  int size_;
1012 
1016  class Stack
1017  {
1018  public:
1019  static const Vertex NullEntry;
1020 
1021  Stack(const MatrixGraph& graph,
1022  const Aggregator<G>& aggregatesBuilder,
1023  const AggregatesMap<Vertex>& aggregates);
1024  ~Stack();
1025  Vertex pop();
1026  private:
1027  enum { N = 1300000 };
1028 
1030  const MatrixGraph& graph_;
1032  const Aggregator<G>& aggregatesBuilder_;
1034  const AggregatesMap<Vertex>& aggregates_;
1036  int size_;
1037  Vertex maxSize_;
1039  typename MatrixGraph::ConstVertexIterator begin_;
1040  typename MatrixGraph::ConstVertexIterator end_;
1041 
1043  Vertex* vals_;
1044 
1045  };
1046 
1047  friend class Stack;
1048 
1059  template<class V>
1060  void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate,
1061  const AggregatesMap<Vertex>& aggregates,
1062  V& visitor) const;
1063 
1068  template<class V>
1069  class AggregateVisitor
1070  {
1071  public:
1075  typedef V Visitor;
1083  AggregateVisitor(const AggregatesMap<Vertex>& aggregates, const AggregateDescriptor& aggregate,
1084  Visitor& visitor);
1085 
1092  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1093 
1094  private:
1096  const AggregatesMap<Vertex>& aggregates_;
1098  AggregateDescriptor aggregate_;
1100  Visitor* visitor_;
1101  };
1102 
1106  class Counter
1107  {
1108  public:
1110  Counter();
1112  int value();
1113 
1114  protected:
1116  void increment();
1118  void decrement();
1119 
1120  private:
1121  int count_;
1122  };
1123 
1124 
1129  class FrontNeighbourCounter : public Counter
1130  {
1131  public:
1136  FrontNeighbourCounter(const MatrixGraph& front);
1137 
1138  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1139 
1140  private:
1141  const MatrixGraph& graph_;
1142  };
1143 
1148  int noFrontNeighbours(const Vertex& vertex) const;
1149 
1153  class TwoWayCounter : public Counter
1154  {
1155  public:
1156  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1157  };
1158 
1170  int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
1171  const AggregatesMap<Vertex>& aggregates) const;
1172 
1176  class OneWayCounter : public Counter
1177  {
1178  public:
1179  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1180  };
1181 
1193  int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
1194  const AggregatesMap<Vertex>& aggregates) const;
1195 
1202  class ConnectivityCounter : public Counter
1203  {
1204  public:
1210  ConnectivityCounter(const VertexSet& connected, const AggregatesMap<Vertex>& aggregates);
1211 
1212  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1213 
1214  private:
1216  const VertexSet& connected_;
1218  const AggregatesMap<Vertex>& aggregates_;
1219 
1220  };
1221 
1233  double connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1241  bool connected(const Vertex& vertex, const AggregateDescriptor& aggregate,
1242  const AggregatesMap<Vertex>& aggregates) const;
1243 
1251  bool connected(const Vertex& vertex, const SLList<AggregateDescriptor>& aggregateList,
1252  const AggregatesMap<Vertex>& aggregates) const;
1253 
1261  class DependencyCounter : public Counter
1262  {
1263  public:
1267  DependencyCounter();
1268 
1269  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1270  };
1271 
1278  class FrontMarker
1279  {
1280  public:
1287  FrontMarker(std::vector<Vertex>& front, MatrixGraph& graph);
1288 
1289  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1290 
1291  private:
1293  std::vector<Vertex>& front_;
1295  MatrixGraph& graph_;
1296  };
1297 
1301  void unmarkFront();
1302 
1317  int unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1318 
1332  std::pair<int,int> neighbours(const Vertex& vertex,
1333  const AggregateDescriptor& aggregate,
1334  const AggregatesMap<Vertex>& aggregates) const;
1351  int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
1352 
1360  bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
1361 
1369  std::size_t distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates);
1370 
1379  Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1380 
1389  void nonisoNeighbourAggregate(const Vertex& vertex,
1390  const AggregatesMap<Vertex>& aggregates,
1391  SLList<Vertex>& neighbours) const;
1392 
1400  template<class C>
1401  void growAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
1402  template<class C>
1403  void growIsolatedAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
1404  };
1405 
1406 #ifndef DOXYGEN
1407 
1408  template<class M, class N>
1409  inline void SymmetricDependency<M,N>::init(const Matrix* matrix)
1410  {
1411  matrix_ = matrix;
1412  }
1413 
1414  template<class M, class N>
1415  inline void SymmetricDependency<M,N>::initRow(const Row& row, int index)
1416  {
1417  initRow(row, index, std::is_convertible<field_type, real_type>());
1418  }
1419 
1420  template<class M, class N>
1421  inline void SymmetricDependency<M,N>::initRow(const Row& /*row*/, int /*index*/, const std::false_type&)
1422  {
1423  DUNE_THROW(InvalidStateException, "field_type needs to convertible to real_type");
1424  }
1425 
1426  template<class M, class N>
1427  inline void SymmetricDependency<M,N>::initRow(const Row& /*row*/, int index, const std::true_type&)
1428  {
1429  using std::min;
1430  maxValue_ = min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
1431  row_ = index;
1432  diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1433  }
1434 
1435  template<class M, class N>
1436  inline void SymmetricDependency<M,N>::examine(const ColIter& col)
1437  {
1438  using std::max;
1439  real_type eij = norm_(*col);
1440  typename Matrix::ConstColIterator opposite_entry =
1441  matrix_->operator[](col.index()).find(row_);
1442  if ( opposite_entry == matrix_->operator[](col.index()).end() )
1443  {
1444  // Consider this a weak connection we disregard.
1445  return;
1446  }
1447  real_type eji = norm_(*opposite_entry);
1448 
1449  // skip positive offdiagonals if norm preserves sign of them.
1450  if(!N::is_sign_preserving || eij<0 || eji<0)
1451  maxValue_ = max(maxValue_,
1452  eij /diagonal_ * eji/
1453  norm_(matrix_->operator[](col.index())[col.index()]));
1454  }
1455 
1456  template<class M, class N>
1457  template<class G>
1458  inline void SymmetricDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
1459  {
1460  real_type eij = norm_(*col);
1461  typename Matrix::ConstColIterator opposite_entry =
1462  matrix_->operator[](col.index()).find(row_);
1463 
1464  if ( opposite_entry == matrix_->operator[](col.index()).end() )
1465  {
1466  // Consider this as a weak connection we disregard.
1467  return;
1468  }
1469  real_type eji = norm_(*opposite_entry);
1470  // skip positive offdiagonals if norm preserves sign of them.
1471  if(!N::is_sign_preserving || (eij<0 || eji<0))
1472  if(eji / norm_(matrix_->operator[](edge.target())[edge.target()]) *
1473  eij/ diagonal_ > alpha() * maxValue_) {
1474  edge.properties().setDepends();
1475  edge.properties().setInfluences();
1476  typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
1477  other.setInfluences();
1478  other.setDepends();
1479  }
1480  }
1481 
1482  template<class M, class N>
1484  {
1485  return maxValue_ < beta();
1486  }
1487 
1488 
1489  template<class M, class N>
1490  inline void Dependency<M,N>::init(const Matrix* matrix)
1491  {
1492  matrix_ = matrix;
1493  }
1494 
1495  template<class M, class N>
1496  inline void Dependency<M,N>::initRow([[maybe_unused]] const Row& row, int index)
1497  {
1498  using std::min;
1499  maxValue_ = min(- std::numeric_limits<real_type>::max(), std::numeric_limits<real_type>::min());
1500  row_ = index;
1501  diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1502  }
1503 
1504  template<class M, class N>
1505  inline void Dependency<M,N>::examine(const ColIter& col)
1506  {
1507  using std::max;
1508  maxValue_ = max(maxValue_, -norm_(*col));
1509  }
1510 
1511  template<class M, class N>
1512  template<class G>
1513  inline void Dependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
1514  {
1515  if(-norm_(*col) >= maxValue_ * alpha()) {
1516  edge.properties().setDepends();
1517  typedef typename G::EdgeDescriptor ED;
1518  ED e= graph.findEdge(edge.target(), edge.source());
1519  if(e!=std::numeric_limits<ED>::max())
1520  {
1521  typename G::EdgeProperties& other = graph.getEdgeProperties(e);
1522  other.setInfluences();
1523  }
1524  }
1525  }
1526 
1527  template<class M, class N>
1528  inline bool Dependency<M,N>::isIsolated()
1529  {
1530  return maxValue_ < beta() * diagonal_;
1531  }
1532 
1533  template<class G,class S>
1534  Aggregate<G,S>::Aggregate(MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
1535  VertexSet& connected, std::vector<Vertex>& front)
1536  : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
1537  connected_(connected), front_(front)
1538  {}
1539 
1540  template<class G,class S>
1541  void Aggregate<G,S>::reconstruct(const Vertex& /*vertex*/)
1542  {
1543  /*
1544  vertices_.push_back(vertex);
1545  typedef typename VertexList::const_iterator iterator;
1546  iterator begin = vertices_.begin();
1547  iterator end = vertices_.end();*/
1548  throw "Not yet implemented";
1549 
1550  // while(begin!=end){
1551  //for();
1552  // }
1553 
1554  }
1555 
1556  template<class G,class S>
1557  inline void Aggregate<G,S>::seed(const Vertex& vertex)
1558  {
1559  dvverb<<"Connected cleared"<<std::endl;
1560  connected_.clear();
1561  vertices_.clear();
1562  connected_.insert(vertex);
1563  dvverb << " Inserting "<<vertex<<" size="<<connected_.size();
1564  ++id_ ;
1565  add(vertex);
1566  }
1567 
1568 
1569  template<class G,class S>
1570  inline void Aggregate<G,S>::add(const Vertex& vertex)
1571  {
1572  vertices_.insert(vertex);
1573  aggregates_[vertex]=id_;
1574  if(front_.size())
1575  front_.erase(std::lower_bound(front_.begin(), front_.end(), vertex));
1576 
1577 
1578  typedef typename MatrixGraph::ConstEdgeIterator iterator;
1579  const iterator end = graph_.endEdges(vertex);
1580  for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge) {
1581  dvverb << " Inserting "<<aggregates_[edge.target()];
1582  connected_.insert(aggregates_[edge.target()]);
1583  dvverb <<" size="<<connected_.size();
1584  if(aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED &&
1585  !graph_.getVertexProperties(edge.target()).front())
1586  {
1587  front_.push_back(edge.target());
1588  graph_.getVertexProperties(edge.target()).setFront();
1589  }
1590  }
1591  dvverb <<std::endl;
1592  std::sort(front_.begin(), front_.end());
1593  }
1594 
1595  template<class G,class S>
1596  inline void Aggregate<G,S>::add(std::vector<Vertex>& vertices)
1597  {
1598 #ifndef NDEBUG
1599  std::size_t oldsize = vertices_.size();
1600 #endif
1601  typedef typename std::vector<Vertex>::iterator Iterator;
1602 
1603  typedef typename VertexSet::iterator SIterator;
1604 
1605  SIterator pos=vertices_.begin();
1606  std::vector<Vertex> newFront;
1607  newFront.reserve(front_.capacity());
1608 
1609  std::set_difference(front_.begin(), front_.end(), vertices.begin(), vertices.end(),
1610  std::back_inserter(newFront));
1611  front_=newFront;
1612 
1613  for(Iterator vertex=vertices.begin(); vertex != vertices.end(); ++vertex)
1614  {
1615  pos=vertices_.insert(pos,*vertex);
1616  vertices_.insert(*vertex);
1617  graph_.getVertexProperties(*vertex).resetFront(); // Not a front node any more.
1618  aggregates_[*vertex]=id_;
1619 
1620  typedef typename MatrixGraph::ConstEdgeIterator iterator;
1621  const iterator end = graph_.endEdges(*vertex);
1622  for(iterator edge = graph_.beginEdges(*vertex); edge != end; ++edge) {
1623  dvverb << " Inserting "<<aggregates_[edge.target()];
1624  connected_.insert(aggregates_[edge.target()]);
1625  if(aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED &&
1626  !graph_.getVertexProperties(edge.target()).front())
1627  {
1628  front_.push_back(edge.target());
1629  graph_.getVertexProperties(edge.target()).setFront();
1630  }
1631  dvverb <<" size="<<connected_.size();
1632  }
1633  dvverb <<std::endl;
1634  }
1635  std::sort(front_.begin(), front_.end());
1636  assert(oldsize+vertices.size()==vertices_.size());
1637  }
1638  template<class G,class S>
1639  inline void Aggregate<G,S>::clear()
1640  {
1641  vertices_.clear();
1642  connected_.clear();
1643  id_=-1;
1644  }
1645 
1646  template<class G,class S>
1647  inline typename Aggregate<G,S>::size_type
1649  {
1650  return vertices_.size();
1651  }
1652 
1653  template<class G,class S>
1654  inline typename Aggregate<G,S>::size_type
1656  {
1657  return connected_.size();
1658  }
1659 
1660  template<class G,class S>
1661  inline int Aggregate<G,S>::id()
1662  {
1663  return id_;
1664  }
1665 
1666  template<class G,class S>
1668  {
1669  return vertices_.begin();
1670  }
1671 
1672  template<class G,class S>
1673  inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::end() const
1674  {
1675  return vertices_.end();
1676  }
1677 
1678  template<class V>
1679  const V AggregatesMap<V>::UNAGGREGATED = std::numeric_limits<V>::max();
1680 
1681  template<class V>
1682  const V AggregatesMap<V>::ISOLATED = std::numeric_limits<V>::max()-1;
1683 
1684  template<class V>
1686  : aggregates_(0)
1687  {}
1688 
1689  template<class V>
1691  {
1692  if(aggregates_!=0)
1693  delete[] aggregates_;
1694  }
1695 
1696 
1697  template<class V>
1698  inline AggregatesMap<V>::AggregatesMap(std::size_t noVertices)
1699  {
1700  allocate(noVertices);
1701  }
1702 
1703  template<class V>
1704  inline std::size_t AggregatesMap<V>::noVertices() const
1705  {
1706  return noVertices_;
1707  }
1708 
1709  template<class V>
1710  inline void AggregatesMap<V>::allocate(std::size_t noVertices)
1711  {
1712  aggregates_ = new AggregateDescriptor[noVertices];
1713  noVertices_ = noVertices;
1714 
1715  for(std::size_t i=0; i < noVertices; i++)
1716  aggregates_[i]=UNAGGREGATED;
1717  }
1718 
1719  template<class V>
1720  inline void AggregatesMap<V>::free()
1721  {
1722  assert(aggregates_ != 0);
1723  delete[] aggregates_;
1724  aggregates_=0;
1725  }
1726 
1727  template<class V>
1728  inline typename AggregatesMap<V>::AggregateDescriptor&
1729  AggregatesMap<V>::operator[](const VertexDescriptor& v)
1730  {
1731  return aggregates_[v];
1732  }
1733 
1734  template<class V>
1735  inline const typename AggregatesMap<V>::AggregateDescriptor&
1736  AggregatesMap<V>::operator[](const VertexDescriptor& v) const
1737  {
1738  return aggregates_[v];
1739  }
1740 
1741  template<class V>
1742  template<bool reset, class G, class F,class VM>
1743  inline std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
1744  const AggregateDescriptor& aggregate,
1745  const G& graph, F& aggregateVisitor,
1746  VM& visitedMap) const
1747  {
1748  VertexList vlist;
1749 
1750  DummyEdgeVisitor dummy;
1751  return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap);
1752  }
1753 
1754  template<class V>
1755  template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
1756  std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
1757  const AggregateDescriptor& aggregate,
1758  const G& graph,
1759  L& visited,
1760  F1& aggregateVisitor,
1761  F2& nonAggregateVisitor,
1762  VM& visitedMap) const
1763  {
1764  typedef typename L::const_iterator ListIterator;
1765  int visitedSpheres = 0;
1766 
1767  visited.push_back(start);
1768  put(visitedMap, start, true);
1769 
1770  ListIterator current = visited.begin();
1771  ListIterator end = visited.end();
1772  std::size_t i=0, size=visited.size();
1773 
1774  // visit the neighbours of all vertices of the
1775  // current sphere.
1776  while(current != end) {
1777 
1778  for(; i<size; ++current, ++i) {
1779  typedef typename G::ConstEdgeIterator EdgeIterator;
1780  const EdgeIterator endEdge = graph.endEdges(*current);
1781 
1782  for(EdgeIterator edge = graph.beginEdges(*current);
1783  edge != endEdge; ++edge) {
1784 
1785  if(aggregates_[edge.target()]==aggregate) {
1786  if(!get(visitedMap, edge.target())) {
1787  put(visitedMap, edge.target(), true);
1788  visited.push_back(edge.target());
1789  aggregateVisitor(edge);
1790  }
1791  }else
1792  nonAggregateVisitor(edge);
1793  }
1794  }
1795  end = visited.end();
1796  size = visited.size();
1797  if(current != end)
1798  visitedSpheres++;
1799  }
1800 
1801  if(reset)
1802  for(current = visited.begin(); current != end; ++current)
1803  put(visitedMap, *current, false);
1804 
1805 
1806  if(remove)
1807  visited.clear();
1808 
1809  return visitedSpheres;
1810  }
1811 
1812  template<class G>
1814  : graph_(0), aggregate_(0), front_(), connected_(), size_(-1)
1815  {}
1816 
1817  template<class G>
1819  {
1820  size_=-1;
1821  }
1822 
1823  template<class G, class C>
1824  void buildDependency(G& graph,
1825  const typename C::Matrix& matrix,
1826  C criterion, bool firstlevel)
1827  {
1828  // assert(graph.isBuilt());
1829  typedef typename C::Matrix Matrix;
1830  typedef typename G::VertexIterator VertexIterator;
1831 
1832  criterion.init(&matrix);
1833 
1834  for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex) {
1835  typedef typename Matrix::row_type Row;
1836 
1837  const Row& row = matrix[*vertex];
1838 
1839  // Tell the criterion what row we will examine now
1840  // This might for example be used for calculating the
1841  // maximum offdiagonal value
1842  criterion.initRow(row, *vertex);
1843 
1844  // On a first path all columns are examined. After this
1845  // the calculator should know whether the vertex is isolated.
1846  typedef typename Matrix::ConstColIterator ColIterator;
1847  ColIterator end = row.end();
1848  typename FieldTraits<typename Matrix::field_type>::real_type absoffdiag=0.;
1849 
1850  using std::max;
1851  if(firstlevel) {
1852  for(ColIterator col = row.begin(); col != end; ++col)
1853  if(col.index()!=*vertex) {
1854  criterion.examine(col);
1855  absoffdiag = max(absoffdiag, Impl::asMatrix(*col).frobenius_norm());
1856  }
1857 
1858  if(absoffdiag==0)
1859  vertex.properties().setExcludedBorder();
1860  }
1861  else
1862  for(ColIterator col = row.begin(); col != end; ++col)
1863  if(col.index()!=*vertex)
1864  criterion.examine(col);
1865 
1866  // reset the vertex properties
1867  //vertex.properties().reset();
1868 
1869  // Check whether the vertex is isolated.
1870  if(criterion.isIsolated()) {
1871  //std::cout<<"ISOLATED: "<<*vertex<<std::endl;
1872  vertex.properties().setIsolated();
1873  }else{
1874  // Examine all the edges beginning at this vertex.
1875  auto eEnd = vertex.end();
1876  auto col = matrix[*vertex].begin();
1877 
1878  for(auto edge = vertex.begin(); edge!= eEnd; ++edge, ++col) {
1879  // Move to the right column.
1880  while(col.index()!=edge.target())
1881  ++col;
1882  criterion.examine(graph, edge, col);
1883  }
1884  }
1885 
1886  }
1887  }
1888 
1889 
1890  template<class G>
1891  template<class V>
1892  inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates,
1893  const AggregateDescriptor& aggregate, V& visitor)
1894  : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
1895  {}
1896 
1897  template<class G>
1898  template<class V>
1899  inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1900  {
1901  if(aggregates_[edge.target()]==aggregate_)
1902  visitor_->operator()(edge);
1903  }
1904 
1905  template<class G>
1906  template<class V>
1907  inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
1908  const AggregateDescriptor& aggregate,
1909  const AggregatesMap<Vertex>& aggregates,
1910  V& visitor) const
1911  {
1912  // Only evaluates for edge pointing to the aggregate
1913  AggregateVisitor<V> v(aggregates, aggregate, visitor);
1914  visitNeighbours(*graph_, vertex, v);
1915  }
1916 
1917 
1918  template<class G>
1919  inline Aggregator<G>::Counter::Counter()
1920  : count_(0)
1921  {}
1922 
1923  template<class G>
1924  inline void Aggregator<G>::Counter::increment()
1925  {
1926  ++count_;
1927  }
1928 
1929  template<class G>
1930  inline void Aggregator<G>::Counter::decrement()
1931  {
1932  --count_;
1933  }
1934  template<class G>
1935  inline int Aggregator<G>::Counter::value()
1936  {
1937  return count_;
1938  }
1939 
1940  template<class G>
1941  inline void Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1942  {
1943  if(edge.properties().isTwoWay())
1944  Counter::increment();
1945  }
1946 
1947  template<class G>
1948  int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
1949  const AggregatesMap<Vertex>& aggregates) const
1950  {
1951  TwoWayCounter counter;
1952  visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
1953  return counter.value();
1954  }
1955 
1956  template<class G>
1957  int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
1958  const AggregatesMap<Vertex>& aggregates) const
1959  {
1960  OneWayCounter counter;
1961  visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
1962  return counter.value();
1963  }
1964 
1965  template<class G>
1966  inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1967  {
1968  if(edge.properties().isOneWay())
1969  Counter::increment();
1970  }
1971 
1972  template<class G>
1973  inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
1974  const AggregatesMap<Vertex>& aggregates)
1975  : Counter(), connected_(connected), aggregates_(aggregates)
1976  {}
1977 
1978 
1979  template<class G>
1980  inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1981  {
1982  if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
1983  // Would be a new connection
1984  Counter::increment();
1985  else{
1986  Counter::increment();
1987  Counter::increment();
1988  }
1989  }
1990 
1991  template<class G>
1992  inline double Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
1993  {
1994  ConnectivityCounter counter(connected_, aggregates);
1995  double noNeighbours=visitNeighbours(*graph_, vertex, counter);
1996  return (double)counter.value()/noNeighbours;
1997  }
1998 
1999  template<class G>
2000  inline Aggregator<G>::DependencyCounter::DependencyCounter()
2001  : Counter()
2002  {}
2003 
2004  template<class G>
2005  inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
2006  {
2007  if(edge.properties().depends())
2008  Counter::increment();
2009  if(edge.properties().influences())
2010  Counter::increment();
2011  }
2012 
2013  template<class G>
2014  int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
2015  {
2016  return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
2017  }
2018 
2019  template<class G>
2020  std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
2021  const AggregateDescriptor& aggregate,
2022  const AggregatesMap<Vertex>& aggregates) const
2023  {
2024  DependencyCounter unused, aggregated;
2025  typedef AggregateVisitor<DependencyCounter> CounterT;
2026  typedef std::tuple<CounterT,CounterT> CounterTuple;
2027  CombinedFunctor<CounterTuple> visitors(CounterTuple(CounterT(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), CounterT(aggregates, aggregate, aggregated)));
2028  visitNeighbours(*graph_, vertex, visitors);
2029  return std::make_pair(unused.value(), aggregated.value());
2030  }
2031 
2032 
2033  template<class G>
2034  int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
2035  {
2036  DependencyCounter counter;
2037  visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
2038  return counter.value();
2039  }
2040 
2041  template<class G>
2042  std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
2043  {
2044  return 0;
2045  typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
2046  VertexList vlist;
2047  typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
2048  return aggregates.template breadthFirstSearch<true,true>(vertex,
2049  aggregate_->id(), *graph_,
2050  vlist, dummy, dummy, visitedMap);
2051  }
2052 
2053  template<class G>
2054  inline Aggregator<G>::FrontMarker::FrontMarker(std::vector<Vertex>& front, MatrixGraph& graph)
2055  : front_(front), graph_(graph)
2056  {}
2057 
2058  template<class G>
2059  inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
2060  {
2061  Vertex target = edge.target();
2062 
2063  if(!graph_.getVertexProperties(target).front()) {
2064  front_.push_back(target);
2065  graph_.getVertexProperties(target).setFront();
2066  }
2067  }
2068 
2069  template<class G>
2070  inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
2071  {
2072  // Todo
2073  Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
2074  return true;
2075  //Situation 1: front node depends on two nodes. Then these
2076  // have to be strongly connected to each other
2077 
2078  // Iterate over all all neighbours of front node
2079  typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2080  Iterator vend = graph_->endEdges(vertex);
2081  for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge) {
2082  // if(edge.properties().depends() && !edge.properties().influences()
2083  if(edge.properties().isStrong()
2084  && aggregates[edge.target()]==aggregate)
2085  {
2086  // Search for another link to the aggregate
2087  Iterator edge1 = edge;
2088  for(++edge1; edge1 != vend; ++edge1) {
2089  //if(edge1.properties().depends() && !edge1.properties().influences()
2090  if(edge1.properties().isStrong()
2091  && aggregates[edge.target()]==aggregate)
2092  {
2093  //Search for an edge connecting the two vertices that is
2094  //strong
2095  bool found=false;
2096  Iterator v2end = graph_->endEdges(edge.target());
2097  for(Iterator edge2 = graph_->beginEdges(edge.target()); edge2 != v2end; ++edge2) {
2098  if(edge2.target()==edge1.target() &&
2099  edge2.properties().isStrong()) {
2100  found =true;
2101  break;
2102  }
2103  }
2104  if(found)
2105  {
2106  return true;
2107  }
2108  }
2109  }
2110  }
2111  }
2112 
2113  // Situation 2: cluster node depends on front node and other cluster node
2115  vend = graph_->endEdges(vertex);
2116  for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge) {
2117  //if(!edge.properties().depends() && edge.properties().influences()
2118  if(edge.properties().isStrong()
2119  && aggregates[edge.target()]==aggregate)
2120  {
2121  // Search for a link from target that stays within the aggregate
2122  Iterator v1end = graph_->endEdges(edge.target());
2123 
2124  for(Iterator edge1=graph_->beginEdges(edge.target()); edge1 != v1end; ++edge1) {
2125  //if(edge1.properties().depends() && !edge1.properties().influences()
2126  if(edge1.properties().isStrong()
2127  && aggregates[edge1.target()]==aggregate)
2128  {
2129  bool found=false;
2130  // Check if front node is also connected to this one
2131  Iterator v2end = graph_->endEdges(vertex);
2132  for(Iterator edge2 = graph_->beginEdges(vertex); edge2 != v2end; ++edge2) {
2133  if(edge2.target()==edge1.target()) {
2134  if(edge2.properties().isStrong())
2135  found=true;
2136  break;
2137  }
2138  }
2139  if(found)
2140  {
2141  return true;
2142  }
2143  }
2144  }
2145  }
2146  }
2147  return false;
2148  }
2149 
2150  template<class G>
2151  void Aggregator<G>::unmarkFront()
2152  {
2153  typedef typename std::vector<Vertex>::const_iterator Iterator;
2154 
2155  for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
2156  graph_->getVertexProperties(*vertex).resetFront();
2157 
2158  front_.clear();
2159  }
2160 
2161  template<class G>
2162  inline void
2163  Aggregator<G>::nonisoNeighbourAggregate(const Vertex& vertex,
2164  const AggregatesMap<Vertex>& aggregates,
2165  SLList<Vertex>& neighbours) const
2166  {
2167  typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2168  Iterator end=graph_->beginEdges(vertex);
2169  neighbours.clear();
2170 
2171  for(Iterator edge=graph_->beginEdges(vertex); edge!=end; ++edge)
2172  {
2173  if(aggregates[edge.target()]!=AggregatesMap<Vertex>::UNAGGREGATED && graph_->getVertexProperties(edge.target()).isolated())
2174  neighbours.push_back(aggregates[edge.target()]);
2175  }
2176  }
2177 
2178  template<class G>
2179  inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
2180  {
2181  typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2182 
2183  Iterator end = graph_->endEdges(vertex);
2184  for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge) {
2185  if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
2186  graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()) {
2187  if( graph_->getVertexProperties(vertex).isolated() ||
2188  ((edge.properties().depends() || edge.properties().influences())
2189  && admissible(vertex, aggregates[edge.target()], aggregates)))
2190  return edge.target();
2191  }
2192  }
2194  }
2195 
2196  template<class G>
2197  Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph)
2198  : Counter(), graph_(graph)
2199  {}
2200 
2201  template<class G>
2202  void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
2203  {
2204  if(graph_.getVertexProperties(edge.target()).front())
2205  Counter::increment();
2206  }
2207 
2208  template<class G>
2209  int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
2210  {
2211  FrontNeighbourCounter counter(*graph_);
2212  visitNeighbours(*graph_, vertex, counter);
2213  return counter.value();
2214  }
2215  template<class G>
2216  inline bool Aggregator<G>::connected(const Vertex& vertex,
2217  const AggregateDescriptor& aggregate,
2218  const AggregatesMap<Vertex>& aggregates) const
2219  {
2220  typedef typename G::ConstEdgeIterator iterator;
2221  const iterator end = graph_->endEdges(vertex);
2222  for(iterator edge = graph_->beginEdges(vertex); edge != end; ++edge)
2223  if(aggregates[edge.target()]==aggregate)
2224  return true;
2225  return false;
2226  }
2227  template<class G>
2228  inline bool Aggregator<G>::connected(const Vertex& vertex,
2229  const SLList<AggregateDescriptor>& aggregateList,
2230  const AggregatesMap<Vertex>& aggregates) const
2231  {
2232  typedef typename SLList<AggregateDescriptor>::const_iterator Iter;
2233  for(Iter i=aggregateList.begin(); i!=aggregateList.end(); ++i)
2234  if(connected(vertex, *i, aggregates))
2235  return true;
2236  return false;
2237  }
2238 
2239  template<class G>
2240  template<class C>
2241  void Aggregator<G>::growIsolatedAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
2242  {
2243  SLList<Vertex> connectedAggregates;
2244  nonisoNeighbourAggregate(seed, aggregates,connectedAggregates);
2245 
2246  while(aggregate_->size()< c.minAggregateSize() && aggregate_->connectSize() < c.maxConnectivity()) {
2247  double maxCon=-1;
2248  std::size_t maxFrontNeighbours=0;
2249 
2251 
2252  typedef typename std::vector<Vertex>::const_iterator Iterator;
2253 
2254  for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2255  if(distance(*vertex, aggregates)>c.maxDistance())
2256  continue; // distance of proposes aggregate too big
2257 
2258  if(connectedAggregates.size()>0) {
2259  // there is already a neighbour cluster
2260  // front node must be connected to same neighbour cluster
2261 
2262  if(!connected(*vertex, connectedAggregates, aggregates))
2263  continue;
2264  }
2265 
2266  double con = connectivity(*vertex, aggregates);
2267 
2268  if(con == maxCon) {
2269  std::size_t frontNeighbours = noFrontNeighbours(*vertex);
2270 
2271  if(frontNeighbours >= maxFrontNeighbours) {
2272  maxFrontNeighbours = frontNeighbours;
2273  candidate = *vertex;
2274  }
2275  }else if(con > maxCon) {
2276  maxCon = con;
2277  maxFrontNeighbours = noFrontNeighbours(*vertex);
2278  candidate = *vertex;
2279  }
2280  }
2281 
2283  break;
2284 
2285  aggregate_->add(candidate);
2286  }
2287  }
2288 
2289  template<class G>
2290  template<class C>
2291  void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
2292  {
2293  using std::min;
2294 
2295  std::size_t distance_ =0;
2296  while(aggregate_->size() < c.minAggregateSize()&& distance_<c.maxDistance()) {
2297  int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1;
2298  double maxCon=-1;
2299 
2300  std::vector<Vertex> candidates;
2301  candidates.reserve(30);
2302 
2303  typedef typename std::vector<Vertex>::const_iterator Iterator;
2304 
2305  for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2306  // Only nonisolated nodes are considered
2307  if(graph_->getVertexProperties(*vertex).isolated())
2308  continue;
2309 
2310  int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
2311 
2312  /* The case of two way connections. */
2313  if( maxTwoCons == twoWayCons && twoWayCons > 0) {
2314  double con = connectivity(*vertex, aggregates);
2315 
2316  if(con == maxCon) {
2317  int neighbours = noFrontNeighbours(*vertex);
2318 
2319  if(neighbours > maxNeighbours) {
2320  maxNeighbours = neighbours;
2321  candidates.clear();
2322  candidates.push_back(*vertex);
2323  }else{
2324  candidates.push_back(*vertex);
2325  }
2326  }else if( con > maxCon) {
2327  maxCon = con;
2328  maxNeighbours = noFrontNeighbours(*vertex);
2329  candidates.clear();
2330  candidates.push_back(*vertex);
2331  }
2332  }else if(twoWayCons > maxTwoCons) {
2333  maxTwoCons = twoWayCons;
2334  maxCon = connectivity(*vertex, aggregates);
2335  maxNeighbours = noFrontNeighbours(*vertex);
2336  candidates.clear();
2337  candidates.push_back(*vertex);
2338 
2339  // two way connections precede
2340  maxOneCons = std::numeric_limits<int>::max();
2341  }
2342 
2343  if(twoWayCons > 0)
2344  {
2345  continue; // THis is a two-way node, skip tests for one way nodes
2346  }
2347 
2348  /* The one way case */
2349  int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
2350 
2351  if(oneWayCons==0)
2352  continue; // No strong connections, skip the tests.
2353 
2354  if(!admissible(*vertex, aggregate_->id(), aggregates))
2355  continue;
2356 
2357  if( maxOneCons == oneWayCons && oneWayCons > 0) {
2358  double con = connectivity(*vertex, aggregates);
2359 
2360  if(con == maxCon) {
2361  int neighbours = noFrontNeighbours(*vertex);
2362 
2363  if(neighbours > maxNeighbours) {
2364  maxNeighbours = neighbours;
2365  candidates.clear();
2366  candidates.push_back(*vertex);
2367  }else{
2368  if(neighbours==maxNeighbours)
2369  {
2370  candidates.push_back(*vertex);
2371  }
2372  }
2373  }else if( con > maxCon) {
2374  maxCon = con;
2375  maxNeighbours = noFrontNeighbours(*vertex);
2376  candidates.clear();
2377  candidates.push_back(*vertex);
2378  }
2379  }else if(oneWayCons > maxOneCons) {
2380  maxOneCons = oneWayCons;
2381  maxCon = connectivity(*vertex, aggregates);
2382  maxNeighbours = noFrontNeighbours(*vertex);
2383  candidates.clear();
2384  candidates.push_back(*vertex);
2385  }
2386  }
2387 
2388 
2389  if(!candidates.size())
2390  break; // No more candidates found
2391  distance_=distance(seed, aggregates);
2392  candidates.resize(min(candidates.size(), c.maxAggregateSize()-
2393  aggregate_->size()));
2394  aggregate_->add(candidates);
2395  }
2396  }
2397 
2398  template<typename V>
2399  template<typename M, typename G, typename C>
2400  std::tuple<int,int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion,
2401  bool finestLevel)
2402  {
2403  Aggregator<G> aggregator;
2404  return aggregator.build(matrix, graph, *this, criterion, finestLevel);
2405  }
2406 
2407  template<class G>
2408  template<class M, class C>
2409  std::tuple<int,int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c,
2410  bool finestLevel)
2411  {
2412  using std::max;
2413  using std::min;
2414  // Stack for fast vertex access
2415  Stack stack_(graph, *this, aggregates);
2416 
2417  graph_ = &graph;
2418 
2419  aggregate_ = new Aggregate<G,VertexSet>(graph, aggregates, connected_, front_);
2420 
2421  Timer watch;
2422  watch.reset();
2423 
2424  buildDependency(graph, m, c, finestLevel);
2425 
2426  dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
2427  int noAggregates, conAggregates, isoAggregates, oneAggregates;
2428  std::size_t maxA=0, minA=1000000, avg=0;
2429  int skippedAggregates;
2430  noAggregates = conAggregates = isoAggregates = oneAggregates =
2431  skippedAggregates = 0;
2432 
2433  while(true) {
2434  Vertex seed = stack_.pop();
2435 
2436  if(seed == Stack::NullEntry)
2437  // No more unaggregated vertices. We are finished!
2438  break;
2439 
2440  // Debugging output
2441  if((noAggregates+1)%10000 == 0)
2442  Dune::dverb<<"c";
2443  unmarkFront();
2444 
2445  if(graph.getVertexProperties(seed).excludedBorder()) {
2446  aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
2447  ++skippedAggregates;
2448  continue;
2449  }
2450 
2451  if(graph.getVertexProperties(seed).isolated()) {
2452  if(c.skipIsolated()) {
2453  // isolated vertices are not aggregated but skipped on the coarser levels.
2454  aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
2455  ++skippedAggregates;
2456  // skip rest as no agglomeration is done.
2457  continue;
2458  }else{
2459  aggregate_->seed(seed);
2460  growIsolatedAggregate(seed, aggregates, c);
2461  }
2462  }else{
2463  aggregate_->seed(seed);
2464  growAggregate(seed, aggregates, c);
2465  }
2466 
2467  /* The rounding step. */
2468  while(!(graph.getVertexProperties(seed).isolated()) && aggregate_->size() < c.maxAggregateSize()) {
2469 
2470  std::vector<Vertex> candidates;
2471  candidates.reserve(30);
2472 
2473  typedef typename std::vector<Vertex>::const_iterator Iterator;
2474 
2475  for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2476 
2477  if(graph.getVertexProperties(*vertex).isolated())
2478  continue; // No isolated nodes here
2479 
2480  if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 &&
2481  (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 ||
2482  !admissible( *vertex, aggregate_->id(), aggregates) ))
2483  continue;
2484 
2485  std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
2486  aggregates);
2487 
2488  //if(aggregateNeighbours(*vertex, aggregate_->id(), aggregates) <= unusedNeighbours(*vertex, aggregates))
2489  // continue;
2490 
2491  if(neighbourPair.first >= neighbourPair.second)
2492  continue;
2493 
2494  if(distance(*vertex, aggregates) > c.maxDistance())
2495  continue; // Distance too far
2496  candidates.push_back(*vertex);
2497  break;
2498  }
2499 
2500  if(!candidates.size()) break; // no more candidates found.
2501 
2502  candidates.resize(min(candidates.size(), c.maxAggregateSize()-
2503  aggregate_->size()));
2504  aggregate_->add(candidates);
2505 
2506  }
2507 
2508  // try to merge aggregates consisting of only one nonisolated vertex with other aggregates
2509  if(aggregate_->size()==1 && c.maxAggregateSize()>1) {
2510  if(!graph.getVertexProperties(seed).isolated()) {
2511  Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
2512 
2513  if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED) {
2514  // assign vertex to the neighbouring cluster
2515  aggregates[seed] = aggregates[mergedNeighbour];
2516  aggregate_->invalidate();
2517  }else{
2518  ++avg;
2519  minA=min(minA,static_cast<std::size_t>(1));
2520  maxA=max(maxA,static_cast<std::size_t>(1));
2521  ++oneAggregates;
2522  ++conAggregates;
2523  }
2524  }else{
2525  ++avg;
2526  minA=min(minA,static_cast<std::size_t>(1));
2527  maxA=max(maxA,static_cast<std::size_t>(1));
2528  ++oneAggregates;
2529  ++isoAggregates;
2530  }
2531  ++avg;
2532  }else{
2533  avg+=aggregate_->size();
2534  minA=min(minA,aggregate_->size());
2535  maxA=max(maxA,aggregate_->size());
2536  if(graph.getVertexProperties(seed).isolated())
2537  ++isoAggregates;
2538  else
2539  ++conAggregates;
2540  }
2541 
2542  }
2543 
2544  Dune::dinfo<<"connected aggregates: "<<conAggregates;
2545  Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
2546  if(conAggregates+isoAggregates>0)
2547  Dune::dinfo<<" one node aggregates: "<<oneAggregates<<" min size="
2548  <<minA<<" max size="<<maxA
2549  <<" avg="<<avg/(conAggregates+isoAggregates)<<std::endl;
2550 
2551  delete aggregate_;
2552  return std::make_tuple(conAggregates+isoAggregates,isoAggregates,
2553  oneAggregates,skippedAggregates);
2554  }
2555 
2556 
2557  template<class G>
2558  Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
2559  const AggregatesMap<Vertex>& aggregates)
2560  : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), begin_(graph.begin()), end_(graph.end())
2561  {
2562  //vals_ = new Vertex[N];
2563  }
2564 
2565  template<class G>
2566  Aggregator<G>::Stack::~Stack()
2567  {
2568  //Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
2569  //delete[] vals_;
2570  }
2571 
2572  template<class G>
2573  const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry
2574  = std::numeric_limits<typename G::VertexDescriptor>::max();
2575 
2576  template<class G>
2577  inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
2578  {
2579  for(; begin_!=end_ && aggregates_[*begin_] != AggregatesMap<Vertex>::UNAGGREGATED; ++begin_) ;
2580 
2581  if(begin_!=end_)
2582  {
2583  typename G::VertexDescriptor current=*begin_;
2584  ++begin_;
2585  return current;
2586  }else
2587  return NullEntry;
2588  }
2589 
2590 #endif // DOXYGEN
2591 
2592  template<class V>
2593  void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m, std::ostream& os)
2594  {
2595  using std::max;
2596 
2597  std::ios_base::fmtflags oldOpts=os.flags();
2598 
2599  os.setf(std::ios_base::right, std::ios_base::adjustfield);
2600 
2601  V maxVal=0;
2602  int width=1;
2603 
2604  for(int i=0; i< n*m; i++)
2605  maxVal=max(maxVal, aggregates[i]);
2606 
2607  for(int i=10; i < 1000000; i*=10)
2608  if(maxVal/i>0)
2609  width++;
2610  else
2611  break;
2612 
2613  for(int j=0, entry=0; j < m; j++) {
2614  for(int i=0; i<n; i++, entry++) {
2615  os.width(width);
2616  os<<aggregates[entry]<<" ";
2617  }
2618 
2619  os<<std::endl;
2620  }
2621  os<<std::endl;
2622  os.flags(oldOpts);
2623  }
2624 
2625 
2626  } // namespace Amg
2627 
2628 } // namespace Dune
2629 
2630 
2631 #endif
int id()
Get the id identifying the aggregate.
void examine(const ColIter &col)
Definition: aggregates.hh:501
const_iterator begin() const
Definition: aggregates.hh:731
void add(const Vertex &vertex)
Add a vertex to the aggregate.
S VertexSet
The type of a single linked list of vertex descriptors.
Definition: aggregates.hh:807
Norm that uses only the [0][0] entry of the block to determine couplings.
Definition: aggregates.hh:456
All parameters for AMG.
Definition: parameters.hh:415
A class for temporarily storing the vertices of an aggregate in.
Definition: aggregates.hh:783
Class for building the aggregates.
Definition: aggregates.hh:554
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:336
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:365
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:156
std::size_t * SphereMap
Type of the mapping of aggregate members onto distance spheres.
Definition: aggregates.hh:820
const_iterator end() const
get an iterator over the vertices of the aggregate.
MatrixImp::DenseMatrixBase< T, A >::window_type row_type
The type implementing a matrix row.
Definition: matrix.hh:574
derive error class from the base class in common
Definition: istlexception.hh:19
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:298
void initRow(const Row &row, int index)
auto operator()(const M &m) const
compute the norm of a matrix.
Definition: aggregates.hh:475
Matrix::field_type field_type
The current max value.
Definition: aggregates.hh:300
UnSymmetricCriterion()
Definition: aggregates.hh:550
auto operator()(const M &m, typename std::enable_if_t< Dune::IsNumber< M >::value > *=nullptr) const
Compute the norm of a scalar.
Definition: aggregates.hh:408
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:275
static const V UNAGGREGATED
Identifier of not yet aggregated vertices.
Definition: aggregates.hh:572
void initRow(const Row &row, int index)
Aggregator()
Constructor.
Dependency policy for symmetric matrices.
Definition: aggregates.hh:254
void init(const Matrix *matrix)
Definition: aggregates.hh:197
Provides classes for handling internal properties in a graph.
Iterator over all edges starting from a vertex.
Definition: graph.hh:94
void clear()
Clear the aggregate.
void printAggregates2d(const AggregatesMap< V > &aggregates, int n, int m, std::ostream &os)
Definition: aggregates.hh:2593
V Visitor
The type of the adapted visitor.
Definition: aggregates.hh:1075
int row_
index of the currently evaluated row.
Definition: aggregates.hh:187
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:331
real_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:189
std::tuple< int, int, int, int > buildAggregates(const M &matrix, G &graph, const C &criterion, bool finestLevel)
Build the aggregates.
void init(const Matrix *matrix)
Col col
Definition: matrixmatrix.hh:351
M::size_type VertexDescriptor
The vertex descriptor.
Definition: graph.hh:73
AggregateDescriptor * iterator
Definition: aggregates.hh:741
AggregatesMap()
Constructs without allocating memory.
std::size_t noVertices() const
Get the number of vertices.
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:185
void seed(const Vertex &vertex)
Initialize the aggregate with one vertex.
Definition: aggregates.hh:485
void allocate(std::size_t noVertices)
Allocate memory for holding the information.
Norm that uses only the [N][N] entry of the block to determine couplings.
Definition: aggregates.hh:380
FieldTraits< typename M::field_type >::real_type operator()(const M &) const
compute the norm of a matrix.
Definition: aggregates.hh:512
Dependency policy for symmetric matrices.
Definition: aggregates.hh:135
int row_
index of the currently evaluated row.
Definition: aggregates.hh:306
void examine(const ColIter &col)
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:270
The (undirected) graph of a matrix.
Definition: graph.hh:50
real_type maxValue_
Definition: aggregates.hh:183
real_type maxValue_
Definition: aggregates.hh:302
UnSymmetricCriterion(const Parameters &parms)
Definition: aggregates.hh:547
real_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:369
SymmetricDependency(const Parameters &parms)
Definition: aggregates.hh:350
SymmetricDependency()
Definition: aggregates.hh:353
Criterion taking advantage of symmetric matrices.
Definition: aggregates.hh:524
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:151
SymmetricCriterion(const Parameters &parms)
Definition: aggregates.hh:527
Functor using the row sum (infinity) norm to determine strong couplings.
Definition: aggregates.hh:464
const_iterator begin() const
get an iterator over the vertices of the aggregate.
row_type::const_iterator ConstColIterator
Const iterator for the entries of each row.
Definition: matrix.hh:589
iterator begin()
Definition: aggregates.hh:743
std::vector< real_type >::iterator valIter_
Definition: aggregates.hh:191
void free()
Free the allocated memory.
PoolAllocator< Vertex, 100 > Allocator
The allocator we use for our lists and the set.
Definition: aggregates.hh:801
AggregationCriterion(const Parameters &parms)
Definition: aggregates.hh:72
Aggregate(MatrixGraph &graph, AggregatesMap< Vertex > &aggregates, VertexSet &connectivity, std::vector< Vertex > &front_)
Constructor.
SymmetricMatrixDependency()
Definition: aggregates.hh:173
Parameter classes for customizing AMG.
bool isIsolated()
Definition: aggregates.hh:242
Dependency(const Parameters &parms)
Definition: aggregates.hh:288
T DependencyPolicy
The policy for calculating the dependency graph.
Definition: aggregates.hh:57
real_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:308
void operator()([[maybe_unused]] const EdgeIterator &edge) const
Definition: aggregates.hh:607
void setDefaultValuesIsotropic(std::size_t dim, std::size_t diameter=2)
Sets reasonable default values for an isotropic problem.
Definition: aggregates.hh:84
std::vector< real_type > vals_
Definition: aggregates.hh:190
int visitNeighbours(const G &graph, const typename G::VertexDescriptor &vertex, V &visitor)
Visit all neighbour vertices of a vertex in a graph.
real_type maxValue_
Definition: aggregates.hh:363
Dependency()
Definition: aggregates.hh:292
EdgeIteratorT< const MatrixGraph< Matrix > > ConstEdgeIterator
The constant edge iterator type.
Definition: graph.hh:298
Matrix::field_type field_type
The current max value.
Definition: aggregates.hh:181
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:260
A Dummy visitor that does nothing for each visited edge.
Definition: aggregates.hh:603
FieldTraits< field_type >::real_type real_type
Definition: aggregates.hh:362
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:304
Definition: aggregates.hh:384
Criterion suitable for unsymmetric matrices.
Definition: aggregates.hh:544
std::size_t breadthFirstSearch(const VertexDescriptor &start, const AggregateDescriptor &aggregate, const G &graph, F &aggregateVisitor, VM &visitedMap) const
Breadth first search within an aggregate.
MatrixGraph::VertexDescriptor Vertex
The vertex identifier.
Definition: aggregates.hh:931
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:359
PoolAllocator< VertexDescriptor, 100 > Allocator
The allocator we use for our lists and the set.
Definition: aggregates.hh:592
void init(const Matrix *matrix)
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:141
FieldTraits< field_type >::real_type real_type
Definition: aggregates.hh:301
Provides classes for building the matrix graph.
void initRow(const Row &row, int index)
Definition: aggregates.hh:203
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:392
void invalidate()
Definition: aggregates.hh:833
typename VertexSet::size_type size_type
Type of size used by allocator of sllist.
Definition: aggregates.hh:812
SymmetricMatrixDependency(const Parameters &parms)
Definition: aggregates.hh:170
G MatrixGraph
The matrix graph type used.
Definition: aggregates.hh:926
SLList< VertexDescriptor, Allocator > VertexList
The type of a single linked list of vertex descriptors.
Definition: aggregates.hh:598
size_type connectSize()
Get the number of connections to other aggregates.
void reconstruct(const Vertex &vertex)
Reconstruct the aggregat from an seed node.
void setDefaultValuesAnisotropic(std::size_t dim, std::size_t diameter=2)
Sets reasonable default values for an aisotropic problem.
Definition: aggregates.hh:107
N Norm
The norm to use for examining the matrix entries.
Definition: aggregates.hh:265
int row_
index of the currently evaluated row.
Definition: aggregates.hh:367
VertexSet::const_iterator const_iterator
Const iterator over a vertex list.
Definition: aggregates.hh:815
void examine(const ColIter &col)
Definition: aggregates.hh:216
G MatrixGraph
Definition: aggregates.hh:791
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:321
N Norm
The norm to use for examining the matrix entries.
Definition: aggregates.hh:146
Matrix::field_type field_type
The current max value.
Definition: aggregates.hh:361
std::tuple< int, int, int, int > build(const M &m, G &graph, AggregatesMap< Vertex > &aggregates, const C &c, bool finestLevel)
Build the aggregates.
static const V ISOLATED
Identifier of isolated vertices.
Definition: aggregates.hh:577
friend class Stack
Definition: aggregates.hh:1047
~Aggregator()
Destructor.
FieldTraits< field_type >::real_type real_type
Definition: aggregates.hh:182
AggregateDescriptor & operator[](const VertexDescriptor &v)
Get the aggregate a vertex belongs to.
MatrixGraph::VertexDescriptor Vertex
The vertex descriptor type.
Definition: aggregates.hh:795
N Norm
The norm to use for examining the matrix entries.
Definition: aggregates.hh:326
size_type size()
Get the size of the aggregate.
V VertexDescriptor
The vertex descriptor type.
Definition: aggregates.hh:581
Definition: aggregates.hh:468
MatrixGraph::VertexDescriptor AggregateDescriptor
The type of the aggregate descriptor.
Definition: aggregates.hh:934
Definition: allocator.hh:11
FieldTraits< typename M::field_type >::real_type operator()(const M &m) const
compute the norm of a matrix.
Definition: aggregates.hh:496
static const Vertex NullEntry
Definition: aggregates.hh:1019
Dependency policy for symmetric matrices.
Definition: aggregates.hh:315
~AggregatesMap()
Destructor.
Class providing information about the mapping of the vertices onto aggregates.
Definition: aggregates.hh:565
The vertex iterator type of the graph.
Definition: graph.hh:208
const_iterator end() const
Definition: aggregates.hh:736
typename Imp::BlockTraits< T >::field_type field_type
Export the type representing the underlying field.
Definition: matrix.hh:565
Base class of all aggregation criterions.
Definition: aggregates.hh:50
iterator end()
Definition: aggregates.hh:748
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:179
const AggregateDescriptor * const_iterator
Definition: aggregates.hh:729
SymmetricCriterion()
Definition: aggregates.hh:530
void buildDependency(G &graph, const typename C::Matrix &matrix, C criterion, bool finestLevel)
Build the dependency of the matrix graph.
AggregationCriterion()
Constructor.
Definition: aggregates.hh:68
V AggregateDescriptor
The aggregate descriptor type.
Definition: aggregates.hh:586