Skip to content
Snippets Groups Projects
Commit e5c95a7e authored by Timo Koch's avatar Timo Koch
Browse files

[geometry] Add FixedSizeGeometricEntitySet

and SingleGeometryEntitySet for GeometricEntitySet
with a fixed number of geometries.

Also add a unit test.
parent 21dedf5e
No related branches found
No related tags found
1 merge request!3880[geometry] Add FixedSizeGeometricEntitySet and optimize IntersectionEntitySet in the case size==1
...@@ -14,7 +14,12 @@ ...@@ -14,7 +14,12 @@
#ifndef DUMUX_GEOMETRY_GEOMETRIC_ENTITY_SET_HH #ifndef DUMUX_GEOMETRY_GEOMETRIC_ENTITY_SET_HH
#define DUMUX_GEOMETRY_GEOMETRIC_ENTITY_SET_HH #define DUMUX_GEOMETRY_GEOMETRIC_ENTITY_SET_HH
#include <array>
#include <vector>
#include <memory> #include <memory>
#include <utility>
#include <initializer_list>
#include <dune/grid/common/mcmgmapper.hh> #include <dune/grid/common/mcmgmapper.hh>
#include <dune/geometry/multilineargeometry.hh> #include <dune/geometry/multilineargeometry.hh>
#include <dumux/common/entitymap.hh> #include <dumux/common/entitymap.hh>
...@@ -98,6 +103,52 @@ private: ...@@ -98,6 +103,52 @@ private:
std::shared_ptr<const EntityMap> entityMap_; std::shared_ptr<const EntityMap> entityMap_;
}; };
} // end namespace Dumux
#ifndef DOXYGEN
namespace Dumux::Detail::GeometricEntity {
/*!
* \brief Wrapper to turn a geometry into a geometric entity
*/
template<class GeoType>
class EntityWrapper
{
public:
using Geometry = GeoType;
/*!
* \brief Constructor
*/
EntityWrapper(const Geometry& geo, const std::size_t index) : geo_(geo), index_(index) {}
/*!
* \brief Constructor
*/
EntityWrapper(Geometry&& geo, const std::size_t index) : geo_(std::move(geo)), index_(index) {}
/*!
* \brief Returns the geometry
*/
const Geometry& geometry() const
{ return geo_; }
/*!
* \brief Returns the index of the geometry
*/
std::size_t index() const
{ return index_; }
private:
Geometry geo_;
std::size_t index_;
};
} // end namespace Dumux::Detail::GeometricEntity
#endif // DOXYGEN
namespace Dumux {
/*! /*!
* \ingroup Geometry * \ingroup Geometry
* \brief An interface for a set of geometric entities * \brief An interface for a set of geometric entities
...@@ -107,43 +158,8 @@ private: ...@@ -107,43 +158,8 @@ private:
template<class GeoType> template<class GeoType>
class GeometriesEntitySet class GeometriesEntitySet
{ {
/*!
* \brief Wrapper to turn a geometry into a geometric entity
*/
class EntityWrapper
{
public:
using Geometry = GeoType;
/*!
* \brief Constructor
*/
EntityWrapper(const Geometry& geo, const std::size_t index) : geo_(geo), index_(index) {}
/*!
* \brief Constructor
*/
EntityWrapper(Geometry&& geo, const std::size_t index) : geo_(std::move(geo)), index_(index) {}
/*!
* \brief Returns the geometry
*/
const Geometry& geometry() const
{ return geo_; }
/*!
* \brief Returns the index of the geometry
*/
std::size_t index() const
{ return index_; }
private:
Geometry geo_;
std::size_t index_;
};
public: public:
using Entity = EntityWrapper; using Entity = Detail::GeometricEntity::EntityWrapper<GeoType>;
/*! /*!
* \brief Constructor for initializer_list * \brief Constructor for initializer_list
...@@ -223,6 +239,90 @@ private: ...@@ -223,6 +239,90 @@ private:
std::vector<Entity> entities_; std::vector<Entity> entities_;
}; };
/*!
* \ingroup Geometry
* \brief An interface for a fixed-size set of geometric entities
* \note This can be used e.g. to construct a bounding box volume hierarchy of a grid
* It defines the minimum requirement for such a set
*/
template<class GeoType, std::size_t N>
class FixedSizeGeometriesEntitySet
{
template<class GT, std::size_t... I>
FixedSizeGeometriesEntitySet(GT&& gt, std::index_sequence<I...>)
: entities_{{ Entity(std::get<I>(gt), I)... }}
{ static_assert(sizeof...(I) == N, "Number of geometries must match the size of the entity set"); }
public:
using Entity = Detail::GeometricEntity::EntityWrapper<GeoType>;
/*!
* \brief Constructor with one or more geometries as arguments
* \note The number of geometries must match the size of the entity set
*/
template<class... G>
FixedSizeGeometriesEntitySet(G&&... g)
: FixedSizeGeometriesEntitySet(std::forward_as_tuple(std::forward<G>(g)...), std::make_index_sequence<N>{})
{}
/*!
* \brief The world dimension of the entity set
*/
static constexpr int dimensionworld = Entity::Geometry::coorddimension;
/*!
* \brief the coordinate type
*/
using ctype = typename Entity::Geometry::ctype;
/*!
* \brief the number of entities in this set
*/
constexpr auto size() const
{ return entities_.size(); }
/*!
* \brief begin iterator to enable range-based for iteration
*/
decltype(auto) begin() const
{ return entities_.begin(); }
/*!
* \brief end iterator to enable range-based for iteration
*/
decltype(auto) end() const
{ return entities_.end(); }
/*!
* \brief get an entities index
*/
template<class Entity>
std::size_t index(const Entity& e) const
{ return e.index(); }
/*!
* \brief get an entity from an index
*/
const Entity& entity(std::size_t index) const
{ assert(index < entities_.size()); return entities_[index]; }
private:
std::array<Entity, N> entities_;
};
/*!
* \ingroup Geometry
* \brief An interface for a geometric entity set with a single geometry
*/
template<class GeoType>
class SingleGeometryEntitySet
: public FixedSizeGeometriesEntitySet<GeoType, 1>
{
using ParentType = FixedSizeGeometriesEntitySet<GeoType, 1>;
public:
using ParentType::ParentType;
};
} // end namespace Dumux } // end namespace Dumux
#endif #endif
...@@ -152,6 +152,31 @@ int main (int argc, char *argv[]) ...@@ -152,6 +152,31 @@ int main (int argc, char *argv[])
testPolyLineIntersections(i, j); testPolyLineIntersections(i, j);
} }
{
std::cout << "\nIntersect two polylines testing fixed size geometric entity sets:\n" << std::endl;
std::cout << "-- Test number of segments: " << 1 << " and " << 2 << "\n";
using Geo = Dune::AffineGeometry<double, 1, 2>;
using Point = Geo::GlobalCoordinate;
// once test constructor with l-values
const auto geo1 = Geo(Dune::GeometryTypes::line, std::array<Point, 2>{{Point({0.0, 0.0}), Point({1.0, 1.0})}});
const auto geo2 = Geo(Dune::GeometryTypes::line, std::array<Point, 2>{{Point({1.0, 1.0}), Point({2.0, 2.0})}});
auto geoSet0 = std::make_shared<FixedSizeGeometriesEntitySet<Geo, 2>>(geo1, geo2);
// once test constructor with move semantics
auto geoSet1 = std::make_shared<SingleGeometryEntitySet<Geo>>(
Geo(Dune::GeometryTypes::line, std::array<Point, 2>{{Point({0.0, 0.0}), Point({2.0, 2.0})}})
);
IntersectionEntitySet<FixedSizeGeometriesEntitySet<Geo, 2>, SingleGeometryEntitySet<Geo>> intersectionEntitySet;
intersectionEntitySet.build(geoSet0, geoSet1);
if (intersectionEntitySet.size() != 2)
DUNE_THROW(Dune::Exception, "Wrong number of line segment intersections."
<< " Expected " << 2 << " got " << intersectionEntitySet.size());
}
std::cout << "All tests passed!" << std::endl; std::cout << "All tests passed!" << std::endl;
return 0; return 0;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment