dune-istl  2.8.0
galerkin.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_GALERKIN_HH
4 #define DUNE_GALERKIN_HH
5 
6 #include "aggregates.hh"
7 #include "pinfo.hh"
8 #include <dune/common/poolallocator.hh>
9 #include <dune/common/enumset.hh>
10 #include <set>
11 #include <limits>
12 #include <algorithm>
13 
14 namespace Dune
15 {
16  namespace Amg
17  {
29  template<class T>
31  {
35  typedef T Aggregate;
36 
40  typedef T Vertex;
41 
46 
51  };
52 
53 
54 
59  template<class M>
61  {
62  public:
68  SparsityBuilder(M& matrix);
69 
70  void insert(const typename M::size_type& index);
71 
72  void operator++();
73 
74  std::size_t minRowSize();
75 
76  std::size_t maxRowSize();
77 
78  std::size_t sumRowSize();
79  std::size_t index()
80  {
81  return row_.index();
82  }
83  private:
85  typename M::CreateIterator row_;
87  std::size_t minRowSize_;
89  std::size_t maxRowSize_;
90  std::size_t sumRowSize_;
91 #ifdef DUNE_ISTL_WITH_CHECKING
92  bool diagonalInserted;
93 #endif
94  };
95 
97  {
98  public:
107  template<class M, class V, class I, class O>
108  void calculate(const M& fine, const AggregatesMap<V>& aggregates, M& coarse,
109  const I& pinfo, const O& copy);
110 
111  };
112 
113  template<class T>
115  : public BaseGalerkinProduct
116  {
117  public:
119 
129  template<class G, class V, class Set>
130  typename G::MutableMatrix* build(G& fineGraph, V& visitedMap,
131  const ParallelInformation& pinfo,
133  const typename G::Matrix::size_type& size,
134  const Set& copy);
135  private:
136 
143  template<class G, class I, class Set>
145  buildOverlapVertices(const G& graph, const I& pinfo,
147  const Set& overlap,
148  std::size_t& overlapCount);
149 
150  template<class A>
151  struct OVLess
152  {
153  bool operator()(const OverlapVertex<A>& o1, const OverlapVertex<A>& o2)
154  {
155  return *o1.aggregate < *o2.aggregate;
156  }
157  };
158  };
159 
160  template<>
162  : public BaseGalerkinProduct
163  {
164  public:
174  template<class G, class V, class Set>
175  typename G::MutableMatrix* build(G& fineGraph, V& visitedMap,
176  const SequentialInformation& pinfo,
178  const typename G::Matrix::size_type& size,
179  const Set& copy);
180  };
181 
183  {
184  template<class R, class G, class V>
185  static void constructOverlapConnectivity(R& row, G& graph, V& visitedMap,
189 
193  template<class R, class G, class V>
194  static void constructNonOverlapConnectivity(R& row, G& graph, V& visitedMap,
196  const typename G::VertexDescriptor& seed);
197 
198 
202  template<class G, class S, class V>
204  {
205  public:
209  typedef G Graph;
213  typedef typename Graph::ConstEdgeIterator ConstEdgeIterator;
214 
218  typedef S Set;
219 
223  typedef V VisitedMap;
224 
228  typedef typename Graph::VertexDescriptor Vertex;
229 
237  ConnectedBuilder(const AggregatesMap<Vertex>& aggregates, Graph& graph,
238  VisitedMap& visitedMap, Set& connected);
239 
244  void operator()(const ConstEdgeIterator& edge);
245 
246  private:
250  const AggregatesMap<Vertex>& aggregates_;
251 
252  Graph& graph_;
253 
257  VisitedMap& visitedMap_;
258 
262  Set& connected_;
263  };
264 
265  };
266 
267  template<class G, class T>
269  {
270  typedef typename G::VertexDescriptor Vertex;
271 
272  template<class V, class O, class R>
273  static void examine(G& graph,
274  V& visitedMap,
275  const T& pinfo,
276  const AggregatesMap<Vertex>& aggregates,
277  const O& overlap,
278  const OverlapVertex<Vertex>* overlapVertices,
279  const OverlapVertex<Vertex>* overlapEnd,
280  R& row);
281  };
282 
283  template<class G>
285  {
286  typedef typename G::VertexDescriptor Vertex;
287 
288  template<class V, class R>
289  static void examine(G& graph,
290  V& visitedMap,
291  const SequentialInformation& pinfo,
292  const AggregatesMap<Vertex>& aggregates,
293  R& row);
294  };
295 
296  template<class T>
298  {
299  template<class M, class O>
300  static void set(M& coarse, const T& pinfo, const O& copy);
301  };
302 
303  template<>
305  {
306  template<class M, class O>
307  static void set(M& coarse, const SequentialInformation& pinfo, const O& copy);
308  };
309 
310  template<class R, class G, class V>
313  const typename G::VertexDescriptor& seed)
314  {
315  assert(row.index()==aggregates[seed]);
316  row.insert(aggregates[seed]);
317  ConnectedBuilder<G,R,V> conBuilder(aggregates, graph, visitedMap, row);
318  typedef typename G::VertexDescriptor Vertex;
319  typedef std::allocator<Vertex> Allocator;
320  typedef SLList<Vertex,Allocator> VertexList;
321  typedef typename AggregatesMap<Vertex>::DummyEdgeVisitor DummyVisitor;
322  VertexList vlist;
323  DummyVisitor dummy;
324  aggregates.template breadthFirstSearch<true,false>(seed,aggregates[seed], graph, vlist, dummy,
325  conBuilder, visitedMap);
326  }
327 
328  template<class R, class G, class V>
329  void BaseConnectivityConstructor::constructOverlapConnectivity(R& row, G& graph, V& visitedMap,
333  {
334  ConnectedBuilder<G,R,V> conBuilder(aggregates, graph, visitedMap, row);
335  const typename G::VertexDescriptor aggregate=*seed->aggregate;
336 
337  if (row.index()==*seed->aggregate) {
338  while(seed != overlapEnd && aggregate == *seed->aggregate) {
339  row.insert(*seed->aggregate);
340  // Walk over all neighbours and add them to the connected array.
341  visitNeighbours(graph, seed->vertex, conBuilder);
342  // Mark vertex as visited
343  put(visitedMap, seed->vertex, true);
344  ++seed;
345  }
346  }
347  }
348 
349  template<class G, class S, class V>
351  Graph& graph, VisitedMap& visitedMap,
352  Set& connected)
353  : aggregates_(aggregates), graph_(graph), visitedMap_(visitedMap), connected_(connected)
354  {}
355 
356  template<class G, class S, class V>
358  {
359  typedef typename G::VertexDescriptor Vertex;
360  const Vertex& vertex = aggregates_[edge.target()];
361  assert(vertex!= AggregatesMap<Vertex>::UNAGGREGATED);
363  connected_.insert(vertex);
364  }
365 
366  template<class T>
367  template<class G, class I, class Set>
369  GalerkinProduct<T>::buildOverlapVertices(const G& graph, const I& pinfo,
371  const Set& overlap,
372  std::size_t& overlapCount)
373  {
374  // count the overlap vertices.
375  typedef typename G::ConstVertexIterator ConstIterator;
376  typedef typename I::GlobalLookupIndexSet GlobalLookup;
377  typedef typename GlobalLookup::IndexPair IndexPair;
378 
379  const ConstIterator end = graph.end();
380  overlapCount = 0;
381 
382  const GlobalLookup& lookup=pinfo.globalLookup();
383 
384  for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex) {
385  const IndexPair* pair = lookup.pair(*vertex);
386 
387  if(pair!=0 && overlap.contains(pair->local().attribute()))
388  ++overlapCount;
389  }
390  // Allocate space
391  typedef typename G::VertexDescriptor Vertex;
392 
393  OverlapVertex<Vertex>* overlapVertices = new OverlapVertex<Vertex>[overlapCount=0 ? 1 : overlapCount];
394  if(overlapCount==0)
395  return overlapVertices;
396 
397  // Initialize them
398  overlapCount=0;
399  for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex) {
400  const IndexPair* pair = lookup.pair(*vertex);
401 
402  if(pair!=0 && overlap.contains(pair->local().attribute())) {
403  overlapVertices[overlapCount].aggregate = &aggregates[pair->local()];
404  overlapVertices[overlapCount].vertex = pair->local();
405  ++overlapCount;
406  }
407  }
408 
409  dverb << overlapCount<<" overlap vertices"<<std::endl;
410 
411  std::sort(overlapVertices, overlapVertices+overlapCount, OVLess<Vertex>());
412  // due to the sorting the isolated aggregates (to be skipped) are at the end.
413 
414  return overlapVertices;
415  }
416 
417  template<class G, class T>
418  template<class V, class O, class R>
420  V& visitedMap,
421  const T& pinfo,
422  const AggregatesMap<Vertex>& aggregates,
423  const O& overlap,
424  const OverlapVertex<Vertex>* overlapVertices,
425  const OverlapVertex<Vertex>* overlapEnd,
426  R& row)
427  {
428  typedef typename T::GlobalLookupIndexSet GlobalLookup;
429  const GlobalLookup& lookup = pinfo.globalLookup();
430 
431  typedef typename G::VertexIterator VertexIterator;
432 
433  VertexIterator vend=graph.end();
434 
435 #ifdef DUNE_ISTL_WITH_CHECKING
436  std::set<Vertex> examined;
437 #endif
438 
439  // The aggregates owned by the process have lower local indices
440  // then those not owned. We process them in the first pass.
441  // They represent the rows 0, 1, ..., n of the coarse matrix
442  for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex)
443  if(!get(visitedMap, *vertex)) {
444  // In the first pass we only process owner nodes
445  typedef typename GlobalLookup::IndexPair IndexPair;
446  const IndexPair* pair = lookup.pair(*vertex);
447  if(pair==0 || !overlap.contains(pair->local().attribute())) {
448 #ifdef DUNE_ISTL_WITH_CHECKING
449  assert(examined.find(aggregates[*vertex])==examined.end());
450  examined.insert(aggregates[*vertex]);
451 #endif
452  constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex);
453 
454  // only needed for ALU
455  // (ghosts with same global id as owners on the same process)
456  if (SolverCategory::category(pinfo) == static_cast<int>(SolverCategory::nonoverlapping)) {
457  if(overlapVertices != overlapEnd) {
458  if(*overlapVertices->aggregate!=AggregatesMap<Vertex>::ISOLATED) {
459  constructOverlapConnectivity(row, graph, visitedMap, aggregates, overlapVertices, overlapEnd);
460  }
461  else{
462  ++overlapVertices;
463  }
464  }
465  }
466  ++row;
467  }
468  }
469 
470  dvverb<<"constructed "<<row.index()<<" non-overlapping rows"<<std::endl;
471 
472  // Now come the aggregates not owned by use.
473  // They represent the rows n+1, ..., N
474  while(overlapVertices != overlapEnd)
475  if(*overlapVertices->aggregate!=AggregatesMap<Vertex>::ISOLATED) {
476 
477 #ifdef DUNE_ISTL_WITH_CHECKING
478  typedef typename GlobalLookup::IndexPair IndexPair;
479  const IndexPair* pair = lookup.pair(overlapVertices->vertex);
480  assert(pair!=0 && overlap.contains(pair->local().attribute()));
481  assert(examined.find(aggregates[overlapVertices->vertex])==examined.end());
482  examined.insert(aggregates[overlapVertices->vertex]);
483 #endif
484  constructOverlapConnectivity(row, graph, visitedMap, aggregates, overlapVertices, overlapEnd);
485  ++row;
486  }else{
487  ++overlapVertices;
488  }
489  }
490 
491  template<class G>
492  template<class V, class R>
494  V& visitedMap,
495  [[maybe_unused]] const SequentialInformation& pinfo,
496  const AggregatesMap<Vertex>& aggregates,
497  R& row)
498  {
499  typedef typename G::VertexIterator VertexIterator;
500 
501  VertexIterator vend=graph.end();
502  for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex) {
503  if(!get(visitedMap, *vertex)) {
504  constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex);
505  ++row;
506  }
507  }
508 
509  }
510 
511  template<class M>
513  : row_(matrix.createbegin()),
514  minRowSize_(std::numeric_limits<std::size_t>::max()),
515  maxRowSize_(0), sumRowSize_(0)
516  {
517 #ifdef DUNE_ISTL_WITH_CHECKING
518  diagonalInserted = false;
519 #endif
520  }
521  template<class M>
523  {
524  return maxRowSize_;
525  }
526  template<class M>
528  {
529  return minRowSize_;
530  }
531 
532  template<class M>
534  {
535  return sumRowSize_;
536  }
537  template<class M>
539  {
540  sumRowSize_ += row_.size();
541  minRowSize_=std::min(minRowSize_, row_.size());
542  maxRowSize_=std::max(maxRowSize_, row_.size());
543  ++row_;
544 #ifdef DUNE_ISTL_WITH_CHECKING
545  assert(diagonalInserted);
546  diagonalInserted = false;
547 #endif
548  }
549 
550  template<class M>
551  void SparsityBuilder<M>::insert(const typename M::size_type& index)
552  {
553  row_.insert(index);
554 #ifdef DUNE_ISTL_WITH_CHECKING
555  diagonalInserted = diagonalInserted || row_.index()==index;
556 #endif
557  }
558 
559  template<class T>
560  template<class G, class V, class Set>
561  typename G::MutableMatrix*
562  GalerkinProduct<T>::build(G& fineGraph, V& visitedMap,
563  const ParallelInformation& pinfo,
565  const typename G::Matrix::size_type& size,
566  const Set& overlap)
567  {
569 
570  std::size_t count;
571 
572  const OverlapVertex* overlapVertices = buildOverlapVertices(fineGraph,
573  pinfo,
574  aggregates,
575  overlap,
576  count);
577  typedef typename G::MutableMatrix M;
578  M* coarseMatrix = new M(size, size, M::row_wise);
579 
580  // Reset the visited flags of all vertices.
581  // As the isolated nodes will be skipped we simply mark them as visited
582 
583  typedef typename G::VertexIterator Vertex;
584  Vertex vend = fineGraph.end();
585  for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex) {
586  assert(aggregates[*vertex] != AggregatesMap<typename G::VertexDescriptor>::UNAGGREGATED);
587  put(visitedMap, *vertex, aggregates[*vertex]==AggregatesMap<typename G::VertexDescriptor>::ISOLATED);
588  }
589 
590  typedef typename G::MutableMatrix M;
591  SparsityBuilder<M> sparsityBuilder(*coarseMatrix);
592 
593  ConnectivityConstructor<G,T>::examine(fineGraph, visitedMap, pinfo,
594  aggregates, overlap,
595  overlapVertices,
596  overlapVertices+count,
597  sparsityBuilder);
598 
599  dinfo<<pinfo.communicator().rank()<<": Matrix ("<<coarseMatrix->N()<<"x"<<coarseMatrix->M()<<" row: min="<<sparsityBuilder.minRowSize()<<" max="
600  <<sparsityBuilder.maxRowSize()<<" avg="
601  <<static_cast<double>(sparsityBuilder.sumRowSize())/coarseMatrix->N()
602  <<std::endl;
603 
604  delete[] overlapVertices;
605 
606  return coarseMatrix;
607  }
608 
609  template<class G, class V, class Set>
610  typename G::MutableMatrix*
612  const SequentialInformation& pinfo,
614  const typename G::Matrix::size_type& size,
615  [[maybe_unused]] const Set& overlap)
616  {
617  typedef typename G::MutableMatrix M;
618  M* coarseMatrix = new M(size, size, M::row_wise);
619 
620  // Reset the visited flags of all vertices.
621  // As the isolated nodes will be skipped we simply mark them as visited
622 
623  typedef typename G::VertexIterator Vertex;
624  Vertex vend = fineGraph.end();
625  for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex) {
626  assert(aggregates[*vertex] != AggregatesMap<typename G::VertexDescriptor>::UNAGGREGATED);
627  put(visitedMap, *vertex, aggregates[*vertex]==AggregatesMap<typename G::VertexDescriptor>::ISOLATED);
628  }
629 
630  SparsityBuilder<M> sparsityBuilder(*coarseMatrix);
631 
633  aggregates, sparsityBuilder);
634  dinfo<<"Matrix row: min="<<sparsityBuilder.minRowSize()<<" max="
635  <<sparsityBuilder.maxRowSize()<<" average="
636  <<static_cast<double>(sparsityBuilder.sumRowSize())/coarseMatrix->N()<<std::endl;
637  return coarseMatrix;
638  }
639 
640  template<class M, class V, class P, class O>
641  void BaseGalerkinProduct::calculate(const M& fine, const AggregatesMap<V>& aggregates, M& coarse,
642  const P& pinfo, [[maybe_unused]] const O& copy)
643  {
644  coarse = static_cast<typename M::field_type>(0);
645 
646  typedef typename M::ConstIterator RowIterator;
647  RowIterator endRow = fine.end();
648 
649  for(RowIterator row = fine.begin(); row != endRow; ++row)
650  if(aggregates[row.index()] != AggregatesMap<V>::ISOLATED) {
651  assert(aggregates[row.index()]!=AggregatesMap<V>::UNAGGREGATED);
652  typedef typename M::ConstColIterator ColIterator;
653  ColIterator endCol = row->end();
654 
655  for(ColIterator col = row->begin(); col != endCol; ++col)
656  if(aggregates[col.index()] != AggregatesMap<V>::ISOLATED) {
657  assert(aggregates[row.index()]!=AggregatesMap<V>::UNAGGREGATED);
658  coarse[aggregates[row.index()]][aggregates[col.index()]]+=*col;
659  }
660  }
661 
662  // get the right diagonal matrix values on copy lines from owner processes
663  typedef typename M::block_type BlockType;
664  std::vector<BlockType> rowsize(coarse.N(),BlockType(0));
665  for (RowIterator row = coarse.begin(); row != coarse.end(); ++row)
666  rowsize[row.index()]=coarse[row.index()][row.index()];
667  pinfo.copyOwnerToAll(rowsize,rowsize);
668  for (RowIterator row = coarse.begin(); row != coarse.end(); ++row)
669  coarse[row.index()][row.index()] = rowsize[row.index()];
670 
671  // don't set dirichlet boundaries for copy lines to make novlp case work,
672  // the preconditioner yields slightly different results now.
673 
674  // Set the dirichlet border
675  //DirichletBoundarySetter<P>::template set<M>(coarse, pinfo, copy);
676 
677  }
678 
679  template<class T>
680  template<class M, class O>
681  void DirichletBoundarySetter<T>::set(M& coarse, const T& pinfo, const O& copy)
682  {
683  typedef typename T::ParallelIndexSet::const_iterator ConstIterator;
684  ConstIterator end = pinfo.indexSet().end();
685  typedef typename M::block_type Block;
686  Block identity=Block(0.0);
687  for(typename Block::RowIterator b=identity.begin(); b != identity.end(); ++b)
688  b->operator[](b.index())=1.0;
689 
690  for(ConstIterator index = pinfo.indexSet().begin();
691  index != end; ++index) {
692  if(copy.contains(index->local().attribute())) {
693  typedef typename M::ColIterator ColIterator;
694  typedef typename M::row_type Row;
695  Row row = coarse[index->local()];
696  ColIterator cend = row.find(index->local());
697  ColIterator col = row.begin();
698  for(; col != cend; ++col)
699  *col = 0;
700 
701  cend = row.end();
702 
703  assert(col != cend); // There should be a diagonal entry
704  *col = identity;
705 
706  for(++col; col != cend; ++col)
707  *col = 0;
708  }
709  }
710  }
711 
712  template<class M, class O>
714  const SequentialInformation& pinfo,
715  const O& overlap)
716  {}
717 
718  } // namespace Amg
719 } // namespace Dune
720 #endif
Provides classes for the Coloring process of AMG.
Col col
Definition: matrixmatrix.hh:349
bool operator()(const OverlapVertex< A > &o1, const OverlapVertex< A > &o2)
Definition: galerkin.hh:153
static void constructNonOverlapConnectivity(R &row, G &graph, V &visitedMap, const AggregatesMap< typename G::VertexDescriptor > &aggregates, const typename G::VertexDescriptor &seed)
Construct the connectivity of an aggregate in the overlap.
Definition: galerkin.hh:311
G Graph
The type of the graph.
Definition: galerkin.hh:209
void operator++()
Definition: galerkin.hh:538
void operator()(const ConstEdgeIterator &edge)
Process an edge pointing to another aggregate.
Definition: galerkin.hh:357
void insert(const typename M::size_type &index)
Definition: galerkin.hh:551
static void constructOverlapConnectivity(R &row, G &graph, V &visitedMap, const AggregatesMap< typename G::VertexDescriptor > &aggregates, const OverlapVertex< typename G::VertexDescriptor > *&seed, const OverlapVertex< typename G::VertexDescriptor > *overlapEnd)
Definition: galerkin.hh:329
G::MutableMatrix * build(G &fineGraph, V &visitedMap, const ParallelInformation &pinfo, AggregatesMap< typename G::VertexDescriptor > &aggregates, const typename G::Matrix::size_type &size, const Set &copy)
Calculates the coarse matrix via a Galerkin product.
Definition: galerkin.hh:562
std::size_t index()
Definition: galerkin.hh:79
T ParallelInformation
Definition: galerkin.hh:118
G::VertexDescriptor Vertex
Definition: galerkin.hh:270
T Aggregate
The aggregate descriptor.
Definition: galerkin.hh:35
SparsityBuilder(M &matrix)
Constructor.
Definition: galerkin.hh:512
ConnectedBuilder(const AggregatesMap< Vertex > &aggregates, Graph &graph, VisitedMap &visitedMap, Set &connected)
Constructor.
Definition: galerkin.hh:350
Graph::ConstEdgeIterator ConstEdgeIterator
The constant edge iterator.
Definition: galerkin.hh:213
T Vertex
The vertex descriptor.
Definition: galerkin.hh:40
G::VertexDescriptor Vertex
Definition: galerkin.hh:286
static void examine(G &graph, V &visitedMap, const T &pinfo, const AggregatesMap< Vertex > &aggregates, const O &overlap, const OverlapVertex< Vertex > *overlapVertices, const OverlapVertex< Vertex > *overlapEnd, R &row)
Definition: galerkin.hh:419
G::MutableMatrix * build(G &fineGraph, V &visitedMap, const SequentialInformation &pinfo, const AggregatesMap< typename G::VertexDescriptor > &aggregates, const typename G::Matrix::size_type &size, const Set &copy)
Calculates the coarse matrix via a Galerkin product.
V VisitedMap
The type of the map for marking vertices as visited.
Definition: galerkin.hh:223
int visitNeighbours(const G &graph, const typename G::VertexDescriptor &vertex, V &visitor)
Visit all neighbour vertices of a vertex in a graph.
S Set
The type of the connected set.
Definition: galerkin.hh:218
Aggregate * aggregate
The aggregate the vertex belongs to.
Definition: galerkin.hh:45
std::size_t sumRowSize()
Definition: galerkin.hh:533
Vertex vertex
The vertex descriptor.
Definition: galerkin.hh:50
std::size_t minRowSize()
Definition: galerkin.hh:527
static void set(M &coarse, const T &pinfo, const O &copy)
Definition: galerkin.hh:681
Graph::VertexDescriptor Vertex
The vertex descriptor of the graph.
Definition: galerkin.hh:228
static void examine(G &graph, V &visitedMap, const SequentialInformation &pinfo, const AggregatesMap< Vertex > &aggregates, R &row)
void calculate(const M &fine, const AggregatesMap< V > &aggregates, M &coarse, const I &pinfo, const O &copy)
Calculate the galerkin product.
std::size_t maxRowSize()
Definition: galerkin.hh:522
Definition: allocator.hh:9
PropertyMapTypeSelector< Amg::VertexVisitedTag, Amg::PropertiesGraph< G, Amg::VertexProperties, EP, VM, EM > >::Type get([[maybe_unused]] const Amg::VertexVisitedTag &tag, Amg::PropertiesGraph< G, Amg::VertexProperties, EP, VM, EM > &graph)
Definition: dependency.hh:291
Class providing information about the mapping of the vertices onto aggregates.
Definition: aggregates.hh:558
Definition: galerkin.hh:31
Functor for building the sparsity pattern of the matrix using examineConnectivity.
Definition: galerkin.hh:61
Definition: galerkin.hh:97
Definition: galerkin.hh:116
Definition: galerkin.hh:183
Visitor for identifying connected aggregates during a breadthFirstSearch.
Definition: galerkin.hh:204
Definition: galerkin.hh:269
Definition: galerkin.hh:298
Definition: pinfo.hh:26
@ nonoverlapping
Category for non-overlapping solvers.
Definition: solvercategory.hh:25
static Category category(const OP &op, decltype(op.category()) *=nullptr)
Helperfunction to extract the solver category either from an enum, or from the newly introduced virtu...
Definition: solvercategory.hh:32