Skip to content
Snippets Groups Projects
entity.hh 13.8 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_ENTITY_HH
#define DUNE_CURVED_SURFACE_GRID_ENTITY_HH
Stenger, Florian's avatar
Stenger, Florian committed

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

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

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

    // Internal Forward Declarations
    // -----------------------------

    /** \class EntityBase
     *  \brief actual implementation of the entity
     *  \ingroup CurvedGeo
Stenger, Florian's avatar
Stenger, Florian committed
     *
     *  \tparam  codim  codimension of the entity
     *  \tparam  Grid   CurvedSurfaceGrid, this entity belongs to
     */
    template< int codim, class Grid >
Stenger, Florian's avatar
Stenger, Florian committed
    class EntityBase;

    /** \class Entity
     *  \brief DUNE-conform implementation of the entity
     *  \ingroup CurvedGeo
Stenger, Florian's avatar
Stenger, Florian committed
     *
     *  This class merely changes the template parameters of the entity to make
     *  DUNE happy. The actual implementation of the entity can be found in
     *  EntityBase.
     *
     *  \tparam  codim  codimension of the entity
     *  \tparam  dim    dimension of the Grid (redundant information)
     *  \tparam  Grid   CurvedSurfaceGrid, this entity belongs to
     */
    template< int codim, int dim, class Grid >
    class Entity;



    // External Forward Declarations
    // -----------------------------

    template< class Grid >
    class HierarchicIterator;

    template< class Grid, class HostIntersectionIterator >
    class IntersectionIterator;



    // EntityBase (real)
    // -----------------

    /** \copydoc EntityBase
     *
     *  This specialization implements the case, where the host grid provides
     *  the entity for this codimension, i.e., \em fake = \b false.
     *
     *  \nosubgrouping
     */
    template< int codim, class Grid >
    class EntityBase
Stenger, Florian's avatar
Stenger, Florian committed
    {
      using Traits = typename std::remove_const_t<Grid>::Traits;
Stenger, Florian's avatar
Stenger, Florian committed

    public:
      /** \name Attributes
       *  \{ */

      //! codimensioon of the entity
      static const int codimension = codim;
      //! dimension of the grid
      static const int dimension = Traits::dimension;
      //! dimension of the entity
      static const int mydimension = dimension - codimension;
      //! dimension of the world
      static const int dimensionworld = Traits::dimensionworld;

      /** \} */

      /** \name Types Required by DUNE
       *  \{ */

      //! coordinate type of the grid
      using ctype = typename Traits::ctype;
Stenger, Florian's avatar
Stenger, Florian committed

      //! type of corresponding geometry
      using Geometry = typename Traits::template Codim<codimension>::Geometry;

Stenger, Florian's avatar
Stenger, Florian committed
      /** \} */

    private:
      using HostGrid = typename Traits::HostGrid;
Stenger, Florian's avatar
Stenger, Florian committed

    public:
      /** \name Host Types
       *  \{ */

      //! type of corresponding host entity
      using HostEntity = typename HostGrid::template Codim<codimension>::Entity;
Stenger, Florian's avatar
Stenger, Florian committed

      //! type of corresponding entity seed
      using EntitySeed = typename Traits::template Codim<codimension>::EntitySeed;
Stenger, Florian's avatar
Stenger, Florian committed

      //! type of host elements, i.e., of host entities of codimension 0
      using HostElement = typename HostGrid::template Codim<0>::Entity;
Stenger, Florian's avatar
Stenger, Florian committed

      /** \} */
Stenger, Florian's avatar
Stenger, Florian committed

    private:
      using GeometryImpl = typename Traits::template Codim<codimension>::GeometryImpl;
      using HostGeometry = typename HostGrid::template Codim<codimension>::Geometry;
Stenger, Florian's avatar
Stenger, Florian committed

    public:
      /** \name Construction, Initialization and Destruction
       *  \{ */

      EntityBase () = default;
Stenger, Florian's avatar
Stenger, Florian committed

      // Construct the entity from an entity seed
      EntityBase (const Grid& grid, const EntitySeed& seed)
        : hostEntity_(grid.hostGrid().entity(seed.impl().hostEntitySeed()))
        , grid_(&grid)
Stenger, Florian's avatar
Stenger, Florian committed
      {}

      // construct the entity from a subentity of a host-entity
      EntityBase (const Grid& grid, const HostElement& hostElement, int i)
        : hostEntity_(hostElement.template subEntity<codim>(i))
        , grid_(&grid)
Stenger, Florian's avatar
Stenger, Florian committed
      {}

      // construct the entity from a host-entity and a transformed geometry
      EntityBase (const GeometryImpl& geo, const HostEntity& hostEntity)
        : hostEntity_(hostEntity)
        , grid_(&geo.grid())
        , geo_(geo)
Stenger, Florian's avatar
Stenger, Florian committed
      {}

      // construct the entity from a host-entity and a transformed geometry
      EntityBase (const GeometryImpl& geo, HostEntity&& hostEntity)
        : hostEntity_(std::move(hostEntity))
        , grid_(&geo.grid())
        , geo_(geo)
Stenger, Florian's avatar
Stenger, Florian committed
      {}

      // construct the entity from a host-entity
      EntityBase (const Grid& grid, const HostEntity& hostEntity)
        : hostEntity_(hostEntity)
        , grid_(&grid)
Stenger, Florian's avatar
Stenger, Florian committed
      {}

      // construct the entity from a host-entity
      EntityBase (const Grid& grid, HostEntity&& hostEntity)
        : hostEntity_(std::move(hostEntity))
        , grid_(&grid)
Stenger, Florian's avatar
Stenger, Florian committed
      {}

      /** \} */

      //! compare two entities
      bool equals (const EntityBase& other) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        return hostEntity_ == other.hostEntity_;
      }

    public:
      /** \name Methods Shared by Entities of All Codimensions
       *  \{ */

      //! obtain the name of the corresponding reference element
      /**
Stenger, Florian's avatar
Stenger, Florian committed
       *  This type can be used to access the DUNE reference element.
       */
      GeometryType type () const
      {
        return hostEntity().type();
      }

      //! obtain the level of this entity
