Newer
Older
// -*- 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 <dune/common/to_unique_ptr.hh>
#include <dune/common/version.hh>
#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>;
public:
/// \brief Constructor
/**
* \param[in] n The number of grids to construct
* \param[in] args Additional parameters passed to the constructor of the
* hostgridfactory
**/
template <class... Args>
explicit GridFactory (std::size_t n, Args&&... args)
gridFactories_.emplace_back(new GridFactory<HostGrid>{args...});
// initialize at least 1 grid
GridFactory ()
: GridFactory{1}
{}
/// \brief Insert a vertex into the macro grid
* \param[in] pos Position of the vertex (in world coordinates)
virtual void insertVertex (const GlobalCoordinate& pos) override
gridFactory->insertVertex(pos);
/// \brief Insert an element into the coarse grid
/**
* \param[in] type GeometryType of the new element
* \param[in] vertices Indices of the element vertices
**/
virtual void insertElement (const GeometryType& type,
const std::vector<unsigned int>& vertices) override
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>>()) );
/// \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
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
/**
* Only influences the ordering of the boundary segments
* \param[in] vertices Vertex indices of boundary face
virtual void insertBoundarySegment (
const std::vector<unsigned int>& vertices) override
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
* \param[in] vertices Vertex indices of boundary face
* \param[in] boundarySegment Geometric realization of shaped boundary
virtual void insertBoundarySegment (
const std::vector<unsigned int>& vertices,
const std::shared_ptr<BoundarySegment>& boundarySegment) override
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
/**
* Create n copies of the grid and store it in unique_pointers
* inside the multimesh grid.
**/
#if DUNE_VERSION_LTE(DUNE_GRID,2,7)
virtual Grid* createGrid () override
{
Grid* multimesh = new Grid{};
for (auto& gridFactory : gridFactories_)
multimesh->grids_.emplace_back(gridFactory->createGrid());
#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
std::vector<std::unique_ptr<GridFactory<HostGrid>>> gridFactories_;
#endif // DUNE_MULTIMESH_GRIDFACTORY_HH