DUNE-FEM (unstable)

galerkin.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_GALERKIN_HH
6 #define DUNE_GALERKIN_HH
7 
8 #include "aggregates.hh"
9 #include "pinfo.hh"
11 #include <dune/common/enumset.hh>
12 #include <set>
13 #include <limits>
14 #include <algorithm>
15 
16 namespace Dune
17 {
18  namespace Amg
19  {
31  template<class T>
32  struct OverlapVertex
33  {
37  typedef T Aggregate;
38 
42  typedef T Vertex;
43 
48 
53  };
54 
55 
56 
61  template<class M>
63  {
64  public:
70  SparsityBuilder(M& matrix);
71 
72  void insert(const typename M::size_type& index);
73 
74  void operator++();
75 
76  std::size_t minRowSize();
77 
78  std::size_t maxRowSize();
79 
80  std::size_t sumRowSize();
81  std::size_t index()
82  {
83  return row_.index();
84  }
85  private:
87  typename M::CreateIterator row_;
89  std::size_t minRowSize_;
91  std::size_t maxRowSize_;
92  std::size_t sumRowSize_;
93 #ifdef DUNE_ISTL_WITH_CHECKING
94  bool diagonalInserted;
95 #endif
96  };
97 
98  class BaseGalerkinProduct
99  {
100  public:
109  template<class M, class V, class I, class O>
110  void calculate(const M& fine, const AggregatesMap<V>& aggregates, M& coarse,
111  const I& pinfo, const O& copy);
112 
113  };
114 
115  template<class T>
116  class GalerkinProduct
117  : public BaseGalerkinProduct
118  {
119  public:
120  typedef T ParallelInformation;
121 
131  template<class G, class V, class Set>
132  typename G::MutableMatrix* build(G& fineGraph, V& visitedMap,
133  const ParallelInformation& pinfo,
135  const typename G::Matrix::size_type& size,
136  const Set& copy);
137  private:
138 
145  template<class G, class I, class Set>
146  const OverlapVertex<typename G::VertexDescriptor>*
147  buildOverlapVertices(const G& graph, const I& pinfo,
149  const Set& overlap,
150  std::size_t& overlapCount);
151 
152  template<class A>
153  struct OVLess
154  {
155  bool operator()(const OverlapVertex<A>& o1, const OverlapVertex<A>& o2)
156  {
157  return *o1.aggregate < *o2.aggregate;
158  }
159  };
160  };
161 
162  template<>
163  class GalerkinProduct<SequentialInformation>
164  : public BaseGalerkinProduct
165  {
166  public:
176  template<class G, class V, class Set>
177  typename G::MutableMatrix* build(G& fineGraph, V& visitedMap,
178  const SequentialInformation& pinfo,
180  const typename G::Matrix::size_type& size,
181  const Set& copy);
182  };
183 
184  struct BaseConnectivityConstructor
185  {
186  template<class R, class G, class V>
187  static void constructOverlapConnectivity(R& row, G& graph, V& visitedMap,
189  const OverlapVertex<typename G::VertexDescriptor>*& seed,
190  const OverlapVertex<typename G::VertexDescriptor>* overlapEnd);
191 
195  template<class R, class G, class V>
196  static void constructNonOverlapConnectivity(R& row, G& graph, V& visitedMap,
198  const typename G::VertexDescriptor& seed);
199 
200 
204  template<class G, class S, class V>
206  {
207  public:
211  typedef G Graph;
215  typedef typename Graph::ConstEdgeIterator ConstEdgeIterator;
216 
220  typedef S Set;
221 
225  typedef V VisitedMap;
226 
230  typedef typename Graph::VertexDescriptor Vertex;
231 
239  ConnectedBuilder(const AggregatesMap<Vertex>& aggregates, Graph& graph,
240  VisitedMap& visitedMap, Set& connected);
241 
246  void operator()(const ConstEdgeIterator& edge);
247 
248  private:
252  const AggregatesMap<Vertex>& aggregates_;
253 
254  Graph& graph_;
255 
259  VisitedMap& visitedMap_;
260 
264  Set& connected_;
265  };
266 
267  };
268 
269  template<class G, class T>
270  struct ConnectivityConstructor : public BaseConnectivityConstructor
271  {
272  typedef typename G::VertexDescriptor Vertex;
273 
274  template<class V, class O, class R>
275  static void examine(G& graph,
276  V& visitedMap,
277  const T& pinfo,
278  const AggregatesMap<Vertex>& aggregates,
279  const O& overlap,
280  const OverlapVertex<Vertex>* overlapVertices,
281  const OverlapVertex<Vertex>* overlapEnd,
282  R& row);
283  };
284 
285  template<class G>
286  struct ConnectivityConstructor<G,SequentialInformation> : public BaseConnectivityConstructor
287  {
288  typedef typename G::VertexDescriptor Vertex;
289 
290  template<class V, class R>
291  static void examine(G& graph,
292  V& visitedMap,
293  const SequentialInformation& pinfo,
294  const AggregatesMap<Vertex>& aggregates,
295  R& row);
296  };
297 
298  template<class T>
299  struct DirichletBoundarySetter
300  {
301  template<class M, class O>
302  static void set(M& coarse, const T& pinfo, const O& copy);
303  };
304 
305  template<>
306  struct DirichletBoundarySetter<SequentialInformation>
307  {
308  template<class M, class O>
309  static void set(M& coarse, const SequentialInformation& pinfo, const O& copy);
310  };
311 
312  template<class R, class G, class V>
313  void BaseConnectivityConstructor::constructNonOverlapConnectivity(R& row, G& graph, V& visitedMap,
315  const typename G::VertexDescriptor& seed)
316  {
317  assert(row.index()==aggregates[seed]);
318  row.insert(aggregates[seed]);
319  ConnectedBuilder<G,R,V> conBuilder(aggregates, graph, visitedMap, row);
320  typedef typename G::VertexDescriptor Vertex;
321  typedef std::allocator<Vertex> Allocator;
322  typedef SLList<Vertex,Allocator> VertexList;
323  typedef typename AggregatesMap<Vertex>::DummyEdgeVisitor DummyVisitor;
324  VertexList vlist;
325  DummyVisitor dummy;
326  aggregates.template breadthFirstSearch<true,false>(seed,aggregates[seed], graph, vlist, dummy,
327  conBuilder, visitedMap);
328  }
329 
330  template<class R, class G, class V>
331  void BaseConnectivityConstructor::constructOverlapConnectivity(R& row, G& graph, V& visitedMap,
333  const OverlapVertex<typename G::VertexDescriptor>*& seed,
334  const OverlapVertex<typename G::VertexDescriptor>* overlapEnd)
335  {
336  ConnectedBuilder<G,R,V> conBuilder(aggregates, graph, visitedMap, row);
337  const typename G::VertexDescriptor aggregate=*seed->aggregate;
338 
339  if (row.index()==*seed->aggregate) {
340  while(seed != overlapEnd && aggregate == *seed->aggregate) {
341  row.insert(*seed->aggregate);
342  // Walk over all neighbours and add them to the connected array.
343  visitNeighbours(graph, seed->vertex, conBuilder);
344  // Mark vertex as visited
345  put(visitedMap, seed->vertex, true);
346  ++seed;
347  }
348  }
349  }
350 
351  template<class G, class S, class V>
353  Graph& graph, VisitedMap& visitedMap,
354  Set& connected)
355  : aggregates_(aggregates), graph_(graph), visitedMap_(visitedMap), connected_(connected)
356  {}
357 
358  template<class G, class S, class V>
360  {
361  const Vertex& vertex = aggregates_[edge.target()];
364  connected_.insert(vertex);
365  }
366 
367  template<class T>
368  template<class G, class I, class Set>
369  const OverlapVertex<typename G::VertexDescriptor>*
370  GalerkinProduct<T>::buildOverlapVertices(const G& graph, const I& pinfo,
372  const Set& overlap,
373  std::size_t& overlapCount)
374  {
375  // count the overlap vertices.
376  typedef typename G::ConstVertexIterator ConstIterator;
377  typedef typename I::GlobalLookupIndexSet GlobalLookup;
378  typedef typename GlobalLookup::IndexPair IndexPair;
379 
380  const ConstIterator end = graph.end();
381  overlapCount = 0;
382 
383  const GlobalLookup& lookup=pinfo.globalLookup();
384 
385  for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex) {
386  const IndexPair* pair = lookup.pair(*vertex);
387 
388  if(pair!=0 && overlap.contains(pair->local().attribute()))
389  ++overlapCount;
390  }
391  // Allocate space
392  typedef typename G::VertexDescriptor Vertex;
393 
394  OverlapVertex<Vertex>* overlapVertices = new OverlapVertex<Vertex>[overlapCount=0 ? 1 : overlapCount];
395  if(overlapCount==0)
396  return overlapVertices;
397 
398  // Initialize them
399  overlapCount=0;
400  for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex) {
401  const IndexPair* pair = lookup.pair(*vertex);
402 
403  if(pair!=0 && overlap.contains(pair->local().attribute())) {
404  overlapVertices[overlapCount].aggregate = &aggregates[pair->local()];
405  overlapVertices[overlapCount].vertex = pair->local();
406  ++overlapCount;
407  }
408  }
409 
410  dverb << overlapCount<<" overlap vertices"<<std::endl;
411 
412  std::sort(overlapVertices, overlapVertices+overlapCount, OVLess<Vertex>());
413  // due to the sorting the isolated aggregates (to be skipped) are at the end.
414 
415  return overlapVertices;
416  }
417 
418  template<class G, class T>
419  template<class V, class O, class R>
420  void ConnectivityConstructor<G,T>::examine(G& graph,
421  V& visitedMap,
422  const T& pinfo,
423  const AggregatesMap<Vertex>& aggregates,
424  const O& overlap,
425  const OverlapVertex<Vertex>* overlapVertices,
426  const OverlapVertex<Vertex>* overlapEnd,
427  R& row)
428  {
429  typedef typename T::GlobalLookupIndexSet GlobalLookup;
430  const GlobalLookup& lookup = pinfo.globalLookup();
431 
432  typedef typename G::VertexIterator VertexIterator;
433 
434  VertexIterator vend=graph.end();
435 
436 #ifdef DUNE_ISTL_WITH_CHECKING
437  std::set<Vertex> examined;
438 #endif
439 
440  // The aggregates owned by the process have lower local indices
441  // then those not owned. We process them in the first pass.
442  // They represent the rows 0, 1, ..., n of the coarse matrix
443  for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex)
444  if(!get(visitedMap, *vertex)) {
445  // In the first pass we only process owner nodes
446  typedef typename GlobalLookup::IndexPair IndexPair;
447  const IndexPair* pair = lookup.pair(*vertex);
448  if(pair==0 || !overlap.contains(pair->local().attribute())) {
449 #ifdef DUNE_ISTL_WITH_CHECKING
450  assert(examined.find(aggregates[*vertex])==examined.end());
451  examined.insert(aggregates[*vertex]);
452 #endif
453  constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex);
454 
455  // only needed for ALU
456  // (ghosts with same global id as owners on the same process)
457  if (SolverCategory::category(pinfo) == static_cast<int>(SolverCategory::nonoverlapping)) {
458  if(overlapVertices != overlapEnd) {
459  if(*overlapVertices->aggregate!=AggregatesMap<Vertex>::ISOLATED) {
460  constructOverlapConnectivity(row, graph, visitedMap, aggregates, overlapVertices, overlapEnd);
461  }
462  else{
463  ++overlapVertices;
464  }
465  }
466  }
467  ++row;
468  }
469  }
470 
471  dvverb<<"constructed "<<row.index()<<" non-overlapping rows"<<std::endl;
472 
473  // Now come the aggregates not owned by use.
474  // They represent the rows n+1, ..., N
475  while(overlapVertices != overlapEnd)
476  if(*overlapVertices->aggregate!=AggregatesMap<Vertex>::ISOLATED) {
477 
478 #ifdef DUNE_ISTL_WITH_CHECKING
479  typedef typename GlobalLookup::IndexPair IndexPair;
480  const IndexPair* pair = lookup.pair(overlapVertices->vertex);
481  assert(pair!=0 && overlap.contains(pair->local().attribute()));
482  assert(examined.find(aggregates[overlapVertices->vertex])==examined.end());
483  examined.insert(aggregates[overlapVertices->vertex]);
484 #endif
485  constructOverlapConnectivity(row, graph, visitedMap, aggregates, overlapVertices, overlapEnd);
486  ++row;
487  }else{
488  ++overlapVertices;
489  }
490  }
491 
492  template<class G>
493  template<class V, class R>
494  void ConnectivityConstructor<G,SequentialInformation>::examine(G& graph,
495  V& visitedMap,
496  [[maybe_unused]] const SequentialInformation& pinfo,
497  const AggregatesMap<Vertex>& aggregates,
498  R& row)
499  {
500  typedef typename G::VertexIterator VertexIterator;
501 
502  VertexIterator vend=graph.end();
503  for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex) {
504  if(!get(visitedMap, *vertex)) {
505  constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex);
506  ++row;
507  }
508  }
509 
510  }
511 
512  template<class M>
514  : row_(matrix.createbegin()),
515  minRowSize_(std::numeric_limits<std::size_t>::max()),
516  maxRowSize_(0), sumRowSize_(0)
517  {
518 #ifdef DUNE_ISTL_WITH_CHECKING
519  diagonalInserted = false;
520 #endif
521  }
522  template<class M>
523  std::size_t SparsityBuilder<M>::maxRowSize()
524  {
525  return maxRowSize_;
526  }
527  template<class M>
528  std::size_t SparsityBuilder<M>::minRowSize()
529  {
530  return minRowSize_;
531  }
532 
533  template<class M>
534  std::size_t SparsityBuilder<M>::sumRowSize()
535  {
536  return sumRowSize_;
537  }
538  template<class M>
539  void SparsityBuilder<M>::operator++()
540  {
541  sumRowSize_ += row_.size();
542  minRowSize_=std::min(minRowSize_, row_.size());
543  maxRowSize_=std::max(maxRowSize_, row_.size());
544  ++row_;
545 #ifdef DUNE_ISTL_WITH_CHECKING
546  assert(diagonalInserted);
547  diagonalInserted = false;
548 #endif
549  }
550 
551  template<class M>
552  void SparsityBuilder<M>::insert(const typename M::size_type& index)
553  {
554  row_.insert(index);
555 #ifdef DUNE_ISTL_WITH_CHECKING
556  diagonalInserted = diagonalInserted || row_.index()==index;
557 #endif
558  }
559 
560  template<class T>
561  template<class G, class V, class Set>
562  typename G::MutableMatrix*
563  GalerkinProduct<T>::build(G& fineGraph, V& visitedMap,
564  const ParallelInformation& pinfo,
566  const typename G::Matrix::size_type& size,
567  const Set& overlap)
568  {
569  typedef OverlapVertex<typename G::VertexDescriptor> OverlapVertex;
570 
571  std::size_t count;
572 
573  const OverlapVertex* overlapVertices = buildOverlapVertices(fineGraph,
574  pinfo,
575  aggregates,
576  overlap,
577  count);
578  typedef typename G::MutableMatrix M;
579  M* coarseMatrix = new M(size, size, M::row_wise);
580 
581  // Reset the visited flags of all vertices.
582  // As the isolated nodes will be skipped we simply mark them as visited
583 
584  typedef typename G::VertexIterator Vertex;
585  Vertex vend = fineGraph.end();
586  for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex) {
589  }
590 
591  typedef typename G::MutableMatrix M;
592  SparsityBuilder<M> sparsityBuilder(*coarseMatrix);
593 
594  ConnectivityConstructor<G,T>::examine(fineGraph, visitedMap, pinfo,
595  aggregates, overlap,
596  overlapVertices,
597  overlapVertices+count,
598  sparsityBuilder);
599 
600  dinfo<<pinfo.communicator().rank()<<": Matrix ("<<coarseMatrix->N()<<"x"<<coarseMatrix->M()<<" row: min="<<sparsityBuilder.minRowSize()<<" max="
601  <<sparsityBuilder.maxRowSize()<<" avg="
602  <<static_cast<double>(sparsityBuilder.sumRowSize())/coarseMatrix->N()
603  <<std::endl;
604 
605  delete[] overlapVertices;
606 
607  return coarseMatrix;
608  }
609 
610  template<class G, class V, class Set>
611  typename G::MutableMatrix*
612  GalerkinProduct<SequentialInformation>::build(G& fineGraph, V& visitedMap,
613  const SequentialInformation& pinfo,
615  const typename G::Matrix::size_type& size,
616  [[maybe_unused]] const Set& overlap)
617  {
618  typedef typename G::MutableMatrix M;
619  M* coarseMatrix = new M(size, size, M::row_wise);
620 
621  // Reset the visited flags of all vertices.
622  // As the isolated nodes will be skipped we simply mark them as visited
623 
624  typedef typename G::VertexIterator Vertex;
625  Vertex vend = fineGraph.end();
626  for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex) {
629  }
630 
631  SparsityBuilder<M> sparsityBuilder(*coarseMatrix);
632 
633  ConnectivityConstructor<G,SequentialInformation>::examine(fineGraph, visitedMap, pinfo,
634  aggregates, sparsityBuilder);
635  dinfo<<"Matrix row: min="<<sparsityBuilder.minRowSize()<<" max="
636  <<sparsityBuilder.maxRowSize()<<" average="
637  <<static_cast<double>(sparsityBuilder.sumRowSize())/coarseMatrix->N()<<std::endl;
638  return coarseMatrix;
639  }
640 
641  template<class M, class V, class P, class O>
642  void BaseGalerkinProduct::calculate(const M& fine, const AggregatesMap<V>& aggregates, M& coarse,
643  const P& pinfo, [[maybe_unused]] const O& copy)
644  {
645  coarse = static_cast<typename M::field_type>(0);
646 
647  typedef typename M::ConstIterator RowIterator;
648  RowIterator endRow = fine.end();
649 
650  for(RowIterator row = fine.begin(); row != endRow; ++row)
651  if(aggregates[row.index()] != AggregatesMap<V>::ISOLATED) {
652  assert(aggregates[row.index()]!=AggregatesMap<V>::UNAGGREGATED);
653  typedef typename M::ConstColIterator ColIterator;
654  ColIterator endCol = row->end();
655 
656  for(ColIterator col = row->begin(); col != endCol; ++col)
657  if(aggregates[col.index()] != AggregatesMap<V>::ISOLATED) {
658  assert(aggregates[row.index()]!=AggregatesMap<V>::UNAGGREGATED);
659  coarse[aggregates[row.index()]][aggregates[col.index()]]+=*col;
660  }
661  }
662 
663  // get the right diagonal matrix values on copy lines from owner processes
664  typedef typename M::block_type BlockType;
665  std::vector<BlockType> rowsize(coarse.N(),BlockType(0));
666  for (RowIterator row = coarse.begin(); row != coarse.end(); ++row)
667  rowsize[row.index()]=coarse[row.index()][row.index()];
668  pinfo.copyOwnerToAll(rowsize,rowsize);
669  for (RowIterator row = coarse.begin(); row != coarse.end(); ++row)
670  coarse[row.index()][row.index()] = rowsize[row.index()];
671 
672  // don't set dirichlet boundaries for copy lines to make novlp case work,
673  // the preconditioner yields slightly different results now.
674 
675  // Set the dirichlet border
676  //DirichletBoundarySetter<P>::template set<M>(coarse, pinfo, copy);
677 
678  }
679 
680  template<class T>
681  template<class M, class O>
682  void DirichletBoundarySetter<T>::set(M& coarse, const T& pinfo, const O& copy)
683  {
684  typedef typename T::ParallelIndexSet::const_iterator ConstIterator;
685  ConstIterator end = pinfo.indexSet().end();
686  typedef typename M::block_type Block;
687  Block identity=Block(0.0);
688  for(typename Block::RowIterator b=identity.begin(); b != identity.end(); ++b)
689  b->operator[](b.index())=1.0;
690 
691  for(ConstIterator index = pinfo.indexSet().begin();
692  index != end; ++index) {
693  if(copy.contains(index->local().attribute())) {
694  typedef typename M::ColIterator ColIterator;
695  typedef typename M::row_type Row;
696  Row row = coarse[index->local()];
697  ColIterator cend = row.find(index->local());
698  ColIterator col = row.begin();
699  for(; col != cend; ++col)
700  *col = 0;
701 
702  cend = row.end();
703 
704  assert(col != cend); // There should be a diagonal entry
705  *col = identity;
706 
707  for(++col; col != cend; ++col)
708  *col = 0;
709  }
710  }
711  }
712 
713  template<class M, class O>
714  void DirichletBoundarySetter<SequentialInformation>::set(M& coarse,
715  const SequentialInformation& pinfo,
716  const O& overlap)
717  {}
718 
719  } // namespace Amg
720 } // namespace Dune
721 #endif
Provides classes for the Coloring process of AMG.
Class providing information about the mapping of the vertices onto aggregates.
Definition: aggregates.hh:560
Visitor for identifying connected aggregates during a breadthFirstSearch.
Definition: galerkin.hh:206
Functor for building the sparsity pattern of the matrix using examineConnectivity.
Definition: galerkin.hh:63
A pair consisting of a global and local index.
Definition: indexset.hh:85
A single linked list.
Definition: sllist.hh:44
Classes for building sets out of enumeration values.
LocalIndex & local()
Get the local index.
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:484
constexpr auto min
Function object that returns the smaller of the given values.
Definition: hybridutilities.hh:506
G Graph
The type of the graph.
Definition: galerkin.hh:211
void operator()(const ConstEdgeIterator &edge)
Process an edge pointing to another aggregate.
Definition: galerkin.hh:359
T Aggregate
The aggregate descriptor.
Definition: galerkin.hh:37
SparsityBuilder(M &matrix)
Constructor.
Definition: galerkin.hh:513
ConnectedBuilder(const AggregatesMap< Vertex > &aggregates, Graph &graph, VisitedMap &visitedMap, Set &connected)
Constructor.
Definition: galerkin.hh:352
Graph::ConstEdgeIterator ConstEdgeIterator
The constant edge iterator.
Definition: galerkin.hh:215
T Vertex
The vertex descriptor.
Definition: galerkin.hh:42
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:225
int visitNeighbours(const G &graph, const typename G::VertexDescriptor &vertex, V &visitor)
Visit all neighbour vertices of a vertex in a graph.
static const Vertex ISOLATED
Identifier of isolated vertices.
Definition: aggregates.hh:571
S Set
The type of the connected set.
Definition: galerkin.hh:220
Aggregate * aggregate
The aggregate the vertex belongs to.
Definition: galerkin.hh:47
Vertex vertex
The vertex descriptor.
Definition: galerkin.hh:52
static const V UNAGGREGATED
Identifier of not yet aggregated vertices.
Definition: aggregates.hh:566
Graph::VertexDescriptor Vertex
The vertex descriptor of the graph.
Definition: galerkin.hh:230
void calculate(const M &fine, const AggregatesMap< V > &aggregates, M &coarse, const I &pinfo, const O &copy)
Calculate the galerkin product.
DVVerbType dvverb(std::cout)
stream for very verbose output.
Definition: stdstreams.hh:95
DInfoType dinfo(std::cout)
Stream for informative output.
Definition: stdstreams.hh:140
DVerbType dverb(std::cout)
Singleton of verbose debug stream.
Definition: stdstreams.hh:116
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 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
An stl-compliant pool allocator.
@ nonoverlapping
Category for non-overlapping solvers.
Definition: solvercategory.hh:27
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:34
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)