Dune Core Modules (2.9.1)

blocklevel.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (C) 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
22namespace Dune {
23template<typename... Args>
24class MultiTypeBlockVector;
25template<typename FirstRow, typename... Args>
26class MultiTypeBlockMatrix;
27} // end namespace Dune
28
29namespace Dune { namespace Impl {
30
31// forward declaration
32template<typename T> struct MaxBlockLevel;
33template<typename T> struct MinBlockLevel;
34
36template<typename M, template<typename B> typename BlockLevel, typename Op>
37constexpr 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
56template<typename V, template<typename B> typename BlockLevel, typename Op>
57constexpr 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
72template<typename T>
73struct 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
83template<typename T>
84struct 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
92template<typename FirstRow, typename... Args>
93struct 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
104template<typename FirstRow, typename... Args>
105struct 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
116template<typename... Args>
117struct 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
128template<typename... Args>
129struct 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
140template<>
141struct MaxBlockLevel<Dune::MultiTypeBlockVector<>>
142{
143 static constexpr std::size_t value()
144 { return 0; };
145};
146
147// special case: empty MultiTypeBlockVector
148template<>
149struct MinBlockLevel<Dune::MultiTypeBlockVector<>>
150{
151 static constexpr std::size_t value()
152 { return 0; };
153};
154
155}} // end namespace Dune::Impl
156
157namespace Dune {
158
160template<typename T>
161constexpr std::size_t maxBlockLevel()
162{ return Impl::MaxBlockLevel<T>::value(); }
163
165template<typename T>
166constexpr std::size_t minBlockLevel()
167{ return Impl::MinBlockLevel<T>::value(); }
168
170template<typename T>
171constexpr bool hasUniqueBlockLevel()
172{ return maxBlockLevel<T>() == minBlockLevel<T>(); }
173
175template<typename T>
176constexpr 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
A Matrix class to support different block types.
Definition: multitypeblockmatrix.hh:46
A Vector class to support different block types.
Definition: multitypeblockvector.hh:59
constexpr index_constant< 0 > _0
Compile time index with value 0.
Definition: indices.hh:53
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:30
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:268
constexpr auto integralRange(const Begin &begin, const End &end)
Create an integral range.
Definition: hybridutilities.hh:184
auto min(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::min()
Definition: defaults.hh:89
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:81
Namespace with predefined compile time indices for the range [0,19].
Definition: indices.hh:51
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
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.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)