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

#include <memory>
#include <type_traits>
Praetorius, Simon's avatar
Praetorius, Simon committed
#include <vector>

#include <dune/common/hybridutilities.hh>
#include <dune/common/to_unique_ptr.hh>
#include <dune/common/version.hh>
#include <dune/common/std/type_traits.hh>
Praetorius, Simon's avatar
Praetorius, Simon committed
#include <dune/grid/common/gridfactory.hh>

#include "multimesh.hh"

namespace Dune
{
  /** \brief specialization of the generic GridFactory for MultiMesh
   *  \ingroup GridFactory
   */
  template <class HostGrid>
  class GridFactory<MultiMesh<HostGrid> >
      : public GridFactoryInterface<MultiMesh<HostGrid> >
  {
  public:
    /// Type of grid this factory is for
    using Grid = MultiMesh<HostGrid>;

    /// Type of (scalar) coordinates
    using ctype = typename Grid::ctype;

    /// dimension of the grid
    static const int dimension = Grid::dimension;

    /// dimension of the world
    static const int dimensionworld = Grid::dimensionworld;

    using LocalCoordinate = FieldVector<ctype, dimension>;
    using GlobalCoordinate = FieldVector<ctype, dimensionworld>;

    using BoundarySegment = Dune::BoundarySegment<dimension, dimensionworld>;
    using ElementParametrization = VirtualFunction<LocalCoordinate, GlobalCoordinate>;
Praetorius, Simon's avatar
Praetorius, Simon committed

  public:
    /// \brief Constructor
    /**
     * \param[in]  n     The number of grids to construct
     * \param[in]  args  Additional parameters passed to the constructor of the
     *                   hostgridfactory
Praetorius, Simon's avatar
Praetorius, Simon committed
     **/
    template <class... Args>
    explicit GridFactory (std::size_t n, Args&&... args)
    {
      for (std::size_t i = 0; i < n; ++i)
        gridFactories_.emplace_back(new GridFactory<HostGrid>{args...});
Praetorius, Simon's avatar
Praetorius, Simon committed

    // initialize at least 1 grid
    GridFactory ()
      : GridFactory{1}
    {}

    /// \brief Insert a vertex into the macro grid
Praetorius, Simon's avatar
Praetorius, Simon committed
    /**
     *  \param[in]  pos  Position of the vertex (in world coordinates)
Praetorius, Simon's avatar
Praetorius, Simon committed
     **/
    virtual void insertVertex (const GlobalCoordinate& pos) override
Praetorius, Simon's avatar
Praetorius, Simon committed
    {
      for (auto& gridFactory : gridFactories_)
        gridFactory->insertVertex(pos);
    /// \brief Insert an element into the coarse grid
Praetorius, Simon's avatar
Praetorius, Simon committed
    /**
     *  \param[in]  type      GeometryType of the new element
     *  \param[in]  vertices  Indices of the element vertices
Praetorius, Simon's avatar
Praetorius, Simon committed
     **/
    virtual void insertElement (const GeometryType& type,
                                const std::vector<unsigned int>& vertices) override
Praetorius, Simon's avatar
Praetorius, Simon committed
    {
      for (auto& gridFactory : gridFactories_)
        gridFactory->insertElement(type, vertices);

    template <class GF>
    using HasInsertElement = decltype( std::declval<GF>().insertElement(
      std::declval<GeometryType>(),
      std::declval<std::vector<unsigned int>>(),
      std::declval<std::shared_ptr<ElementParametrization>>()) );

Praetorius, Simon's avatar
Praetorius, Simon committed
    /// \brief Insert a parametrized element into the coarse grid
    /**
     *   \param[in] type      The GeometryType of the new element
     *   \param[in] vertices  The vertices of the new element
     *   \param[in] param     A function prescribing the shape of this element
Praetorius, Simon's avatar
Praetorius, Simon committed
     **/
    virtual void insertElement (
        const GeometryType& type,
        const std::vector<unsigned int>& vertices,
        const std::shared_ptr<ElementParametrization>& param) override
    {
      Hybrid::ifElse(Std::is_detected<HasInsertElement, GridFactory<HostGrid>>{},
      [&](auto id) {
        for (auto& gridFactory : gridFactories_)
          id(gridFactory)->insertElement(type, vertices, param);
      });
    }

    /// \brief Insert a boundary segment into the macro grid
Praetorius, Simon's avatar
Praetorius, Simon committed
    /**
     *  Only influences the ordering of the boundary segments
     *  \param[in]  vertices  Vertex indices of boundary face
Praetorius, Simon's avatar
Praetorius, Simon committed
     **/
    virtual void insertBoundarySegment (
        const std::vector<unsigned int>& vertices) override
Praetorius, Simon's avatar
Praetorius, Simon committed
    {
      for (auto& gridFactory : gridFactories_)
        gridFactory->insertBoundarySegment(vertices);

    template <class GF>
    using HasInsertBoundarySegment = decltype( std::declval<GF>().insertBoundarySegment(
      std::declval<std::vector<unsigned int>>(),
      std::declval<std::shared_ptr<BoundarySegment>>()) );

    /** \brief Insert a shaped boundary segment into the macro grid
Praetorius, Simon's avatar
Praetorius, Simon committed
     *
     *  \param[in]  vertices         Vertex indices of boundary face
     *  \param[in]  boundarySegment  Geometric realization of shaped boundary
Praetorius, Simon's avatar
Praetorius, Simon committed
     */
    virtual void insertBoundarySegment (
        const std::vector<unsigned int>& vertices,
        const std::shared_ptr<BoundarySegment>& boundarySegment) override
Praetorius, Simon's avatar
Praetorius, Simon committed
    {
      Hybrid::ifElse(Std::is_detected<HasInsertBoundarySegment, GridFactory<HostGrid>>{},
      [&](auto id) {
        for (auto& gridFactory : gridFactories_)
          id(gridFactory)->insertBoundarySegment(vertices, boundarySegment);
    /// \brief Finalize grid creation and hand over the grid
Praetorius, Simon's avatar
Praetorius, Simon committed
    /**
     * Create n copies of the grid and store it in unique_pointers
     * inside the multimesh grid.
     **/
#if DUNE_VERSION_LTE(DUNE_GRID,2,7)
Praetorius, Simon's avatar
Praetorius, Simon committed
    virtual Grid* createGrid () override
    {
      Grid* multimesh = new Grid{};
      for (auto& gridFactory : gridFactories_)
        multimesh->grids_.emplace_back(gridFactory->createGrid());
Praetorius, Simon's avatar
Praetorius, Simon committed
      return multimesh;
    }
#else
    virtual ToUniquePtr<Grid> createGrid () override
    {
      std::unique_ptr<Grid> multimesh{std::make_unique<Grid>()};
      for (auto& gridFactory : gridFactories_)
        multimesh->grids_.emplace_back(gridFactory->createGrid());
      return std::move(multimesh);
    }
#endif
Praetorius, Simon's avatar
Praetorius, Simon committed

  private:
    std::vector<std::unique_ptr<GridFactory<HostGrid>>> gridFactories_;
Praetorius, Simon's avatar
Praetorius, Simon committed
  };

} // end namespace Dune

#endif // DUNE_MULTIMESH_GRIDFACTORY_HH