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
26namespace Dune
27{
28 namespace Amg
29 {
30
44 template<class T>
45 class AggregationCriterion : public T
46 {
47
48 public:
53
64 : T()
65 {}
66
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:
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:
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:
354 int row_;
357 };
358
363 template<int N>
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;
514
519
525
531
536 {
537 public:
538 template<class EdgeIterator>
539 void operator()(const EdgeIterator& edge) const
540 {
542 }
543 };
544
545
550
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>
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_;
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;
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:
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 {
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 {
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>
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>
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
tuple< int, int, int, int > build(const M &m, G &graph, AggregatesMap< Vertex > &aggregates, const C &c, bool finestLevel)
Build the aggregates.
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
tuple< int, int, int, int > buildAggregates(const M &matrix, G &graph, const C &criterion, bool finestLevel)
Build the aggregates.
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
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
const AggregateDescriptor & operator[](const VertexDescriptor &v) const
Get the aggregate a vertex belongs to.
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.
void add(const Vertex &vertex)
Add a vertex to the aggregate.
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.
AggregateDescriptor & operator[](const VertexDescriptor &v)
Get the aggregate a vertex belongs to.
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
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.111.3 (Nov 12, 23:30, 2024)