multibasis.hh 3.31 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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 66 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
#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
  {
    using MultiGridView = typename MultiMesh::LeafGridView;

    /// 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
    const MultiGridView& gridView () const { return multiGridView_; }

    /// 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:
    MultiGridView multiGridView_;
    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