7#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_ISTLVECTORBACKEND_HH
8#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_ISTLVECTORBACKEND_HH
14#include <dune/common/std/type_traits.hh>
15#include <dune/common/indices.hh>
16#include <dune/common/hybridutilities.hh>
17#include <dune/common/concept.hh>
19#include <dune/functions/common/indexaccess.hh>
20#include <dune/functions/functionspacebases/concepts.hh>
29 std::enable_if_t<not Dune::models<Imp::Concept::HasStaticIndexAccess, V>() ,
int> = 0>
36 std::enable_if_t<Dune::models<Imp::Concept::HasStaticIndexAccess, V>(),
int> = 0>
39 if constexpr (Dune::models<Imp::Concept::HasDynamicIndexAccess<std::size_t>, V>())
40 return fieldTypes(v[std::size_t{0}]);
43 auto indexRange =
typename decltype(range(Hybrid::size(v)))::integer_sequence();
44 return unpackIntegerSequence([&](
auto... i) {
45 return uniqueTypeList(std::tuple_cat(fieldTypes(v[i])...));
67constexpr auto fieldTypes()
69 return decltype(Impl::fieldTypes(std::declval<V>())){};
78constexpr bool hasUniqueFieldType()
80 return std::tuple_size_v<std::decay_t<decltype(fieldTypes<V>())>> ==1;
105class ISTLVectorBackend
110 using dynamicIndexAccess_t =
decltype(std::declval<C>()[0]);
113 using staticIndexAccess_t =
decltype(std::declval<C>()[Dune::Indices::_0]);
116 using resizeMethod_t =
decltype(std::declval<C>().resize(0));
122 using hasDynamicIndexAccess = Dune::Std::is_detected<dynamicIndexAccess_t, std::remove_reference_t<C>>;
125 using hasStaticIndexAccess = Dune::Std::is_detected<staticIndexAccess_t, std::remove_reference_t<C>>;
128 using hasResizeMethod = Dune::Std::is_detected<resizeMethod_t, std::remove_reference_t<C>>;
131 using isDynamicVector = Dune::Std::is_detected<dynamicIndexAccess_t, std::remove_reference_t<C>>;
134 using isStaticVector = Dune::Std::bool_constant<
135 Dune::Std::is_detected_v<staticIndexAccess_t, std::remove_reference_t<C>>
136 and not Dune::Std::is_detected_v<dynamicIndexAccess_t, std::remove_reference_t<C>>>;
139 using isScalar = Dune::Std::bool_constant<not Dune::Std::is_detected_v<staticIndexAccess_t, std::remove_reference_t<C>>>;
142 using isVector = Dune::Std::bool_constant<Dune::Std::is_detected_v<staticIndexAccess_t, std::remove_reference_t<C>>>;
146 template<
class... Args>
147 static void forwardToResize(Args&&... args)
149 resize(std::forward<Args>(args)...);
153 template<
class C,
class SizeProvider,
154 std::enable_if_t<hasResizeMethod<C>::value,
int> = 0>
155 static void resize(C&& c,
const SizeProvider& sizeProvider,
typename SizeProvider::SizePrefix prefix)
157 auto size = sizeProvider.size(prefix);
170 DUNE_THROW(RangeError,
"The vector entry v[" << prefix <<
"] should refer to a "
171 <<
"scalar coefficient, but is a dynamically sized vector of size==0");
180 for(std::size_t i=0; i<size; ++i)
183 resize(c[i], sizeProvider, prefix);
187 template<
class C,
class SizeProvider,
188 std::enable_if_t<not hasResizeMethod<C>::value,
int> = 0,
189 std::enable_if_t<isVector<C>::value,
int> = 0>
190 static void resize(C&& c,
const SizeProvider& sizeProvider,
typename SizeProvider::SizePrefix prefix)
192 auto size = sizeProvider.size(prefix);
207 if (c.size() != size)
208 DUNE_THROW(RangeError,
"Can't resize non-resizable entry v[" << prefix <<
"] of size " << c.size() <<
" to size(" << prefix <<
")=" << size);
211 using namespace Dune::Hybrid;
213 forEach(integralRange(Hybrid::size(c)), [&](
auto&& i) {
221 ISTLVectorBackend<V>::forwardToResize(c[i], sizeProvider, prefix);
225 template<
class C,
class SizeProvider,
226 std::enable_if_t<not hasResizeMethod<C>::value,
int> = 0,
227 std::enable_if_t<isScalar<C>::value,
int> = 0>
228 static void resize(C&&,
const SizeProvider& sizeProvider,
typename SizeProvider::SizePrefix prefix)
230 auto size = sizeProvider.size(prefix);
232 DUNE_THROW(RangeError,
"Can't resize scalar vector entry v[" << prefix <<
"] to size(" << prefix <<
")=" << size);
235 template<
class C,
class T,
236 std::enable_if_t<std::is_assignable_v<C&,T>,
int> = 0>
237 void recursiveAssign(C& c,
const T& t)
242 template<
class C,
class T,
243 std::enable_if_t<not std::is_assignable_v<C&,T>,
int> = 0>
244 void recursiveAssign(C& c,
const T& t)
246 Dune::Hybrid::forEach(c, [&](
auto&& ci) {
247 recursiveAssign(ci, t);
255 ISTLVectorBackend(Vector& vector) :
259 template<
class SizeProv
ider>
260 void resize(
const SizeProvider& sizeProvider)
262 auto prefix =
typename SizeProvider::SizePrefix();
264 resize(*vector_, sizeProvider, prefix);
267 template<
class MultiIndex>
268 decltype(
auto)
operator[](
const MultiIndex& index)
const
273 template<
class MultiIndex>
274 decltype(
auto)
operator[](
const MultiIndex& index)
288 void operator= (
const T& other)
290 recursiveAssign(vector(), other);
294 void operator= (
const ISTLVectorBackend<T>& other)
296 vector() = other.vector();
299 const Vector& vector()
const
349template<
class Vector>
352 static_assert(hasUniqueFieldType<Vector&>(),
"Vector type passed to istlVectorBackend() does not have a unique field type.");
353 return Impl::ISTLVectorBackend<Vector>(v);
387template<
class Vector>
390 static_assert(hasUniqueFieldType<const Vector&>(),
"Vector type passed to istlVectorBackend() does not have a unique field type.");
391 return Impl::ISTLVectorBackend<const Vector>(v);
auto istlVectorBackend(const Vector &v)
Return a vector backend wrapping const ISTL like containers.
Definition: istlvectorbackend.hh:388
constexpr decltype(auto) resolveDynamicMultiIndex(C &&c, const MultiIndex &multiIndex, const IsFinal &isFinal)
Provide multi-index access by chaining operator[].
Definition: indexaccess.hh:377
Definition: polynomial.hh:17