multigridview.hh 7.15 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_MULTI_GRIDVIEW_HH
#define DUNE_MULTI_GRIDVIEW_HH

#if ! DUNE_HAVE_CXX_VARIANT
#error "Require C++17 variant!"
#endif

#include <variant>

#include <dune/common/typetraits.hh>
#include <dune/common/exceptions.hh>
#include <dune/common/std/type_traits.hh>

#include <dune/grid/common/capabilities.hh>
#include <dune/grid/common/gridview.hh>

Praetorius, Simon's avatar
Praetorius, Simon committed
19
#include "multiindexset.hh"
20
#include "multiiterator.hh"
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

namespace Dune
{
  // forward declaration
  template <class HostGrid>
  class MultiGridView;

  template <class HostGrid>
  struct MultiGridViewTraits
  {
    using Grid = typename std::remove_const<HostGrid>::type;

    using IndexSet = MultiIndexSet<HostGrid>;

    using Intersection = std::variant<
      typename HostGrid::Traits::LeafIntersection, typename HostGrid::Traits::LevelIntersection>;

    using IntersectionIterator = std::variant<
      typename HostGrid::Traits::LeafIntersectionIterator, typename HostGrid::Traits::LevelIntersectionIterator>;

    using CollectiveCommunication = typename HostGrid::Traits::CollectiveCommunication;

    template <int cd>
    struct Codim
    {
      using Entity = typename Grid::Traits::template Codim<cd>::Entity;
      using Geometry = typename Grid::template Codim<cd>::Geometry;
      using LocalGeometry = typename Grid::template Codim<cd>::LocalGeometry;

      template <PartitionIteratorType pit>
      struct Partition
      {
53
        using Iterator = MultiIterator<cd,pit,HostGrid>;
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
      };
    };

    enum { conforming = Capabilities::isLevelwiseConforming<HostGrid>::v };
  };


  template <class HostGrid>
  class MultiGridView
  {
  public:
    using Traits = MultiGridViewTraits<HostGrid>;

    /// The MultiMesh GridType
    using Grid = typename Traits::Grid;

    using GridViewTypes = std::variant<typename HostGrid::LeafGridView, typename HostGrid::LevelGridView>;
Praetorius, Simon's avatar
Praetorius, Simon committed
71

72
    using IndexSet = typename Traits::IndexSet;
Praetorius, Simon's avatar
Praetorius, Simon committed
73
    using IndexSetTypes = typename IndexSet::IndexSetTypes;
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
    using IntersectionIterator = typename Traits::IntersectionIterator;

    using CollectiveCommunication = typename Traits::CollectiveCommunication;

    template <class GV>
    using IsGridView = Std::disjunction<
      std::is_same<std::decay_t<GV>,typename HostGrid::LeafGridView>,
      std::is_same<std::decay_t<GV>,typename HostGrid::LevelGridView> >;

    template <int cd>
    struct Codim : public Traits::template Codim<cd> {};

    enum { dimension = HostGrid::dimension };
    enum { dimensionworld = HostGrid::dimensionworld };
    enum { conforming = Traits::conforming };

  public:
    /// Constructor.
    template <class... GridViews,
      std::enable_if_t<Std::conjunction<IsGridView<GridViews>...>::value, int> = 0>
    MultiGridView (GridViews&&... gridViews)
      : gridViews_{std::forward<GridViews>(gridViews)...}
    {}

    template <class GridView,
      std::enable_if_t<IsGridView<GridView>::value, int> = 0>
    MultiGridView (const std::vector<GridView>& gridViews)
      : gridViews_(gridViews.begin(), gridViews.end())
    {}

    template <class Iter,
      std::enable_if_t<IsGridView<typename std::iterator_traits<Iter>::value_type>::value, int> = 0>
    MultiGridView (Iter first, Iter last)
      : gridViews_(first, last)
    {}

    template <class Iter,
      std::enable_if_t<IsGridView<typename std::iterator_traits<Iter>::value_type>::value, int> = 0>
    MultiGridView (const IteratorRange<Iter>& gridViews)
      : gridViews_(gridViews.begin(), gridViews.end())
    {}

