ContextGeometry.hpp 4.41 KB
Newer Older
1 2
#pragma once

3 4 5 6 7 8
#include <type_traits>

#include <dune/common/typetraits.hh>
#include <dune/common/std/optional.hh>
#include <dune/geometry/type.hh>

9 10
namespace AMDiS
{
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
  namespace Impl
  {
    template <class E, class = Dune::void_t<>>
    struct ContextTypes
    {
      using Entity = E;
      using LocalGeometry = typename E::Geometry;
    };

    // specialization for intersections
    template <class I>
    struct ContextTypes<I, Dune::void_t<decltype(std::declval<I>().inside())>>
    {
      using Entity = typename I::Entity;
      using LocalGeometry = typename I::LocalGeometry;
    };

  } // end namespace Impl


  /// \brief Wrapper class for element and geometry
  /**
   * A LocalContext can be either a grid entity of codim 0 (called an element)
   * or an intersection of elements. The element and its geometry may be stored
   * externally and can be passed along with the localContext object.
   * Since an intersection has a geometry (and localGeometry) different from the
   * geometry (and localGeometry) of the entity it belongs to, these objects
   * are provided as well.
39 40
   *
   * \tparam LC  LocalContext, either element or intersection
41
   **/
42
  template <class LC>
43 44
  struct ContextGeometry
  {
45
    using ContextType = Impl::ContextTypes<LC>;
46

47 48 49
  public:
    using LocalContext = LC;
    using Element = typename ContextType::Entity;
50
    using Geometry = typename Element::Geometry;
51
    using LocalGeometry = typename ContextType::LocalGeometry;
52 53 54

    using IsEntity = std::is_same<Element, LocalContext>;

55 56 57 58 59
    enum {
      dim = Geometry::mydimension,    //< the dimension of the grid element
      dow = Geometry::coorddimension  //< the dimension of the world
    };

60 61 62 63 64
    /// Constructor. Stores pointer to localContext, element, and geometry.
    ContextGeometry(LocalContext const& localContext, Element const& element, Geometry const& geometry)
      : localContext_(&localContext)
      , element_(&element)
      , geometry_(&geometry)
65 66
    {}

67
  public:
68
    /// Return the bound element (entity of codim 0)
69
    Element const& element() const
70
    {
71
      return *element_;
72 73
    }

74
    /// Return the LocalContext, either the element or an intersection.
75 76 77 78 79
    LocalContext const& localContext() const
    {
      return *localContext_;
    }

80
    /// Return the geometry of the \ref Element
81 82 83 84 85
    Geometry const& geometry() const
    {
      return *geometry_;
    }

86
    /// Return the geometry of the element, or geometryInInside of the intersection
87 88
    LocalGeometry const& localGeometry() const
    {
89
      return localGeometry_impl(IsEntity{});
90 91 92 93 94
    }


  public:

95
    /// Coordinate `p` given in `localGeometry`, transformed to coordinate in geometry of the LocalContext.
96
    template <class Coordinate>
97
    decltype(auto) local(Coordinate const& p) const
98
    {
99
      return local_impl(p, IsEntity{});
100 101 102 103 104 105
    }

    /// Transformation of coordinate `p` given in `localGeometry` to world space coordinates.
    template <class Coordinate>
    decltype(auto) global(Coordinate const& p) const
    {
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
      return geometry_->global(p);
    }

    /// Return the geometry-type of the localContext
    Dune::GeometryType type() const
    {
      return localContext_->type();
    }

    /// The integration element from the `localGeometry`, the quadrature points are
    /// defined in.
    template <class Coordinate>
    auto integrationElement(Coordinate const& p) const
    {
      return localGeometry().integrationElement(p);
121 122 123 124 125 126
    }

  private: // implementation detail

    // position for elements
    template <class Coordinate>
127
    Coordinate const& local_impl(Coordinate const& p, std::true_type) const
128 129 130 131 132 133
    {
      return p;
    }

    // position for intersection
    template <class Coordinate>
134
    auto local_impl(Coordinate const& p, std::false_type) const
135 136 137 138 139
    {
      return localGeometry().global(p);
    }

    // local-geometry is the same as geometry
140
    Geometry const& localGeometry_impl(std::true_type) const
141 142 143 144 145
    {
      return *geometry_;
    }

    // local-geometry of intersection in inside element
146
    LocalGeometry const& localGeometry_impl(std::false_type) const
147
    {
148 149 150 151
      if (!localGeometry_)
        localGeometry_.emplace(localContext_->geometryInInside());

      return *localGeometry_;
152 153
    }

154 155 156 157 158 159
  private:
    LocalContext const* localContext_;
    Element const* element_;
    Geometry const* geometry_;

    // The localGeometry may be constructed only if needed
160
    mutable Dune::Std::optional<LocalGeometry> localGeometry_;
161 162 163
  };

} // end namespace AMDiS