Commit c1f0b965 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Put TreeContainer in a separate namespace TypeTree and rename makeTreeContainer into treeContainer

parent 29c3c685
...@@ -94,7 +94,7 @@ namespace AMDiS ...@@ -94,7 +94,7 @@ namespace AMDiS
template <class Node> template <class Node>
using NodeElementData = typename NodeDataTransfer<Node, Container, Basis>::NodeElementData; using NodeElementData = typename NodeDataTransfer<Node, Container, Basis>::NodeElementData;
using ElementData = TreeContainer<NodeElementData,Tree,true>; using ElementData = TypeTree::TreeContainer<NodeElementData,Tree,true>;
using Interface = DataTransferInterface<Container>; using Interface = DataTransferInterface<Container>;
...@@ -138,7 +138,7 @@ namespace AMDiS ...@@ -138,7 +138,7 @@ namespace AMDiS
/// Data transfer on a single basis node /// Data transfer on a single basis node
template <class Node> template <class Node>
using NDT = NodeDataTransfer<Node, Container, Basis>; using NDT = NodeDataTransfer<Node, Container, Basis>;
using NodeDataTransferContainer = TreeContainer<NDT,Tree,true>; using NodeDataTransferContainer = TypeTree::TreeContainer<NDT,Tree,true>;
NodeDataTransferContainer nodeDataTransfer_; NodeDataTransferContainer nodeDataTransfer_;
}; };
......
...@@ -66,7 +66,7 @@ preAdapt(C const& coeff, bool mightCoarsen) ...@@ -66,7 +66,7 @@ preAdapt(C const& coeff, bool mightCoarsen)
persistentContainer_.clear(); // Redundant if postAdapt was correctly called last cycle persistentContainer_.clear(); // Redundant if postAdapt was correctly called last cycle
for (const auto& e : elements(gv)) for (const auto& e : elements(gv))
{ {
auto it = persistentContainer_.emplace(idSet.id(e), makeTreeContainer<NodeElementData,true>(lv.tree())); auto it = persistentContainer_.emplace(idSet.id(e), TypeTree::treeContainer<NodeElementData,true>(lv.tree()));
lv.bind(e); lv.bind(e);
auto& treeContainer = it.first->second; auto& treeContainer = it.first->second;
...@@ -88,7 +88,7 @@ preAdapt(C const& coeff, bool mightCoarsen) ...@@ -88,7 +88,7 @@ preAdapt(C const& coeff, bool mightCoarsen)
while (father.mightVanish() && father.hasFather()) while (father.mightVanish() && father.hasFather())
{ {
father = father.father(); father = father.father();
auto it = persistentContainer_.emplace(idSet.id(father), makeTreeContainer<NodeElementData,true>(lv.tree())); auto it = persistentContainer_.emplace(idSet.id(father), TypeTree::treeContainer<NodeElementData,true>(lv.tree()));
if (!it.second) if (!it.second)
continue; continue;
......
...@@ -141,14 +141,14 @@ namespace AMDiS ...@@ -141,14 +141,14 @@ namespace AMDiS
template <class RowBasis, class ColBasis, class ElementMatrix> template <class RowBasis, class ColBasis, class ElementMatrix>
using MatrixOperators using MatrixOperators
= TreeMatrix< = TypeTree::TreeMatrix<
OperatorLists<typename RowBasis::GridView,ElementMatrix>::template MatData, OperatorLists<typename RowBasis::GridView,ElementMatrix>::template MatData,
typename RowBasis::LocalView::TreeCache, typename RowBasis::LocalView::TreeCache,
typename ColBasis::LocalView::TreeCache>; typename ColBasis::LocalView::TreeCache>;
template <class Basis, class ElementVector> template <class Basis, class ElementVector>
using VectorOperators using VectorOperators
= TreeContainer< = TypeTree::TreeContainer<
OperatorLists<typename Basis::GridView,ElementVector>::template VecData, OperatorLists<typename Basis::GridView,ElementVector>::template VecData,
typename Basis::LocalView::TreeCache>; typename Basis::LocalView::TreeCache>;
......
...@@ -6,6 +6,6 @@ install(FILES ...@@ -6,6 +6,6 @@ install(FILES
Traits.hpp Traits.hpp
Traversal.hpp Traversal.hpp
TreeContainer.hpp TreeContainer.hpp
TreeContainerTransformation.hpp TreeContainerTrafo.hpp
TreePath.hpp TreePath.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/typetree) DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/typetree)
...@@ -16,110 +16,50 @@ ...@@ -16,110 +16,50 @@
// NOTE: backport of dune/typetree/treecontainer.hh // NOTE: backport of dune/typetree/treecontainer.hh
namespace AMDiS namespace AMDiS {
{ namespace TypeTree {
/// \brief Vector data-structure with tree-path index access and hierarchic structure
/// given by the `Container` template type
/**
* This Vector container is parametrized with the actual container type that is stored
* internally. Access to the elements of the container is possible by using a tree-path
* index.
*
* The internal container is constructed by the \ref ContainerFactory, storing for each
* tree node a corresponding array or tuple plus a value. The data-structure to hold
* both, the value and the container is defined in \ref ValueAndContainer.
**/
template <class Container>
class TreeContainerStorage
{
using Self = TreeContainerStorage;
template <class C>
static constexpr decltype(auto)
accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<> const&)
{
return container.value();
}
template <class C, class... T>
static constexpr decltype(auto)
accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<T...> const& path)
{
auto head = Dune::TypeTree::treePathEntry(path,Dune::Indices::_0);
return accessByTreePath(container[head], pop_front(path));
}
public:
/// \brief Default-construct the tree-container
TreeContainerStorage()
: container_()
{}
TreeContainerStorage(Container const& container) template <class Value>
: container_(container) class LeafNodeStorage
{
public:
template <class V>
LeafNodeStorage(V&& value)
: value_(FWD(value))
{} {}
/// \brief Construct the tree-container from a given container storage LeafNodeStorage()
TreeContainerStorage(Container&& container) : value_()
: container_(std::move(container))
{} {}
/// \brief Access a (const) element of the container by treepath Value& value() { return value_; }
template <class... T> Value const& value() const { return value_; }
decltype(auto) operator[](Dune::TypeTree::HybridTreePath<T...> const& path) const
{
return accessByTreePath(container_, path);
}
/// \brief Access a (mutable) element of the container by treepath
template <class... T>
decltype(auto) operator[](Dune::TypeTree::HybridTreePath<T...> const& path)
{
return accessByTreePath(container_, path);
}
/// \brief Obtain the container (const)
Container const& data() const
{
return container_;
}
/// \brief Obtain the container (mutable)
Container& data()
{
return container_;
}
/// \brief Compare two containers for equality bool operator==(LeafNodeStorage const& other) const
bool operator==(TreeContainerStorage const& other) const
{ {
return container_ == other.container_; return value_ == other.value_;
} }
/// \brief Compare two containers for inequality private:
bool operator!=(TreeContainerStorage const& other) const Value value_;
{ };
return container_ != other.container_;
}
private: template <class Value>
Container container_; LeafNodeStorage(Value const&)
}; -> LeafNodeStorage<Value>;
namespace Impl template <class Value, class Container>
{ class InnerNodeStorage
template <class Value, class Container> {
class ValueAndContainer public:
{
public:
template <class V, class C> template <class V, class C>
ValueAndContainer(V&& value, C&& container) InnerNodeStorage(V&& value, C&& container)
: value_(FWD(value)) : value_(FWD(value))
, container_(FWD(container)) , container_(FWD(container))
{} {}
ValueAndContainer() InnerNodeStorage()
: value_() : value_()
, container_() , container_()
{} {}
...@@ -136,89 +76,23 @@ namespace AMDiS ...@@ -136,89 +76,23 @@ namespace AMDiS
Container& container() { return container_; } Container& container() { return container_; }
Container const& container() const { return container_; } Container const& container() const { return container_; }
bool operator==(ValueAndContainer const& other) const bool operator==(InnerNodeStorage const& other) const
{ {
return value_ == other.value_ && container_ == other.container_; return value_ == other.value_ && container_ == other.container_;
} }
private: private:
Value value_; Value value_;
Container container_; Container container_;
}; };
template <class Value>
class ValueAndContainer<Value,void>
{
public:
template <class V, Dune::disableCopyMove<ValueAndContainer,V> = 0>
ValueAndContainer(V&& value)
: value_(FWD(value))
{}
ValueAndContainer()
: value_()
{}
Value& value() { return value_; }
Value const& value() const { return value_; }
bool operator==(ValueAndContainer const& other) const
{
return value_ == other.value_;
}
private:
Value value_;
};
struct Ignore{};
template <class Container>
class ValueAndContainer<Ignore,Container>
{
public:
template <class C>
ValueAndContainer(Ignore, C&& container)
: container_(FWD(container))
{}
ValueAndContainer()
: container_()
{}
template <class I>
auto& operator[](I const& i) { return container_[i]; }
template <class I>
auto const& operator[](I const& i) const { return container_[i]; }
Ignore value() { return {}; }
Ignore value() const { return {}; }
Container& container() { return container_; }
Container const& container() const { return container_; }
bool operator==(ValueAndContainer const& other) const
{
return container_ == other.container_;
}
private:
Container container_;
};
template <class Value, class Container> template <class Value, class Container>
ValueAndContainer(Value const&, Container const&) InnerNodeStorage(Value const&, Container const&)
-> ValueAndContainer<Value,Container>; -> InnerNodeStorage<Value, Container>;
template <class Value>
ValueAndContainer(Value const&)
-> ValueAndContainer<Value,void>;
/// \brief A factory class creating a hybrid container compatible with a type tree
/// \brief A factory class creating a hybrid container compatible with a type tree /**
/**
* This class allows to create a nested hybrid container having the same structure * This class allows to create a nested hybrid container having the same structure
* as a given type tree. Power nodes are represented as std::array's while composite * as a given type tree. Power nodes are represented as std::array's while composite
* nodes are represented as Dune::TupleVector's. The stored values for the leaf nodes * nodes are represented as Dune::TupleVector's. The stored values for the leaf nodes
...@@ -228,10 +102,10 @@ namespace AMDiS ...@@ -228,10 +102,10 @@ namespace AMDiS
* \tparam NodeToValue Type of a predicate that determines the stored values at the * \tparam NodeToValue Type of a predicate that determines the stored values at the
* leafs * leafs
**/ **/
template <class NodeToValue, bool leafOnly = false> template <class NodeToValue, bool leafOnly = false>
class ContainerFactory class ContainerFactory
{ {
public: public:
/// \brief Create ContainerFactory /// \brief Create ContainerFactory
/** /**
* The given predicate will be stored by value. * The given predicate will be stored by value.
...@@ -247,46 +121,132 @@ namespace AMDiS ...@@ -247,46 +121,132 @@ namespace AMDiS
auto operator()(Node const& node) const auto operator()(Node const& node) const
{ {
if constexpr (Node::isLeaf) if constexpr (Node::isLeaf)
return ValueAndContainer{value(node)}; return LeafNodeStorage{nodeToValue_(node)};
else else
if constexpr (Node::isPower) { if constexpr (Node::isPower) {
using TransformedChild = decltype((*this)(node.child(0))); using TransformedChild = decltype((*this)(node.child(0)));
return ValueAndContainer{ return makeInnerNodeStorage(node,
value(node), std::array<TransformedChild, Node::degree()>());
std::array<TransformedChild, Node::degree()>()};
} }
else else
if constexpr (Node::isComposite) { if constexpr (Node::isComposite) {
return ValueAndContainer{ return makeInnerNodeStorage(node,
value(node),
Ranges::applyIndices<Node::degree()>( Ranges::applyIndices<Node::degree()>(
[&](auto... ii) { return Dune::makeTupleVector((*this)(node.child(ii))...); })}; [&](auto... ii) { return Dune::makeTupleVector((*this)(node.child(ii))...); }));
} }
else { else {
static_assert(Node::isLeaf || Node::isPower || Node::isComposite, static_assert(Node::isLeaf || Node::isPower || Node::isComposite,
"Node must be one of leaf,power,composite."); "Node must be one of leaf, power, composite.");
return; return;
} }
} }
template <class Node> template <class Node, class Container>
decltype(auto) value(Node const& node) const auto makeInnerNodeStorage(Node const& node, Container&& container) const
{ {
if constexpr(!Node::isLeaf && leafOnly) if constexpr(!Node::isLeaf && leafOnly)
return Ignore{}; return FWD(container);
else else
return nodeToValue_(node); return InnerNodeStorage{nodeToValue_(node), FWD(container)};
} }
private: private:
NodeToValue nodeToValue_; NodeToValue nodeToValue_;
}; };
/// \brief Vector data-structure with tree-path index access and hierarchic structure
/// given by the `Container` template type
/**
* This Vector container is parametrized with the actual container type that is stored
* internally. Access to the elements of the container is possible by using a tree-path
* index.
*
* The internal container is constructed by the \ref ContainerFactory, storing for each
* tree node a corresponding array or tuple plus a value. The data-structure to hold
* both, the value and the container is defined in \ref InnerNodeStorage.
**/
template <class Container>
class TreeContainerStorage
{
using Self = TreeContainerStorage;
template <class C>
static constexpr auto
accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<>) -> decltype(container.value())
{
return container.value();
}
} // end namespace Impl template <class C, class T0, class... T>
static constexpr decltype(auto)
accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<T0,T...> const& path)
{
auto head = Dune::TypeTree::treePathEntry(path,Dune::Indices::_0);
return accessByTreePath(container[head], pop_front(path));
}
public:
/// \brief Default-construct the tree-container
TreeContainerStorage()
: container_()
{}
/// \brief Create container having the same structure as the given tree /// \brief Construct the tree-container from a given container storage
/** TreeContainerStorage(Container const& container)
: container_(container)
{}
/// \brief Construct the tree-container from a given container storage
TreeContainerStorage(Container&& container)
: container_(std::move(container))
{}
/// \brief Access a (const) element of the container by treepath
template <class... T>
decltype(auto) operator[](Dune::TypeTree::HybridTreePath<T...> const& path) const
{
return accessByTreePath(container_, path);
}
/// \brief Access a (mutable) element of the container by treepath
template <class... T>
decltype(auto) operator[](Dune::TypeTree::HybridTreePath<T...> const& path)
{
return accessByTreePath(container_, path);
}
/// \brief Obtain the container (const)
Container const& data() const
{
return container_;
}
/// \brief Obtain the container (mutable)
Container& data()
{
return container_;
}
/// \brief Compare two containers for equality
bool operator==(TreeContainerStorage const& other) const
{
return container_ == other.container_;
}
/// \brief Compare two containers for inequality
bool operator!=(TreeContainerStorage const& other) const
{
return container_ != other.container_;
}
private:
Container container_;
};
/// \brief Create container having the same structure as the given tree
/**
* This class allows to create a nested hybrid container having the same structure * This class allows to create a nested hybrid container having the same structure
* as a given type tree. Power nodes are represented as std::array's while composite * as a given type tree. Power nodes are represented as std::array's while composite
* nodes are represented as Dune::TupleVector's. The stored values for the leaf nodes * nodes are represented as Dune::TupleVector's. The stored values for the leaf nodes
...@@ -294,22 +254,22 @@ namespace AMDiS ...@@ -294,22 +254,22 @@ namespace AMDiS
* not returned directly. Instead, the returned object stores the container and * not returned directly. Instead, the returned object stores the container and
* provides operator[] access using a HybridTreePath. * provides operator[] access using a HybridTreePath.
* *
* \tparam leafOnly Create a container for the leaf tree nodes
* \param tree The tree which should be mapper to a container * \param tree The tree which should be mapper to a container
* \param nodeToValue A predicate used to generate the stored values for the nodes * \param nodeToValue A predicate used to generate the stored values for the nodes
* *
* \returns A container matching the tree structure * \returns A container matching the tree structure
*/ */
template <bool leafOnly = false, class Tree, class NodeToValue> template <bool leafOnly = false, class Tree, class NodeToValue>
auto makeTreeContainer(Tree const& tree, NodeToValue&& nodeToValue) auto treeContainer(Tree const& tree, NodeToValue nodeToValue)
{ {
auto f = std::ref(nodeToValue); auto factory = ContainerFactory<NodeToValue,leafOnly>{nodeToValue};
auto factory = Impl::ContainerFactory<decltype(f),leafOnly>(f);
return TreeContainerStorage{factory(tree)}; return TreeContainerStorage{factory(tree)};
} }
/// \brief Create container having the same structure as the given tree /// \brief Create container having the same structure as the given tree
/** /**
* This class allows to create a nested hybrid container having the same structure * This class allows to create a nested hybrid container having the same structure
* as a given type tree. Power nodes are represented as std::array's while composite * as a given type tree. Power nodes are represented as std::array's while composite
* nodes are represented as Dune::TupleVector's. The stored values for the leaf nodes * nodes are represented as Dune::TupleVector's. The stored values for the leaf nodes
...@@ -323,42 +283,42 @@ namespace AMDiS ...@@ -323,42 +283,42 @@ namespace AMDiS
* *
* \returns A container matching the tree structure * \returns A container matching the tree structure
*/ */
template <class Value, bool leafOnly = false, class Tree> template <class Value, bool leafOnly = false, class Tree>
auto makeTreeContainer(Tree const& tree) auto treeContainer(Tree const& tree)
{ {
return makeTreeContainer<leafOnly>(tree, [](auto&&) { return Value{}; }); return treeContainer<leafOnly>(tree, [](auto&&) { return Value{}; });
} }
template <template<class> class NodeData, bool leafOnly = false, class Tree>
auto makeTreeContainer(Tree const& tree)
{
return makeTreeContainer<leafOnly>(tree, [](auto&& node) { return NodeData<TYPEOF(node)>{}; });
}
/// Alias to container type generated by makeTreeContainer for given tree type and
/// uniform value type
template <class Value, class Tree, bool leafOnly = false>
using UniformTreeContainer
= TYPEOF(makeTreeContainer<Value,leafOnly>(std::declval<const Tree&>()));
/// Alias to matrix-container type generated by makeTreeContainer for given tree types template <template<class> class NodeData, bool leafOnly = false, class Tree>
/// and uniform value type