multibasis.hh 3.32 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#pragma once

#include <tuple>
#include <utility>

#include <dune/common/hybridutilities.hh>
#include <dune/common/rangeutilities.hh>
#include <dune/common/indices.hh>
#include <dune/common/std/apply.hh>

// requires the dune-functions module
#include <dune/functions/functionspacebases/defaultglobalbasis.hh>

namespace Dune
{
  template <class MultiMesh, class... Bases>
  struct MultiBasis
  {
19
    using MultiLeafGridView = typename MultiMesh::LeafGridView;
20
21
22
23
24
25
26
27
28
29

    /// Constructor. Stores a leafgridView of the MultiMesh and LocalView/LocalIndexSet of the bases
    MultiBasis (MultiMesh const& mm, Bases&&... bases)
      : multiGridView_(mm.leafGridView())
      , bases_{std::forward<Bases>(bases)...}
      , localViews_(Std::apply([](auto const&... b) { return std::make_tuple(b.localView()...); }, bases_))
      , localIndexSets_(Std::apply([](auto const&... b) { return std::make_tuple(b.localIndexSet()...); }, bases_))
    {}

    /// Return the leafGridView of the MultiMesh
30
    const MultiLeafGridView& gridView () const { return multiGridView_; }
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

    /// Return the I'th basis
    template <std::size_t I>
    auto const& basis (index_constant<I>) const { return std::get<I>(bases_); }

    /// Return the LocalView assiciated with the I'th basis
    template <std::size_t I>
    auto const& localView (index_constant<I>) const { return std::get<I>(localViews_); }

    /// Return the LocalIndexSet assiciated with the I'th basis
    template <std::size_t I>
    auto const& localIndexSet (index_constant<I>) const { return std::get<I>(localIndexSets_); }

    /// Update all bases
    void update ()
    {
      Hybrid::forEach(range(index_constant<sizeof...(Bases)>{}), [&,this](const auto i)
      {
        std::get<i.value>(bases_).update(multiGridView_.grid().leafGridView(i));
      });
    }

    /// \brief Bind all localViews to the corresponding element and
    /// bind the localIndexSets to these localViews
    template <class MultiElement>
    void bind (const MultiElement& multiElement)
    {
      Hybrid::forEach(range(index_constant<sizeof...(Bases)>{}), [&,this](const auto i)
      {
        std::get<i.value>(localViews_).bind(multiElement[i]);
        std::get<i.value>(localIndexSets_).bind(std::get<i.value>(localViews_));
      });
    }

  private:
66
    MultiLeafGridView multiGridView_;
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
    std::tuple<Bases...> bases_;

    std::tuple<typename Bases::LocalView...> localViews_;
    std::tuple<typename Bases::LocalIndexSet...> localIndexSets_;
  };

  namespace Impl
  {
    template <class MM, class... Bases>
    auto makeMultiBasisFinal(MM const& mm, Bases&&... bases)
    {
      return MultiBasis<MM, std::decay_t<Bases>...>{mm, std::forward<Bases>(bases)...};
    }

    template <class MM, class FactoryTuple, std::size_t... I>
    auto makeMultiBasisImpl(MM const& mm, FactoryTuple&& factories, std::index_sequence<I...>)
    {
      using Functions::BasisBuilder::makeBasis;
      return makeMultiBasisFinal(mm, makeBasis(mm[I].leafGridView(), std::get<I>(factories))...);
    }
  }

  /// Construct a tuple of bases from its factories (factoryTags) and return a MultiBasis
  template <class MM, class... Factories>
  auto makeMultiBasis(MM const& mm, Factories&&... factories)
  {
    return Impl::makeMultiBasisImpl(mm, std::forward_as_tuple(factories...),
      std::make_index_sequence<sizeof...(Factories)>{});
  }

} // end namespace Dune