Stenger, Florian's avatar
Stenger, Florian committed
      int level () const
      {
        return hostEntity().level();
      }

      //! obtain the partition type of this entity
Stenger, Florian's avatar
Stenger, Florian committed
      PartitionType partitionType () const
      {
        return hostEntity().partitionType();
      }

      GeometryImpl makeGeometry () const
      {
        auto ff = [f=grid().coordFunction(),geo=hostEntity().geometry()](const auto& local) {
          return f(geo.global(local));
        };
        return GeometryImpl(type(), ff);
      }

      //! obtain the geometry of this entity
      /**
Stenger, Florian's avatar
Stenger, Florian committed
       *  Each DUNE entity encapsulates a geometry object, representing the map
       *  from the reference element to world coordinates. Wrapping the geometry
       *  is the main objective of the CurvedSurfaceGrid.
       *
       *  The CurvedSurfaceGrid provides geometries by parametrization with local basis
       *  functions, using the CurvedGeometry.
Stenger, Florian's avatar
Stenger, Florian committed
       *
       *  \returns a new curvedgeometry object
Stenger, Florian's avatar
Stenger, Florian committed
       */
      Geometry geometry () const
      {
        if (!geo_) {
          if (grid_->useGeometryCaching())
            auto const& idSet = grid_->hostGrid().localIdSet();
            auto& cached_geo = std::get<codim>(grid_->geometryCache_)[id(idSet)];

            // if geometry is already in cache
            if (cached_geo)
              geo_ = *cached_geo;
            // otherwise cache a new constructed geometry
            else {
              geo_ = makeGeometry();
              *cached_geo = *geo_;
            }
          else
          {
            geo_ = makeGeometry();
Stenger, Florian's avatar
Stenger, Florian committed
        }

        return Geometry(*geo_);
Stenger, Florian's avatar
Stenger, Florian committed
      }

      //! obtain number of sub-entities of the current entity
      unsigned int subEntities (unsigned int cc) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        return hostEntity().subEntities( cc );
Stenger, Florian's avatar
Stenger, Florian committed
      }

      //! return EntitySeed of host grid entity
      EntitySeed seed () const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        return typename EntitySeed::Implementation(hostEntity().seed());
Stenger, Florian's avatar
Stenger, Florian committed
      }

      /** \} */


      /** \name Methods Supporting the Grid Implementation
Stenger, Florian's avatar
Stenger, Florian committed
       *  \{ */

      const Grid& grid () const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        assert(grid_);
        return *grid_;
