dune-istl 2.12-git
Loading...
Searching...
No Matches
aggregates.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4// vi: set et ts=4 sw=2 sts=2:
5#ifndef DUNE_AMG_AGGREGATES_HH
6#define DUNE_AMG_AGGREGATES_HH
7
8
9#include "parameters.hh"
10#include "graph.hh"
11#include "properties.hh"
12#include "combinedfunctor.hh"
13
14#include <dune/common/timer.hh>
17#include <dune/common/sllist.hh>
21
22#include <utility>
23#include <set>
24#include <algorithm>
25#include <complex>
26#include <limits>
27#include <ostream>
28#include <tuple>
29#include <cmath>
30
31namespace Dune
32{
33 namespace Amg
34 {
35
49 template<class T>
50 class AggregationCriterion : public T
51 {
52
53 public:
58
69 : T()
70 {}
71
73 : T(parms)
74 {}
85 {
86 this->setMaxDistance(diameter-1);
87 std::size_t csize=1;
88
89 for(; dim>0; dim--) {
90 csize*=diameter;
91 this->setMaxDistance(this->maxDistance()+diameter-1);
92 }
93 this->setMinAggregateSize(csize);
94 this->setMaxAggregateSize(static_cast<std::size_t>(csize*1.5));
95 }
96
108 {
110 this->setMaxDistance(this->maxDistance()+dim-1);
111 }
112 };
113
114 template<class T>
116 {
117 os<<"{ maxdistance="<<criterion.maxDistance()<<" minAggregateSize="
118 <<criterion.minAggregateSize()<< " maxAggregateSize="<<criterion.maxAggregateSize()
119 <<" connectivity="<<criterion.maxConnectivity()<<" debugLevel="<<criterion.debugLevel()<<"}";
120 return os;
121 }
122
134 template<class M, class N>
136 {
137 public:
141 typedef M Matrix;
142
146 typedef N Norm;
147
151 typedef typename Matrix::row_type Row;
152
157
158 void init(const Matrix* matrix);
159
160 template<class R>
161 void initRow(const R& row, int index);
162
163 template<class C>
164 void examine(const C& col);
165
166 template<class G, class C>
167 void examine(G& graph, const typename G::EdgeIterator& edge, const C& col);
168
169 bool isIsolated();
170
171
173 : Parameters(parms)
174 {}
178
179 protected:
189 int row_;
194
195 };
196
197
198 template<class M, class N>
200 {
201 matrix_ = matrix;
202 }
203
204 template<class M, class N>
205 template<class R>
206 inline void SymmetricMatrixDependency<M,N>::initRow(const R& row, int index)
207 {
208 using std::min;
209 vals_.assign(row.size(), 0.0);
210 assert(vals_.size()==row.size());
211 valIter_=vals_.begin();
212
214 diagonal_=norm_(row[index]);
215 row_ = index;
216 }
217
218 template<class M, class N>
219 template<class C>
221 {
222 using std::max;
223 // skip positive offdiagonals if norm preserves sign of them.
224 real_type eij = norm_(*col);
225 if(!N::is_sign_preserving || eij<0) // || eji<0)
226 {
227 *valIter_ = eij/diagonal_*eij/norm_(matrix_->operator[](col.index())[col.index()]);
228 maxValue_ = max(maxValue_, *valIter_);
229 }else
230 *valIter_ =0;
231 ++valIter_;
232 }
233
234 template<class M, class N>
235 template<class G, class C>
236 inline void SymmetricMatrixDependency<M,N>::examine(G&, const typename G::EdgeIterator& edge, const C&)
237 {
238 if(*valIter_ > alpha() * maxValue_) {
239 edge.properties().setDepends();
240 edge.properties().setInfluences();
241 }
242 ++valIter_;
243 }
244
245 template<class M, class N>
247 {
248 if(diagonal_==0)
249 DUNE_THROW(Dune::ISTLError, "No diagonal entry for row "<<row_<<".");
250 valIter_=vals_.begin();
251 return maxValue_ < beta();
252 }
253
257 template<class M, class N>
258 class Dependency : public Parameters
259 {
260 public:
264 typedef M Matrix;
265
269 typedef N Norm;
270
274 typedef typename Matrix::row_type Row;
275
280
281 void init(const Matrix* matrix);
282
283 template<class R>
284 void initRow(const R& row, int index);
285
286 template<class C>
287 void examine(const C& col);
288
289 template<class G, class C>
290 void examine(G& graph, const typename G::EdgeIterator& edge, const C& col);
291
293
294 Dependency(const Parameters& parms)
295 : Parameters(parms)
296 {}
297
299 : Parameters()
300 {}
301
302 protected:
312 int row_;
315 };
316
320 template<class M, class N>
322 {
323 public:
327 typedef M Matrix;
328
332 typedef N Norm;
333
337 typedef typename Matrix::row_type Row;
338
343
344 void init(const Matrix* matrix);
345
346 template<class R>
347 void initRow(const R& row, int index);
348
349 template<class C>
350 void examine(const C& col);
351
352 template<class G, class C>
353 void examine(G& graph, const typename G::EdgeIterator& edge, const C& col);
354
356
357
359 : Parameters(parms)
360 {}
364
365 protected:
375 int row_;
378 private:
379 template<class R>
380 void initRow(const R& row, int index, const std::true_type&);
381 template<class R>
382 void initRow(const R& row, int index, const std::false_type&);
383 };
384
389 template<int N>
391 {
392 public:
393 enum { /* @brief We preserve the sign.*/
394 is_sign_preserving = true
395 };
396
401 template<class M>
402 typename FieldTraits<M>::real_type operator()(const M& m) const
403 {
404 using field_type = typename FieldTraits<M>::field_type;
405 using real_type = typename FieldTraits<field_type>::real_type;
406 static_assert( std::is_convertible_v<field_type, real_type >,
407 "use of diagonal norm in AMG not implemented for complex field_type");
408 auto&& mm = Impl::asMatrix(m);
409#ifdef DUNE_ISTL_WITH_CHECKING
410 if (mm.N() <= N || mm.M() <= N)
412 "Diagonal<" << N << "> norm requested entry (" << N << "," << N << ") for block of size "
413 << "(" << mm.N() << "x" << mm.M() << ").");
414#endif
415 return mm[N][N];
416 // possible implementation for complex types: return signed_abs(m[N][N]);
417 }
418
419 private:
420
422 template<typename T>
423 static T signed_abs(const T & v)
424 {
425 return v;
426 }
427
429 template<typename T>
430 static T signed_abs(const std::complex<T> & v)
431 {
432 // return sign * abs_value
433 // in case of complex numbers this extends to using the csgn function to determine the sign
434 return csgn(v) * std::abs(v);
435 }
436
438 template<typename T>
439 static T csgn(const T & v)
440 {
441 return (T(0) < v) - (v < T(0));
442 }
443
445 template<typename T>
446 static T csgn(std::complex<T> a)
447 {
448 return csgn(a.real())+(a.real() == 0.0)*csgn(a.imag());
449 }
450
451 };
452
457 class FirstDiagonal : public Diagonal<0>
458 {};
459
465 struct RowSum
466 {
467
468 enum { /* @brief We preserve the sign.*/
469 is_sign_preserving = false
470 };
475 template<class M>
476 typename FieldTraits<M>::real_type operator()(const M& m) const
477 {
478 return Impl::asMatrix(m).infinity_norm();
479 }
480 };
481
483 {
484
485 enum { /* @brief We preserve the sign.*/
486 is_sign_preserving = false
487 };
492 template<class M>
493 typename FieldTraits<M>::real_type operator()(const M& m) const
494 {
495 return Impl::asMatrix(m).frobenius_norm();
496 }
497 };
499 {
500
501 enum { /* @brief We preserve the sign.*/
502 is_sign_preserving = false
503 };
508 template<class M>
509 typename FieldTraits<M>::real_type operator()(const M& /*m*/) const
510 {
511 return 1;
512 }
513 };
520 template<class M, class Norm>
521 class SymmetricCriterion : public AggregationCriterion<SymmetricDependency<M,Norm> >
522 {
523 public:
529 };
530
531
540 template<class M, class Norm>
541 class UnSymmetricCriterion : public AggregationCriterion<Dependency<M,Norm> >
542 {
543 public:
549 };
550 // forward declaration
551 template<class G> class Aggregator;
552
553
561 template<class V>
563 {
564 public:
565
569 static const V UNAGGREGATED;
570
574 static const V ISOLATED;
579
584
590
596
601 {
602 public:
603 template<class EdgeIterator>
604 void operator()([[maybe_unused]] const EdgeIterator& edge) const
605 {}
606 };
607
608
613
620
625
637 template<class M, class G, class C>
638 std::tuple<int,int,int,int> buildAggregates(const M& matrix, G& graph, const C& criterion,
639 bool finestLevel);
640
658 template<bool reset, class G, class F, class VM>
660 const AggregateDescriptor& aggregate,
661 const G& graph,
662 F& aggregateVisitor,
663 VM& visitedMap) const;
664
688 template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
690 const AggregateDescriptor& aggregate,
691 const G& graph, L& visited, F1& aggregateVisitor,
692 F2& nonAggregateVisitor,
693 VM& visitedMap) const;
694
701
706
710 void free();
711
718
725
727
729 {
730 return aggregates_;
731 }
732
734 {
735 return aggregates_+noVertices();
736 }
737
739
741 {
742 return aggregates_;
743 }
744
746 {
747 return aggregates_+noVertices();
748 }
749 private:
751 AggregatesMap(const AggregatesMap<V>&) = delete;
753 AggregatesMap<V>& operator=(const AggregatesMap<V>&) = delete;
754
758 AggregateDescriptor* aggregates_;
759
763 std::size_t noVertices_;
764 };
765
769 template<class G, class C>
770 void buildDependency(G& graph,
771 const typename C::Matrix& matrix,
772 C criterion,
773 bool finestLevel);
774
779 template<class G, class S>
781 {
782
783 public:
784
785 /***
786 * @brief The type of the matrix graph we work with.
787 */
788 typedef G MatrixGraph;
793
799
804 typedef S VertexSet;
805
809 using size_type = typename VertexSet::size_type;
810
812 typedef typename VertexSet::const_iterator const_iterator;
813
818
828 VertexSet& connectivity, std::vector<Vertex>& front_);
829
831 {
832 --id_;
833 }
834
841 void reconstruct(const Vertex& vertex);
842
846 void seed(const Vertex& vertex);
847
851 void add(const Vertex& vertex);
852
857 void clear();
858
867
871 int id();
872
875
878
879 private:
883 VertexSet vertices_;
884
889 int id_;
890
894 MatrixGraph& graph_;
895
899 AggregatesMap<Vertex>& aggregates_;
900
904 VertexSet& connected_;
905
909 std::vector<Vertex>& front_;
910 };
911
915 template<class G>
917 {
918 public:
919
923 typedef G MatrixGraph;
924
929
932
937
942
959 template<class M, class C>
961 AggregatesMap<Vertex>& aggregates, const C& c,
962 bool finestLevel);
963 private:
969
974
979
983 typedef std::size_t* SphereMap;
984
988 MatrixGraph* graph_;
989
994
998 std::vector<Vertex> front_;
999
1003 VertexSet connected_;
1004
1008 int size_;
1009
1013 class Stack
1014 {
1015 public:
1016 static const Vertex NullEntry;
1017
1018 Stack(const MatrixGraph& graph,
1019 const Aggregator<G>& aggregatesBuilder,
1020 const AggregatesMap<Vertex>& aggregates);
1023 private:
1024 enum { N = 1300000 };
1025
1027 const MatrixGraph& graph_;
1029 const Aggregator<G>& aggregatesBuilder_;
1031 const AggregatesMap<Vertex>& aggregates_;
1033 int size_;
1034 Vertex maxSize_;
1036 typename MatrixGraph::ConstVertexIterator begin_;
1038
1040 Vertex* vals_;
1041
1042 };
1043
1044 friend class Stack;
1045
1056 template<class V>
1057 void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate,
1058 const AggregatesMap<Vertex>& aggregates,
1059 V& visitor) const;
1060
1065 template<class V>
1066 class AggregateVisitor
1067 {
1068 public:
1072 typedef V Visitor;
1081 Visitor& visitor);
1082
1089 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1090
1091 private:
1093 const AggregatesMap<Vertex>& aggregates_;
1095 AggregateDescriptor aggregate_;
1097 Visitor* visitor_;
1098 };
1099
1103 class Counter
1104 {
1105 public:
1109 int value();
1110
1111 protected:
1116
1117 private:
1118 int count_;
1119 };
1120
1121
1126 class FrontNeighbourCounter : public Counter
1127 {
1128 public:
1134
1135 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1136
1137 private:
1138 const MatrixGraph& graph_;
1139 };
1140
1145 int noFrontNeighbours(const Vertex& vertex) const;
1146
1150 class TwoWayCounter : public Counter
1151 {
1152 public:
1153 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1154 };
1155
1167 int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
1168 const AggregatesMap<Vertex>& aggregates) const;
1169
1173 class OneWayCounter : public Counter
1174 {
1175 public:
1176 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1177 };
1178
1190 int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
1191 const AggregatesMap<Vertex>& aggregates) const;
1192
1199 class ConnectivityCounter : public Counter
1200 {
1201 public:
1207 ConnectivityCounter(const VertexSet& connected, const AggregatesMap<Vertex>& aggregates);
1208
1209 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1210
1211 private:
1213 const VertexSet& connected_;
1215 const AggregatesMap<Vertex>& aggregates_;
1216
1217 };
1218
1230 double connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1238 bool connected(const Vertex& vertex, const AggregateDescriptor& aggregate,
1239 const AggregatesMap<Vertex>& aggregates) const;
1240
1248 bool connected(const Vertex& vertex, const SLList<AggregateDescriptor>& aggregateList,
1249 const AggregatesMap<Vertex>& aggregates) const;
1250
1258 class DependencyCounter : public Counter
1259 {
1260 public:
1265
1266 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1267 };
1268
1275 class FrontMarker
1276 {
1277 public:
1285
1286 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
1287
1288 private:
1290 std::vector<Vertex>& front_;
1292 MatrixGraph& graph_;
1293 };
1294
1298 void unmarkFront();
1299
1314 int unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1315
1329 std::pair<int,int> neighbours(const Vertex& vertex,
1330 const AggregateDescriptor& aggregate,
1331 const AggregatesMap<Vertex>& aggregates) const;
1348 int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
1349
1357 bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
1358
1366 std::size_t distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates);
1367
1376 Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
1377
1386 void nonisoNeighbourAggregate(const Vertex& vertex,
1387 const AggregatesMap<Vertex>& aggregates,
1388 SLList<Vertex>& neighbours) const;
1389
1397 template<class C>
1398 void growAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
1399 template<class C>
1400 void growIsolatedAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
1401 };
1402
1403#ifndef DOXYGEN
1404
1405 template<class M, class N>
1406 inline void SymmetricDependency<M,N>::init(const Matrix* matrix)
1407 {
1408 matrix_ = matrix;
1409 }
1410
1411 template<class M, class N>
1412 template<class R>
1413 inline void SymmetricDependency<M,N>::initRow(const R& row, int index)
1414 {
1416 }
1417
1418 template<class M, class N>
1419 template<class R>
1420 inline void SymmetricDependency<M,N>::initRow(const R& /*row*/, int /*index*/, const std::false_type&)
1421 {
1422 DUNE_THROW(InvalidStateException, "field_type needs to convertible to real_type");
1423 }
1424
1425 template<class M, class N>
1426 template<class R>
1427 inline void SymmetricDependency<M,N>::initRow(const R& /*row*/, int index, const std::true_type&)
1428 {
1429 using std::min;
1431 row_ = index;
1432 diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1433 }
1434
1435 template<class M, class N>
1436 template<class C>
1437 inline void SymmetricDependency<M,N>::examine(const C& col)
1438 {
1439 using std::max;
1440 real_type eij = norm_(*col);
1441 typename Matrix::ConstColIterator opposite_entry =
1442 matrix_->operator[](col.index()).find(row_);
1443 if ( opposite_entry == matrix_->operator[](col.index()).end() )
1444 {
1445 // Consider this a weak connection we disregard.
1446 return;
1447 }
1448 real_type eji = norm_(*opposite_entry);
1449
1450 // skip positive offdiagonals if norm preserves sign of them.
1451 if(!N::is_sign_preserving || eij<0 || eji<0)
1452 maxValue_ = max(maxValue_,
1453 eij /diagonal_ * eji/
1454 norm_(matrix_->operator[](col.index())[col.index()]));
1455 }
1456
1457 template<class M, class N>
1458 template<class G, class C>
1459 inline void SymmetricDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const C& col)
1460 {
1461 real_type eij = norm_(*col);
1462 typename Matrix::ConstColIterator opposite_entry =
1463 matrix_->operator[](col.index()).find(row_);
1464
1465 if ( opposite_entry == matrix_->operator[](col.index()).end() )
1466 {
1467 // Consider this as a weak connection we disregard.
1468 return;
1469 }
1470 real_type eji = norm_(*opposite_entry);
1471 // skip positive offdiagonals if norm preserves sign of them.
1472 if(!N::is_sign_preserving || (eij<0 || eji<0))
1473 if(eji / norm_(matrix_->operator[](edge.target())[edge.target()]) *
1474 eij/ diagonal_ > alpha() * maxValue_) {
1475 edge.properties().setDepends();
1476 edge.properties().setInfluences();
1477 typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
1478 other.setInfluences();
1479 other.setDepends();
1480 }
1481 }
1482
1483 template<class M, class N>
1485 {
1486 return maxValue_ < beta();
1487 }
1488
1489
1490 template<class M, class N>
1491 inline void Dependency<M,N>::init(const Matrix* matrix)
1492 {
1493 matrix_ = matrix;
1494 }
1495
1496 template<class M, class N>
1497 template<class R>
1498 inline void Dependency<M,N>::initRow([[maybe_unused]] const R& row, int index)
1499 {
1500 using std::min;
1502 row_ = index;
1503 diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1504 }
1505
1506 template<class M, class N>
1507 template<class C>
1508 inline void Dependency<M,N>::examine(const C& col)
1509 {
1510 using std::max;
1511 maxValue_ = max(maxValue_, -norm_(*col));
1512 }
1513
1514 template<class M, class N>
1515 template<class G, class C>
1516 inline void Dependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const C& col)
1517 {
1518 if(-norm_(*col) >= maxValue_ * alpha()) {
1519 edge.properties().setDepends();
1520 typedef typename G::EdgeDescriptor ED;
1521 ED e= graph.findEdge(edge.target(), edge.source());
1523 {
1524 typename G::EdgeProperties& other = graph.getEdgeProperties(e);
1525 other.setInfluences();
1526 }
1527 }
1528 }
1529
1530 template<class M, class N>
1531 inline bool Dependency<M,N>::isIsolated()
1532 {
1533 return maxValue_ < beta() * diagonal_;
1534 }
1535
1536 template<class G,class S>
1537 Aggregate<G,S>::Aggregate(MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
1538 VertexSet& connected, std::vector<Vertex>& front)
1539 : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
1540 connected_(connected), front_(front)
1541 {}
1542
1543 template<class G,class S>
1544 void Aggregate<G,S>::reconstruct(const Vertex& /*vertex*/)
1545 {
1546 /*
1547 vertices_.push_back(vertex);
1548 typedef typename VertexList::const_iterator iterator;
1549 iterator begin = vertices_.begin();
1550 iterator end = vertices_.end();*/
1551 throw "Not yet implemented";
1552
1553 // while(begin!=end){
1554 //for();
1555 // }
1556
1557 }
1558
1559 template<class G,class S>
1560 inline void Aggregate<G,S>::seed(const Vertex& vertex)
1561 {
1562 dvverb<<"Connected cleared"<<std::endl;
1563 connected_.clear();
1564 vertices_.clear();
1565 connected_.insert(vertex);
1566 dvverb << " Inserting "<<vertex<<" size="<<connected_.size();
1567 ++id_ ;
1568 add(vertex);
1569 }
1570
1571
1572 template<class G,class S>
1573 inline void Aggregate<G,S>::add(const Vertex& vertex)
1574 {
1575 vertices_.insert(vertex);
1576 aggregates_[vertex]=id_;
1577 if(front_.size())
1578 front_.erase(std::lower_bound(front_.begin(), front_.end(), vertex));
1579
1580
1582 const iterator end = graph_.endEdges(vertex);
1583 for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge) {
1584 dvverb << " Inserting "<<aggregates_[edge.target()];
1585 connected_.insert(aggregates_[edge.target()]);
1586 dvverb <<" size="<<connected_.size();
1587 if(aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED &&
1588 !graph_.getVertexProperties(edge.target()).front())
1589 {
1590 front_.push_back(edge.target());
1591 graph_.getVertexProperties(edge.target()).setFront();
1592 }
1593 }
1594 dvverb <<std::endl;
1595 std::sort(front_.begin(), front_.end());
1596 }
1597
1598 template<class G,class S>
1599 inline void Aggregate<G,S>::add(std::vector<Vertex>& vertices)
1600 {
1601#ifndef NDEBUG
1602 std::size_t oldsize = vertices_.size();
1603#endif
1604 typedef typename std::vector<Vertex>::iterator Iterator;
1605
1606 typedef typename VertexSet::iterator SIterator;
1607
1608 SIterator pos=vertices_.begin();
1609 std::vector<Vertex> newFront;
1610 newFront.reserve(front_.capacity());
1611
1612 std::set_difference(front_.begin(), front_.end(), vertices.begin(), vertices.end(),
1613 std::back_inserter(newFront));
1614 front_=newFront;
1615
1616 for(Iterator vertex=vertices.begin(); vertex != vertices.end(); ++vertex)
1617 {
1618 pos=vertices_.insert(pos,*vertex);
1619 vertices_.insert(*vertex);
1620 graph_.getVertexProperties(*vertex).resetFront(); // Not a front node any more.
1621 aggregates_[*vertex]=id_;
1622
1624 const iterator end = graph_.endEdges(*vertex);
1625 for(iterator edge = graph_.beginEdges(*vertex); edge != end; ++edge) {
1626 dvverb << " Inserting "<<aggregates_[edge.target()];
1627 connected_.insert(aggregates_[edge.target()]);
1628 if(aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED &&
1629 !graph_.getVertexProperties(edge.target()).front())
1630 {
1631 front_.push_back(edge.target());
1632 graph_.getVertexProperties(edge.target()).setFront();
1633 }
1634 dvverb <<" size="<<connected_.size();
1635 }
1636 dvverb <<std::endl;
1637 }
1638 std::sort(front_.begin(), front_.end());
1639 assert(oldsize+vertices.size()==vertices_.size());
1640 }
1641 template<class G,class S>
1642 inline void Aggregate<G,S>::clear()
1643 {
1644 vertices_.clear();
1645 connected_.clear();
1646 id_=-1;
1647 }
1648
1649 template<class G,class S>
1650 inline typename Aggregate<G,S>::size_type
1652 {
1653 return vertices_.size();
1654 }
1655
1656 template<class G,class S>
1657 inline typename Aggregate<G,S>::size_type
1659 {
1660 return connected_.size();
1661 }
1662
1663 template<class G,class S>
1664 inline int Aggregate<G,S>::id()
1665 {
1666 return id_;
1667 }
1668
1669 template<class G,class S>
1671 {
1672 return vertices_.begin();
1673 }
1674
1675 template<class G,class S>
1677 {
1678 return vertices_.end();
1679 }
1680
1681 template<class V>
1683
1684 template<class V>
1686
1687 template<class V>
1689 : aggregates_(0)
1690 {}
1691
1692 template<class V>
1694 {
1695 if(aggregates_!=0)
1696 delete[] aggregates_;
1697 }
1698
1699
1700 template<class V>
1702 {
1703 allocate(noVertices);
1704 }
1705
1706 template<class V>
1708 {
1709 return noVertices_;
1710 }
1711
1712 template<class V>
1713 inline void AggregatesMap<V>::allocate(std::size_t noVertices)
1714 {
1715 aggregates_ = new AggregateDescriptor[noVertices];
1716 noVertices_ = noVertices;
1717
1718 for(std::size_t i=0; i < noVertices; i++)
1719 aggregates_[i]=UNAGGREGATED;
1720 }
1721
1722 template<class V>
1723 inline void AggregatesMap<V>::free()
1724 {
1725 assert(aggregates_ != 0);
1726 delete[] aggregates_;
1727 aggregates_=0;
1728 }
1729
1730 template<class V>
1732 AggregatesMap<V>::operator[](const VertexDescriptor& v)
1733 {
1734 return aggregates_[v];
1735 }
1736
1737 template<class V>
1738 inline const typename AggregatesMap<V>::AggregateDescriptor&
1739 AggregatesMap<V>::operator[](const VertexDescriptor& v) const
1740 {
1741 return aggregates_[v];
1742 }
1743
1744 template<class V>
1745 template<bool reset, class G, class F,class VM>
1747 const AggregateDescriptor& aggregate,
1748 const G& graph, F& aggregateVisitor,
1749 VM& visitedMap) const
1750 {
1751 VertexList vlist;
1752
1753 DummyEdgeVisitor dummy;
1754 return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap);
1755 }
1756
1757 template<class V>
1758 template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
1760 const AggregateDescriptor& aggregate,
1761 const G& graph,
1762 L& visited,
1763 F1& aggregateVisitor,
1764 F2& nonAggregateVisitor,
1765 VM& visitedMap) const
1766 {
1767 typedef typename L::const_iterator ListIterator;
1768 int visitedSpheres = 0;
1769
1770 visited.push_back(start);
1771 put(visitedMap, start, true);
1772
1773 ListIterator current = visited.begin();
1774 ListIterator end = visited.end();
1775 std::size_t i=0, size=visited.size();
1776
1777 // visit the neighbours of all vertices of the
1778 // current sphere.
1779 while(current != end) {
1780
1781 for(; i<size; ++current, ++i) {
1782 typedef typename G::ConstEdgeIterator EdgeIterator;
1783 const EdgeIterator endEdge = graph.endEdges(*current);
1784
1785 for(EdgeIterator edge = graph.beginEdges(*current);
1786 edge != endEdge; ++edge) {
1787
1788 if(aggregates_[edge.target()]==aggregate) {
1789 if(!get(visitedMap, edge.target())) {
1790 put(visitedMap, edge.target(), true);
1791 visited.push_back(edge.target());
1792 aggregateVisitor(edge);
1793 }
1794 }else
1795 nonAggregateVisitor(edge);
1796 }
1797 }
1798 end = visited.end();
1799 size = visited.size();
1800 if(current != end)
1801 visitedSpheres++;
1802 }
1803
1804 if(reset)
1805 for(current = visited.begin(); current != end; ++current)
1806 put(visitedMap, *current, false);
1807
1808
1809 if(remove)
1810 visited.clear();
1811
1812 return visitedSpheres;
1813 }
1814
1815 template<class G>
1817 : graph_(0), aggregate_(0), front_(), connected_(), size_(-1)
1818 {}
1819
1820 template<class G>
1822 {
1823 size_=-1;
1824 }
1825
1826 template<class G, class C>
1827 void buildDependency(G& graph,
1828 const typename C::Matrix& matrix,
1829 C criterion, bool firstlevel)
1830 {
1831 // assert(graph.isBuilt());
1832 typedef typename C::Matrix Matrix;
1833 typedef typename G::VertexIterator VertexIterator;
1834
1835 criterion.init(&matrix);
1836
1837 for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex) {
1838
1839 const auto& row = matrix[*vertex];
1840
1841 // Tell the criterion what row we will examine now
1842 // This might for example be used for calculating the
1843 // maximum offdiagonal value
1844 criterion.initRow(row, *vertex);
1845
1846 // On a first path all columns are examined. After this
1847 // the calculator should know whether the vertex is isolated.
1848 auto end = row.end();
1850
1851 using std::max;
1852 if(firstlevel) {
1853 for(auto col = row.begin(); col != end; ++col)
1854 if(col.index()!=*vertex) {
1855 criterion.examine(col);
1856 absoffdiag = max(absoffdiag, Impl::asMatrix(*col).frobenius_norm());
1857 }
1858
1859 if(absoffdiag==0)
1860 vertex.properties().setExcludedBorder();
1861 }
1862 else
1863 for(auto col = row.begin(); col != end; ++col)
1864 if(col.index()!=*vertex)
1865 criterion.examine(col);
1866
1867 // reset the vertex properties
1868 //vertex.properties().reset();
1869
1870 // Check whether the vertex is isolated.
1871 if(criterion.isIsolated()) {
1872 //std::cout<<"ISOLATED: "<<*vertex<<std::endl;
1873 vertex.properties().setIsolated();
1874 }else{
1875 // Examine all the edges beginning at this vertex.
1876 auto eEnd = vertex.end();
1877 auto col = matrix[*vertex].begin();
1878
1879 for(auto edge = vertex.begin(); edge!= eEnd; ++edge, ++col) {
1880 // Move to the right column.
1881 while(col.index()!=edge.target())
1882 ++col;
1883 criterion.examine(graph, edge, col);
1884 }
1885 }
1886
1887 }
1888 }
1889
1890
1891 template<class G>
1892 template<class V>
1893 inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates,
1894 const AggregateDescriptor& aggregate, V& visitor)
1895 : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
1896 {}
1897
1898 template<class G>
1899 template<class V>
1901 {
1902 if(aggregates_[edge.target()]==aggregate_)
1903 visitor_->operator()(edge);
1904 }
1905
1906 template<class G>
1907 template<class V>
1908 inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
1909 const AggregateDescriptor& aggregate,
1910 const AggregatesMap<Vertex>& aggregates,
1911 V& visitor) const
1912 {
1913 // Only evaluates for edge pointing to the aggregate
1914 AggregateVisitor<V> v(aggregates, aggregate, visitor);
1915 visitNeighbours(*graph_, vertex, v);
1916 }
1917
1918
1919 template<class G>
1921 : count_(0)
1922 {}
1923
1924 template<class G>
1926 {
1927 ++count_;
1928 }
1929
1930 template<class G>
1932 {
1933 --count_;
1934 }
1935 template<class G>
1937 {
1938 return count_;
1939 }
1940
1941 template<class G>
1943 {
1944 if(edge.properties().isTwoWay())
1946 }
1947
1948 template<class G>
1949 int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
1950 const AggregatesMap<Vertex>& aggregates) const
1951 {
1952 TwoWayCounter counter;
1953 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
1954 return counter.value();
1955 }
1956
1957 template<class G>
1958 int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
1959 const AggregatesMap<Vertex>& aggregates) const
1960 {
1961 OneWayCounter counter;
1962 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
1963 return counter.value();
1964 }
1965
1966 template<class G>
1968 {
1969 if(edge.properties().isOneWay())
1971 }
1972
1973 template<class G>
1974 inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
1975 const AggregatesMap<Vertex>& aggregates)
1976 : Counter(), connected_(connected), aggregates_(aggregates)
1977 {}
1978
1979
1980 template<class G>
1982 {
1983 if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
1984 // Would be a new connection
1986 else{
1989 }
1990 }
1991
1992 template<class G>
1993 inline double Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
1994 {
1995 ConnectivityCounter counter(connected_, aggregates);
1996 double noNeighbours=visitNeighbours(*graph_, vertex, counter);
1997 return (double)counter.value()/noNeighbours;
1998 }
1999
2000 template<class G>
2002 : Counter()
2003 {}
2004
2005 template<class G>
2007 {
2008 if(edge.properties().depends())
2010 if(edge.properties().influences())
2012 }
2013
2014 template<class G>
2015 int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
2016 {
2017 return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
2018 }
2019
2020 template<class G>
2021 std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
2022 const AggregateDescriptor& aggregate,
2023 const AggregatesMap<Vertex>& aggregates) const
2024 {
2025 DependencyCounter unused, aggregated;
2026 typedef AggregateVisitor<DependencyCounter> CounterT;
2027 typedef std::tuple<CounterT,CounterT> CounterTuple;
2028 CombinedFunctor<CounterTuple> visitors(CounterTuple(CounterT(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), CounterT(aggregates, aggregate, aggregated)));
2029 visitNeighbours(*graph_, vertex, visitors);
2030 return std::make_pair(unused.value(), aggregated.value());
2031 }
2032
2033
2034 template<class G>
2035 int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
2036 {
2037 DependencyCounter counter;
2038 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
2039 return counter.value();
2040 }
2041
2042 template<class G>
2043 std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
2044 {
2045 return 0;
2046 typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
2047 VertexList vlist;
2048 typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
2049 return aggregates.template breadthFirstSearch<true,true>(vertex,
2050 aggregate_->id(), *graph_,
2051 vlist, dummy, dummy, visitedMap);
2052 }
2053
2054 template<class G>
2056 : front_(front), graph_(graph)
2057 {}
2058
2059 template<class G>
2061 {
2062 Vertex target = edge.target();
2063
2064 if(!graph_.getVertexProperties(target).front()) {
2065 front_.push_back(target);
2066 graph_.getVertexProperties(target).setFront();
2067 }
2068 }
2069
2070 template<class G>
2071 inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
2072 {
2073 // Todo
2074 Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
2075 return true;
2076 //Situation 1: front node depends on two nodes. Then these
2077 // have to be strongly connected to each other
2078
2079 // Iterate over all all neighbours of front node
2080 typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2081 Iterator vend = graph_->endEdges(vertex);
2082 for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge) {
2083 // if(edge.properties().depends() && !edge.properties().influences()
2084 if(edge.properties().isStrong()
2085 && aggregates[edge.target()]==aggregate)
2086 {
2087 // Search for another link to the aggregate
2088 Iterator edge1 = edge;
2089 for(++edge1; edge1 != vend; ++edge1) {
2090 //if(edge1.properties().depends() && !edge1.properties().influences()
2091 if(edge1.properties().isStrong()
2092 && aggregates[edge.target()]==aggregate)
2093 {
2094 //Search for an edge connecting the two vertices that is
2095 //strong
2096 bool found=false;
2097 Iterator v2end = graph_->endEdges(edge.target());
2098 for(Iterator edge2 = graph_->beginEdges(edge.target()); edge2 != v2end; ++edge2) {
2099 if(edge2.target()==edge1.target() &&
2100 edge2.properties().isStrong()) {
2101 found =true;
2102 break;
2103 }
2104 }
2105 if(found)
2106 {
2107 return true;
2108 }
2109 }
2110 }
2111 }
2112 }
2113
2114 // Situation 2: cluster node depends on front node and other cluster node
2116 vend = graph_->endEdges(vertex);
2117 for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge) {
2118 //if(!edge.properties().depends() && edge.properties().influences()
2119 if(edge.properties().isStrong()
2120 && aggregates[edge.target()]==aggregate)
2121 {
2122 // Search for a link from target that stays within the aggregate
2123 Iterator v1end = graph_->endEdges(edge.target());
2124
2125 for(Iterator edge1=graph_->beginEdges(edge.target()); edge1 != v1end; ++edge1) {
2126 //if(edge1.properties().depends() && !edge1.properties().influences()
2127 if(edge1.properties().isStrong()
2128 && aggregates[edge1.target()]==aggregate)
2129 {
2130 bool found=false;
2131 // Check if front node is also connected to this one
2132 Iterator v2end = graph_->endEdges(vertex);
2133 for(Iterator edge2 = graph_->beginEdges(vertex); edge2 != v2end; ++edge2) {
2134 if(edge2.target()==edge1.target()) {
2135 if(edge2.properties().isStrong())
2136 found=true;
2137 break;
2138 }
2139 }
2140 if(found)
2141 {
2142 return true;
2143 }
2144 }
2145 }
2146 }
2147 }
2148 return false;
2149 }
2150
2151 template<class G>
2152 void Aggregator<G>::unmarkFront()
2153 {
2154 typedef typename std::vector<Vertex>::const_iterator Iterator;
2155
2156 for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
2157 graph_->getVertexProperties(*vertex).resetFront();
2158
2159 front_.clear();
2160 }
2161
2162 template<class G>
2163 inline void
2164 Aggregator<G>::nonisoNeighbourAggregate(const Vertex& vertex,
2165 const AggregatesMap<Vertex>& aggregates,
2166 SLList<Vertex>& neighbours) const
2167 {
2168 typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2169 Iterator end=graph_->beginEdges(vertex);
2170 neighbours.clear();
2171
2172 for(Iterator edge=graph_->beginEdges(vertex); edge!=end; ++edge)
2173 {
2174 if(aggregates[edge.target()]!=AggregatesMap<Vertex>::UNAGGREGATED && graph_->getVertexProperties(edge.target()).isolated())
2175 neighbours.push_back(aggregates[edge.target()]);
2176 }
2177 }
2178
2179 template<class G>
2180 inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
2181 {
2182 typedef typename MatrixGraph::ConstEdgeIterator Iterator;
2183
2184 Iterator end = graph_->endEdges(vertex);
2185 for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge) {
2186 if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
2187 graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()) {
2188 if( graph_->getVertexProperties(vertex).isolated() ||
2189 ((edge.properties().depends() || edge.properties().influences())
2190 && admissible(vertex, aggregates[edge.target()], aggregates)))
2191 return edge.target();
2192 }
2193 }
2194 return AggregatesMap<Vertex>::UNAGGREGATED;
2195 }
2196
2197 template<class G>
2199 : Counter(), graph_(graph)
2200 {}
2201
2202 template<class G>
2204 {
2205 if(graph_.getVertexProperties(edge.target()).front())
2207 }
2208
2209 template<class G>
2210 int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
2211 {
2212 FrontNeighbourCounter counter(*graph_);
2213 visitNeighbours(*graph_, vertex, counter);
2214 return counter.value();
2215 }
2216 template<class G>
2217 inline bool Aggregator<G>::connected(const Vertex& vertex,
2218 const AggregateDescriptor& aggregate,
2219 const AggregatesMap<Vertex>& aggregates) const
2220 {
2221 typedef typename G::ConstEdgeIterator iterator;
2222 const iterator end = graph_->endEdges(vertex);
2223 for(iterator edge = graph_->beginEdges(vertex); edge != end; ++edge)
2224 if(aggregates[edge.target()]==aggregate)
2225 return true;
2226 return false;
2227 }
2228 template<class G>
2229 inline bool Aggregator<G>::connected(const Vertex& vertex,
2230 const SLList<AggregateDescriptor>& aggregateList,
2231 const AggregatesMap<Vertex>& aggregates) const
2232 {
2233 typedef typename SLList<AggregateDescriptor>::const_iterator Iter;
2234 for(Iter i=aggregateList.begin(); i!=aggregateList.end(); ++i)
2235 if(connected(vertex, *i, aggregates))
2236 return true;
2237 return false;
2238 }
2239
2240 template<class G>
2241 template<class C>
2242 void Aggregator<G>::growIsolatedAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
2243 {
2244 SLList<Vertex> connectedAggregates;
2245 nonisoNeighbourAggregate(seed, aggregates,connectedAggregates);
2246
2247 while(aggregate_->size()< c.minAggregateSize() && aggregate_->connectSize() < c.maxConnectivity()) {
2248 double maxCon=-1;
2249 std::size_t maxFrontNeighbours=0;
2250
2251 Vertex candidate=AggregatesMap<Vertex>::UNAGGREGATED;
2252
2253 typedef typename std::vector<Vertex>::const_iterator Iterator;
2254
2255 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2256 if(distance(*vertex, aggregates)>c.maxDistance())
2257 continue; // distance of proposes aggregate too big
2258
2259 if(connectedAggregates.size()>0) {
2260 // there is already a neighbour cluster
2261 // front node must be connected to same neighbour cluster
2262
2263 if(!connected(*vertex, connectedAggregates, aggregates))
2264 continue;
2265 }
2266
2267 double con = connectivity(*vertex, aggregates);
2268
2269 if(con == maxCon) {
2270 std::size_t frontNeighbours = noFrontNeighbours(*vertex);
2271
2272 if(frontNeighbours >= maxFrontNeighbours) {
2273 maxFrontNeighbours = frontNeighbours;
2274 candidate = *vertex;
2275 }
2276 }else if(con > maxCon) {
2277 maxCon = con;
2278 maxFrontNeighbours = noFrontNeighbours(*vertex);
2279 candidate = *vertex;
2280 }
2281 }
2282
2283 if(candidate==AggregatesMap<Vertex>::UNAGGREGATED)
2284 break;
2285
2286 aggregate_->add(candidate);
2287 }
2288 }
2289
2290 template<class G>
2291 template<class C>
2292 void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
2293 {
2294 using std::min;
2295
2296 std::size_t distance_ =0;
2297 while(aggregate_->size() < c.minAggregateSize()&& distance_<c.maxDistance()) {
2298 int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1;
2299 double maxCon=-1;
2300
2301 std::vector<Vertex> candidates;
2302 candidates.reserve(30);
2303
2304 typedef typename std::vector<Vertex>::const_iterator Iterator;
2305
2306 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2307 // Only nonisolated nodes are considered
2308 if(graph_->getVertexProperties(*vertex).isolated())
2309 continue;
2310
2311 int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
2312
2313 /* The case of two way connections. */
2314 if( maxTwoCons == twoWayCons && twoWayCons > 0) {
2315 double con = connectivity(*vertex, aggregates);
2316
2317 if(con == maxCon) {
2318 int neighbours = noFrontNeighbours(*vertex);
2319
2320 if(neighbours > maxNeighbours) {
2321 maxNeighbours = neighbours;
2322 candidates.clear();
2323 candidates.push_back(*vertex);
2324 }else{
2325 candidates.push_back(*vertex);
2326 }
2327 }else if( con > maxCon) {
2328 maxCon = con;
2329 maxNeighbours = noFrontNeighbours(*vertex);
2330 candidates.clear();
2331 candidates.push_back(*vertex);
2332 }
2333 }else if(twoWayCons > maxTwoCons) {
2334 maxTwoCons = twoWayCons;
2335 maxCon = connectivity(*vertex, aggregates);
2336 maxNeighbours = noFrontNeighbours(*vertex);
2337 candidates.clear();
2338 candidates.push_back(*vertex);
2339
2340 // two way connections precede
2341 maxOneCons = std::numeric_limits<int>::max();
2342 }
2343
2344 if(twoWayCons > 0)
2345 {
2346 continue; // THis is a two-way node, skip tests for one way nodes
2347 }
2348
2349 /* The one way case */
2350 int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
2351
2352 if(oneWayCons==0)
2353 continue; // No strong connections, skip the tests.
2354
2355 if(!admissible(*vertex, aggregate_->id(), aggregates))
2356 continue;
2357
2358 if( maxOneCons == oneWayCons && oneWayCons > 0) {
2359 double con = connectivity(*vertex, aggregates);
2360
2361 if(con == maxCon) {
2362 int neighbours = noFrontNeighbours(*vertex);
2363
2364 if(neighbours > maxNeighbours) {
2365 maxNeighbours = neighbours;
2366 candidates.clear();
2367 candidates.push_back(*vertex);
2368 }else{
2369 if(neighbours==maxNeighbours)
2370 {
2371 candidates.push_back(*vertex);
2372 }
2373 }
2374 }else if( con > maxCon) {
2375 maxCon = con;
2376 maxNeighbours = noFrontNeighbours(*vertex);
2377 candidates.clear();
2378 candidates.push_back(*vertex);
2379 }
2380 }else if(oneWayCons > maxOneCons) {
2381 maxOneCons = oneWayCons;
2382 maxCon = connectivity(*vertex, aggregates);
2383 maxNeighbours = noFrontNeighbours(*vertex);
2384 candidates.clear();
2385 candidates.push_back(*vertex);
2386 }
2387 }
2388
2389
2390 if(!candidates.size())
2391 break; // No more candidates found
2392 distance_=distance(seed, aggregates);
2393 candidates.resize(min(candidates.size(), c.maxAggregateSize()-
2394 aggregate_->size()));
2395 aggregate_->add(candidates);
2396 }
2397 }
2398
2399 template<typename V>
2400 template<typename M, typename G, typename C>
2401 std::tuple<int,int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion,
2402 bool finestLevel)
2403 {
2404 Aggregator<G> aggregator;
2405 return aggregator.build(matrix, graph, *this, criterion, finestLevel);
2406 }
2407
2408 template<class G>
2409 template<class M, class C>
2410 std::tuple<int,int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c,
2411 bool finestLevel)
2412 {
2413 using std::max;
2414 using std::min;
2415 // Stack for fast vertex access
2416 Stack stack_(graph, *this, aggregates);
2417
2418 graph_ = &graph;
2419
2420 aggregate_ = new Aggregate<G,VertexSet>(graph, aggregates, connected_, front_);
2421
2422 Timer watch;
2423 watch.reset();
2424
2425 buildDependency(graph, m, c, finestLevel);
2426
2427 dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
2428 int noAggregates, conAggregates, isoAggregates, oneAggregates;
2429 std::size_t maxA=0, minA=1000000, avg=0;
2430 int skippedAggregates;
2431 noAggregates = conAggregates = isoAggregates = oneAggregates =
2432 skippedAggregates = 0;
2433
2434 while(true) {
2435 Vertex seed = stack_.pop();
2436
2437 if(seed == Stack::NullEntry)
2438 // No more unaggregated vertices. We are finished!
2439 break;
2440
2441 // Debugging output
2442 if((noAggregates+1)%10000 == 0)
2443 Dune::dverb<<"c";
2444 unmarkFront();
2445
2446 if(graph.getVertexProperties(seed).excludedBorder()) {
2447 aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
2448 ++skippedAggregates;
2449 continue;
2450 }
2451
2452 if(graph.getVertexProperties(seed).isolated()) {
2453 if(c.skipIsolated()) {
2454 // isolated vertices are not aggregated but skipped on the coarser levels.
2455 aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
2456 ++skippedAggregates;
2457 // skip rest as no agglomeration is done.
2458 continue;
2459 }else{
2460 aggregate_->seed(seed);
2461 growIsolatedAggregate(seed, aggregates, c);
2462 }
2463 }else{
2464 aggregate_->seed(seed);
2465 growAggregate(seed, aggregates, c);
2466 }
2467
2468 /* The rounding step. */
2469 while(!(graph.getVertexProperties(seed).isolated()) && aggregate_->size() < c.maxAggregateSize()) {
2470
2471 std::vector<Vertex> candidates;
2472 candidates.reserve(30);
2473
2474 typedef typename std::vector<Vertex>::const_iterator Iterator;
2475
2476 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) {
2477
2478 if(graph.getVertexProperties(*vertex).isolated())
2479 continue; // No isolated nodes here
2480
2481 if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 &&
2482 (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 ||
2483 !admissible( *vertex, aggregate_->id(), aggregates) ))
2484 continue;
2485
2486 std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
2487 aggregates);
2488
2489 //if(aggregateNeighbours(*vertex, aggregate_->id(), aggregates) <= unusedNeighbours(*vertex, aggregates))
2490 // continue;
2491
2492 if(neighbourPair.first >= neighbourPair.second)
2493 continue;
2494
2495 if(distance(*vertex, aggregates) > c.maxDistance())
2496 continue; // Distance too far
2497 candidates.push_back(*vertex);
2498 break;
2499 }
2500
2501 if(!candidates.size()) break; // no more candidates found.
2502
2503 candidates.resize(min(candidates.size(), c.maxAggregateSize()-
2504 aggregate_->size()));
2505 aggregate_->add(candidates);
2506
2507 }
2508
2509 // try to merge aggregates consisting of only one nonisolated vertex with other aggregates
2510 if(aggregate_->size()==1 && c.maxAggregateSize()>1) {
2511 if(!graph.getVertexProperties(seed).isolated()) {
2512 Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
2513
2514 if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED) {
2515 // assign vertex to the neighbouring cluster
2516 aggregates[seed] = aggregates[mergedNeighbour];
2517 aggregate_->invalidate();
2518 }else{
2519 ++avg;
2520 minA=min(minA,static_cast<std::size_t>(1));
2521 maxA=max(maxA,static_cast<std::size_t>(1));
2522 ++oneAggregates;
2523 ++conAggregates;
2524 }
2525 }else{
2526 ++avg;
2527 minA=min(minA,static_cast<std::size_t>(1));
2528 maxA=max(maxA,static_cast<std::size_t>(1));
2529 ++oneAggregates;
2530 ++isoAggregates;
2531 }
2532 ++avg;
2533 }else{
2534 avg+=aggregate_->size();
2535 minA=min(minA,aggregate_->size());
2536 maxA=max(maxA,aggregate_->size());
2537 if(graph.getVertexProperties(seed).isolated())
2538 ++isoAggregates;
2539 else
2540 ++conAggregates;
2541 }
2542
2543 }
2544
2545 Dune::dinfo<<"connected aggregates: "<<conAggregates;
2546 Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
2547 if(conAggregates+isoAggregates>0)
2548 Dune::dinfo<<" one node aggregates: "<<oneAggregates<<" min size="
2549 <<minA<<" max size="<<maxA
2550 <<" avg="<<avg/(conAggregates+isoAggregates)<<std::endl;
2551
2552 delete aggregate_;
2553 return std::make_tuple(conAggregates+isoAggregates,isoAggregates,
2554 oneAggregates,skippedAggregates);
2555 }
2556
2557
2558 template<class G>
2559 Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
2560 const AggregatesMap<Vertex>& aggregates)
2561 : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), begin_(graph.begin()), end_(graph.end())
2562 {
2563 //vals_ = new Vertex[N];
2564 }
2565
2566 template<class G>
2568 {
2569 //Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
2570 //delete[] vals_;
2571 }
2572
2573 template<class G>
2576
2577 template<class G>
2578 inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
2579 {
2580 for(; begin_!=end_ && aggregates_[*begin_] != AggregatesMap<Vertex>::UNAGGREGATED; ++begin_) ;
2581
2582 if(begin_!=end_)
2583 {
2584 typename G::VertexDescriptor current=*begin_;
2585 ++begin_;
2586 return current;
2587 }else
2588 return NullEntry;
2589 }
2590
2591#endif // DOXYGEN
2592
2593 template<class V>
2594 void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m, std::ostream& os)
2595 {
2596 using std::max;
2597
2598 std::ios_base::fmtflags oldOpts=os.flags();
2599
2600 os.setf(std::ios_base::right, std::ios_base::adjustfield);
2601
2602 V maxVal=0;
2603 int width=1;
2604
2605 for(int i=0; i< n*m; i++)
2606 maxVal=max(maxVal, aggregates[i]);
2607
2608 for(int i=10; i < 1000000; i*=10)
2609 if(maxVal/i>0)
2610 width++;
2611 else
2612 break;
2613
2614 for(int j=0, entry=0; j < m; j++) {
2615 for(int i=0; i<n; i++, entry++) {
2616 os.width(width);
2617 os<<aggregates[entry]<<" ";
2618 }
2619
2620 os<<std::endl;
2621 }
2622 os<<std::endl;
2623 os.flags(oldOpts);
2624 }
2625
2626
2627 } // namespace Amg
2628
2629} // namespace Dune
2630
2631
2632#endif
Provides classes for building the matrix graph.
Parameter classes for customizing AMG.
Provides classes for handling internal properties in a graph.
Col col
Definition matrixmatrix.hh:351
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition aggregates.hh:279
std::vector< real_type >::iterator valIter_
Definition aggregates.hh:193
void initRow(const R &row, int index)
Definition aggregates.hh:206
void initRow(const R &row, int index)
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition aggregates.hh:156
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:589
FieldTraits< M >::real_type operator()(const M &m) const
compute the norm of a matrix.
Definition aggregates.hh:402
iterator begin()
Definition aggregates.hh:740
int id()
Get the id identifying the aggregate.
Norm norm_
The functor for calculating the norm.
Definition aggregates.hh:310
size_type size()
Get the size of the aggregate.
MatrixGraph::VertexDescriptor Vertex
The vertex identifier.
Definition aggregates.hh:928
AggregationCriterion()
Constructor.
Definition aggregates.hh:68
const Matrix * matrix_
The matrix we work on.
Definition aggregates.hh:367
FieldTraits< M >::real_type operator()(const M &m) const
compute the norm of a matrix.
Definition aggregates.hh:493
SymmetricMatrixDependency(const Parameters &parms)
Definition aggregates.hh:172
void examine(G &graph, const typename G::EdgeIterator &edge, const C &col)
M Matrix
The matrix type we build the dependency of.
Definition aggregates.hh:264
G MatrixGraph
The matrix graph type used.
Definition aggregates.hh:923
Norm norm_
The functor for calculating the norm.
Definition aggregates.hh:373
FieldTraits< M >::real_type operator()(const M &) const
compute the norm of a matrix.
Definition aggregates.hh:509
void operator()(const EdgeIterator &edge) const
Definition aggregates.hh:604
typename VertexSet::size_type size_type
Type of size used by allocator of sllist.
Definition aggregates.hh:809
SymmetricCriterion()
Definition aggregates.hh:527
Dependency()
Definition aggregates.hh:298
void examine(const C &col)
Definition aggregates.hh:220
M Matrix
The matrix type we build the dependency of.
Definition aggregates.hh:327
real_type diagonal_
The norm of the current diagonal.
Definition aggregates.hh:191
N Norm
The norm to use for examining the matrix entries.
Definition aggregates.hh:269
iterator end()
Definition aggregates.hh:745
UnSymmetricCriterion(const Parameters &parms)
Definition aggregates.hh:544
void operator()(const typename MatrixGraph::ConstEdgeIterator &edge)
static const Vertex NullEntry
Definition aggregates.hh:1016
void examine(const C &col)
Dependency(const Parameters &parms)
Definition aggregates.hh:294
int row_
index of the currently evaluated row.
Definition aggregates.hh:189
friend class Stack
Definition aggregates.hh:1044
void operator()(const typename MatrixGraph::ConstEdgeIterator &edge)
std::tuple< int, int, int, int > build(const M &m, G &graph, AggregatesMap< Vertex > &aggregates, const C &c, bool finestLevel)
Build the aggregates.
FrontNeighbourCounter(const MatrixGraph &front)
Constructor.
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition aggregates.hh:337
const Matrix * matrix_
The matrix we work on.
Definition aggregates.hh:304
size_type connectSize()
Get the number of connections to other aggregates.
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:342
~AggregatesMap()
Destructor.
Matrix::field_type field_type
The current max value.
Definition aggregates.hh:183
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:1072
std::size_t * SphereMap
Type of the mapping of aggregate members onto distance spheres.
Definition aggregates.hh:817
AggregationCriterion(const Parameters &parms)
Definition aggregates.hh:72
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition aggregates.hh:274
std::vector< real_type > vals_
Definition aggregates.hh:192
N Norm
The norm to use for examining the matrix entries.
Definition aggregates.hh:332
void printAggregates2d(const AggregatesMap< V > &aggregates, int n, int m, std::ostream &os)
Definition aggregates.hh:2594
void invalidate()
Definition aggregates.hh:830
const_iterator begin() const
Definition aggregates.hh:728
real_type maxValue_
Definition aggregates.hh:185
Norm norm_
The functor for calculating the norm.
Definition aggregates.hh:187
void operator()(const typename MatrixGraph::ConstEdgeIterator &edge)
VertexSet::const_iterator const_iterator
Const iterator over a vertex list.
Definition aggregates.hh:812
SymmetricCriterion(const Parameters &parms)
Definition aggregates.hh:524
MatrixGraph::VertexDescriptor AggregateDescriptor
The type of the aggregate descriptor.
Definition aggregates.hh:931
real_type maxValue_
Definition aggregates.hh:371
void init(const Matrix *matrix)
Definition aggregates.hh:199
real_type diagonal_
The norm of the current diagonal.
Definition aggregates.hh:377
AggregateDescriptor * iterator
Definition aggregates.hh:738
SymmetricDependency(const Parameters &parms)
Definition aggregates.hh:358
FieldTraits< field_type >::real_type real_type
Definition aggregates.hh:370
~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:57
void add(std::vector< Vertex > &vertex)
Aggregator()
Constructor.
void operator()(const typename MatrixGraph::ConstEdgeIterator &edge)
Examine an edge.
FrontMarker(std::vector< Vertex > &front, MatrixGraph &graph)
Constructor.
void init(const Matrix *matrix)
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:84
const_iterator end() const
Definition aggregates.hh:733
V AggregateDescriptor
The aggregate descriptor type.
Definition aggregates.hh:583
static const V ISOLATED
Identifier of isolated vertices.
Definition aggregates.hh:574
int row_
index of the currently evaluated row.
Definition aggregates.hh:375
SymmetricMatrixDependency()
Definition aggregates.hh:175
void examine(G &graph, const typename G::EdgeIterator &edge, const C &col)
real_type diagonal_
The norm of the current diagonal.
Definition aggregates.hh:314
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:107
AggregatesMap(std::size_t noVertices)
Constructs with allocating memory.
Matrix::field_type field_type
The current max value.
Definition aggregates.hh:369
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:595
ConnectivityCounter(const VertexSet &connected, const AggregatesMap< Vertex > &aggregates)
Constructor.
const_iterator end() const
get an iterator over the vertices of the aggregate.
void init(const Matrix *matrix)
UnSymmetricCriterion()
Definition aggregates.hh:547
void operator()(const typename MatrixGraph::ConstEdgeIterator &edge)
const AggregateDescriptor * const_iterator
Definition aggregates.hh:726
int row_
index of the currently evaluated row.
Definition aggregates.hh:312
Stack(const MatrixGraph &graph, const Aggregator< G > &aggregatesBuilder, const AggregatesMap< Vertex > &aggregates)
FieldTraits< field_type >::real_type real_type
Definition aggregates.hh:184
M Matrix
The matrix type we build the dependency of.
Definition aggregates.hh:141
void examine(const C &col)
FieldTraits< field_type >::real_type real_type
Definition aggregates.hh:307
const Matrix * matrix_
The matrix we work on.
Definition aggregates.hh:181
S VertexSet
The type of a single linked list of vertex descriptors.
Definition aggregates.hh:804
static const V UNAGGREGATED
Identifier of not yet aggregated vertices.
Definition aggregates.hh:569
std::size_t breadthFirstSearch(const VertexDescriptor &start, const AggregateDescriptor &aggregate, const G &graph, F &aggregateVisitor, VM &visitedMap) const
Breadth first search within an aggregate.
void initRow(const R &row, int index)
Matrix::field_type field_type
The current max value.
Definition aggregates.hh:306
void operator()(const typename MatrixGraph::ConstEdgeIterator &edge)
std::ostream & operator<<(std::ostream &os, const AggregationCriterion< T > &criterion)
Definition aggregates.hh:115
bool isIsolated()
Definition aggregates.hh:246
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:146
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:792
void seed(const Vertex &vertex)
Initialize the aggregate with one vertex.
SymmetricDependency()
Definition aggregates.hh:361
void clear()
Clear the aggregate.
void free()
Free the allocated memory.
void increment()
Increment counter.
void buildDependency(G &graph, const typename C::Matrix &matrix, C criterion, bool finestLevel)
Build the dependency of the matrix graph.
V VertexDescriptor
The vertex descriptor type.
Definition aggregates.hh:578
real_type maxValue_
Definition aggregates.hh:308
std::tuple< int, int, int, int > buildAggregates(const M &matrix, G &graph, const C &criterion, bool finestLevel)
Build the aggregates.
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition aggregates.hh:151
FieldTraits< M >::real_type operator()(const M &m) const
compute the norm of a matrix.
Definition aggregates.hh:476
PoolAllocator< Vertex, 100 > Allocator
The allocator we use for our lists and the set.
Definition aggregates.hh:798
G MatrixGraph
Definition aggregates.hh:788
void operator()(const typename MatrixGraph::ConstEdgeIterator &edge)
@ is_sign_preserving
Definition aggregates.hh:469
@ is_sign_preserving
Definition aggregates.hh:394
@ is_sign_preserving
Definition aggregates.hh:502
@ is_sign_preserving
Definition aggregates.hh:486
int size() const
iterator end()
SLListConstIterator< T, A > const_iterator
void remove()
iterator begin()
void * allocate()
constexpr auto max
constexpr auto min
size_type dim() const
static constexpr size_type M()
static constexpr size_type N()
std::ptrdiff_t index() const
#define DUNE_THROW(E,...)
void add(const GlobalIndex &global)
int neighbours() const
iterator(ParallelIndexSet< TG, TL, N > &indexSet, const Father &father)
const_iterator find(int proc) const
DVVerbType dvverb
DVerbType dverb
DInfoType dinfo
void put(const RAPropertyMapHelper< Reference, PropertyMap > &pmap, const Key &key, const Value &value)
constexpr std::integral_constant< T, I0 > front(std::integer_sequence< T, I0, II... >)
constexpr auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
derive error class from the base class in common
Definition istlexception.hh:19
A generic dynamic dense matrix.
Definition matrix.hh:561
typename Imp::BlockTraits< T >::field_type field_type
Export the type representing the underlying field.
Definition matrix.hh:565
row_type::const_iterator ConstColIterator
Const iterator for the entries of each row.
Definition matrix.hh:589
MatrixImp::DenseMatrixBase< T, A >::window_type row_type
The type implementing a matrix row.
Definition matrix.hh:574
Base class of all aggregation criterions.
Definition aggregates.hh:51
Dependency policy for symmetric matrices.
Definition aggregates.hh:136
Dependency policy for symmetric matrices.
Definition aggregates.hh:259
Dependency policy for symmetric matrices.
Definition aggregates.hh:322
Norm that uses only the [N][N] entry of the block to determine couplings.
Definition aggregates.hh:391
Norm that uses only the [0][0] entry of the block to determine couplings.
Definition aggregates.hh:458
Functor using the row sum (infinity) norm to determine strong couplings.
Definition aggregates.hh:466
Definition aggregates.hh:483
Definition aggregates.hh:499
Criterion taking advantage of symmetric matrices.
Definition aggregates.hh:522
Criterion suitable for unsymmetric matrices.
Definition aggregates.hh:542
Class for building the aggregates.
Definition aggregates.hh:917
Class providing information about the mapping of the vertices onto aggregates.
Definition aggregates.hh:563
A Dummy visitor that does nothing for each visited edge.
Definition aggregates.hh:601
A class for temporarily storing the vertices of an aggregate in.
Definition aggregates.hh:781
M::size_type VertexDescriptor
The vertex descriptor.
Definition graph.hh:73
EdgeIteratorT< const MatrixGraph< Matrix > > ConstEdgeIterator
The constant edge iterator type.
Definition graph.hh:298
Iterator over all edges starting from a vertex.
Definition graph.hh:95
The vertex iterator type of the graph.
Definition graph.hh:209
All parameters for AMG.
Definition parameters.hh:416
T assign(T... args)
T back_inserter(T... args)
T begin(T... args)
T beta(T... args)
T capacity(T... args)
T clear(T... args)
T end(T... args)
T endl(T... args)
T erase(T... args)
T find(T... args)
T flags(T... args)
T imag(T... args)
T insert(T... args)
T lower_bound(T... args)
T make_pair(T... args)
T make_tuple(T... args)
T max(T... args)
T min(T... args)
T push_back(T... args)
T real(T... args)
T reserve(T... args)
T resize(T... args)
T set_difference(T... args)
T setf(T... args)
T size(T... args)
T sort(T... args)
T width(T... args)