5#ifndef DUNE_AMG_AGGREGATES_HH
6#define DUNE_AMG_AGGREGATES_HH
12#include "combinedfunctor.hh"
86 this->setMaxDistance(diameter-1);
91 this->setMaxDistance(this->maxDistance()+diameter-1);
93 this->setMinAggregateSize(csize);
94 this->setMaxAggregateSize(
static_cast<std::size_t
>(csize*1.5));
110 this->setMaxDistance(this->maxDistance()+dim-1);
115 std::ostream& operator<<(std::ostream& os,
const AggregationCriterion<T>& criterion)
117 os<<
"{ maxdistance="<<criterion.maxDistance()<<
" minAggregateSize="
118 <<criterion.minAggregateSize()<<
" maxAggregateSize="<<criterion.maxAggregateSize()
119 <<
" connectivity="<<criterion.maxConnectivity()<<
" debugLevel="<<criterion.debugLevel()<<
"}";
134 template<
class M,
class N>
158 void init(
const Matrix* matrix);
160 void initRow(
const Row& row,
int index);
162 void examine(
const ColIter& col);
165 void examine(G& graph,
const typename G::EdgeIterator& edge,
const ColIter& col);
182 typedef typename FieldTraits<field_type>::real_type real_type;
190 std::vector<real_type> vals_;
191 typename std::vector<real_type>::iterator valIter_;
196 template<
class M,
class N>
202 template<
class M,
class N>
203 inline void SymmetricMatrixDependency<M,N>::initRow(
const Row& row,
int index)
206 vals_.assign(row.size(), 0.0);
207 assert(vals_.size()==row.size());
208 valIter_=vals_.begin();
211 diagonal_=norm_(row[index]);
215 template<
class M,
class N>
216 inline void SymmetricMatrixDependency<M,N>::examine(
const ColIter& col)
220 real_type eij = norm_(*col);
221 if(!N::is_sign_preserving || eij<0)
223 *valIter_ = eij/diagonal_*eij/norm_(matrix_->operator[](col.index())[col.index()]);
224 maxValue_ =
max(maxValue_, *valIter_);
230 template<
class M,
class N>
232 inline void SymmetricMatrixDependency<M,N>::examine(G&,
const typename G::EdgeIterator& edge,
const ColIter&)
234 if(*valIter_ > alpha() * maxValue_) {
235 edge.properties().setDepends();
236 edge.properties().setInfluences();
241 template<
class M,
class N>
242 inline bool SymmetricMatrixDependency<M,N>::isIsolated()
246 valIter_=vals_.begin();
247 return maxValue_ < beta();
253 template<
class M,
class N>
277 void init(
const Matrix* matrix);
279 void initRow(
const Row& row,
int index);
281 void examine(
const ColIter& col);
284 void examine(G& graph,
const typename G::EdgeIterator& edge,
const ColIter& col);
301 typedef typename FieldTraits<field_type>::real_type real_type;
314 template<
class M,
class N>
338 void init(
const Matrix* matrix);
340 void initRow(
const Row& row,
int index);
342 void examine(
const ColIter& col);
345 void examine(G& graph,
const typename G::EdgeIterator& edge,
const ColIter& col);
362 typedef typename FieldTraits<field_type>::real_type real_type;
371 void initRow(
const Row& row,
int index,
const std::true_type&);
372 void initRow(
const Row& row,
int index,
const std::false_type&);
384 is_sign_preserving =
true
392 typename FieldTraits<typename M::field_type>::real_type
operator()(
const M& m,
395 typedef typename M::field_type field_type;
396 typedef typename FieldTraits<field_type>::real_type real_type;
397 static_assert( std::is_convertible<field_type, real_type >::value,
398 "use of diagonal norm in AMG not implemented for complex field_type");
411 typedef typename FieldTraits<M>::real_type real_type;
412 static_assert( std::is_convertible<M, real_type >::value,
413 "use of diagonal norm in AMG not implemented for complex field_type");
422 static T signed_abs(
const T & v)
429 static T signed_abs(
const std::complex<T> & v)
433 return csgn(v) * std::abs(v);
438 static T csgn(
const T & v)
440 return (T(0) < v) - (v < T(0));
445 static T csgn(std::complex<T> a)
447 return csgn(a.real())+(a.real() == 0.0)*csgn(a.imag());
468 is_sign_preserving =
false
475 typename FieldTraits<M>::real_type
operator()(
const M& m)
const
481 return m.infinity_norm();
489 is_sign_preserving =
false
496 typename FieldTraits<M>::real_type
operator()(
const M& m)
const
502 return m.frobenius_norm();
509 is_sign_preserving =
false
516 typename FieldTraits<M>::real_type
operator()(
const M& )
const
527 template<
class M,
class Norm>
547 template<
class M,
class Norm>
610 template<
class EdgeIterator>
611 void operator()([[maybe_unused]]
const EdgeIterator& edge)
const
644 template<
class M,
class G,
class C>
645 std::tuple<int,int,int,int>
buildAggregates(
const M& matrix, G& graph,
const C& criterion,
665 template<
bool reset,
class G,
class F,
class VM>
670 VM& visitedMap)
const;
695 template<
bool remove,
bool reset,
class G,
class L,
class F1,
class F2,
class VM>
698 const G& graph, L& visited, F1& aggregateVisitor,
699 F2& nonAggregateVisitor,
700 VM& visitedMap)
const;
735 const_iterator begin()
const
740 const_iterator end()
const
760 AggregatesMap<V>& operator=(
const AggregatesMap<V>&) =
delete;
770 std::size_t noVertices_;
776 template<
class G,
class C>
778 const typename C::Matrix& matrix,
786 template<
class G,
class S>
795 typedef G MatrixGraph;
835 VertexSet& connectivity, std::vector<Vertex>& front_);
916 std::vector<Vertex>& front_;
966 template<
class M,
class C>
967 std::tuple<int,int,int,int>
build(
const M& m, G& graph,
985 typedef std::set<Vertex,std::less<Vertex>,
Allocator> VertexSet;
990 typedef std::size_t* SphereMap;
1005 std::vector<Vertex> front_;
1010 VertexSet connected_;
1023 static const Vertex NullEntry;
1031 enum { N = 1300000 };
1065 const AggregatesMap<Vertex>& aggregates,
1073 class AggregateVisitor
1133 class FrontNeighbourCounter :
public Counter
1157 class TwoWayCounter :
public Counter
1180 class OneWayCounter :
public Counter
1198 const AggregatesMap<Vertex>& aggregates)
const;
1206 class ConnectivityCounter :
public Counter
1220 const VertexSet& connected_;
1265 class DependencyCounter :
public Counter
1297 std::vector<Vertex>& front_;
1412 template<
class M,
class N>
1418 template<
class M,
class N>
1419 inline void SymmetricDependency<M,N>::initRow(
const Row& row,
int index)
1421 initRow(row, index, std::is_convertible<field_type, real_type>());
1424 template<
class M,
class N>
1425 inline void SymmetricDependency<M,N>::initRow(
const Row& ,
int ,
const std::false_type&)
1427 DUNE_THROW(InvalidStateException,
"field_type needs to convertible to real_type");
1430 template<
class M,
class N>
1431 inline void SymmetricDependency<M,N>::initRow(
const Row& ,
int index,
const std::true_type&)
1436 diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1439 template<
class M,
class N>
1440 inline void SymmetricDependency<M,N>::examine(
const ColIter& col)
1443 real_type eij = norm_(*col);
1445 matrix_->operator[](col.index()).find(row_);
1446 if ( opposite_entry == matrix_->operator[](col.index()).end() )
1451 real_type eji = norm_(*opposite_entry);
1454 if(!N::is_sign_preserving || eij<0 || eji<0)
1455 maxValue_ =
max(maxValue_,
1456 eij /diagonal_ * eji/
1457 norm_(matrix_->operator[](col.index())[col.index()]));
1460 template<
class M,
class N>
1462 inline void SymmetricDependency<M,N>::examine(G& graph,
const typename G::EdgeIterator& edge,
const ColIter& col)
1464 real_type eij = norm_(*col);
1466 matrix_->operator[](col.index()).find(row_);
1468 if ( opposite_entry == matrix_->operator[](col.index()).end() )
1473 real_type eji = norm_(*opposite_entry);
1475 if(!N::is_sign_preserving || (eij<0 || eji<0))
1476 if(eji / norm_(matrix_->operator[](edge.target())[edge.target()]) *
1477 eij/ diagonal_ > alpha() * maxValue_) {
1478 edge.properties().setDepends();
1479 edge.properties().setInfluences();
1480 typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
1481 other.setInfluences();
1486 template<
class M,
class N>
1487 inline bool SymmetricDependency<M,N>::isIsolated()
1489 return maxValue_ < beta();
1493 template<
class M,
class N>
1494 inline void Dependency<M,N>::init(
const Matrix* matrix)
1499 template<
class M,
class N>
1500 inline void Dependency<M,N>::initRow([[maybe_unused]]
const Row& row,
int index)
1505 diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1508 template<
class M,
class N>
1509 inline void Dependency<M,N>::examine(
const ColIter& col)
1512 maxValue_ =
max(maxValue_, -norm_(*col));
1515 template<
class M,
class N>
1517 inline void Dependency<M,N>::examine(G& graph,
const typename G::EdgeIterator& edge,
const ColIter& col)
1519 if(-norm_(*col) >= maxValue_ * alpha()) {
1520 edge.properties().setDepends();
1521 typedef typename G::EdgeDescriptor ED;
1522 ED e= graph.findEdge(edge.target(), edge.source());
1525 typename G::EdgeProperties& other = graph.getEdgeProperties(e);
1526 other.setInfluences();
1531 template<
class M,
class N>
1532 inline bool Dependency<M,N>::isIsolated()
1534 return maxValue_ < beta() * diagonal_;
1537 template<
class G,
class S>
1539 VertexSet& connected, std::vector<Vertex>&
front)
1540 : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
1541 connected_(connected), front_(
front)
1544 template<
class G,
class S>
1552 throw "Not yet implemented";
1560 template<
class G,
class S>
1563 dvverb<<
"Connected cleared"<<std::endl;
1566 connected_.insert(
vertex);
1567 dvverb <<
" Inserting "<<
vertex<<
" size="<<connected_.size();
1573 template<
class G,
class S>
1576 vertices_.insert(
vertex);
1579 front_.erase(std::lower_bound(front_.begin(), front_.end(),
vertex));
1583 const iterator end = graph_.endEdges(
vertex);
1584 for(iterator edge = graph_.beginEdges(
vertex); edge != end; ++edge) {
1585 dvverb <<
" Inserting "<<aggregates_[edge.target()];
1586 connected_.insert(aggregates_[edge.target()]);
1587 dvverb <<
" size="<<connected_.size();
1589 !graph_.getVertexProperties(edge.target()).front())
1591 front_.push_back(edge.target());
1592 graph_.getVertexProperties(edge.target()).setFront();
1596 std::sort(front_.begin(), front_.end());
1599 template<
class G,
class S>
1603 std::size_t oldsize = vertices_.size();
1605 typedef typename std::vector<Vertex>::iterator Iterator;
1607 typedef typename VertexSet::iterator SIterator;
1609 SIterator pos=vertices_.begin();
1610 std::vector<Vertex> newFront;
1611 newFront.reserve(front_.capacity());
1613 std::set_difference(front_.begin(), front_.end(), vertices.begin(), vertices.end(),
1614 std::back_inserter(newFront));
1619 pos=vertices_.insert(pos,*
vertex);
1620 vertices_.insert(*
vertex);
1621 graph_.getVertexProperties(*vertex).resetFront();
1622 aggregates_[*
vertex]=id_;
1625 const iterator end = graph_.endEdges(*
vertex);
1626 for(iterator edge = graph_.beginEdges(*
vertex); edge != end; ++edge) {
1627 dvverb <<
" Inserting "<<aggregates_[edge.target()];
1628 connected_.insert(aggregates_[edge.target()]);
1630 !graph_.getVertexProperties(edge.target()).front())
1632 front_.push_back(edge.target());
1633 graph_.getVertexProperties(edge.target()).setFront();
1635 dvverb <<
" size="<<connected_.size();
1639 std::sort(front_.begin(), front_.end());
1640 assert(oldsize+vertices.size()==vertices_.size());
1642 template<
class G,
class S>
1650 template<
class G,
class S>
1654 return vertices_.size();
1657 template<
class G,
class S>
1661 return connected_.size();
1664 template<
class G,
class S>
1670 template<
class G,
class S>
1673 return vertices_.begin();
1676 template<
class G,
class S>
1679 return vertices_.end();
1697 delete[] aggregates_;
1704 allocate(noVertices);
1717 noVertices_ = noVertices;
1719 for(std::size_t i=0; i < noVertices; i++)
1720 aggregates_[i]=UNAGGREGATED;
1726 assert(aggregates_ != 0);
1727 delete[] aggregates_;
1735 return aggregates_[v];
1742 return aggregates_[v];
1746 template<
bool reset,
class G,
class F,
class VM>
1749 const G& graph, F& aggregateVisitor,
1750 VM& visitedMap)
const
1754 DummyEdgeVisitor dummy;
1755 return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap);
1759 template<
bool remove,
bool reset,
class G,
class L,
class F1,
class F2,
class VM>
1764 F1& aggregateVisitor,
1765 F2& nonAggregateVisitor,
1766 VM& visitedMap)
const
1768 typedef typename L::const_iterator ListIterator;
1769 int visitedSpheres = 0;
1771 visited.push_back(start);
1772 put(visitedMap, start,
true);
1774 ListIterator current = visited.begin();
1775 ListIterator end = visited.end();
1776 std::size_t i=0,
size=visited.size();
1780 while(current != end) {
1782 for(; i<
size; ++current, ++i) {
1783 typedef typename G::ConstEdgeIterator EdgeIterator;
1784 const EdgeIterator endEdge = graph.endEdges(*current);
1786 for(EdgeIterator edge = graph.beginEdges(*current);
1787 edge != endEdge; ++edge) {
1789 if(aggregates_[edge.target()]==aggregate) {
1790 if(!
get(visitedMap, edge.target())) {
1791 put(visitedMap, edge.target(),
true);
1792 visited.push_back(edge.target());
1793 aggregateVisitor(edge);
1796 nonAggregateVisitor(edge);
1799 end = visited.end();
1800 size = visited.size();
1806 for(current = visited.begin(); current != end; ++current)
1807 put(visitedMap, *current,
false);
1813 return visitedSpheres;
1818 : graph_(0), aggregate_(0), front_(), connected_(), size_(-1)
1827 template<
class G,
class C>
1829 const typename C::Matrix& matrix,
1830 C criterion,
bool firstlevel)
1833 typedef typename C::Matrix Matrix;
1834 typedef typename G::VertexIterator VertexIterator;
1836 criterion.init(&matrix);
1841 const Row& row = matrix[*
vertex];
1846 criterion.initRow(row, *
vertex);
1851 ColIterator end = row.end();
1852 typename FieldTraits<typename Matrix::field_type>::real_type absoffdiag=0.;
1856 for(ColIterator col = row.begin(); col != end; ++col)
1857 if(col.index()!=*
vertex) {
1858 criterion.examine(col);
1859 absoffdiag =
max(absoffdiag, Impl::asMatrix(*col).frobenius_norm());
1863 vertex.properties().setExcludedBorder();
1866 for(ColIterator col = row.begin(); col != end; ++col)
1868 criterion.examine(col);
1874 if(criterion.isIsolated()) {
1876 vertex.properties().setIsolated();
1879 auto eEnd =
vertex.end();
1880 auto col = matrix[*
vertex].begin();
1882 for(
auto edge =
vertex.begin(); edge!= eEnd; ++edge, ++col) {
1884 while(col.index()!=edge.target())
1886 criterion.examine(graph, edge, col);
1896 inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(
const AggregatesMap<Vertex>& aggregates,
1898 : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
1905 if(aggregates_[edge.target()]==aggregate_)
1906 visitor_->operator()(edge);
1911 inline void Aggregator<G>::visitAggregateNeighbours(
const Vertex&
vertex,
1913 const AggregatesMap<Vertex>& aggregates,
1917 AggregateVisitor<V> v(aggregates, aggregate, visitor);
1923 inline Aggregator<G>::Counter::Counter()
1928 inline void Aggregator<G>::Counter::increment()
1934 inline void Aggregator<G>::Counter::decrement()
1939 inline int Aggregator<G>::Counter::value()
1947 if(edge.properties().isTwoWay())
1948 Counter::increment();
1953 const AggregatesMap<Vertex>& aggregates)
const
1955 TwoWayCounter counter;
1956 visitAggregateNeighbours(
vertex, aggregate, aggregates, counter);
1957 return counter.value();
1962 const AggregatesMap<Vertex>& aggregates)
const
1964 OneWayCounter counter;
1965 visitAggregateNeighbours(
vertex, aggregate, aggregates, counter);
1966 return counter.value();
1972 if(edge.properties().isOneWay())
1973 Counter::increment();
1977 inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(
const VertexSet& connected,
1978 const AggregatesMap<Vertex>& aggregates)
1979 : Counter(), connected_(connected), aggregates_(aggregates)
1988 Counter::increment();
1990 Counter::increment();
1991 Counter::increment();
1996 inline double Aggregator<G>::connectivity(
const Vertex&
vertex,
const AggregatesMap<Vertex>& aggregates)
const
1998 ConnectivityCounter counter(connected_, aggregates);
2000 return (
double)counter.value()/noNeighbours;
2004 inline Aggregator<G>::DependencyCounter::DependencyCounter()
2011 if(edge.properties().depends())
2012 Counter::increment();
2013 if(edge.properties().influences())
2014 Counter::increment();
2018 int Aggregator<G>::unusedNeighbours(
const Vertex&
vertex,
const AggregatesMap<Vertex>& aggregates)
const
2024 std::pair<int,int> Aggregator<G>::neighbours(
const Vertex&
vertex,
2026 const AggregatesMap<Vertex>& aggregates)
const
2028 DependencyCounter unused, aggregated;
2029 typedef AggregateVisitor<DependencyCounter> CounterT;
2030 typedef std::tuple<CounterT,CounterT> CounterTuple;
2033 return std::make_pair(unused.value(), aggregated.value());
2040 DependencyCounter counter;
2041 visitAggregateNeighbours(
vertex, aggregate, aggregates, counter);
2042 return counter.value();
2046 std::size_t Aggregator<G>::distance(
const Vertex&
vertex,
const AggregatesMap<Vertex>& aggregates)
2049 typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap =
get(VertexVisitedTag(), *graph_);
2051 typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
2052 return aggregates.template breadthFirstSearch<true,true>(
vertex,
2053 aggregate_->
id(), *graph_,
2054 vlist, dummy, dummy, visitedMap);
2058 inline Aggregator<G>::FrontMarker::FrontMarker(std::vector<Vertex>&
front,
MatrixGraph& graph)
2059 : front_(
front), graph_(graph)
2065 Vertex target = edge.target();
2067 if(!graph_.getVertexProperties(target).front()) {
2068 front_.push_back(target);
2069 graph_.getVertexProperties(target).setFront();
2077 Dune::dvverb<<
" Admissible not yet implemented!"<<std::endl;
2084 Iterator vend = graph_->endEdges(
vertex);
2085 for(Iterator edge = graph_->beginEdges(
vertex); edge != vend; ++edge) {
2087 if(edge.properties().isStrong()
2088 && aggregates[edge.target()]==aggregate)
2091 Iterator edge1 = edge;
2092 for(++edge1; edge1 != vend; ++edge1) {
2094 if(edge1.properties().isStrong()
2095 && aggregates[edge.target()]==aggregate)
2100 Iterator v2end = graph_->endEdges(edge.target());
2101 for(Iterator edge2 = graph_->beginEdges(edge.target()); edge2 != v2end; ++edge2) {
2102 if(edge2.target()==edge1.target() &&
2103 edge2.properties().isStrong()) {
2119 vend = graph_->endEdges(
vertex);
2120 for(Iterator edge = graph_->beginEdges(
vertex); edge != vend; ++edge) {
2122 if(edge.properties().isStrong()
2123 && aggregates[edge.target()]==aggregate)
2126 Iterator v1end = graph_->endEdges(edge.target());
2128 for(Iterator edge1=graph_->beginEdges(edge.target()); edge1 != v1end; ++edge1) {
2130 if(edge1.properties().isStrong()
2131 && aggregates[edge1.target()]==aggregate)
2135 Iterator v2end = graph_->endEdges(
vertex);
2136 for(Iterator edge2 = graph_->beginEdges(
vertex); edge2 != v2end; ++edge2) {
2137 if(edge2.target()==edge1.target()) {
2138 if(edge2.properties().isStrong())
2155 void Aggregator<G>::unmarkFront()
2157 typedef typename std::vector<Vertex>::const_iterator Iterator;
2160 graph_->getVertexProperties(*vertex).resetFront();
2167 Aggregator<G>::nonisoNeighbourAggregate(
const Vertex&
vertex,
2168 const AggregatesMap<Vertex>& aggregates,
2169 SLList<Vertex>& neighbours)
const
2172 Iterator end=graph_->beginEdges(
vertex);
2175 for(Iterator edge=graph_->beginEdges(
vertex); edge!=end; ++edge)
2178 neighbours.push_back(aggregates[edge.target()]);
2183 inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(
const Vertex&
vertex,
const AggregatesMap<Vertex>& aggregates)
const
2187 Iterator end = graph_->endEdges(
vertex);
2188 for(Iterator edge = graph_->beginEdges(
vertex); edge != end; ++edge) {
2190 graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()) {
2191 if( graph_->getVertexProperties(
vertex).isolated() ||
2192 ((edge.properties().depends() || edge.properties().influences())
2193 && admissible(
vertex, aggregates[edge.target()], aggregates)))
2194 return edge.target();
2201 Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(
const MatrixGraph& graph)
2202 : Counter(), graph_(graph)
2208 if(graph_.getVertexProperties(edge.target()).front())
2209 Counter::increment();
2213 int Aggregator<G>::noFrontNeighbours(
const Vertex&
vertex)
const
2215 FrontNeighbourCounter counter(*graph_);
2217 return counter.value();
2220 inline bool Aggregator<G>::connected(
const Vertex&
vertex,
2222 const AggregatesMap<Vertex>& aggregates)
const
2224 typedef typename G::ConstEdgeIterator iterator;
2225 const iterator end = graph_->endEdges(
vertex);
2226 for(iterator edge = graph_->beginEdges(
vertex); edge != end; ++edge)
2227 if(aggregates[edge.target()]==aggregate)
2232 inline bool Aggregator<G>::connected(
const Vertex&
vertex,
2233 const SLList<AggregateDescriptor>& aggregateList,
2234 const AggregatesMap<Vertex>& aggregates)
const
2237 for(Iter i=aggregateList.begin(); i!=aggregateList.end(); ++i)
2238 if(connected(
vertex, *i, aggregates))
2245 void Aggregator<G>::growIsolatedAggregate(
const Vertex& seed,
const AggregatesMap<Vertex>& aggregates,
const C& c)
2247 SLList<Vertex> connectedAggregates;
2248 nonisoNeighbourAggregate(seed, aggregates,connectedAggregates);
2250 while(aggregate_->
size()< c.minAggregateSize() && aggregate_->
connectSize() < c.maxConnectivity()) {
2252 std::size_t maxFrontNeighbours=0;
2256 typedef typename std::vector<Vertex>::const_iterator Iterator;
2259 if(distance(*
vertex, aggregates)>c.maxDistance())
2262 if(connectedAggregates.size()>0) {
2266 if(!connected(*
vertex, connectedAggregates, aggregates))
2270 double con = connectivity(*
vertex, aggregates);
2273 std::size_t frontNeighbours = noFrontNeighbours(*
vertex);
2275 if(frontNeighbours >= maxFrontNeighbours) {
2276 maxFrontNeighbours = frontNeighbours;
2279 }
else if(con > maxCon) {
2281 maxFrontNeighbours = noFrontNeighbours(*
vertex);
2289 aggregate_->
add(candidate);
2295 void Aggregator<G>::growAggregate(
const Vertex& seed,
const AggregatesMap<Vertex>& aggregates,
const C& c)
2299 std::size_t distance_ =0;
2300 while(aggregate_->
size() < c.minAggregateSize()&& distance_<c.maxDistance()) {
2301 int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1;
2304 std::vector<Vertex> candidates;
2305 candidates.reserve(30);
2307 typedef typename std::vector<Vertex>::const_iterator Iterator;
2311 if(graph_->getVertexProperties(*vertex).isolated())
2314 int twoWayCons = twoWayConnections(*
vertex, aggregate_->
id(), aggregates);
2317 if( maxTwoCons == twoWayCons && twoWayCons > 0) {
2318 double con = connectivity(*
vertex, aggregates);
2321 int neighbours = noFrontNeighbours(*
vertex);
2323 if(neighbours > maxNeighbours) {
2324 maxNeighbours = neighbours;
2326 candidates.push_back(*
vertex);
2328 candidates.push_back(*
vertex);
2330 }
else if( con > maxCon) {
2332 maxNeighbours = noFrontNeighbours(*
vertex);
2334 candidates.push_back(*
vertex);
2336 }
else if(twoWayCons > maxTwoCons) {
2337 maxTwoCons = twoWayCons;
2338 maxCon = connectivity(*
vertex, aggregates);
2339 maxNeighbours = noFrontNeighbours(*
vertex);
2341 candidates.push_back(*
vertex);
2353 int oneWayCons = oneWayConnections(*
vertex, aggregate_->
id(), aggregates);
2358 if(!admissible(*
vertex, aggregate_->
id(), aggregates))
2361 if( maxOneCons == oneWayCons && oneWayCons > 0) {
2362 double con = connectivity(*
vertex, aggregates);
2365 int neighbours = noFrontNeighbours(*
vertex);
2367 if(neighbours > maxNeighbours) {
2368 maxNeighbours = neighbours;
2370 candidates.push_back(*
vertex);
2372 if(neighbours==maxNeighbours)
2374 candidates.push_back(*
vertex);
2377 }
else if( con > maxCon) {
2379 maxNeighbours = noFrontNeighbours(*
vertex);
2381 candidates.push_back(*
vertex);
2383 }
else if(oneWayCons > maxOneCons) {
2384 maxOneCons = oneWayCons;
2385 maxCon = connectivity(*
vertex, aggregates);
2386 maxNeighbours = noFrontNeighbours(*
vertex);
2388 candidates.push_back(*
vertex);
2393 if(!candidates.size())
2395 distance_=distance(seed, aggregates);
2396 candidates.resize(
min(candidates.size(), c.maxAggregateSize()-
2397 aggregate_->
size()));
2398 aggregate_->
add(candidates);
2402 template<
typename V>
2403 template<
typename M,
typename G,
typename C>
2407 Aggregator<G> aggregator;
2408 return aggregator.build(matrix, graph, *
this, criterion, finestLevel);
2412 template<
class M,
class C>
2413 std::tuple<int,int,int,int>
Aggregator<G>::build(
const M& m, G& graph, AggregatesMap<Vertex>& aggregates,
const C& c,
2419 Stack stack_(graph, *
this, aggregates);
2423 aggregate_ =
new Aggregate<G,VertexSet>(graph, aggregates, connected_, front_);
2430 dverb<<
"Build dependency took "<< watch.elapsed()<<
" seconds."<<std::endl;
2431 int noAggregates, conAggregates, isoAggregates, oneAggregates;
2432 std::size_t maxA=0, minA=1000000, avg=0;
2433 int skippedAggregates;
2434 noAggregates = conAggregates = isoAggregates = oneAggregates =
2435 skippedAggregates = 0;
2438 Vertex seed = stack_.pop();
2440 if(seed == Stack::NullEntry)
2445 if((noAggregates+1)%10000 == 0)
2449 if(graph.getVertexProperties(seed).excludedBorder()) {
2451 ++skippedAggregates;
2455 if(graph.getVertexProperties(seed).isolated()) {
2456 if(c.skipIsolated()) {
2459 ++skippedAggregates;
2463 aggregate_->
seed(seed);
2464 growIsolatedAggregate(seed, aggregates, c);
2467 aggregate_->
seed(seed);
2468 growAggregate(seed, aggregates, c);
2472 while(!(graph.getVertexProperties(seed).isolated()) && aggregate_->
size() < c.maxAggregateSize()) {
2474 std::vector<Vertex> candidates;
2475 candidates.reserve(30);
2477 typedef typename std::vector<Vertex>::const_iterator Iterator;
2481 if(graph.getVertexProperties(*vertex).isolated())
2484 if(twoWayConnections( *
vertex, aggregate_->
id(), aggregates) == 0 &&
2485 (oneWayConnections( *
vertex, aggregate_->
id(), aggregates) == 0 ||
2486 !admissible( *
vertex, aggregate_->
id(), aggregates) ))
2489 std::pair<int,int> neighbourPair=neighbours(*
vertex, aggregate_->
id(),
2495 if(neighbourPair.first >= neighbourPair.second)
2498 if(distance(*
vertex, aggregates) > c.maxDistance())
2500 candidates.push_back(*
vertex);
2504 if(!candidates.size())
break;
2506 candidates.resize(
min(candidates.size(), c.maxAggregateSize()-
2507 aggregate_->
size()));
2508 aggregate_->
add(candidates);
2513 if(aggregate_->
size()==1 && c.maxAggregateSize()>1) {
2514 if(!graph.getVertexProperties(seed).isolated()) {
2515 Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
2519 aggregates[seed] = aggregates[mergedNeighbour];
2520 aggregate_->invalidate();
2523 minA=
min(minA,
static_cast<std::size_t
>(1));
2524 maxA=
max(maxA,
static_cast<std::size_t
>(1));
2530 minA=
min(minA,
static_cast<std::size_t
>(1));
2531 maxA=
max(maxA,
static_cast<std::size_t
>(1));
2537 avg+=aggregate_->
size();
2538 minA=
min(minA,aggregate_->
size());
2539 maxA=
max(maxA,aggregate_->
size());
2540 if(graph.getVertexProperties(seed).isolated())
2548 Dune::dinfo<<
"connected aggregates: "<<conAggregates;
2549 Dune::dinfo<<
" isolated aggregates: "<<isoAggregates;
2550 if(conAggregates+isoAggregates>0)
2551 Dune::dinfo<<
" one node aggregates: "<<oneAggregates<<
" min size="
2552 <<minA<<
" max size="<<maxA
2553 <<
" avg="<<avg/(conAggregates+isoAggregates)<<std::endl;
2556 return std::make_tuple(conAggregates+isoAggregates,isoAggregates,
2557 oneAggregates,skippedAggregates);
2562 Aggregator<G>::Stack::Stack(
const MatrixGraph& graph,
const Aggregator<G>& aggregatesBuilder,
2563 const AggregatesMap<Vertex>& aggregates)
2564 : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), begin_(graph.begin()), end_(graph.end())
2570 Aggregator<G>::Stack::~Stack()
2581 inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
2587 typename G::VertexDescriptor current=*begin_;
2597 void printAggregates2d(
const AggregatesMap<V>& aggregates,
int n,
int m, std::ostream& os)
2601 std::ios_base::fmtflags oldOpts=os.flags();
2603 os.setf(std::ios_base::right, std::ios_base::adjustfield);
2608 for(
int i=0; i< n*m; i++)
2609 maxVal=
max(maxVal, aggregates[i]);
2611 for(
int i=10; i < 1000000; i*=10)
2617 for(
int j=0, entry=0; j < m; j++) {
2618 for(
int i=0; i<n; i++, entry++) {
2620 os<<aggregates[entry]<<
" ";
A class for temporarily storing the vertices of an aggregate in.
Definition: aggregates.hh:788
A Dummy visitor that does nothing for each visited edge.
Definition: aggregates.hh:608
Class providing information about the mapping of the vertices onto aggregates.
Definition: aggregates.hh:570
Base class of all aggregation criterions.
Definition: aggregates.hh:51
Class for building the aggregates.
Definition: aggregates.hh:924
Dependency policy for symmetric matrices.
Definition: aggregates.hh:255
Norm that uses only the [N][N] entry of the block to determine couplings.
Definition: aggregates.hh:381
Norm that uses only the [0][0] entry of the block to determine couplings.
Definition: aggregates.hh:457
Iterator over all edges starting from a vertex.
Definition: graph.hh:95
The vertex iterator type of the graph.
Definition: graph.hh:209
The (undirected) graph of a matrix.
Definition: graph.hh:51
M::size_type VertexDescriptor
The vertex descriptor.
Definition: graph.hh:73
EdgeIteratorT< const MatrixGraph< Matrix > > ConstEdgeIterator
The constant edge iterator type.
Definition: graph.hh:298
All parameters for AMG.
Definition: parameters.hh:416
Criterion taking advantage of symmetric matrices.
Definition: aggregates.hh:529
Dependency policy for symmetric matrices.
Definition: aggregates.hh:316
Dependency policy for symmetric matrices.
Definition: aggregates.hh:136
Criterion suitable for unsymmetric matrices.
Definition: aggregates.hh:549
derive error class from the base class in common
Definition: istlexception.hh:19
A generic dynamic dense matrix.
Definition: matrix.hh:561
typename Imp::BlockTraits< T >::field_type field_type
Export the type representing the underlying field.
Definition: matrix.hh:565
row_type::const_iterator ConstColIterator
Const iterator for the entries of each row.
Definition: matrix.hh:589
MatrixImp::DenseMatrixBase< T, A >::window_type row_type
The type implementing a matrix row.
Definition: matrix.hh:574
An allocator managing a pool of objects for reuse.
Definition: poolallocator.hh:223
A single linked list.
Definition: sllist.hh:44
Type traits to determine the type of reals (when working with complex numbers)
Provides classes for building the matrix graph.
SLListConstIterator< T, A > const_iterator
The constant iterator of the list.
Definition: sllist.hh:74
#define DUNE_THROW(E,...)
Definition: exceptions.hh:314
constexpr GeometryType vertex
GeometryType representing a vertex.
Definition: type.hh:492
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:489
constexpr auto min
Function object that returns the smaller of the given values.
Definition: hybridutilities.hh:511
Matrix::ConstColIterator ColIter
Constant column iterator of the matrix.
Definition: aggregates.hh:275
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:596
int id()
Get the id identifying the aggregate.
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:304
size_type size()
Get the size of the aggregate.
MatrixGraph::VertexDescriptor Vertex
The vertex identifier.
Definition: aggregates.hh:935
AggregationCriterion()
Constructor.
Definition: aggregates.hh:68
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:359
FieldTraits< M >::real_type operator()(const M &m) const
compute the norm of a matrix.
Definition: aggregates.hh:496
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:260
G MatrixGraph
The matrix graph type used.
Definition: aggregates.hh:930
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:365
FieldTraits< M >::real_type operator()(const M &) const
compute the norm of a matrix.
Definition: aggregates.hh:516
typename VertexSet::size_type size_type
Type of size used by allocator of sllist.
Definition: aggregates.hh:816
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:321
real_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:189
N Norm
The norm to use for examining the matrix entries.
Definition: aggregates.hh:265
int row_
index of the currently evaluated row.
Definition: aggregates.hh:187
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:331
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:298
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:336
~AggregatesMap()
Destructor.
Matrix::field_type field_type
The current max value.
Definition: aggregates.hh:181
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:1079
std::size_t * SphereMap
Type of the mapping of aggregate members onto distance spheres.
Definition: aggregates.hh:824
Matrix::row_type Row
Constant Row iterator of the matrix.
Definition: aggregates.hh:270
N Norm
The norm to use for examining the matrix entries.
Definition: aggregates.hh:326
Norm norm_
The functor for calculating the norm.
Definition: aggregates.hh:185
VertexSet::const_iterator const_iterator
Const iterator over a vertex list.
Definition: aggregates.hh:819
MatrixGraph::VertexDescriptor AggregateDescriptor
The type of the aggregate descriptor.
Definition: aggregates.hh:938
real_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:369
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 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:84
V AggregateDescriptor
The aggregate descriptor type.
Definition: aggregates.hh:590
static const V ISOLATED
Identifier of isolated vertices.
Definition: aggregates.hh:581
int row_
index of the currently evaluated row.
Definition: aggregates.hh:367
DependencyCounter()
Constructor.
real_type diagonal_
The norm of the current diagonal.
Definition: aggregates.hh:308
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:361
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:602
ConnectivityCounter(const VertexSet &connected, const AggregatesMap< Vertex > &aggregates)
Constructor.
const_iterator end() const
get an iterator over the vertices of the aggregate.
int row_
index of the currently evaluated row.
Definition: aggregates.hh:306
M Matrix
The matrix type we build the dependency of.
Definition: aggregates.hh:141
const Matrix * matrix_
The matrix we work on.
Definition: aggregates.hh:179
S VertexSet
The type of a single linked list of vertex descriptors.
Definition: aggregates.hh:811
static const V UNAGGREGATED
Identifier of not yet aggregated vertices.
Definition: aggregates.hh:576
std::size_t breadthFirstSearch(const VertexDescriptor &start, const AggregateDescriptor &aggregate, const G &graph, F &aggregateVisitor, VM &visitedMap) const
Breadth first search within an aggregate.
auto operator()(const M &m, typename std::enable_if_t< Dune::IsNumber< M >::value > *=nullptr) const
Compute the norm of a scalar.
Definition: aggregates.hh:408
Matrix::field_type field_type
The current max value.
Definition: aggregates.hh:300
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.
FieldTraits< typenameM::field_type >::real_type operator()(const M &m, typename std::enable_if_t<!Dune::IsNumber< M >::value > *sfinae=nullptr) const
compute the norm of a matrix.
Definition: aggregates.hh:392
MatrixGraph::VertexDescriptor Vertex
The vertex descriptor type.
Definition: aggregates.hh:799
void seed(const Vertex &vertex)
Initialize the aggregate with one vertex.
void clear()
Clear the aggregate.
void free()
Free the allocated memory.
void increment()
Increment counter.
void buildDependency(G &graph, const typename C::Matrix &matrix, C criterion, bool finestLevel)
Build the dependency of the matrix graph.
V VertexDescriptor
The vertex descriptor type.
Definition: aggregates.hh:585
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:475
PoolAllocator< Vertex, 100 > Allocator
The allocator we use for our lists and the set.
Definition: aggregates.hh:805
DVVerbType dvverb(std::cout)
stream for very verbose output.
Definition: stdstreams.hh:96
DInfoType dinfo(std::cout)
Stream for informative output.
Definition: stdstreams.hh:141
DVerbType dverb(std::cout)
Singleton of verbose debug stream.
Definition: stdstreams.hh:117
Dune namespace
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
constexpr auto front(const HybridMultiIndex< T... > &tp) -> decltype(tp.front())
Returns a copy of the first element of the HybridMultiIndex.
Definition: hybridmultiindex.hh:217
constexpr auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
Return the entry at position pos of the given sequence.
Definition: integersequence.hh:22
Parameter classes for customizing AMG.
An stl-compliant pool allocator.
Provides classes for handling internal properties in a graph.
Implements a scalar matrix view wrapper around an existing scalar.
Implements a singly linked list together with the necessary iterators.
Standard Dune debug streams.
Functor using the row sum (infinity) norm to determine strong couplings.
Definition: aggregates.hh:465
Whether this type acts as a scalar in the context of (hierarchically blocked) containers.
Definition: typetraits.hh:194
Traits for type conversions and type information.