Dune Core Modules (2.3.1)

aggregates.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 // $Id$
4 #ifndef DUNE_AMG_AGGREGATES_HH
5 #define DUNE_AMG_AGGREGATES_HH
6 
7 
8 #include "parameters.hh"
9 #include "graph.hh"
10 #include "properties.hh"
11 #include "combinedfunctor.hh"
12 
13 #include <dune/common/timer.hh>
14 #include <dune/common/tuples.hh>
17 #include <dune/common/sllist.hh>
18 #include <dune/common/unused.hh>
19 
20 #include <utility>
21 #include <set>
22 #include <algorithm>
23 #include <limits>
24 #include <ostream>
25 
26 namespace Dune
27 {
28  namespace Amg
29  {
30 
44  template<class T>
45  class AggregationCriterion : public T
46  {
47 
48  public:
52  typedef T DependencyPolicy;
53 
64  : T()
65  {}
66 
67  AggregationCriterion(const Parameters& parms)
68  : T(parms)
69  {}
79  void setDefaultValuesIsotropic(std::size_t dim, std::size_t diameter=2)
80  {
81  this->setMaxDistance(diameter-1);
82  std::size_t csize=1;
83 
84  for(; dim>0; dim--) {
85  csize*=diameter;
86  this->setMaxDistance(this->maxDistance()+diameter-1);
87  }
88  this->setMinAggregateSize(csize);
89  this->setMaxAggregateSize(static_cast<std::size_t>(csize*1.5));
90  }
91 
102  void setDefaultValuesAnisotropic(std::size_t dim,std::size_t diameter=2)
103  {
104  setDefaultValuesIsotropic(dim, diameter);
105  this->setMaxDistance(this->maxDistance()+dim-1);
106  }
107  };
108 
109  template<class T>
110  std::ostream& operator<<(std::ostream& os, const AggregationCriterion<T>& criterion)
111  {
112  os<<"{ maxdistance="<<criterion.maxDistance()<<" minAggregateSize="
113  <<criterion.minAggregateSize()<< " maxAggregateSize="<<criterion.maxAggregateSize()
114  <<" connectivity="<<criterion.maxConnectivity()<<" debugLevel="<<criterion.debugLevel()<<"}";
115  return os;
116  }
117 
129  template<class M, class N>
131  {
132  public:
136  typedef M Matrix;
137 
141  typedef N Norm;
142 
146  typedef typename Matrix::row_type Row;
147 
152 
153  void init(const Matrix* matrix);
154 
155  void initRow(const Row& row, int index);
156 
157  void examine(const ColIter& col);
158 
159  template<class G>
160  void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
161 
162  bool isIsolated();
163 
164 
166  : Parameters(parms)
167  {}
169  : Parameters()
170  {}
171 
172  protected:
174  const Matrix* matrix_;
180  int row_;
183  std::vector<typename Matrix::field_type> vals_;
184  typename std::vector<typename Matrix::field_type>::iterator valIter_;
185 
186  };
187 
188 
189  template<class M, class N>
190  inline void SymmetricMatrixDependency<M,N>::init(const Matrix* matrix)
191  {
192  matrix_ = matrix;
193  }
194 
195  template<class M, class N>
196  inline void SymmetricMatrixDependency<M,N>::initRow(const Row& row, int index)
197  {
198  vals_.assign(row.size(), 0.0);
199  assert(vals_.size()==row.size());
200  valIter_=vals_.begin();
201 
202  maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
203  diagonal_=norm_(row[index]);
204  row_ = index;
205  }
206 
207  template<class M, class N>
208  inline void SymmetricMatrixDependency<M,N>::examine(const ColIter& col)
209  {
210  // skip positive offdiagonals if norm preserves sign of them.
211  typename Matrix::field_type eij = norm_(*col);
212  if(!N::is_sign_preserving || eij<0) // || eji<0)
213  {
214  *valIter_ = eij/diagonal_*eij/norm_(matrix_->operator[](col.index())[col.index()]);
215  maxValue_ = std::max(maxValue_, *valIter_);
216  }else
217  *valIter_ =0;
218  ++valIter_;
219  }
220 
221  template<class M, class N>
222  template<class G>
223  inline void SymmetricMatrixDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
224  {
225  if(*valIter_ > alpha() * maxValue_) {
226  edge.properties().setDepends();
227  edge.properties().setInfluences();
228  }
229  ++valIter_;
230  }
231 
232  template<class M, class N>
233  inline bool SymmetricMatrixDependency<M,N>::isIsolated()
234  {
235  if(diagonal_==0)
236  DUNE_THROW(Dune::ISTLError, "No diagonal entry for row "<<row_<<".");
237  valIter_=vals_.begin();
238  return maxValue_ < beta();
239  }
240 
244  template<class M, class N>
245  class Dependency : public Parameters
246  {
247  public:
251  typedef M Matrix;
252 
256  typedef N Norm;
257 
261  typedef typename Matrix::row_type Row;
262 
267 
268  void init(const Matrix* matrix);
269 
270  void initRow(const Row& row, int index);
271 
272  void examine(const ColIter& col);
273 
274  template<class G>
275  void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
276 
277  bool isIsolated();
278 
279  Dependency(const Parameters& parms)
280  : Parameters(parms)
281  {}
282 
283  Dependency()
284  : Parameters()
285  {}
286 
287  protected:
289  const Matrix* matrix_;
295  int row_;
298  };
299 
303  template<class M, class N>
305  {
306  public:
310  typedef M Matrix;
311 
315  typedef N Norm;
316 
320  typedef typename Matrix::row_type Row;
321 
326 
327  void init(const Matrix* matrix);
328 
329  void initRow(const Row& row, int index);
330 
331  void examine(const ColIter& col);
332 
333  template<class G>
334  void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
335 
336  bool isIsolated();
337 
338 
339  SymmetricDependency(const Parameters& parms)
340  : Parameters(parms)
341  {}
343  : Parameters()
344  {}
345 
346  protected:
348  const Matrix* matrix_;
354  int row_;
357  };
358 
363  template<int N>
364  class Diagonal
365  {
366  public:
367  enum { /* @brief We preserve the sign.*/
368  is_sign_preserving = true
369  };
370 
375  template<class M>
376  typename M::field_type operator()(const M& m) const
377  {
378  return m[N][N];
379  }
380  };
381 
386  class FirstDiagonal : public Diagonal<0>
387  {};
388 
394  struct RowSum
395  {
396 
397  enum { /* @brief We preserve the sign.*/
398  is_sign_preserving = false
399  };
404  template<class M>
405  typename M::field_type operator()(const M& m) const
406  {
407  return m.infinity_norm();
408  }
409  };
410 
411  struct FrobeniusNorm
412  {
413 
414  enum { /* @brief We preserve the sign.*/
415  is_sign_preserving = false
416  };
421  template<class M>
422  typename M::field_type operator()(const M& m) const
423  {
424  return m.frobenius_norm();
425  }
426  };
427  struct AlwaysOneNorm
428  {
429 
430  enum { /* @brief We preserve the sign.*/
431  is_sign_preserving = false
432  };
437  template<class M>
438  typename M::field_type operator()(const M& m) const
439  {
440  return 1;
441  }
442  };
452  template<class M, class Norm>
453  class SymmetricCriterion : public AggregationCriterion<SymmetricDependency<M,Norm> >
454  {
455  public:
456  SymmetricCriterion(const Parameters& parms)
458  {}
460  {}
461  };
462 
463 
475  template<class M, class Norm>
476  class UnSymmetricCriterion : public AggregationCriterion<Dependency<M,Norm> >
477  {
478  public:
479  UnSymmetricCriterion(const Parameters& parms)
481  {}
483  {}
484  };
485  // forward declaration
486  template<class G> class Aggregator;
487 
488 
496  template<class V>
498  {
499  public:
500 
504  static const V UNAGGREGATED;
505 
509  static const V ISOLATED;
513  typedef V VertexDescriptor;
514 
519 
525 
531 
536  {
537  public:
538  template<class EdgeIterator>
539  void operator()(const EdgeIterator& edge) const
540  {
541  DUNE_UNUSED_PARAMETER(edge);
542  }
543  };
544 
545 
550 
556  AggregatesMap(std::size_t noVertices);
557 
562 
574  template<class M, class G, class C>
575  tuple<int,int,int,int> buildAggregates(const M& matrix, G& graph, const C& criterion,
576  bool finestLevel);
577 
597  template<bool reset, class G, class F, class VM>
598  std::size_t breadthFirstSearch(const VertexDescriptor& start,
599  const AggregateDescriptor& aggregate,
600  const G& graph,
601  F& aggregateVisitor,
602  VM& visitedMap) const;
603 
627  template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
628  std::size_t breadthFirstSearch(const VertexDescriptor& start,
629  const AggregateDescriptor& aggregate,
630  const G& graph, L& visited, F1& aggregateVisitor,
631  F2& nonAggregateVisitor,
632  VM& visitedMap) const;
633 
639  void allocate(std::size_t noVertices);
640 
644  std::size_t noVertices() const;
645 
649  void free();
650 
657 
664 
665  typedef const AggregateDescriptor* const_iterator;
666 
667  const_iterator begin() const
668  {
669  return aggregates_;
670  }
671 
672  const_iterator end() const
673  {
674  return aggregates_+noVertices();
675  }
676 
677  typedef AggregateDescriptor* iterator;
678 
679  iterator begin()
680  {
681  return aggregates_;
682  }
683 
684  iterator end()
685  {
686  return aggregates_+noVertices();
687  }
688  private:
690  AggregatesMap(const AggregatesMap<V>& map)
691  {
692  throw "Auch!";
693  }
694 
696  AggregatesMap<V>& operator=(const AggregatesMap<V>& map)
697  {
698  throw "Auch!";
699  return this;
700  }
701 
705  AggregateDescriptor* aggregates_;
706 
710  std::size_t noVertices_;
711  };
712 
716  template<class G, class C>
717  void buildDependency(G& graph,
718  const typename C::Matrix& matrix,
719  C criterion,
720  bool finestLevel);
721 
726  template<class G, class S>
727  class Aggregate
728  {
729 
730  public:
731 
732  /***
733  * @brief The type of the matrix graph we work with.
734  */
735  typedef G MatrixGraph;
740 
746 
751  typedef S VertexSet;
752 
754  typedef typename VertexSet::const_iterator const_iterator;
755 
759  typedef std::size_t* SphereMap;
760 
769  Aggregate(MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
770  VertexSet& connectivity, std::vector<Vertex>& front_);
771 
772  void invalidate()
773  {
774  --id_;
775  }
776 
783  void reconstruct(const Vertex& vertex);
784 
788  void seed(const Vertex& vertex);
789 
793  void add(const Vertex& vertex);
794 
795  void add(std::vector<Vertex>& vertex);
799  void clear();
800 
804  typename VertexSet::size_type size();
808  typename VertexSet::size_type connectSize();
809 
813  int id();
814 
817 
820 
821  private:
825  VertexSet vertices_;
826 
831  int id_;
832 
836  MatrixGraph& graph_;
837 
841  AggregatesMap<Vertex>& aggregates_;
842 
846  VertexSet& connected_;
847 
851  std::vector<Vertex>& front_;
852  };
853 
857  template<class G>
859  {
860  public:
861 
865  typedef G MatrixGraph;
866 
871 
874 
879 
884 
901  template<class M, class C>
902  tuple<int,int,int,int> build(const M& m, G& graph,
903  AggregatesMap<Vertex>& aggregates, const C& c,
904  bool finestLevel);
905  private:
911 
916 
920  typedef std::set<Vertex,std::less<Vertex>,Allocator> VertexSet;
921 
925  typedef std::size_t* SphereMap;
926 
930  MatrixGraph* graph_;
931 
936 
940  std::vector<Vertex> front_;
941 
945  VertexSet connected_;
946 
950  int size_;
951 
955  class Stack
956  {
957  public:
958  static const Vertex NullEntry;
959 
960  Stack(const MatrixGraph& graph,
961  const Aggregator<G>& aggregatesBuilder,
962  const AggregatesMap<Vertex>& aggregates);
963  ~Stack();
964  Vertex pop();
965  private:
966  enum { N = 1300000 };
967 
969  const MatrixGraph& graph_;
971  const Aggregator<G>& aggregatesBuilder_;
973  const AggregatesMap<Vertex>& aggregates_;
975  int size_;
976  Vertex maxSize_;
978  typename MatrixGraph::ConstVertexIterator begin_;
979  typename MatrixGraph::ConstVertexIterator end_;
980 
982  Vertex* vals_;
983 
984  };
985 
986  friend class Stack;
987 
998  template<class V>
999  void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate,
1000  const AggregatesMap<Vertex>& aggregates,
1001  V& visitor) const;
1002 
1007  template<class V>
1008  class AggregateVisitor
1009  {
1010  public:
1014  typedef V Visitor;
1022  AggregateVisitor(const AggregatesMap<Vertex>& aggregates, const AggregateDescriptor& aggregate,
1023  Visitor& visitor);
1024 
1031  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1032 
1033  private:
1035  const AggregatesMap<Vertex>& aggregates_;
1037  AggregateDescriptor aggregate_;
1039  Visitor* visitor_;
1040  };
1041 
1045  class Counter
1046  {
1047  public:
1051  int value();
1052 
1053  protected:
1055  void increment();
1057  void decrement();
1058 
1059  private:
1060  int count_;
1061  };
1062 
1063 
1068  class FrontNeighbourCounter : public Counter
1069  {
1070  public:
1076 
1077  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1078 
1079  private:
1080  const MatrixGraph& graph_;
1081  };
1082 
1087  int noFrontNeighbours(const Vertex& vertex) const;
1088 
1092  class TwoWayCounter : public Counter
1093  {
1094  public:
1095  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1096  };
1097 
1109  int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
1110  const AggregatesMap<Vertex>& aggregates) const;
1111 
1115  class OneWayCounter : public Counter
1116  {
1117  public:
1118  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1119  };
1120 
1132  int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
1133  const AggregatesMap<Vertex>& aggregates) const;
1134 
1141  class ConnectivityCounter : public Counter
1142  {
1143  public:
1150  ConnectivityCounter(const VertexSet& connected, const AggregatesMap<Vertex>& aggregates);
1151 
1152  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1153 
1154  private:
1156  const VertexSet& connected_;
1158  const AggregatesMap<Vertex>& aggregates_;
1159 
1160  };
1161 
1173  double connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1181  bool connected(const Vertex& vertex, const AggregateDescriptor& aggregate,
1182  const AggregatesMap<Vertex>& aggregates) const;
1183 
1191  bool connected(const Vertex& vertex, const SLList<AggregateDescriptor>& aggregateList,
1192  const AggregatesMap<Vertex>& aggregates) const;
1193 
1201  class DependencyCounter : public Counter
1202  {
1203  public:
1208 
1209  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1210  };
1211 
1218  class FrontMarker
1219  {
1220  public:
1227  FrontMarker(std::vector<Vertex>& front, MatrixGraph& graph);
1228 
1229  void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1230 
1231  private:
1233  std::vector<Vertex>& front_;
1235  MatrixGraph& graph_;
1236  };
1237 
1241  void unmarkFront();
1242 
1257  int unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1258 
1272  std::pair<int,int> neighbours(const Vertex& vertex,
1273  const AggregateDescriptor& aggregate,
1274  const AggregatesMap<Vertex>& aggregates) const;
1291  int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
1292 
1300  bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
1301 
1309  std::size_t distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates);
1310 
1319  Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1320 
1329  void nonisoNeighbourAggregate(const Vertex& vertex,
1330  const AggregatesMap<Vertex>& aggregates,
1331  SLList<Vertex>& neighbours) const;
1332 
1340  template<class C>
1341  void growAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
1342  template<class C>
1343  void growIsolatedAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
1344  };
1345 
1346 #ifndef DOXYGEN
1347 
1348  template<class M, class N>
1349  inline void SymmetricDependency<M,N>::init(const Matrix* matrix)
1350  {
1351  matrix_ = matrix;
1352  }
1353 
1354  template<class M, class N>
1355  inline void SymmetricDependency<M,N>::initRow(const Row& row, int index)
1356  {
1357  DUNE_UNUSED_PARAMETER(row);
1358  maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
1359  row_ = index;
1360  diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1361  }
1362 
1363  template<class M, class N>
1364  inline void SymmetricDependency<M,N>::examine(const ColIter& col)
1365  {
1366  typename Matrix::field_type eij = norm_(*col);
1367  typename Matrix::field_type eji = norm_(matrix_->operator[](col.index())[row_]);
1368 
1369  // skip positive offdiagonals if norm preserves sign of them.
1370  if(!N::is_sign_preserving || eij<0 || eji<0)
1371  maxValue_ = std::max(maxValue_,
1372  eij /diagonal_ * eji/
1373  norm_(matrix_->operator[](col.index())[col.index()]));
1374  }
1375 
1376  template<class M, class N>
1377  template<class G>
1378  inline void SymmetricDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
1379  {
1380  typename Matrix::field_type eij = norm_(*col);
1381  typename Matrix::field_type eji = norm_(matrix_->operator[](col.index())[row_]);
1382 
1383  // skip positve offdiagonals if norm preserves sign of them.
1384  if(!N::is_sign_preserving || (eij<0 || eji<0))
1385  if(eji / norm_(matrix_->operator[](edge.target())[edge.target()]) *
1386  eij/ diagonal_ > alpha() * maxValue_) {
1387  edge.properties().setDepends();
1388  edge.properties().setInfluences();
1389 
1390  typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
1391  other.setInfluences();
1392  other.setDepends();
1393  }
1394  }
1395 
1396  template<class M, class N>
1397  inline bool SymmetricDependency<M,N>::isIsolated()
1398  {
1399  return maxValue_ < beta();
1400  }
1401 
1402 
1403  template<class M, class N>
1404  inline void Dependency<M,N>::init(const Matrix* matrix)
1405  {
1406  matrix_ = matrix;
1407  }
1408 
1409  template<class M, class N>
1410  inline void Dependency<M,N>::initRow(const Row& row, int index)
1411  {
1412  DUNE_UNUSED_PARAMETER(row);
1413  maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
1414  row_ = index;
1415  diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1416  }
1417 
1418  template<class M, class N>
1419  inline void Dependency<M,N>::examine(const ColIter& col)
1420  {
1421  maxValue_ = std::max(maxValue_,
1422  -norm_(*col));
1423  }
1424 
1425  template<class M, class N>
1426  template<class G>
1427  inline void Dependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
1428  {
1429  if(-norm_(*col) >= maxValue_ * alpha()) {
1430  edge.properties().setDepends();
1431  typedef typename G::EdgeDescriptor ED;
1432  ED e= graph.findEdge(edge.target(), edge.source());
1433  if(e!=std::numeric_limits<ED>::max())
1434  {
1435  typename G::EdgeProperties& other = graph.getEdgeProperties(e);
1436  other.setInfluences();
1437  }
1438  }
1439  }
1440 
1441  template<class M, class N>
1442  inline bool Dependency<M,N>::isIsolated()
1443  {
1444  return maxValue_ < beta() * diagonal_;
1445  }
1446 
1447  template<class G,class S>
1448  Aggregate<G,S>::Aggregate(MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
1449  VertexSet& connected, std::vector<Vertex>& front)
1450  : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
1451  connected_(connected), front_(front)
1452  {}
1453 
1454  template<class G,class S>
1455  void Aggregate<G,S>::reconstruct(const Vertex& vertex)
1456  {
1457  /*
1458  vertices_.push_back(vertex);
1459  typedef typename VertexList::const_iterator iterator;
1460  iterator begin = vertices_.begin();
1461  iterator end = vertices_.end();*/
1462  throw "Not yet implemented";
1463 
1464  // while(begin!=end){
1465  //for();
1466  // }
1467 
1468  }
1469 
1470  template<class G,class S>
1471  inline void Aggregate<G,S>::seed(const Vertex& vertex)
1472  {
1473  dvverb<<"Connected cleared"<<std::endl;
1474  connected_.clear();
1475  vertices_.clear();
1476  connected_.insert(vertex);
1477  dvverb << " Inserting "<<vertex<<" size="<<connected_.size();
1478  ++id_ ;
1479  add(vertex);
1480  }
1481 
1482 
1483  template<class G,class S>
1484  inline void Aggregate<G,S>::add(const Vertex& vertex)
1485  {
1486  vertices_.insert(vertex);
1487  aggregates_[vertex]=id_;
1488  if(front_.size())
1489  front_.erase(std::lower_bound(front_.begin(), front_.end(), vertex));
1490 
1491 
1492  typedef typename MatrixGraph::ConstEdgeIterator iterator;
1493  const iterator end = graph_.endEdges(vertex);
1494  for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge) {
1495  dvverb << " Inserting "<<aggregates_[edge.target()];
1496  connected_.insert(aggregates_[edge.target()]);
1497  dvverb <<" size="<<connected_.size();
1498  if(aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED &&
1499  !graph_.getVertexProperties(edge.target()).front())
1500  {
1501  front_.push_back(edge.target());
1502  graph_.getVertexProperties(edge.target()).setFront();
1503  }
1504  }
1505  dvverb <<std::endl;
1506  std::sort(front_.begin(), front_.end());
1507  }
1508 
1509  template<class G,class S>
1510  inline void Aggregate<G,S>::add(std::vector<Vertex>& vertices)
1511  {
1512 #ifndef NDEBUG
1513  std::size_t oldsize = vertices_.size();
1514 #endif
1515  typedef typename std::vector<Vertex>::iterator Iterator;
1516 
1517  typedef typename VertexSet::iterator SIterator;
1518 
1519  SIterator pos=vertices_.begin();
1520  std::vector<Vertex> newFront;
1521  newFront.reserve(front_.capacity());
1522 
1523  std::set_difference(front_.begin(), front_.end(), vertices.begin(), vertices.end(),
1524  std::back_inserter(newFront));
1525  front_=newFront;
1526 
1527  for(Iterator vertex=vertices.begin(); vertex != vertices.end(); ++vertex)
1528  {
1529  pos=vertices_.insert(pos,*vertex);
1530  vertices_.insert(*vertex);
1531  graph_.getVertexProperties(*vertex).resetFront(); // Not a front node any more.
1532  aggregates_[*vertex]=id_;
1533 
1534  typedef typename MatrixGraph::ConstEdgeIterator iterator;
1535  const iterator end = graph_.endEdges(*vertex);
1536  for(iterator edge = graph_.beginEdges(*vertex); edge != end; ++edge) {
1537  dvverb << " Inserting "<<aggregates_[edge.target()];
1538  connected_.insert(aggregates_[edge.target()]);
1539  if(aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED &&
1540  !graph_.getVertexProperties(edge.target()).front())
1541  {
1542  front_.push_back(edge.target());
1543  graph_.getVertexProperties(edge.target()).setFront();
1544  }
1545  dvverb <<" size="<<connected_.size();
1546  }
1547  dvverb <<std::endl;
1548  }
1549  std::sort(front_.begin(), front_.end());
1550  assert(oldsize+vertices.size()==vertices_.size());
1551  }
1552  template<class G,class S>
1553  inline void Aggregate<G,S>::clear()
1554  {
1555  vertices_.clear();
1556  connected_.clear();
1557  id_=-1;
1558  }
1559 
1560  template<class G,class S>
1561  inline typename Aggregate<G,S>::VertexSet::size_type
1563  {
1564  return vertices_.size();
1565  }
1566 
1567  template<class G,class S>
1568  inline typename Aggregate<G,S>::VertexSet::size_type
1570  {
1571  return connected_.size();
1572  }
1573 
1574  template<class G,class S>
1575  inline int Aggregate<G,S>::id()
1576  {
1577  return id_;
1578  }
1579 
1580  template<class G,class S>
1582  {
1583  return vertices_.begin();
1584  }
1585 
1586  template<class G,class S>
1587  inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::end() const
1588  {
1589  return vertices_.end();
1590  }
1591 
1592  template<class V>
1593  const V AggregatesMap<V>::UNAGGREGATED = std::numeric_limits<V>::max();
1594 
1595  template<class V>
1596  const V AggregatesMap<V>::ISOLATED = std::numeric_limits<V>::max()-1;
1597 
1598  template<class V>
1600  : aggregates_(0)
1601  {}
1602 
1603  template<class V>
1605  {
1606  if(aggregates_!=0)
1607  delete[] aggregates_;
1608  }
1609 
1610 
1611  template<class V>
1612  inline AggregatesMap<V>::AggregatesMap(std::size_t noVertices)
1613  {
1614  allocate(noVertices);
1615  }
1616 
1617  template<class V>
1618  inline std::size_t AggregatesMap<V>::noVertices() const
1619  {
1620  return noVertices_;
1621  }
1622 
1623  template<class V>
1624  inline void AggregatesMap<V>::allocate(std::size_t noVertices)
1625  {
1626  aggregates_ = new AggregateDescriptor[noVertices];
1627  noVertices_ = noVertices;
1628 
1629  for(std::size_t i=0; i < noVertices; i++)
1630  aggregates_[i]=UNAGGREGATED;
1631  }
1632 
1633  template<class V>
1634  inline void AggregatesMap<V>::free()
1635  {
1636  assert(aggregates_ != 0);
1637  delete[] aggregates_;
1638  aggregates_=0;
1639  }
1640 
1641  template<class V>
1642  inline typename AggregatesMap<V>::AggregateDescriptor&
1643  AggregatesMap<V>::operator[](const VertexDescriptor& v)
1644  {
1645  return aggregates_[v];
1646  }
1647 
1648  template<class V>
1649  inline const typename AggregatesMap<V>::AggregateDescriptor&
1650  AggregatesMap<V>::operator[](const VertexDescriptor& v) const
1651  {
1652  return aggregates_[v];
1653  }
1654 
1655  template<class V>
1656  template<bool reset, class G, class F,class VM>
1657  inline std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
1658  const AggregateDescriptor& aggregate,
1659  const G& graph, F& aggregateVisitor,
1660  VM& visitedMap) const
1661  {
1662  VertexList vlist;
1663 
1664  DummyEdgeVisitor dummy;
1665  return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap);
1666  }
1667 
1668  template<class V>
1669  template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
1670  std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
1671  const AggregateDescriptor& aggregate,
1672  const G& graph,
1673  L& visited,
1674  F1& aggregateVisitor,
1675  F2& nonAggregateVisitor,
1676  VM& visitedMap) const
1677  {
1678  typedef typename L::const_iterator ListIterator;
1679  int visitedSpheres = 0;
1680 
1681  visited.push_back(start);
1682  put(visitedMap, start, true);
1683 
1684  ListIterator current = visited.begin();
1685  ListIterator end = visited.end();
1686  std::size_t i=0, size=visited.size();
1687 
1688  // visit the neighbours of all vertices of the
1689  // current sphere.
1690  while(current != end) {
1691 
1692  for(; i<size; ++current, ++i) {
1693  typedef typename G::ConstEdgeIterator EdgeIterator;
1694  const EdgeIterator endEdge = graph.endEdges(*current);
1695 
1696  for(EdgeIterator edge = graph.beginEdges(*current);
1697  edge != endEdge; ++edge) {
1698 
1699  if(aggregates_[edge.target()]==aggregate) {
1700  if(!get(visitedMap, edge.target())) {
1701  put(visitedMap, edge.target(), true);
1702  visited.push_back(edge.target());
1703  aggregateVisitor(edge);
1704  }
1705  }else
1706  nonAggregateVisitor(edge);
1707  }
1708  }
1709  end = visited.end();
1710  size = visited.size();
1711  if(current != end)
1712  visitedSpheres++;
1713  }
1714 
1715  if(reset)
1716  for(current = visited.begin(); current != end; ++current)
1717  put(visitedMap, *current, false);
1718 
1719 
1720  if(remove)
1721  visited.clear();
1722 
1723  return visitedSpheres;
1724  }
1725 
1726  template<class G>
1728  : graph_(0), aggregate_(0), front_(), connected_(), size_(-1)
1729  {}
1730 
1731  template<class G>
1733  {
1734  size_=-1;
1735  }
1736 
1737  template<class G, class C>
1738  void buildDependency(G& graph,
1739  const typename C::Matrix& matrix,
1740  C criterion, bool firstlevel)
1741  {
1742  // assert(graph.isBuilt());
1743  typedef typename C::Matrix Matrix;
1744  typedef typename G::VertexIterator VertexIterator;
1745 
1746  criterion.init(&matrix);
1747 
1748  for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex) {
1749  typedef typename Matrix::row_type Row;
1750 
1751  const Row& row = matrix[*vertex];
1752 
1753  // Tell the criterion what row we will examine now
1754  // This might for example be used for calculating the
1755  // maximum offdiagonal value
1756  criterion.initRow(row, *vertex);
1757 
1758  // On a first path all columns are examined. After this
1759  // the calculator should know whether the vertex is isolated.
1760  typedef typename Matrix::ConstColIterator ColIterator;
1761  ColIterator end = row.end();
1762  typename Matrix::field_type absoffdiag=0;
1763 
1764  if(firstlevel) {
1765  for(ColIterator col = row.begin(); col != end; ++col)
1766  if(col.index()!=*vertex) {
1767  criterion.examine(col);
1768  absoffdiag=std::max(absoffdiag, col->frobenius_norm());
1769  }
1770 
1771  if(absoffdiag==0)
1772  vertex.properties().setExcludedBorder();
1773  }
1774  else
1775  for(ColIterator col = row.begin(); col != end; ++col)
1776  if(col.index()!=*vertex)
1777  criterion.examine(col);
1778 
1779  // reset the vertex properties
1780  //vertex.properties().reset();
1781 
1782  // Check whether the vertex is isolated.
1783  if(criterion.isIsolated()) {
1784  //std::cout<<"ISOLATED: "<<*vertex<<std::endl;
1785  vertex.properties().setIsolated();
1786  }else{
1787  // Examine all the edges beginning at this vertex.
1788  typedef typename G::EdgeIterator EdgeIterator;
1789  typedef typename Matrix::ConstColIterator ColIterator;
1790  EdgeIterator eEnd = vertex.end();
1791  ColIterator col = matrix[*vertex].begin();
1792 
1793  for(EdgeIterator edge = vertex.begin(); edge!= eEnd; ++edge, ++col) {
1794  // Move to the right column.
1795  while(col.index()!=edge.target())
1796  ++col;
1797  criterion.examine(graph, edge, col);
1798  }
1799  }
1800 
1801  }
1802  }
1803 
1804 
1805  template<class G>
1806  template<class V>
1807  inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates,
1808  const AggregateDescriptor& aggregate, V& visitor)
1809  : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
1810  {}
1811 
1812  template<class G>
1813  template<class V>
1814  inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1815  {
1816  if(aggregates_[edge.target()]==aggregate_)
1817  visitor_->operator()(edge);
1818  }
1819 
1820  template<class G>
1821  template<class V>
1822  inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
1823  const AggregateDescriptor& aggregate,
1824  const AggregatesMap<Vertex>& aggregates,
1825  V& visitor) const
1826  {
1827  // Only evaluates for edge pointing to the aggregate
1828  AggregateVisitor<V> v(aggregates, aggregate, visitor);
1829  visitNeighbours(*graph_, vertex, v);
1830  }
1831 
1832 
1833  template<class G>
1834  inline Aggregator<G>::Counter::Counter()
1835  : count_(0)
1836  {}
1837 
1838  template<class G>
1839  inline void Aggregator<G>::Counter::increment()
1840  {
1841  ++count_;
1842  }
1843 
1844  template<class G>
1845  inline void Aggregator<G>::Counter::decrement()
1846  {
1847  --count_;
1848  }
1849  template<class G>
1850  inline int Aggregator<G>::Counter::value()
1851  {
1852  return count_;
1853  }
1854 
1855  template<class G>
1856  inline void Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1857  {
1858  if(edge.properties().isTwoWay())
1859  Counter::increment();
1860  }
1861 
1862  template<class G>
1863  int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
1864  const AggregatesMap<Vertex>& aggregates) const
1865  {
1866  TwoWayCounter counter;
1867  visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
1868  return counter.value();
1869  }
1870 
1871  template<class G>
1872  int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
1873  const AggregatesMap<Vertex>& aggregates) const
1874  {
1875  OneWayCounter counter;
1876  visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
1877  return counter.value();
1878  }
1879 
1880  template<class G>
1881  inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1882  {
1883  if(edge.properties().isOneWay())
1884  Counter::increment();
1885  }
1886 
1887  template<class G>
1888  inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
1889  const AggregatesMap<Vertex>& aggregates)
1890  : Counter(), connected_(connected), aggregates_(aggregates)
1891  {}
1892 
1893 
1894  template<class G>
1895  inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1896  {
1897  if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
1898  // Would be a new connection
1899  Counter::increment();
1900  else{
1901  Counter::increment();
1902  Counter::increment();
1903  }
1904  }
1905 
1906  template<class G>
1907  inline double Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
1908  {
1909  ConnectivityCounter counter(connected_, aggregates);
1910  double noNeighbours=visitNeighbours(*graph_, vertex, counter);
1911  return (double)counter.value()/noNeighbours;
1912  }
1913 
1914  template<class G>
1915  inline Aggregator<G>::DependencyCounter::DependencyCounter()
1916  : Counter()
1917  {}
1918 
1919  template<class G>
1920  inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1921  {
1922  if(edge.properties().depends())
1923  Counter::increment();
1924  if(edge.properties().influences())
1925  Counter::increment();
1926  }
1927 
1928  template<class G>
1929  int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
1930  {
1931  return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
1932  }
1933 
1934  template<class G>
1935  std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
1936  const AggregateDescriptor& aggregate,
1937  const AggregatesMap<Vertex>& aggregates) const
1938  {
1939  DependencyCounter unused, aggregated;
1940  typedef AggregateVisitor<DependencyCounter> Counter;
1941  typedef tuple<Counter,Counter> CounterTuple;
1942  CombinedFunctor<CounterTuple> visitors(CounterTuple(Counter(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), Counter(aggregates, aggregate, aggregated)));
1943  visitNeighbours(*graph_, vertex, visitors);
1944  return std::make_pair(unused.value(), aggregated.value());
1945  }
1946 
1947 
1948  template<class G>
1949  int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
1950  {
1951  DependencyCounter counter;
1952  visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
1953  return counter.value();
1954  }
1955 
1956  template<class G>
1957  std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
1958  {
1959  return 0;
1960  typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
1961  VertexList vlist;
1962  typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
1963  return aggregates.template breadthFirstSearch<true,true>(vertex,
1964  aggregate_->id(), *graph_,
1965  vlist, dummy, dummy, visitedMap);
1966  }
1967 
1968  template<class G>
1969  inline Aggregator<G>::FrontMarker::FrontMarker(std::vector<Vertex>& front, MatrixGraph& graph)
1970  : front_(front), graph_(graph)
1971  {}
1972 
1973  template<class G>
1974  inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
1975  {
1976  Vertex target = edge.target();
1977 
1978  if(!graph_.getVertexProperties(target).front()) {
1979  front_.push_back(target);
1980  graph_.getVertexProperties(target).setFront();
1981  }
1982  }
1983 
1984  template<class G>
1985  inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
1986  {
1987  // Todo
1988  Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
1989  return true;
1990  //Situation 1: front node depends on two nodes. Then these
1991  // have to be strongly connected to each other
1992 
1993  // Iterate over all all neighbours of front node
1994  typedef typename MatrixGraph::ConstEdgeIterator Iterator;
1995  Iterator vend = graph_->endEdges(vertex);
1996  for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge) {
1997  // if(edge.properties().depends() && !edge.properties().influences()
1998  if(edge.properties().isStrong()
1999  && aggregates[edge.target()]==aggregate)
2000  {
2001  // Search for another link to the aggregate
2002  Iterator edge1 = edge;
2003  for(++edge1; edge1 != vend; ++edge1) {
2004  //if(edge1.properties().depends() && !edge1.properties().influences()
2005  if(edge1.properties().isStrong()
2006  && aggregates[edge.target()]==aggregate)
2007  {
2008  //Search for an edge connecting the two vertices that is
2009  //strong
2010  bool found=false;
2011  Iterator v2end = graph_->endEdges(edge.target());
2012  for(Iterator edge2 = graph_->beginEdges(edge.target()); edge2 != v2end; ++edge2) {
2013  if(edge2.target()==edge1.target() &&
2014  edge2.properties().isStrong()) {
2015  found =true;
2016  break;
2017  }
2018  }
2019  if(found)
2020  {
2021  return true;
2022  }
2023  }
2024  }
2025  }
2026  }
2027 
2028  // Situation 2: cluster node depends on front node and other cluster node
2030  vend = graph_->endEdges(vertex);
2031  for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge) {
2032  //if(!edge.properties().depends() && edge.properties().influences()
2033  if(edge.properties().isStrong()
2034  && aggregates[edge.target()]==aggregate)
2035  {
2036  // Search for a link from target that stays within the aggregate
2037  Iterator v1end = graph_->endEdges(edge.target());
2038 
2039  for(Iterator edge1=graph_->beginEdges(edge.target()); edge1 != v1end; ++edge1) {
2040  //if(edge1.properties().depends() && !edge1.properties().influences()
2041  if(edge1.properties().isStrong()
2042  && aggregates[edge1.target()]==aggregate)
2043  {
2044  bool found=false;
2045  // Check if front node is also connected to this one
2046  Iterator v2end = graph_->endEdges(vertex);
2047  for(Iterator edge2 = graph_->beginEdges(vertex); edge2 != v2end; ++edge2) {
2048  if(edge2.target()==edge1.target()) {
2049  if(edge2.properties().isStrong())
2050  found=true;
2051  break;
2052  }
2053  }
2054  if(found)
2055  {
2056  return true;
2057  }
2058  }
2059  }
2060  }
2061  }
2062  return false;
2063  }
2064 
2065  template<class G>
2066  void Aggregator<G>::unmarkFront()
2067  {
2068  typedef typename std::vector<Vertex>::const_iterator Iterator;
2069 
2070  for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
2071  graph_->getVertexProperties(*vertex).resetFront();
2072 
2073  front_.clear();
2074  }
2075 
2076  template<class G>
2077  inline void
2078  Aggregator<G>::nonisoNeighbourAggregate(const Vertex& vertex,
2079  const AggregatesMap<Vertex>& aggregates,
2080  SLList<Vertex>& neighbours) const
2081  {
2082  typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2083  Iterator end=graph_->beginEdges(vertex);
2084  neighbours.clear();
2085 
2086  for(Iterator edge=graph_->beginEdges(vertex); edge!=end; ++edge)
2087  {
2088  if(aggregates[edge.target()]!=AggregatesMap<Vertex>::UNAGGREGATED && graph_->getVertexProperties(edge.target()).isolated())
2089  neighbours.push_back(aggregates[edge.target()]);
2090  }
2091  }
2092 
2093  template<class G>
2094  inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
2095  {
2096  typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2097 
2098  Iterator end = graph_->endEdges(vertex);
2099  for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge) {
2100  if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
2101  graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()) {
2102  if( graph_->getVertexProperties(vertex).isolated() ||
2103  ((edge.properties().depends() || edge.properties().influences())
2104  && admissible(vertex, aggregates[edge.target()], aggregates)))
2105  return edge.target();
2106  }
2107  }
2109  }
2110 
2111  template<class G>
2112  Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph)
2113  : Counter(), graph_(graph)
2114  {}
2115 
2116  template<class G>
2117  void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
2118  {
2119  if(graph_.getVertexProperties(edge.target()).front())
2120  Counter::increment();
2121  }
2122 
2123  template<class G>
2124  int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
2125  {
2126  FrontNeighbourCounter counter(*graph_);
2127  visitNeighbours(*graph_, vertex, counter);
2128  return counter.value();
2129  }
2130  template<class G>
2131  inline bool Aggregator<G>::connected(const Vertex& vertex,
2132  const AggregateDescriptor& aggregate,
2133  const AggregatesMap<Vertex>& aggregates) const
2134  {
2135  typedef typename G::ConstEdgeIterator iterator;
2136  const iterator end = graph_->endEdges(vertex);
2137  for(iterator edge = graph_->beginEdges(vertex); edge != end; ++edge)
2138  if(aggregates[edge.target()]==aggregate)
2139  return true;
2140  return false;
2141  }
2142  template<class G>
2143  inline bool Aggregator<G>::connected(const Vertex& vertex,
2144  const SLList<AggregateDescriptor>& aggregateList,
2145  const AggregatesMap<Vertex>& aggregates) const
2146  {
2147  typedef typename SLList<AggregateDescriptor>::const_iterator Iter;
2148  for(Iter i=aggregateList.begin(); i!=aggregateList.end(); ++i)
2149  if(connected(vertex, *i, aggregates))
2150  return true;
2151  return false;
2152  }
2153 
2154  template<class G>
2155  template<class C>
2156  void Aggregator<G>::growIsolatedAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
2157  {
2158  SLList<Vertex> connectedAggregates;
2159  nonisoNeighbourAggregate(seed, aggregates,connectedAggregates);
2160 
2161  while(aggregate_->size()< c.minAggregateSize() && aggregate_->connectSize() < c.maxConnectivity()) {
2162  double maxCon=-1;
2163  std::size_t maxFrontNeighbours=0;
2164 
2166 
2167  typedef typename std::vector<Vertex>::const_iterator Iterator;
2168 
2169  for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2170  if(distance(*vertex, aggregates)>c.maxDistance())
2171  continue; // distance of proposes aggregate too big
2172 
2173  if(connectedAggregates.size()>0) {
2174  // there is already a neighbour cluster
2175  // front node must be connected to same neighbour cluster
2176 
2177  if(!connected(*vertex, connectedAggregates, aggregates))
2178  continue;
2179  }
2180 
2181  double con = connectivity(*vertex, aggregates);
2182 
2183  if(con == maxCon) {
2184  std::size_t frontNeighbours = noFrontNeighbours(*vertex);
2185 
2186  if(frontNeighbours >= maxFrontNeighbours) {
2187  maxFrontNeighbours = frontNeighbours;
2188  candidate = *vertex;
2189  }
2190  }else if(con > maxCon) {
2191  maxCon = con;
2192  maxFrontNeighbours = noFrontNeighbours(*vertex);
2193  candidate = *vertex;
2194  }
2195  }
2196 
2198  break;
2199 
2200  aggregate_->add(candidate);
2201  }
2202  }
2203 
2204  template<class G>
2205  template<class C>
2206  void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
2207  {
2208 
2209  std::size_t distance_ =0;
2210  while(aggregate_->size() < c.minAggregateSize()&& distance_<c.maxDistance()) {
2211  int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1;
2212  double maxCon=-1;
2213 
2214  std::vector<Vertex> candidates;
2215  candidates.reserve(30);
2216 
2217  typedef typename std::vector<Vertex>::const_iterator Iterator;
2218 
2219  for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2220  // Only nonisolated nodes are considered
2221  if(graph_->getVertexProperties(*vertex).isolated())
2222  continue;
2223 
2224  int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
2225 
2226  /* The case of two way connections. */
2227  if( maxTwoCons == twoWayCons && twoWayCons > 0) {
2228  double con = connectivity(*vertex, aggregates);
2229 
2230  if(con == maxCon) {
2231  int neighbours = noFrontNeighbours(*vertex);
2232 
2233  if(neighbours > maxNeighbours) {
2234  maxNeighbours = neighbours;
2235  candidates.clear();
2236  candidates.push_back(*vertex);
2237  }else{
2238  candidates.push_back(*vertex);
2239  }
2240  }else if( con > maxCon) {
2241  maxCon = con;
2242  maxNeighbours = noFrontNeighbours(*vertex);
2243  candidates.clear();
2244  candidates.push_back(*vertex);
2245  }
2246  }else if(twoWayCons > maxTwoCons) {
2247  maxTwoCons = twoWayCons;
2248  maxCon = connectivity(*vertex, aggregates);
2249  maxNeighbours = noFrontNeighbours(*vertex);
2250  candidates.clear();
2251  candidates.push_back(*vertex);
2252 
2253  // two way connections preceed
2254  maxOneCons = std::numeric_limits<int>::max();
2255  }
2256 
2257  if(twoWayCons > 0)
2258  {
2259  continue; // THis is a two-way node, skip tests for one way nodes
2260  }
2261 
2262  /* The one way case */
2263  int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
2264 
2265  if(oneWayCons==0)
2266  continue; // No strong connections, skip the tests.
2267 
2268  if(!admissible(*vertex, aggregate_->id(), aggregates))
2269  continue;
2270 
2271  if( maxOneCons == oneWayCons && oneWayCons > 0) {
2272  double con = connectivity(*vertex, aggregates);
2273 
2274  if(con == maxCon) {
2275  int neighbours = noFrontNeighbours(*vertex);
2276 
2277  if(neighbours > maxNeighbours) {
2278  maxNeighbours = neighbours;
2279  candidates.clear();
2280  candidates.push_back(*vertex);
2281  }else{
2282  if(neighbours==maxNeighbours)
2283  {
2284  candidates.push_back(*vertex);
2285  }
2286  }
2287  }else if( con > maxCon) {
2288  maxCon = con;
2289  maxNeighbours = noFrontNeighbours(*vertex);
2290  candidates.clear();
2291  candidates.push_back(*vertex);
2292  }
2293  }else if(oneWayCons > maxOneCons) {
2294  maxOneCons = oneWayCons;
2295  maxCon = connectivity(*vertex, aggregates);
2296  maxNeighbours = noFrontNeighbours(*vertex);
2297  candidates.clear();
2298  candidates.push_back(*vertex);
2299  }
2300  }
2301 
2302 
2303  if(!candidates.size())
2304  break; // No more candidates found
2305  distance_=distance(seed, aggregates);
2306  candidates.resize(std::min(candidates.size(), c.maxAggregateSize()-
2307  aggregate_->size()));
2308  aggregate_->add(candidates);
2309  }
2310  }
2311 
2312  template<typename V>
2313  template<typename M, typename G, typename C>
2314  tuple<int,int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion,
2315  bool finestLevel)
2316  {
2317  Aggregator<G> aggregator;
2318  return aggregator.build(matrix, graph, *this, criterion, finestLevel);
2319  }
2320 
2321  template<class G>
2322  template<class M, class C>
2323  tuple<int,int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c,
2324  bool finestLevel)
2325  {
2326  // Stack for fast vertex access
2327  Stack stack_(graph, *this, aggregates);
2328 
2329  graph_ = &graph;
2330 
2331  aggregate_ = new Aggregate<G,VertexSet>(graph, aggregates, connected_, front_);
2332 
2333  Timer watch;
2334  watch.reset();
2335 
2336  buildDependency(graph, m, c, finestLevel);
2337 
2338  dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
2339  int noAggregates, conAggregates, isoAggregates, oneAggregates;
2340  std::size_t maxA=0, minA=1000000, avg=0;
2341  int skippedAggregates;
2342  noAggregates = conAggregates = isoAggregates = oneAggregates =
2343  skippedAggregates = 0;
2344 
2345  while(true) {
2346  Vertex seed = stack_.pop();
2347 
2348  if(seed == Stack::NullEntry)
2349  // No more unaggregated vertices. We are finished!
2350  break;
2351 
2352  // Debugging output
2353  if((noAggregates+1)%10000 == 0)
2354  Dune::dverb<<"c";
2355  unmarkFront();
2356 
2357  if(graph.getVertexProperties(seed).excludedBorder()) {
2358  aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
2359  ++skippedAggregates;
2360  continue;
2361  }
2362 
2363  if(graph.getVertexProperties(seed).isolated()) {
2364  if(c.skipIsolated()) {
2365  // isolated vertices are not aggregated but skipped on the coarser levels.
2366  aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
2367  ++skippedAggregates;
2368  // skip rest as no agglomeration is done.
2369  continue;
2370  }else{
2371  aggregate_->seed(seed);
2372  growIsolatedAggregate(seed, aggregates, c);
2373  }
2374  }else{
2375  aggregate_->seed(seed);
2376  growAggregate(seed, aggregates, c);
2377  }
2378 
2379  /* The rounding step. */
2380  while(!(graph.getVertexProperties(seed).isolated()) && aggregate_->size() < c.maxAggregateSize()) {
2381 
2382  std::vector<Vertex> candidates;
2383  candidates.reserve(30);
2384 
2385  typedef typename std::vector<Vertex>::const_iterator Iterator;
2386 
2387  for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2388 
2389  if(graph.getVertexProperties(*vertex).isolated())
2390  continue; // No isolated nodes here
2391 
2392  if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 &&
2393  (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 ||
2394  !admissible( *vertex, aggregate_->id(), aggregates) ))
2395  continue;
2396 
2397  std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
2398  aggregates);
2399 
2400  //if(aggregateNeighbours(*vertex, aggregate_->id(), aggregates) <= unusedNeighbours(*vertex, aggregates))
2401  // continue;
2402 
2403  if(neighbourPair.first >= neighbourPair.second)
2404  continue;
2405 
2406  if(distance(*vertex, aggregates) > c.maxDistance())
2407  continue; // Distance too far
2408  candidates.push_back(*vertex);
2409  break;
2410  }
2411 
2412  if(!candidates.size()) break; // no more candidates found.
2413 
2414  candidates.resize(std::min(candidates.size(), c.maxAggregateSize()-
2415  aggregate_->size()));
2416  aggregate_->add(candidates);
2417 
2418  }
2419 
2420  // try to merge aggregates consisting of only one nonisolated vertex with other aggregates
2421  if(aggregate_->size()==1 && c.maxAggregateSize()>1) {
2422  if(!graph.getVertexProperties(seed).isolated()) {
2423  Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
2424 
2425  if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED) {
2426  // assign vertex to the neighbouring cluster
2427  aggregates[seed] = aggregates[mergedNeighbour];
2428  aggregate_->invalidate();
2429  }else{
2430  ++avg;
2431  minA=std::min(minA,static_cast<std::size_t>(1));
2432  maxA=std::max(maxA,static_cast<std::size_t>(1));
2433  ++oneAggregates;
2434  ++conAggregates;
2435  }
2436  }else{
2437  ++avg;
2438  minA=std::min(minA,static_cast<std::size_t>(1));
2439  maxA=std::max(maxA,static_cast<std::size_t>(1));
2440  ++oneAggregates;
2441  ++isoAggregates;
2442  }
2443  ++avg;
2444  }else{
2445  avg+=aggregate_->size();
2446  minA=std::min(minA,aggregate_->size());
2447  maxA=std::max(maxA,aggregate_->size());
2448  if(graph.getVertexProperties(seed).isolated())
2449  ++isoAggregates;
2450  else
2451  ++conAggregates;
2452  }
2453 
2454  }
2455 
2456  Dune::dinfo<<"connected aggregates: "<<conAggregates;
2457  Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
2458  if(conAggregates+isoAggregates>0)
2459  Dune::dinfo<<" one node aggregates: "<<oneAggregates<<" min size="
2460  <<minA<<" max size="<<maxA
2461  <<" avg="<<avg/(conAggregates+isoAggregates)<<std::endl;
2462 
2463  delete aggregate_;
2464  return make_tuple(conAggregates+isoAggregates,isoAggregates,
2465  oneAggregates,skippedAggregates);
2466  }
2467 
2468 
2469  template<class G>
2470  Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
2471  const AggregatesMap<Vertex>& aggregates)
2472  : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), begin_(graph.begin()), end_(graph.end())
2473  {
2474  //vals_ = new Vertex[N];
2475  }
2476 
2477  template<class G>
2478  Aggregator<G>::Stack::~Stack()
2479  {
2480  //Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
2481  //delete[] vals_;
2482  }
2483 
2484  template<class G>
2485  const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry
2486  = std::numeric_limits<typename G::VertexDescriptor>::max();
2487 
2488  template<class G>
2489  inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
2490  {
2491  for(; begin_!=end_ && aggregates_[*begin_] != AggregatesMap<Vertex>::UNAGGREGATED; ++begin_) ;
2492 
2493  if(begin_!=end_)
2494  {
2495  typename G::VertexDescriptor current=*begin_;
2496  ++begin_;
2497  return current;
2498  }else
2499  return NullEntry;
2500  }
2501 
2502 #endif // DOXYGEN
2503 
2504  template<class V>
2505  void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m, std::ostream& os)
2506  {
2507  std::ios_base::fmtflags oldOpts=os.flags();
2508 
2509  os.setf(std::ios_base::right, std::ios_base::adjustfield);
2510 
2511  V max=0;
2512  int width=1;
2513 
2514  for(int i=0; i< n*m; i++)
2515  max=std::max(max, aggregates[i]);
2516 
2517  for(int i=10; i < 1000000; i*=10)
2518  if(max/i>0)
2519  width++;
2520  else
2521  break;
2522 
2523  for(int j=0, entry=0; j < m; j++) {
2524  for(int i=0; i<n; i++, entry++) {
2525  os.width(width);
2526  os<<aggregates[entry]<<" ";
2527  }
2528 
2529  os<<std::endl;
2530  }
2531  os<<std::endl;
2532  os.flags(oldOpts);
2533  }
2534 
2535 
2536  } // namespace Amg
2537 
2538 } // namespace Dune
2539 
2540 
2541 #endif
A class for temporarily storing the vertices of an aggregate in.
Definition: aggregates.hh:728
A Dummy visitor that does nothing for each visited edge.
Definition: aggregates.hh:536
Class providing information about the mapping of the vertices onto aggregates.
Definition: aggregates.hh:498
Base class of all aggregation criterions.
Definition: aggregates.hh:46
Class for building the aggregates.
Definition: aggregates.hh:859
Dependency policy for symmetric matrices.
Definition: aggregates.hh:246
Norm that uses only the [N][N] entry of the block to determine couplings.
Definition: aggregates.hh:365
Norm that uses only the [0][0] entry of the block to determine couplings.
Definition: aggregates.hh:387
Iterator over all edges starting from a vertex.
Definition: graph.hh:94
The vertex iterator type of the graph.
Definition: graph.hh:208
The (undirected) graph of a matrix.
Definition: graph.hh:50
M::size_type VertexDescriptor
The vertex descriptor.
Definition: graph.hh:72
EdgeIteratorT< const MatrixGraph< Matrix > > ConstEdgeIterator
The constant edge iterator type.
Definition: graph.hh:297
All parameters for AMG.
Definition: parameters.hh:391
Criterion taking advantage of symmetric matrices.
Definition: aggregates.hh:454
Dependency policy for symmetric matrices.
Definition: aggregates.hh:305
Dependency policy for symmetric matrices.
Definition: aggregates.hh:131
Criterion suited for unsymmetric matrices.
Definition: aggregates.hh:477
Definition: bvector.hh:585
derive error class from the base class in common
Definition: istlexception.hh:16
A generic dynamic dense matrix.
Definition: matrix.hh:25
VariableBlockVector< T, A >::window_type row_type
The type implementing a matrix row.
Definition: matrix.hh:38
T::field_type field_type
Export the type representing the underlying field.
Definition: matrix.hh:29
row_type::const_iterator ConstColIterator
Const iterator for the entries of each row.
Definition: matrix.hh:53
An allocator managing a pool of objects for reuse.
Definition: poolallocator.hh:249
A single linked list.
Definition: sllist.hh:43
A Tuple of objects.
Definition: tuples.hh:294
Provides classes for building the matrix graph.
std::ostream & operator<<(std::ostream &s, const array< T, N > &e)
Output operator for array.
Definition: array.hh:159
SLListConstIterator< T, A > const_iterator
The constant iterator of the list.
Definition: sllist.hh:73
#define DUNE_THROW(E, m)
Definition: exceptions.hh:244
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:266
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:151
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:524
int id()
Get the id identifying the aggregate.
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:293
M::field_type operator()(const M &m) const
compute the norm of a matrix.
Definition: aggregates.hh:438
MatrixGraph::VertexDescriptor Vertex
The vertex identifier.
Definition: aggregates.hh:870
AggregationCriterion()
Constructor.
Definition: aggregates.hh:63
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:348
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:251
G MatrixGraph
The matrix graph type used.
Definition: aggregates.hh:865
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:352
Matrix::field_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:356
M::field_type operator()(const M &m) const
compute the norm of a matrix.
Definition: aggregates.hh:422
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:310
N Norm
The norm to use for examining the matrix entries.
Definition: aggregates.hh:256
int row_
index of the currently evaluated row.
Definition: aggregates.hh:180
FrontNeighbourCounter(const MatrixGraph &front)
Constructor.
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:320
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:289
AggregateVisitor(const AggregatesMap< Vertex > &aggregates, const AggregateDescriptor &aggregate, Visitor &visitor)
Constructor.
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:325
~AggregatesMap()
Destructor.
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:1014
std::size_t * SphereMap
Type of the mapping of aggregate members onto distance spheres.
Definition: aggregates.hh:759
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:261
VertexSet::size_type connectSize()
Get tne number of connections to other aggregates.
N Norm
The norm to use for examining the matrix entries.
Definition: aggregates.hh:315
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:178
Matrix::field_type maxValue_
The current max value.
Definition: aggregates.hh:350
VertexSet::const_iterator const_iterator
Const iterator over a vertex list.
Definition: aggregates.hh:754
MatrixGraph::VertexDescriptor AggregateDescriptor
The type of the aggregate descriptor.
Definition: aggregates.hh:873
~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.
tuple< int, int, int, int > build(const M &m, G &graph, AggregatesMap< Vertex > &aggregates, const C &c, bool finestLevel)
Build the aggregates.
T DependencyPolicy
The policy for calculating the dependency graph.
Definition: aggregates.hh:52
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:79
V AggregateDescriptor
The aggregate descriptor type.
Definition: aggregates.hh:518
static const V ISOLATED
Identifier of isolated vertices.
Definition: aggregates.hh:509
int row_
index of the currently evaluated row.
Definition: aggregates.hh:354
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:102
AggregatesMap(std::size_t noVertices)
Constructs with allocating memory.
AggregatesMap()
Constructs without allocating memory.
int value()
Access the current count.
SLList< VertexDescriptor, Allocator > VertexList
The type of a single linked list of vertex descriptors.
Definition: aggregates.hh:530
Matrix::field_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:297
ConnectivityCounter(const VertexSet &connected, const AggregatesMap< Vertex > &aggregates)
Constructor.
M::field_type operator()(const M &m) const
compute the norm of a matrix.
Definition: aggregates.hh:376
VertexSet::size_type size()
Get the size of the aggregate.
const_iterator end() const
get an iterator over the vertices of the aggregate.
int row_
index of the currently evaluated row.
Definition: aggregates.hh:295
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:136
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:174
S VertexSet
The type of a single linked list of vertex descriptors.
Definition: aggregates.hh:751
static const V UNAGGREGATED
Identifier of not yet aggregated vertices.
Definition: aggregates.hh:504
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 maxValue_
The current max value.
Definition: aggregates.hh:291
tuple< int, int, int, int > buildAggregates(const M &matrix, G &graph, const C &criterion, bool finestLevel)
Build the aggregates.
Matrix::field_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:182
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:141
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:739
void seed(const Vertex &vertex)
Initialize the aggregate with one vertex.
void clear()
Clear the aggregate.
Matrix::field_type maxValue_
The current max value.
Definition: aggregates.hh:176
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:513
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:146
PoolAllocator< Vertex, 100 > Allocator
The allocator we use for our lists and the set.
Definition: aggregates.hh:745
M::field_type operator()(const M &m) const
compute the norm of a matrix.
Definition: aggregates.hh:405
DVVerbType dvverb(std::cout)
stream for very verbose output.
Definition: stdstreams.hh:94
DInfoType dinfo(std::cout)
Stream for informative output.
Definition: stdstreams.hh:139
DVerbType dverb(std::cout)
Singleton of verbose debug stream.
Definition: stdstreams.hh:115
Dune namespace.
Definition: alignment.hh:14
Parameter classes for customizing AMG.
An stl-compliant pool allocator.
Provides classes for handling internal properties in a graph.
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:395
A simple timing class.
Fallback implementation of the std::tuple class.
Definition of the DUNE_UNUSED macro for the case that config.h is not available.
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentional unused function parameters with.
Definition: unused.hh:18
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 15, 22:30, 2024)