#pragma once #include #include #include #if ! DUNE_VERSION_GT(DUNE_GRID,2,6) #include #endif namespace Dune { template struct CubedWrapper : public GridType {}; template class GridFactory> : public GridFactoryInterface { using Self = GridFactory; using Super = GridFactoryInterface; using ctype = typename GridType::ctype; enum { dim = GridType::dimension }; enum { dimworld = GridType::dimensionworld }; public: template = 0> GridFactory (Args&&... args) : factory_(std::make_shared>(std::forward(args)...)) {} GridFactory (GridFactory& factory) : factory_(stackobject_to_shared_ptr(factory)) {} /// \brief Insert a vertex into the coarse grid void insertVertex (const FieldVector& pos) override { factory_->insertVertex(pos); } /// \brief Insert simplex elements into the coarse grid /** * Creates a simplex subdividion of the cube element. * * \param type The GeometryType of the box grid * \param vertices Indices of the cube corners **/ void insertElement (const GeometryType& type, const std::vector& vertices) override { // triangulation of reference cube static const auto reference_cubes = std::make_tuple( std::array, 1>{std::array{0,1}}, std::array, 2>{std::array{3,0,1}, std::array{0,3,2}}, std::array, 6>{std::array{0,7,3,1}, std::array{0,7,5,1}, std::array{0,7,5,4}, std::array{0,7,3,2}, std::array{0,7,6,2}, std::array{0,7,6,4}} ); assert(type == GeometryTypes::cube(dim)); auto const& simplices = std::get(reference_cubes); thread_local std::vector corners(dim+1); for (auto const& simplex : simplices) { for (std::size_t i = 0; i < simplex.size(); ++i) corners[i] = vertices[simplex[i]]; factory_->insertElement(GeometryTypes::simplex(dim), corners); } } using Super::insertElement; /// \brief insert a boundary segment // TODO: maybe split boundary segment in simplices void insertBoundarySegment (const std::vector& vertices) override { factory_->insertBoundarySegment(vertices); } using Super::insertBoundarySegment; /// \brief Finalize grid creation and hand over the grid #if DUNE_VERSION_GT(DUNE_GRID,2,6) ToUniquePtr createGrid () override #else GridType* createGrid () override #endif { return factory_->createGrid(); } private: std::shared_ptr> factory_; }; } // end namespace Dune namespace AMDiS { template class MacroGridFactory { using ctype = typename GridType::ctype; enum { dim = GridType::dimension }; enum { dimworld = GridType::dimensionworld }; public: #if DUNE_VERSION_GT(DUNE_GRID,2,6) /// \brief insert structured simplex grid into grid factory static std::unique_ptr createSimplexGrid (Dune::GridFactory& originalFactory, const Dune::FieldVector& lowerLeft, const Dune::FieldVector& upperRight, const std::array& numElements) { Dune::GridFactory> factory(originalFactory); Dune::StructuredGridFactory>::createCubeGrid(factory, lowerLeft, upperRight, numElements); return std::unique_ptr(factory.createGrid()); } #endif /// \brief Create a structured simplex grid static std::unique_ptr createSimplexGrid (const Dune::FieldVector& lowerLeft, const Dune::FieldVector& upperRight, const std::array& numElements) { Dune::GridFactory> factory; #if DUNE_VERSION_GT(DUNE_GRID,2,6) Dune::StructuredGridFactory>::createCubeGrid(factory, lowerLeft, upperRight, numElements); #else // fallback implementation using temporary YaspGrid using TempGrid = Dune::YaspGrid>; auto grid = Dune::StructuredGridFactory::createCubeGrid(lowerLeft, upperRight, numElements); for (auto const& v : vertices(grid->leafGridView())) factory.insertVertex(v.geometry().corner(0)); auto const& indexSet = grid->leafIndexSet(); for (auto const& e : elements(grid->leafGridView())) { thread_local std::vector vertices; vertices.resize(e.subEntities(dim)); for (unsigned int i = 0; i < e.subEntities(dim); ++i) vertices[i] = indexSet.subIndex(e,i,dim); factory.insertElement(Dune::GeometryTypes::cube(dim), vertices); } #endif return std::unique_ptr(factory.createGrid()); } }; } // end namespace AMDiS