Stenger, Florian's avatar
Stenger, Florian committed
      }

      //! return the wrapped host-entity
      const HostEntity& hostEntity () const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        return hostEntity_;
Stenger, Florian's avatar
Stenger, Florian committed
      }

      //! initiliaze an entity by a corresponding host-entity
      /**
       *  \param[in]  hostEntity  reference to the host entity
Stenger, Florian's avatar
Stenger, Florian committed
       */
      void initialize (const HostEntity& hostEntity)
Stenger, Florian's avatar
Stenger, Florian committed
      {
        hostEntity_ = hostEntity;
Stenger, Florian's avatar
Stenger, Florian committed
      }

      //! obtain the entity's index from a host IndexSet
      /**
Stenger, Florian's avatar
Stenger, Florian committed
       *  \internal This method is provided by the entity, because its
       *  implementation is different for fake and non-fake entities.
       *
       *  \param[in]  indexSet  host IndexSet to use
       */
      template< class HostIndexSet >
      typename HostIndexSet::IndexType
      index (const HostIndexSet& indexSet) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        return indexSet.template index<codimension>(hostEntity());
Stenger, Florian's avatar
Stenger, Florian committed
      }

      //! obtain the index of a subentity from a host IndexSet
      /**
Stenger, Florian's avatar
Stenger, Florian committed
       *  \internal This method is provided by the entity, because its
       *  implementation is different for fake and non-fake entities.
       *
       *  \param[in]  indexSet  host IndexSet to use
       *  \param[in]  i         number of the subentity
       *  \param[in]  cd        codimension of the subentity
       */
      template< class HostIndexSet >
      typename HostIndexSet::IndexType
      subIndex (const HostIndexSet& indexSet, int i, unsigned int cd) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        return indexSet.subIndex(hostEntity(), i, cd);
Stenger, Florian's avatar
Stenger, Florian committed
      }

      //! check whether the entity is contained in a host index set
      /**
Stenger, Florian's avatar
Stenger, Florian committed
       *  \internal This method is provided by the entity, because its
       *  implementation is different for fake and non-fake entities.
       *
       *  \param  indexSet  host IndexSet to use
       */
      template< class HostIndexSet >
      bool isContained (const HostIndexSet& indexSet) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        return indexSet.contains(hostEntity());
Stenger, Florian's avatar
Stenger, Florian committed
      }

      //! obtain the entity's id from a host IdSet
      /**
Stenger, Florian's avatar
Stenger, Florian committed
       *  \internal This method is provided by the entity, because its
       *  implementation is different for fake and non-fake entities.
       *
       *  \param  idSet  host IdSet to use
       */
      template< class HostIdSet >
      typename HostIdSet::IdType id (const HostIdSet& idSet) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        return idSet.template id<codimension>(hostEntity());
Stenger, Florian's avatar
Stenger, Florian committed
      }

      /** \} */
Stenger, Florian's avatar
Stenger, Florian committed

    private:
      HostEntity hostEntity_ = {};
      const Grid* grid_ = nullptr;
      mutable Std::optional<GeometryImpl> geo_;
Stenger, Florian's avatar
Stenger, Florian committed
    };


    // Entity
    // ------

    template< int codim, int dim, class Grid >
    class Entity
        : public EntityBase<codim, Grid>
Stenger, Florian's avatar
Stenger, Florian committed
    {
      using Super = EntityBase<codim, Grid>;
Stenger, Florian's avatar
Stenger, Florian committed

    public:
      // import constructors from base class
      using Super::Super;
Stenger, Florian's avatar
Stenger, Florian committed
    };


    // Entity for codimension 0
    // ------------------------

    template< int dim, class Grid >
    class Entity<0, dim, Grid>
        : public EntityBase<0, Grid>
