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,366 +16,326 @@ ...@@ -16,366 +16,326 @@
// NOTE: backport of dune/typetree/treecontainer.hh // NOTE: backport of dune/typetree/treecontainer.hh
namespace AMDiS namespace AMDiS {
namespace TypeTree {
template <class Value>
class LeafNodeStorage
{ {
/// \brief Vector data-structure with tree-path index access and hierarchic structure public:
/// given by the `Container` template type template <class V>
/** LeafNodeStorage(V&& value)
* This Vector container is parametrized with the actual container type that is stored : value_(FWD(value))
* internally. Access to the elements of the container is possible by using a tree-path {}
* index.
* LeafNodeStorage()
* The internal container is constructed by the \ref ContainerFactory, storing for each : value_()
* 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.
**/ Value& value() { return value_; }
template <class Container> Value const& value() const { return value_; }
class TreeContainerStorage
bool operator==(LeafNodeStorage const& other) const
{ {
using Self = TreeContainerStorage; return value_ == other.value_;
}
template <class C> private:
static constexpr decltype(auto) Value value_;
accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<> const&) };
{
return container.value();
}
template <class C, class... T> template <class Value>
static constexpr decltype(auto) LeafNodeStorage(Value const&)
accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<T...> const& path) -> LeafNodeStorage<Value>;
{
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)
: 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 Value, class Container>
template <class... T> class InnerNodeStorage
decltype(auto) operator[](Dune::TypeTree::HybridTreePath<T...> const& path) {
{ public:
return accessByTreePath(container_, path); template <class V, class C>
} InnerNodeStorage(V&& value, C&& container)
: value_(FWD(value))
, container_(FWD(container))
{}
/// \brief Obtain the container (const) InnerNodeStorage()
Container const& data() const : value_()
{ , container_()
return container_; {}
}
/// \brief Obtain the container (mutable) template <class I>
Container& data() auto& operator[](I const& i) { return container_[i]; }
{
return container_;
}
/// \brief Compare two containers for equality template <class I>
bool operator==(TreeContainerStorage const& other) const auto const& operator[](I const& i) const { return container_[i]; }
{
return container_ == other.container_;
}
/// \brief Compare two containers for inequality Value& value() { return value_; }
bool operator!=(TreeContainerStorage const& other) const Value const& value() const { return value_; }
{
return container_ != other.container_; Container& container() { return container_; }
Container const& container() const { return container_; }
bool operator==(InnerNodeStorage const& other) const
{
return value_ == other.value_ && container_ == other.container_;
}
private:
Value value_;
Container container_;
};
template <class Value, class Container>
InnerNodeStorage(Value const&, Container const&)
-> InnerNodeStorage<Value, Container>;
/// \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
* 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
* are creating using a given predicate. Once created, the factory provides an
* operator() creating the container for the tree given as argument.
*
* \tparam NodeToValue Type of a predicate that determines the stored values at the
* leafs
**/
template <class NodeToValue, bool leafOnly = false>
class ContainerFactory
{
public:
/// \brief Create ContainerFactory
/**
* The given predicate will be stored by value.
*
* \param A predicate used to generate the stored values for the leaves
*/
ContainerFactory(NodeToValue nodeToValue)
: nodeToValue_(std::move(nodeToValue))
{}
/// \brief Return a container for storing the node content
template <class Node>
auto operator()(Node const& node) const
{
if constexpr (Node::isLeaf)
return LeafNodeStorage{nodeToValue_(node)};
else
if constexpr (Node::isPower) {
using TransformedChild = decltype((*this)(node.child(0)));
return makeInnerNodeStorage(node,
std::array<TransformedChild, Node::degree()>());
}
else
if constexpr (Node::isComposite) {
return makeInnerNodeStorage(node,
Ranges::applyIndices<Node::degree()>(
[&](auto... ii) { return Dune::makeTupleVector((*this)(node.child(ii))...); }));
} }
else {
static_assert(Node::isLeaf || Node::isPower || Node::isComposite,
"Node must be one of leaf, power, composite.");
return;
}
}
private: template <class Node, class Container>
Container container_; auto makeInnerNodeStorage(Node const& node, Container&& container) const
}; {
if constexpr(!Node::isLeaf && leafOnly)
return FWD(container);
else
return InnerNodeStorage{nodeToValue_(node), FWD(container)};
}
private:
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;
namespace Impl template <class C>
static constexpr auto
accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<>) -> decltype(container.value())
{ {
template <class Value, class Container> return container.value();
class ValueAndContainer }
{
public: template <class C, class T0, class... T>
template <class V, class C> static constexpr decltype(auto)
ValueAndContainer(V&& value, C&& container) accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<T0,T...> const& path)
: value_(FWD(value))
, container_(FWD(container))
{}
ValueAndContainer()
: value_()
, 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]; }
Value& value() { return value_; }
Value const& value() const { return value_; }
Container& container() { return container_; }
Container const& container() const { return container_; }
bool operator==(ValueAndContainer const& other) const
{
return value_ == other.value_ && container_ == other.container_;
}
private:
Value value_;
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>
ValueAndContainer(Value const&, Container const&)
-> ValueAndContainer<Value,Container>;
template <class Value>
ValueAndContainer(Value const&)
-> ValueAndContainer<Value,void>;
/// \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
* 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
* are creating using a given predicate. Once created, the factory provides an
* operator() creating the container for the tree given as argument.
*
* \tparam NodeToValue Type of a predicate that determines the stored values at the
* leafs
**/
template <class NodeToValue, bool leafOnly = false>
class ContainerFactory
{
public:
/// \brief Create ContainerFactory
/**
* The given predicate will be stored by value.
*
* \param A predicate used to generate the stored values for the leaves
*/
ContainerFactory(NodeToValue nodeToValue)
: nodeToValue_(std::move(nodeToValue))
{}
/// \brief Return a container for storing the node content
template <class Node>
auto operator()(Node const& node) const
{
if constexpr (Node::isLeaf)
return ValueAndContainer{value(node)};
else
if constexpr (Node::isPower) {
using TransformedChild = decltype((*this)(node.child(0)));
return ValueAndContainer{
value(node),
std::array<TransformedChild, Node::degree()>()};
}
else
if constexpr (Node::isComposite) {
return ValueAndContainer{
value(node),
Ranges::applyIndices<Node::degree()>(
[&](auto... ii) { return Dune::makeTupleVector((*this)(node.child(ii))...); })};
}
else {
static_assert(Node::isLeaf || Node::isPower || Node::isComposite,
"Node must be one of leaf,power,composite.");
return;
}
}
template <class Node>
decltype(auto) value(Node const& node) const
{
if constexpr(!Node::isLeaf && leafOnly)
return Ignore{};
else
return nodeToValue_(node);
}
private:
NodeToValue nodeToValue_;
};
} // end namespace Impl
/// \brief Create container having the same structure as the given tree
/**
* 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
* nodes are represented as Dune::TupleVector's. The stored values for the leaf nodes
* are creating using a given predicate. For convenience the created container is
* not returned directly. Instead, the returned object stores the container and
* provides operator[] access using a HybridTreePath.
*
* \param tree The tree which should be mapper to a container
* \param nodeToValue A predicate used to generate the stored values for the nodes
*
* \returns A container matching the tree structure
*/
template <bool leafOnly = false, class Tree, class NodeToValue>
auto makeTreeContainer(Tree const& tree, NodeToValue&& nodeToValue)
{ {
auto f = std::ref(nodeToValue); auto head = Dune::TypeTree::treePathEntry(path,Dune::Indices::_0);
auto factory = Impl::ContainerFactory<decltype(f),leafOnly>(f); return accessByTreePath(container[head], pop_front(path));
return TreeContainerStorage{factory(tree)};
} }
public:
/// \brief Default-construct the tree-container
TreeContainerStorage()
: container_()
{}
/// \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 Create container having the same structure as the given tree /// \brief Access a (mutable) element of the container by treepath
/** template <class... T>
* This class allows to create a nested hybrid container having the same structure decltype(auto) operator[](Dune::TypeTree::HybridTreePath<T...> const& path)
* 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 return accessByTreePath(container_, path);
* are of the given type Value. For convenience the created container is }
* not returned directly. Instead, the returned object stores the container and
* provides operator[] access using a HybridTreePath. /// \brief Obtain the container (const)
* Container const& data() const
* \tparam Value Type of the values to be stored for the leafs. Should be default {
* constructible. return container_;
* \param nodeToValue A predicate used to generate the stored values for the nodes }
*
* \returns A container matching the tree structure /// \brief Obtain the container (mutable)
*/ Container& data()
template <class Value, bool leafOnly = false, class Tree> {
auto makeTreeContainer(Tree const& tree) return container_;
}
/// \brief Compare two containers for equality
bool operator==(TreeContainerStorage const& other) const
{ {
return makeTreeContainer<leafOnly>(tree, [](auto&&) { return Value{}; }); return container_ == other.container_;
} }
template <template<class> class NodeData, bool leafOnly = false, class Tree> /// \brief Compare two containers for inequality
auto makeTreeContainer(Tree const& tree) bool operator!=(TreeContainerStorage const& other) const