Dune Core Modules (unstable)

blocklevel.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 
6 #ifndef DUNE_ISTL_BLOCKLEVEL_HH
7 #define DUNE_ISTL_BLOCKLEVEL_HH
8 
9 #include <algorithm>
10 #include <type_traits>
11 
12 #include <dune/common/indices.hh>
14 #include <dune/common/hybridutilities.hh>
15 
21 // forward declaration
22 namespace Dune {
23 template<typename... Args>
24 class MultiTypeBlockVector;
25 template<typename FirstRow, typename... Args>
26 class MultiTypeBlockMatrix;
27 } // end namespace Dune
28 
29 namespace Dune { namespace Impl {
30 
31 // forward declaration
32 template<typename T> struct MaxBlockLevel;
33 template<typename T> struct MinBlockLevel;
34 
36 template<typename M, template<typename B> typename BlockLevel, typename Op>
37 constexpr std::size_t blockLevelMultiTypeBlockMatrix(const Op& op)
38 {
39  // inialize with zeroth diagonal block
40  using namespace Dune::Indices;
41  using Block00 = typename std::decay_t<decltype(std::declval<M>()[_0][_0])>;
42  std::size_t blockLevel = BlockLevel<Block00>::value() + 1;
43  // iterate over all blocks to determine min/max block level
44  using namespace Dune::Hybrid;
45  forEach(integralRange(index_constant<M::N()>()), [&](auto&& i) {
46  using namespace Dune::Hybrid; // needed for icc, see issue #31
47  forEach(integralRange(index_constant<M::M()>()), [&](auto&& j) {
48  using Block = typename std::decay_t<decltype(std::declval<M>()[i][j])>;
49  blockLevel = op(blockLevel, BlockLevel<Block>::value() + 1);
50  });
51  });
52  return blockLevel;
53 }
54 
56 template<typename V, template<typename B> typename BlockLevel, typename Op>
57 constexpr std::size_t blockLevelMultiTypeBlockVector(const Op& op)
58 {
59  // inialize with zeroth block
60  using namespace Dune::Indices;
61  using Block0 = typename std::decay_t<decltype(std::declval<V>()[_0])>;
62  std::size_t blockLevel = BlockLevel<Block0>::value() + 1;
63  // iterate over all blocks to determine min/max block level
64  using namespace Dune::Hybrid;
65  forEach(integralRange(index_constant<V::size()>()), [&](auto&& i) {
66  using Block = typename std::decay_t<decltype(std::declval<V>()[i])>;
67  blockLevel = op(blockLevel, BlockLevel<Block>::value() + 1);
68  });
69  return blockLevel;
70 }
71 
72 template<typename T>
73 struct MaxBlockLevel
74 {
75  static constexpr std::size_t value(){
76  if constexpr (IsNumber<T>::value)
77  return 0;
78  else
79  return MaxBlockLevel<typename T::block_type>::value() + 1;
80  }
81 };
82 
83 template<typename T>
84 struct MinBlockLevel
85 {
86  // the default implementation assumes minBlockLevel == maxBlockLevel
87  static constexpr std::size_t value()
88  { return MaxBlockLevel<T>::value(); }
89 };
90 
91 // max block level for MultiTypeBlockMatrix
92 template<typename FirstRow, typename... Args>
93 struct MaxBlockLevel<Dune::MultiTypeBlockMatrix<FirstRow, Args...>>
94 {
95  static constexpr std::size_t value()
96  {
97  using M = MultiTypeBlockMatrix<FirstRow, Args...>;
98  constexpr auto max = [](const auto& a, const auto& b){ return std::max(a,b); };
99  return blockLevelMultiTypeBlockMatrix<M, MaxBlockLevel>(max);
100  }
101 };
102 
103 // min block level for MultiTypeBlockMatrix
104 template<typename FirstRow, typename... Args>
105 struct MinBlockLevel<Dune::MultiTypeBlockMatrix<FirstRow, Args...>>
106 {
107  static constexpr std::size_t value()
108  {
109  using M = MultiTypeBlockMatrix<FirstRow, Args...>;
110  constexpr auto min = [](const auto& a, const auto& b){ return std::min(a,b); };
111  return blockLevelMultiTypeBlockMatrix<M, MinBlockLevel>(min);
112  }
113 };
114 
115 // max block level for MultiTypeBlockVector
116 template<typename... Args>
117 struct MaxBlockLevel<Dune::MultiTypeBlockVector<Args...>>
118 {
119  static constexpr std::size_t value()
120  {
121  using V = MultiTypeBlockVector<Args...>;
122  constexpr auto max = [](const auto& a, const auto& b){ return std::max(a,b); };
123  return blockLevelMultiTypeBlockVector<V, MaxBlockLevel>(max);
124  }
125 };
126 
127 // min block level for MultiTypeBlockVector
128 template<typename... Args>
129 struct MinBlockLevel<Dune::MultiTypeBlockVector<Args...>>
130 {
131  static constexpr std::size_t value()
132  {
133  using V = MultiTypeBlockVector<Args...>;
134  constexpr auto min = [](const auto& a, const auto& b){ return std::min(a,b); };
135  return blockLevelMultiTypeBlockVector<V, MinBlockLevel>(min);
136  }
137 };
138 
139 // special case: empty MultiTypeBlockVector
140 template<>
141 struct MaxBlockLevel<Dune::MultiTypeBlockVector<>>
142 {
143  static constexpr std::size_t value()
144  { return 0; };
145 };
146 
147 // special case: empty MultiTypeBlockVector
148 template<>
149 struct MinBlockLevel<Dune::MultiTypeBlockVector<>>
150 {
151  static constexpr std::size_t value()
152  { return 0; };
153 };
154 
155 }} // end namespace Dune::Impl
156 
157 namespace Dune {
158 
160 template<typename T>
161 constexpr std::size_t maxBlockLevel()
162 { return Impl::MaxBlockLevel<T>::value(); }
163 
165 template<typename T>
166 constexpr std::size_t minBlockLevel()
167 { return Impl::MinBlockLevel<T>::value(); }
168 
170 template<typename T>
171 constexpr bool hasUniqueBlockLevel()
172 { return maxBlockLevel<T>() == minBlockLevel<T>(); }
173 
175 template<typename T>
176 constexpr std::size_t blockLevel()
177 {
178  static_assert(hasUniqueBlockLevel<T>(), "Block level cannot be uniquely determined!");
179  return Impl::MaxBlockLevel<T>::value();
180 }
181 
182 } // end namespace Dune
183 
184 #endif
constexpr index_constant< 0 > _0
Compile time index with value 0.
Definition: indices.hh:52
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:29
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:256
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
constexpr auto integralRange(const Begin &begin, const End &end)
Create an integral range.
Definition: hybridutilities.hh:172
Namespace with predefined compile time indices for the range [0,19].
Definition: indices.hh:50
Dune namespace.
Definition: alignedallocator.hh:13
constexpr bool hasUniqueBlockLevel()
Determine if a vector/matrix has a uniquely determinable block level.
Definition: blocklevel.hh:171
constexpr std::size_t maxBlockLevel()
Determine the maximum block level of a possibly nested vector/matrix type.
Definition: blocklevel.hh:161
constexpr std::size_t blockLevel()
Determine the block level of a possibly nested vector/matrix type.
Definition: blocklevel.hh:176
constexpr std::size_t minBlockLevel()
Determine the minimum block level of a possibly nested vector/matrix type.
Definition: blocklevel.hh:166
Traits for type conversions and type information.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (Apr 27, 22:29, 2024)