Skip to content
Snippets Groups Projects
intersection.hh 5.71 KiB
Newer Older
Stenger, Florian's avatar
Stenger, Florian committed
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_CURVED_SURFACE_GRID_INTERSECTION_HH
#define DUNE_CURVED_SURFACE_GRID_INTERSECTION_HH
Stenger, Florian's avatar
Stenger, Florian committed

#include <type_traits>
#include <utility>

#include <dune/common/fvector.hh>
#include <dune/common/std/optional.hh>
#include <dune/geometry/referenceelements.hh>
Stenger, Florian's avatar
Stenger, Florian committed

namespace Dune
{
  namespace CGeo
Stenger, Florian's avatar
Stenger, Florian committed
  {

    // Intersection
    // ------------

    template< class Grid, class HostIntersection >
    class Intersection
    {
      using HostGeometry = typename HostIntersection::Geometry;
      using HostLocalGeometry = typename HostIntersection::LocalGeometry;
Stenger, Florian's avatar
Stenger, Florian committed

      using Traits = typename std::remove_const_t<Grid>::Traits;
Stenger, Florian's avatar
Stenger, Florian committed

    public:
      using ctype = typename Traits::ctype;
Stenger, Florian's avatar
Stenger, Florian committed

      static const int dimension = Traits::dimension;
      static const int dimensionworld = Traits::dimensionworld;

      using Entity = typename Traits::template Codim<0>::Entity;
      using Geometry = typename Traits::template Codim<1>::Geometry;
      using LocalGeometry = typename Traits::template Codim<1>::LocalGeometry;
      using ElementGeometry = typename Traits::template Codim<0>::Geometry;
Stenger, Florian's avatar
Stenger, Florian committed

    private:
      using EntityImpl = typename Traits::template Codim<0>::EntityImpl;
      using GeometryImpl = typename Traits::template Codim<1>::GeometryImpl;
      using ElementGeometryImpl = typename Traits::template Codim<0>::GeometryImpl;
Stenger, Florian's avatar
Stenger, Florian committed

    public:
      Intersection() = default;
Stenger, Florian's avatar
Stenger, Florian committed

      template <class HI>
      Intersection (HI&& hostIntersection, const ElementGeometryImpl& insideGeo, const Grid& grid)
        : hostIntersection_(std::forward<HI>(hostIntersection))
        , insideGeo_ (insideGeo)
        , grid_(&grid)
Stenger, Florian's avatar
Stenger, Florian committed
      {}

      bool equals (const Intersection& other) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        return hostIntersection_ == other.hostIntersection_;
      }

      explicit operator bool () const { return bool(hostIntersection_); }
Stenger, Florian's avatar
Stenger, Florian committed

      Entity inside () const
      {
        return EntityImpl(grid(), hostIntersection().inside());
Stenger, Florian's avatar
Stenger, Florian committed
      }

      Entity outside () const
      {
        return EntityImpl(grid(), hostIntersection().outside());
Stenger, Florian's avatar
Stenger, Florian committed
      }

      bool boundary () const { return hostIntersection().boundary(); }

      bool conforming () const { return hostIntersection().conforming(); }

      bool neighbor () const { return hostIntersection().neighbor(); }

      size_t boundarySegmentIndex () const
      {
        return hostIntersection().boundarySegmentIndex();
      }

      LocalGeometry geometryInInside () const
      {
        return hostIntersection().geometryInInside();
      }

      LocalGeometry geometryInOutside () const
      {
        return hostIntersection().geometryInOutside();
      }

      //! Construct a curved geometry for the intersection.
      /**
       * This does only work properly if the intersection is a full subEntity of inside and
       * outside and the trace of the local basis functions along that subEntity is again
       * a local basis function of codim=1
       **/
Stenger, Florian's avatar
Stenger, Florian committed
      Geometry geometry () const
      {
        if (!geo_)
Stenger, Florian's avatar
Stenger, Florian committed
        {
          auto ff = [f=grid().coordFunction(),geo=hostIntersection().geometry()](const auto& local) {
            return f(geo.global(local));
          };
          geo_ = GeometryImpl(type(), ff);
Stenger, Florian's avatar
Stenger, Florian committed
        }
        return Geometry(*geo_);
Stenger, Florian's avatar
Stenger, Florian committed
      }

      GeometryType type () const { return hostIntersection().type(); }

      int indexInInside () const
      {
        return hostIntersection().indexInInside();
      }

      int indexInOutside () const
      {
        return hostIntersection().indexInOutside();
      }

      FieldVector<ctype, dimensionworld> outerNormal (const FieldVector<ctype, dimension-1>& local) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        return outerNormalImpl(local, false);
Stenger, Florian's avatar
Stenger, Florian committed
      }

      FieldVector<ctype, dimensionworld> integrationOuterNormal (const FieldVector<ctype, dimension-1>& local) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        return outerNormalImpl(local, true);
Stenger, Florian's avatar
Stenger, Florian committed
      }

      FieldVector<ctype, dimensionworld> unitOuterNormal (const FieldVector<ctype, dimension-1>& local) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        FieldVector<ctype, dimensionworld> normal = outerNormal(local);
        return normal /= normal.two_norm();
Stenger, Florian's avatar
Stenger, Florian committed
      }

      FieldVector<ctype, dimensionworld> centerUnitOuterNormal () const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        auto refFace = referenceElement<ctype, dimension-1>(type());
        return unitOuterNormal(refFace.position(0, 0));
Stenger, Florian's avatar
Stenger, Florian committed
      }

      const HostIntersection& hostIntersection () const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        return hostIntersection_;
      }

      const Grid& grid () const { return *grid_; }

    private:
      FieldVector<ctype, dimensionworld>
      outerNormalImpl (const FieldVector<ctype, dimension-1>& local, bool scaleByIntegrationElement) const
      {
        const LocalGeometry geoInInside = geometryInInside();
        const int idxInInside = indexInInside();
        auto refElement = referenceElement<ctype, dimension>(insideGeo_->type());

        FieldVector<ctype, dimension> x(geoInInside.global(local));
        const auto& jit = insideGeo_->jacobianInverseTransposed(x);
        FieldVector<ctype, dimension> refNormal = refElement.integrationOuterNormal(idxInInside);

        FieldVector<ctype, dimensionworld> normal;
        jit.mv(refNormal, normal);

        if (scaleByIntegrationElement) {
          if (!conforming())
            normal *= geoInInside.volume() / refElement.template geometry<1>(idxInInside).volume();
          // normal *= jit.detInv(); TODO: what is detInv()?
Stenger, Florian's avatar
Stenger, Florian committed

    private:
      HostIntersection hostIntersection_;
      Std::optional<ElementGeometryImpl> insideGeo_;
      mutable Std::optional<GeometryImpl> geo_;
      const Grid* grid_;
Stenger, Florian's avatar
Stenger, Florian committed
    };

  } // namespace CGeo
Stenger, Florian's avatar
Stenger, Florian committed
} // namespace Dune

#endif // DUNE_CURVED_SURFACE_GRID_INTERSECTION_HH