Stenger, Florian's avatar
Stenger, Florian committed
    {
      using Super = EntityBase<0, Grid>;
Stenger, Florian's avatar
Stenger, Florian committed

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

    public:

      /** \name Types Required by DUNE
       *  \{ */

      //! type of corresponding local geometry
      using LocalGeometry = typename Traits::template Codim<0>::LocalGeometry;
Stenger, Florian's avatar
Stenger, Florian committed

      //! facade type for entities
      using EntityFacade = Dune::Entity<0, dim, Grid, Dune::CGeo::Entity>;
Stenger, Florian's avatar
Stenger, Florian committed

      //! type of hierarchic iterator
      using HierarchicIterator = typename Traits::HierarchicIterator;

Stenger, Florian's avatar
Stenger, Florian committed
      //! type of leaf intersection iterator
      using LeafIntersectionIterator = typename Traits::LeafIntersectionIterator;

Stenger, Florian's avatar
Stenger, Florian committed
      //! type of level intersection iterator
      using LevelIntersectionIterator = typename Traits::LevelIntersectionIterator;
Stenger, Florian's avatar
Stenger, Florian committed

      /** \} */

      // import constructors from base class
      using Super::Super;
Stenger, Florian's avatar
Stenger, Florian committed

      template< int codim >
      typename Grid::template Codim<codim>::Entity subEntity (int i) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        using EntityImpl = typename Traits::template Codim<codim>::EntityImpl;
        return EntityImpl(Super::grid(), Super::hostEntity(), i);
Stenger, Florian's avatar
Stenger, Florian committed
      }

      LevelIntersectionIterator ilevelbegin () const
      {
        using LevelIntersectionIteratorImpl = CGeo::IntersectionIterator<Grid, typename HostGrid::LevelIntersectionIterator>;
        return LevelIntersectionIteratorImpl(*this, Super::hostEntity().ilevelbegin());
Stenger, Florian's avatar
Stenger, Florian committed
      }

      LevelIntersectionIterator ilevelend () const
      {
        using LevelIntersectionIteratorImpl = CGeo::IntersectionIterator<Grid, typename HostGrid::LevelIntersectionIterator>;
        return LevelIntersectionIteratorImpl(*this, Super::hostEntity().ilevelend());
Stenger, Florian's avatar
Stenger, Florian committed
      }

      LeafIntersectionIterator ileafbegin () const
      {
        using LeafIntersectionIteratorImpl = CGeo::IntersectionIterator<Grid, typename HostGrid::LeafIntersectionIterator>;
        return LeafIntersectionIteratorImpl(*this, Super::hostEntity().ileafbegin());
Stenger, Florian's avatar
Stenger, Florian committed
      }

      LeafIntersectionIterator ileafend () const
      {
        using LeafIntersectionIteratorImpl = CGeo::IntersectionIterator<Grid, typename HostGrid::LeafIntersectionIterator>;
        return LeafIntersectionIteratorImpl(*this, Super::hostEntity().ileafend());
Stenger, Florian's avatar
Stenger, Florian committed
      }

      bool hasBoundaryIntersections () const
      {
        return Super::hostEntity().hasBoundaryIntersections();
Stenger, Florian's avatar
Stenger, Florian committed
      }

      bool isLeaf () const
      {
        return Super::hostEntity().isLeaf();
Stenger, Florian's avatar
Stenger, Florian committed
      }

      EntityFacade father () const
      {
        return Entity(Super::grid(), Super::hostEntity().father());
Stenger, Florian's avatar
Stenger, Florian committed
      }

      bool hasFather () const
      {
        return Super::hostEntity().hasFather();
Stenger, Florian's avatar
Stenger, Florian committed
      }

      LocalGeometry geometryInFather () const
      {
        return Super::hostEntity().geometryInFather();
Stenger, Florian's avatar
Stenger, Florian committed
      }

      HierarchicIterator hbegin (int maxLevel) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        using HierarchicIteratorImpl = CGeo::HierarchicIterator<Grid>;
        return HierarchicIteratorImpl(Super::grid(), Super::hostEntity().hbegin(maxLevel));
Stenger, Florian's avatar
Stenger, Florian committed
      }

      HierarchicIterator hend (int maxLevel) const
Stenger, Florian's avatar
Stenger, Florian committed
      {
        using HierarchicIteratorImpl = CGeo::HierarchicIterator<Grid>;
        return HierarchicIteratorImpl(Super::grid(), Super::hostEntity().hend(maxLevel));
Stenger, Florian's avatar
Stenger, Florian committed
      }

      bool isRegular () const
      {
        return Super::hostEntity().isRegular();
Stenger, Florian's avatar
Stenger, Florian committed
      }

      bool isNew () const
      {
        return Super::hostEntity().isNew();
Stenger, Florian's avatar
Stenger, Florian committed
      }

      bool mightVanish () const
      {
        return Super::hostEntity().mightVanish();
Stenger, Florian's avatar
Stenger, Florian committed
      }
    };

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

} // namespace Dune

#endif // DUNE_CURVED_SURFACE_GRID_ENTITY_HH