#pragma once #include #include #include #include namespace AMDiS { namespace Impl { template > struct ContextTypes { using Entity = E; using LocalGeometry = typename E::Geometry; }; // specialization for intersections template struct ContextTypes().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. * * \tparam LC LocalContext, either element or intersection **/ template struct ContextGeometry { using ContextType = Impl::ContextTypes; public: using LocalContext = LC; using Element = typename ContextType::Entity; using Geometry = typename Element::Geometry; using LocalGeometry = typename ContextType::LocalGeometry; using IsEntity = std::is_same; enum { dim = Geometry::mydimension, //< the dimension of the grid element dow = Geometry::coorddimension //< the dimension of the world }; /// Constructor. Stores pointer to localContext, element, and geometry. ContextGeometry(LocalContext const& localContext, Element const& element, Geometry const& geometry) : localContext_(&localContext) , element_(&element) , geometry_(&geometry) {} public: /// Return the bound element (entity of codim 0) Element const& element() const { return *element_; } /// Return the LocalContext, either the element or an intersection. LocalContext const& localContext() const { return *localContext_; } /// Return the geometry of the \ref Element Geometry const& geometry() const { return *geometry_; } /// Return the geometry of the element, or geometryInInside of the intersection LocalGeometry const& localGeometry() const { return localGeometry_impl(IsEntity{}); } public: /// Coordinate `p` given in `localGeometry`, transformed to coordinate in geometry of the LocalContext. template decltype(auto) local(Coordinate const& p) const { return local_impl(p, IsEntity{}); } /// Transformation of coordinate `p` given in `localGeometry` to world space coordinates. template decltype(auto) global(Coordinate const& p) const { 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 auto integrationElement(Coordinate const& p) const { return localGeometry().integrationElement(p); } private: // implementation detail // position for elements template Coordinate const& local_impl(Coordinate const& p, std::true_type) const { return p; } // position for intersection template auto local_impl(Coordinate const& p, std::false_type) const { return localGeometry().global(p); } // local-geometry is the same as geometry Geometry const& localGeometry_impl(std::true_type) const { return *geometry_; } // local-geometry of intersection in inside element LocalGeometry const& localGeometry_impl(std::false_type) const { if (!localGeometry_) localGeometry_.emplace(localContext_->geometryInInside()); return *localGeometry_; } private: LocalContext const* localContext_; Element const* element_; Geometry const* geometry_; // The localGeometry may be constructed only if needed mutable Dune::Std::optional localGeometry_; }; } // end namespace AMDiS