3 #ifndef DUNE_AMG_AGGREGATES_HH 4 #define DUNE_AMG_AGGREGATES_HH 12 #include <dune/common/timer.hh> 13 #include <dune/common/stdstreams.hh> 14 #include <dune/common/poolallocator.hh> 15 #include <dune/common/sllist.hh> 16 #include <dune/common/unused.hh> 17 #include <dune/common/ftraits.hh> 82 this->setMaxDistance(diameter-1);
87 this->setMaxDistance(this->maxDistance()+diameter-1);
89 this->setMinAggregateSize(csize);
90 this->setMaxAggregateSize(static_cast<std::size_t>(csize*1.5));
106 this->setMaxDistance(this->maxDistance()+dim-1);
111 std::ostream& operator<<(std::ostream& os, const AggregationCriterion<T>& criterion)
113 os<<
"{ maxdistance="<<criterion.maxDistance()<<
" minAggregateSize=" 114 <<criterion.minAggregateSize()<<
" maxAggregateSize="<<criterion.maxAggregateSize()
115 <<
" connectivity="<<criterion.maxConnectivity()<<
" debugLevel="<<criterion.debugLevel()<<
"}";
130 template<
class M,
class N>
154 void init(
const Matrix* matrix);
156 void initRow(
const Row& row,
int index);
158 void examine(
const ColIter&
col);
161 void examine(G& graph,
const typename G::EdgeIterator& edge,
const ColIter&
col);
178 typedef typename FieldTraits<field_type>::real_type
real_type;
187 typename std::vector<real_type>::iterator
valIter_;
192 template<
class M,
class N>
198 template<
class M,
class N>
201 vals_.assign(row.size(), 0.0);
202 assert(vals_.size()==row.size());
203 valIter_=vals_.begin();
205 maxValue_ = std::min(- std::numeric_limits<real_type>::max(), std::numeric_limits<real_type>::min());
206 diagonal_=norm_(row[index]);
210 template<
class M,
class N>
215 if(!N::is_sign_preserving || eij<0)
217 *valIter_ = eij/diagonal_*eij/norm_(matrix_->operator[](col.index())[col.index()]);
218 maxValue_ = std::max(maxValue_, *valIter_);
224 template<
class M,
class N>
228 if(*valIter_ > alpha() * maxValue_) {
229 edge.properties().setDepends();
230 edge.properties().setInfluences();
235 template<
class M,
class N>
240 valIter_=vals_.begin();
241 return maxValue_ < beta();
247 template<
class M,
class N>
271 void init(
const Matrix* matrix);
273 void initRow(
const Row& row,
int index);
275 void examine(
const ColIter&
col);
278 void examine(G& graph,
const typename G::EdgeIterator& edge,
const ColIter&
col);
295 typedef typename FieldTraits<field_type>::real_type
real_type;
308 template<
class M,
class N>
332 void init(
const Matrix* matrix);
334 void initRow(
const Row& row,
int index);
336 void examine(
const ColIter&
col);
339 void examine(G& graph,
const typename G::EdgeIterator& edge,
const ColIter&
col);
356 typedef typename FieldTraits<field_type>::real_type
real_type;
375 is_sign_preserving =
true 383 typename FieldTraits<typename M::field_type>::real_type
operator()(
const M& m)
const 385 typedef typename M::field_type field_type;
386 typedef typename FieldTraits<field_type>::real_type real_type;
387 static_assert( std::is_convertible<field_type, real_type >::value,
388 "use of diagonal norm in AMG not implemented for complex field_type");
397 static T signed_abs(
const T & v)
404 static T signed_abs(
const std::complex<T> & v)
408 return csgn(v) * std::abs(v);
413 static T csgn(
const T & v)
415 return (T(0) < v) - (v < T(0));
420 static T csgn(std::complex<T> a)
422 return csgn(a.real())+(a.real() == 0.0)*csgn(a.imag());
443 is_sign_preserving =
false 450 typename FieldTraits<typename M::field_type>::real_type
operator()(
const M& m)
const 452 return m.infinity_norm();
460 is_sign_preserving =
false 467 typename FieldTraits<typename M::field_type>::real_type
operator()(
const M& m)
const 469 return m.frobenius_norm();
476 is_sign_preserving =
false 483 typename FieldTraits<typename M::field_type>::real_type
operator()(
const M& m)
const 497 template<
class M,
class Norm>
520 template<
class M,
class Norm>
583 template<
class EdgeIterator>
586 DUNE_UNUSED_PARAMETER(edge);
619 template<
class M,
class G,
class C>
620 std::tuple<int,int,int,int> buildAggregates(
const M& matrix, G& graph,
const C& criterion,
642 template<
bool reset,
class G,
class F,
class VM>
643 std::size_t breadthFirstSearch(
const VertexDescriptor& start,
644 const AggregateDescriptor& aggregate,
647 VM& visitedMap)
const;
672 template<
bool remove,
bool reset,
class G,
class L,
class F1,
class F2,
class VM>
673 std::size_t breadthFirstSearch(
const VertexDescriptor& start,
674 const AggregateDescriptor& aggregate,
675 const G& graph, L& visited, F1& aggregateVisitor,
676 F2& nonAggregateVisitor,
677 VM& visitedMap)
const;
684 void allocate(std::size_t noVertices);
689 std::size_t noVertices()
const;
701 AggregateDescriptor& operator[](
const VertexDescriptor& v);
708 const AggregateDescriptor& operator[](
const VertexDescriptor& v)
const;
717 const_iterator
end()
const 719 return aggregates_+noVertices();
731 return aggregates_+noVertices();
742 AggregateDescriptor* aggregates_;
747 std::size_t noVertices_;
753 template<
class G,
class C>
755 const typename C::Matrix& matrix,
763 template<
class G,
class S>
807 VertexSet& connectivity, std::vector<Vertex>& front_);
820 void reconstruct(
const Vertex& vertex);
825 void seed(
const Vertex& vertex);
830 void add(
const Vertex& vertex);
832 void add(std::vector<Vertex>& vertex);
841 typename VertexSet::size_type size();
845 typename VertexSet::size_type connectSize();
853 const_iterator begin()
const;
856 const_iterator end()
const;
883 VertexSet& connected_;
888 std::vector<Vertex>& front_;
938 template<
class M,
class C>
939 std::tuple<int,int,int,int> build(
const M& m, G& graph,
947 typedef PoolAllocator<Vertex,100> Allocator;
952 typedef SLList<Vertex,Allocator> VertexList;
957 typedef std::set<Vertex,std::less<Vertex>,Allocator> VertexSet;
962 typedef std::size_t* SphereMap;
977 std::vector<Vertex> front_;
982 VertexSet connected_;
997 Stack(
const MatrixGraph& graph,
1003 enum { N = 1300000 };
1006 const MatrixGraph& graph_;
1036 void visitAggregateNeighbours(
const Vertex& vertex,
const AggregateDescriptor& aggregate,
1045 class AggregateVisitor
1074 AggregateDescriptor aggregate_;
1105 class FrontNeighbourCounter :
public Counter
1112 FrontNeighbourCounter(
const MatrixGraph& front);
1117 const MatrixGraph& graph_;
1124 int noFrontNeighbours(
const Vertex& vertex)
const;
1129 class TwoWayCounter :
public Counter
1146 int twoWayConnections(
const Vertex&,
const AggregateDescriptor& aggregate,
1152 class OneWayCounter :
public Counter
1169 int oneWayConnections(
const Vertex&,
const AggregateDescriptor& aggregate,
1178 class ConnectivityCounter :
public Counter
1193 const VertexSet& connected_;
1218 bool connected(
const Vertex& vertex,
const AggregateDescriptor& aggregate,
1228 bool connected(
const Vertex& vertex,
const SLList<AggregateDescriptor>& aggregateList,
1238 class DependencyCounter :
public Counter
1244 DependencyCounter();
1264 FrontMarker(std::vector<Vertex>& front, MatrixGraph& graph);
1270 std::vector<Vertex>& front_;
1272 MatrixGraph& graph_;
1309 std::pair<int,int> neighbours(
const Vertex& vertex,
1310 const AggregateDescriptor& aggregate,
1328 int aggregateNeighbours(
const Vertex& vertex,
const AggregateDescriptor& aggregate,
const AggregatesMap<Vertex>& aggregates)
const;
1337 bool admissible(
const Vertex& vertex,
const AggregateDescriptor& aggregate,
const AggregatesMap<Vertex>& aggregates)
const;
1366 void nonisoNeighbourAggregate(
const Vertex& vertex,
1368 SLList<Vertex>& neighbours)
const;
1380 void growIsolatedAggregate(
const Vertex& vertex,
const AggregatesMap<Vertex>& aggregates,
const C& c);
1385 template<
class M,
class N>
1391 template<
class M,
class N>
1394 DUNE_UNUSED_PARAMETER(row);
1395 maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
1397 diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1400 template<
class M,
class N>
1403 real_type eij = norm_(*col);
1405 matrix_->operator[](col.index()).find(row_);
1406 if ( opposite_entry == matrix_->operator[](col.index()).end() )
1411 real_type eji = norm_(*opposite_entry);
1414 if(!N::is_sign_preserving || eij<0 || eji<0)
1415 maxValue_ = std::max(maxValue_,
1416 eij /diagonal_ * eji/
1417 norm_(matrix_->operator[](col.index())[col.index()]));
1420 template<
class M,
class N>
1424 real_type eij = norm_(*col);
1426 matrix_->operator[](col.index()).find(row_);
1428 if ( opposite_entry == matrix_->operator[](col.index()).end() )
1433 real_type eji = norm_(*opposite_entry);
1435 if(!N::is_sign_preserving || (eij<0 || eji<0))
1436 if(eji / norm_(matrix_->operator[](edge.target())[edge.target()]) *
1437 eij/ diagonal_ > alpha() * maxValue_) {
1438 edge.properties().setDepends();
1439 edge.properties().setInfluences();
1440 typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
1441 other.setInfluences();
1446 template<
class M,
class N>
1449 return maxValue_ < beta();
1453 template<
class M,
class N>
1459 template<
class M,
class N>
1462 DUNE_UNUSED_PARAMETER(row);
1463 maxValue_ = std::min(- std::numeric_limits<real_type>::max(), std::numeric_limits<real_type>::min());
1465 diagonal_ = norm_(matrix_->operator[](row_)[row_]);
1468 template<
class M,
class N>
1471 maxValue_ = std::max(maxValue_,
1475 template<
class M,
class N>
1479 if(-norm_(*col) >= maxValue_ * alpha()) {
1480 edge.properties().setDepends();
1481 typedef typename G::EdgeDescriptor ED;
1482 ED e= graph.findEdge(edge.target(), edge.source());
1483 if(e!=std::numeric_limits<ED>::max())
1485 typename G::EdgeProperties& other = graph.getEdgeProperties(e);
1486 other.setInfluences();
1491 template<
class M,
class N>
1494 return maxValue_ < beta() * diagonal_;
1497 template<
class G,
class S>
1499 VertexSet& connected, std::vector<Vertex>& front)
1500 : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
1501 connected_(connected), front_(front)
1504 template<
class G,
class S>
1512 throw "Not yet implemented";
1520 template<
class G,
class S>
1523 dvverb<<
"Connected cleared"<<std::endl;
1526 connected_.insert(vertex);
1527 dvverb <<
" Inserting "<<vertex<<
" size="<<connected_.size();
1533 template<
class G,
class S>
1536 vertices_.insert(vertex);
1537 aggregates_[vertex]=id_;
1539 front_.erase(std::lower_bound(front_.begin(), front_.end(), vertex));
1543 const iterator end = graph_.endEdges(vertex);
1544 for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge) {
1545 dvverb <<
" Inserting "<<aggregates_[edge.target()];
1546 connected_.insert(aggregates_[edge.target()]);
1547 dvverb <<
" size="<<connected_.size();