    /// Obtain a const reference to the underlying hierarchic grid
    const HostGrid& grid (std::size_t idx) const
    {
      return std::visit([](auto const& gv) { return gv.grid(); }, gridViews_[idx]);
    }

    /// Obtain the level-indexSet
    // NOTE: IndexSet is one of {LeafIndexSet, LevelIndexSet}
    // NOTE: do not return a reference, but a reference wrapper
    IndexSet indexSet (std::size_t idx) const
    {
      return std::visit([](auto const& gv) -> IndexSetTypes { return &gv.indexSet(); }, gridViews_[idx]);
    }

    /// Obtain number of entities in a given codimension
    int size (std::size_t idx, int codim) const
    {
      return std::visit([codim](auto const& gv) { return gv.size(codim); }, gridViews_[idx]);
    }

    /// Obtain number of entities with a given geometry type
    int size (std::size_t idx, const GeometryType& type) const
    {
      return std::visit([&type](auto const& gv) { return gv.size(type); }, gridViews_[idx]);
    }

    /// Obtain begin iterator for this view
    template <int cd, PartitionIteratorType pit = All_Partition>
    typename Codim<cd>::template Partition<pit>::Iterator begin () const
    {
      static_assert(cd == 0, "Implemented for codim == 0 only");
147
      return MultiIterator<cd,pit,HostGrid>(tag::begin_iterator{}, gridViews_);
148 149 150 151 152 153 154
    }

    /// Obtain end iterator for this view
    template <int cd, PartitionIteratorType pit = All_Partition>
    typename Codim<cd>::template Partition<pit>::Iterator end () const
    {
      static_assert(cd == 0, "Implemented for codim == 0 only");
155
      return MultiIterator<cd,pit,HostGrid>(tag::end_iterator{}, gridViews_);
156 157 158 159 160 161
    }

    /// Obtain begin intersection iterator with respect to this view
    // NOTE: IntersectionIterator is one of {LeafIntersectionIterator, LevelIntersectionIterator}
    IntersectionIterator ibegin (std::size_t idx, const typename Codim<0>::Entity& entity) const
    {
Praetorius, Simon's avatar
Praetorius, Simon committed
162 163
      using II = IntersectionIterator;
      return std::visit([&entity](auto const& gv) -> II { return gv.ibegin(entity); }, gridViews_[idx]);
164 165 166 167 168 169
    }

    /// Obtain end intersection iterator with respect to this view
    // NOTE: IntersectionIterator is one of {LeafIntersectionIterator, LevelIntersectionIterator}
    IntersectionIterator iend (std::size_t idx, const typename Codim<0>::Entity& entity) const
    {
Praetorius, Simon's avatar
Praetorius, Simon committed
170 171
      using II = IntersectionIterator;
      return std::visit([&entity](auto const& gv) -> II { return gv.iend(entity); }, gridViews_[idx]);
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
    }

    /// Obtain collective communication object
    const CollectiveCommunication& comm (std::size_t idx) const
    {
      return std::visit([](auto const& gv) -> const auto& { return gv.comm(); }, gridViews_[idx]);
    }

    /// Return size of the overlap region for a given codim on the grid view.
    int overlapSize (std::size_t idx, int codim) const
    {
      return std::visit([codim](auto const& gv) { return gv.overlapSize(codim); }, gridViews_[idx]);
    }

    /// Return size of the ghost region for a given codim on the grid view.
    int ghostSize (std::size_t idx, int codim) const
    {
      return std::visit([codim](auto const& gv) { return gv.ghostSize(codim); }, gridViews_[idx]);
    }

    /// Communicate data on this view
    template <class DataHandleImp, class DataType>
    void communicate (std::size_t idx,
                      CommDataHandleIF<DataHandleImp, DataType>& data,
                      InterfaceType iftype,
                      CommunicationDirection dir) const
    {
      std::visit([&data,iftype,dir](auto const& gv) { gv.communicate(data,iftype,dir); }, gridViews_[idx]);
    }

  private:
    std::vector<GridViewTypes> gridViews_;
  };

} // end namespace Dune

#endif // DUNE_MULTI_GRIDVIEW_HH