mmgridfactory.hh 5.63 KB
Newer Older
Praetorius, Simon's avatar
Praetorius, Simon committed
1 2 3 4 5 6
// -*- 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>
Praetorius, Simon's avatar
Praetorius, Simon committed
7
#include <type_traits>
Praetorius, Simon's avatar
Praetorius, Simon committed
8 9
#include <vector>

Praetorius, Simon's avatar
Praetorius, Simon committed
10
#include <dune/common/hybridutilities.hh>
11 12
#include <dune/common/to_unique_ptr.hh>
#include <dune/common/version.hh>
Praetorius, Simon's avatar
Praetorius, Simon committed
13
#include <dune/common/std/type_traits.hh>
Praetorius, Simon's avatar
Praetorius, Simon committed
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 39 40 41 42 43
#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>;
Praetorius, Simon's avatar
Praetorius, Simon committed
44
    using ElementParametrization = VirtualFunction<LocalCoordinate, GlobalCoordinate>;
Praetorius, Simon's avatar
Praetorius, Simon committed
45 46 47 48 49

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

60 61 62 63 64
    // initialize at least 1 grid
    GridFactory ()
      : GridFactory{1}
    {}

Praetorius, Simon's avatar
Praetorius, Simon committed
65
    /// \brief Insert a vertex into the macro grid
Praetorius, Simon's avatar
Praetorius, Simon committed
66
    /**
Praetorius, Simon's avatar
Praetorius, Simon committed
67
     *  \param[in]  pos  Position of the vertex (in world coordinates)
Praetorius, Simon's avatar
Praetorius, Simon committed
68
     **/
Praetorius, Simon's avatar
Praetorius, Simon committed
69
    virtual void insertVertex (const GlobalCoordinate& pos) override
Praetorius, Simon's avatar
Praetorius, Simon committed
70 71
    {
      for (auto& gridFactory : gridFactories_)
72
        gridFactory->insertVertex(pos);
Praetorius, Simon's avatar
Praetorius, Simon committed
73 74
    }

Praetorius, Simon's avatar
Praetorius, Simon committed
75
    /// \brief Insert an element into the coarse grid
Praetorius, Simon's avatar
Praetorius, Simon committed
76 77
    /**
     *  \param[in]  type      GeometryType of the new element
Praetorius, Simon's avatar
Praetorius, Simon committed
78
     *  \param[in]  vertices  Indices of the element vertices
Praetorius, Simon's avatar
Praetorius, Simon committed
79 80
     **/
    virtual void insertElement (const GeometryType& type,
Praetorius, Simon's avatar
Praetorius, Simon committed
81
                                const std::vector<unsigned int>& vertices) override
Praetorius, Simon's avatar
Praetorius, Simon committed
82 83
    {
      for (auto& gridFactory : gridFactories_)
84
        gridFactory->insertElement(type, vertices);
Praetorius, Simon's avatar
Praetorius, Simon committed
85 86
    }

Praetorius, Simon's avatar
Praetorius, Simon committed
87 88 89 90 91 92 93

    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
94 95
    /// \brief Insert a parametrized element into the coarse grid
    /**
Praetorius, Simon's avatar
Praetorius, Simon committed
96 97 98
     *   \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
99
     **/
Praetorius, Simon's avatar
Praetorius, Simon committed
100 101 102 103 104 105 106 107
    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_)
108
          id(gridFactory)->insertElement(type, vertices, param);
Praetorius, Simon's avatar
Praetorius, Simon committed
109 110 111 112
      });
    }

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

Praetorius, Simon's avatar
Praetorius, Simon committed
124 125 126 127 128 129 130

    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
131
     *
Praetorius, Simon's avatar
Praetorius, Simon committed
132 133
     *  \param[in]  vertices         Vertex indices of boundary face
     *  \param[in]  boundarySegment  Geometric realization of shaped boundary
Praetorius, Simon's avatar
Praetorius, Simon committed
134
     */
Praetorius, Simon's avatar
Praetorius, Simon committed
135 136 137
    virtual void insertBoundarySegment (
        const std::vector<unsigned int>& vertices,
        const std::shared_ptr<BoundarySegment>& boundarySegment) override
Praetorius, Simon's avatar
Praetorius, Simon committed
138
    {
Praetorius, Simon's avatar
Praetorius, Simon committed
139 140 141
      Hybrid::ifElse(Std::is_detected<HasInsertBoundarySegment, GridFactory<HostGrid>>{},
      [&](auto id) {
        for (auto& gridFactory : gridFactories_)
142
          id(gridFactory)->insertBoundarySegment(vertices, boundarySegment);
Praetorius, Simon's avatar
Praetorius, Simon committed
143
      });
Praetorius, Simon's avatar
Praetorius, Simon committed
144 145 146
    }


Praetorius, Simon's avatar
Praetorius, Simon committed
147
    /// \brief Finalize grid creation and hand over the grid
Praetorius, Simon's avatar
Praetorius, Simon committed
148 149 150 151
    /**
     * Create n copies of the grid and store it in unique_pointers
     * inside the multimesh grid.
     **/
152
#if DUNE_VERSION_LT(DUNE_GRID,2,7)
Praetorius, Simon's avatar
Praetorius, Simon committed
153 154 155 156
    virtual Grid* createGrid () override
    {
      Grid* multimesh = new Grid{};
      for (auto& gridFactory : gridFactories_)
157
        multimesh->grids_.emplace_back(gridFactory->createGrid());
Praetorius, Simon's avatar
Praetorius, Simon committed
158 159
      return multimesh;
    }
160 161 162
#else
    virtual ToUniquePtr<Grid> createGrid () override
    {
163
      auto multimesh = makeToUnique<Grid>();
164 165 166 167 168
      for (auto& gridFactory : gridFactories_)
        multimesh->grids_.emplace_back(gridFactory->createGrid());
      return std::move(multimesh);
    }
#endif
Praetorius, Simon's avatar
Praetorius, Simon committed
169 170

  private:
171
    std::vector<std::unique_ptr<GridFactory<HostGrid>>> gridFactories_;
Praetorius, Simon's avatar
Praetorius, Simon committed
172 173 174 175
  };

} // end namespace Dune

176
#endif // DUNE_MULTIMESH_GRIDFACTORY_HH