diff --git a/dune/fu-tutorial/CMakeLists.txt b/dune/fu-tutorial/CMakeLists.txt index 9d885454cb6eb31ab83df5fb6f48ca993b8b2f18..b36d4ad7c3cc1872062a4f18f0a475980e5eaa0a 100644 --- a/dune/fu-tutorial/CMakeLists.txt +++ b/dune/fu-tutorial/CMakeLists.txt @@ -1,2 +1,5 @@ #install headers -install(FILES fu-tutorial.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/fu-tutorial) +install(FILES + fu-tutorial.hh + referenceelementutility.hh + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/fu-tutorial) diff --git a/dune/fu-tutorial/referenceelementutility.hh b/dune/fu-tutorial/referenceelementutility.hh new file mode 100644 index 0000000000000000000000000000000000000000..4239f53ecfcdfab77bea706fccfa75fd11af85da --- /dev/null +++ b/dune/fu-tutorial/referenceelementutility.hh @@ -0,0 +1,285 @@ +// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set ts=8 sw=2 et sts=2: +#ifndef DUNE_FU_TUTORIAL_REFERENCEELEMENTUTILITY_hh +#define DUNE_FU_TUTORIAL_REFERENCEELEMENTUTILITY_hh + +#include <dune/common/reservedvector.hh> +#include <dune/common/power.hh> +#include <dune/geometry/referenceelements.hh> +#include <dune/geometry/dimension.hh> + +namespace Dune { +namespace FuTutorial { + + + +/** + * \brief Encapsulate dynamic codim value + */ +class DynamicCodim +{ +public: + constexpr DynamicCodim(): + value_(0) + {} + + constexpr explicit DynamicCodim(std::size_t value) : + value_(value) + {} + + /** + * \brief Allow conversion from static Codim value + */ + template<int value> + constexpr DynamicCodim(Dune::Codim<value> staticCodim): + value_(value) + {} + + constexpr operator std::size_t() const + { + return value_; + } + +private: + std::size_t value_; +}; + + + +/** + * \brief Generate dynamic codim from dynamic raw value + */ +auto codim(std::size_t i) +{ + return DynamicCodim(i); +} + + + +/** + * \brief Encapsulate dynamic subentity information + * + * This is a strongly typed pair of codimension and index + */ +class DynamicSubEntity +{ +public: + + constexpr DynamicSubEntity(): + codim_(0), + index_(0) + {} + + constexpr DynamicSubEntity(DynamicCodim codim, std::size_t index): + codim_(codim), + index_(index) + {} + + constexpr DynamicCodim codim() const + { + return codim_; + } + + constexpr std::size_t index() const + { + return index_; + } + + constexpr operator std::size_t() const + { + return index_; + } + +private: + DynamicCodim codim_; + std::size_t index_; +}; + + + +/** + * \brief Create subentity identifier for given codim and index + */ +auto subEntity(DynamicCodim codim, std::size_t index) +{ + return DynamicSubEntity(codim, index); +} + + + +/** + * \brief Create subentity identifier for facet of given index + */ +auto facet(std::size_t index) +{ + return subEntity(codim(1), index); +} + + + +/** + * \brief Create subentity identifier for inside facet + */ +template<class Intersection> +auto insideFacet(const Intersection& intersection) +{ + return subEntity(codim(1), intersection.indexInInside()); +} + + + +/** + * \brief Get reference element for given entity + */ +template<class FieldType, class Entity> +const auto& referenceElement(const Entity& entity) +{ + return Dune::ReferenceElements<FieldType, Entity::dimension>::general(entity.type()); +} + + +/** + * \brief Get reference element for given entity + */ +template<class Entity> +const auto& referenceElement(const Entity& entity) +{ + return Dune::ReferenceElements<double, Entity::dimension>::general(entity.type()); +} + + +/** + * \brief Get number of subentities of given codim + * + * This should (maybe) be a member of ReferenceElement. + */ +template<class ctype, int dim> +std::size_t size(const Dune::ReferenceElement<ctype, dim>& referenceElement, DynamicCodim codim) +{ + return referenceElement.size(codim); +} + + + +/** + * \brief Get GeometryType of subentity + * + * This should (maybe) be a member of ReferenceElement. + */ +template<class ctype, int dim> +Dun::GeometryType type(const Dune::ReferenceElement<ctype, dim>& referenceElement, DynamicSubEntity subEntity) +{ + return referenceElement.type(subEntity.index(), subEntity.codim()); +} + + + +/** + * \brief Get number of subsubentities of given codim for a subentity + * + * This should (maybe) be a member of ReferenceElement. + */ +template<class ctype, int dim> +std::size_t size(const Dune::ReferenceElement<ctype, dim>& referenceElement, DynamicSubEntity subEntity, DynamicCodim subSubEntityCodim) +{ + return referenceElement.size(subEntity.index(), subEntity.codim(), subSubEntityCodim); +} + + + +/** + * \brief Get index of a subsubentity for a subentity within the ReferenceElement + * + * This should (maybe) be a member of ReferenceElement. + * However, this could also be hidden, because the + * functionality is often misunderstood and you normaly + * need all subsubentities anyway. + */ +template<class ctype, int dim> +auto subEntity(const Dune::ReferenceElement<ctype, dim>& referenceElement, DynamicSubEntity se, DynamicSubEntity subSubEntity) +{ + return subEntity(subSubEntity.codim(), referenceElement.subEntity(se.index(), se.codim(), subSubEntity.index(), subSubEntity.codim())); +} + + + +/** + * \brief Get index-range of subsubentities of given codim for a subentity within the ReferenceElement + * + * This should (maybe) be a member of ReferenceElement. + */ +template<class ctype, int dim> +auto subEntities(const Dune::ReferenceElement<ctype, dim>& referenceElement, const DynamicSubEntity subEntityTag, DynamicCodim codim) +{ + static const std::size_t maxSubEntityCount = Dune::StaticPower<2,dim>::power; + std::size_t subEntityCount = size(referenceElement, subEntityTag, codim); + + // Todo: This could be replaced by an on-the fly range by doing a + // transformation to an index range. Unfortunately these range tools + // have not arrived in std yet. + Dune::ReservedVector<DynamicSubEntity, maxSubEntityCount > indices; + indices.resize(subEntityCount); + for(std::size_t i=0; i<subEntityCount; ++i) + indices[i] = subEntity(referenceElement, subEntityTag, subEntity(codim, i)); + + return indices; +} + + + +/** + * \brief Get index-range of subentities of given codim + * + * This should (maybe) be a member of ReferenceElement. + */ +template<class ctype, int dim> +auto subEntities(const Dune::ReferenceElement<ctype, dim>& referenceElement, DynamicCodim cd) +{ + return subEntities(referenceElement, subEntity(codim(0), 0), cd); +} + + + +/** + * \brief Get index-range of vertices of given subentity within the ReferenceElement + */ +template<class ctype, int dim> +auto subVertices(const Dune::ReferenceElement<ctype, dim>& referenceElement, const DynamicSubEntity subEntityTag) +{ + return subEntities(referenceElement, subEntityTag, codim(dim)); +} + + + +/** + * \brief Get index of subentity + * + * This should (maybe) be a member of IndexSet + */ +template<class IndexSet, class Entity> +auto subIndex(const IndexSet& indexSet, const Entity& entity, DynamicSubEntity subEntity) +{ + return indexSet.subIndex(entity, subEntity.index(), subEntity.codim()); +} + + + +/** + * \brief Get id of subentity + * + * This should (maybe) be a member of IdSet. + */ +template<class IdSet, class Entity> +auto subId(const IdSet& idSet, const Entity& entity, DynamicSubEntity subEntity) +{ + return idSet.subId(entity, subEntity.index(), subEntity.codim()); +} + + + +} // end namespace FuTutorial +} // end namespace Dune + + + +#endif // DUNE_FU_TUTORIAL_REFERENCEELEMENTUTILITY_hh