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
template <class Node>
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>;
......@@ -138,7 +138,7 @@ namespace AMDiS
/// Data transfer on a single basis node
template <class Node>
using NDT = NodeDataTransfer<Node, Container, Basis>;
using NodeDataTransferContainer = TreeContainer<NDT,Tree,true>;
using NodeDataTransferContainer = TypeTree::TreeContainer<NDT,Tree,true>;
NodeDataTransferContainer nodeDataTransfer_;
};
......
......@@ -66,7 +66,7 @@ preAdapt(C const& coeff, bool mightCoarsen)
persistentContainer_.clear(); // Redundant if postAdapt was correctly called last cycle
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);
auto& treeContainer = it.first->second;
......@@ -88,7 +88,7 @@ preAdapt(C const& coeff, bool mightCoarsen)
while (father.mightVanish() && father.hasFather())
{
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)
continue;
......
......@@ -141,14 +141,14 @@ namespace AMDiS
template <class RowBasis, class ColBasis, class ElementMatrix>
using MatrixOperators
= TreeMatrix<
= TypeTree::TreeMatrix<
OperatorLists<typename RowBasis::GridView,ElementMatrix>::template MatData,
typename RowBasis::LocalView::TreeCache,
typename ColBasis::LocalView::TreeCache>;
template <class Basis, class ElementVector>
using VectorOperators
= TreeContainer<
= TypeTree::TreeContainer<
OperatorLists<typename Basis::GridView,ElementVector>::template VecData,
typename Basis::LocalView::TreeCache>;
......
......@@ -6,6 +6,6 @@ install(FILES
Traits.hpp
Traversal.hpp
TreeContainer.hpp
TreeContainerTransformation.hpp
TreeContainerTrafo.hpp
TreePath.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/typetree)
......@@ -16,110 +16,50 @@
// NOTE: backport of dune/typetree/treecontainer.hh
namespace AMDiS
{
/// \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_()
{}
namespace AMDiS {
namespace TypeTree {
TreeContainerStorage(Container const& container)
: container_(container)
template <class Value>
class LeafNodeStorage
{
public:
template <class V>
LeafNodeStorage(V&& value)
: value_(FWD(value))
{}
/// \brief Construct the tree-container from a given container storage
TreeContainerStorage(Container&& container)
: container_(std::move(container))
LeafNodeStorage()
: value_()
{}
/// \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_;
}
Value& value() { return value_; }
Value const& value() const { return value_; }
/// \brief Compare two containers for equality
bool operator==(TreeContainerStorage const& other) const
bool operator==(LeafNodeStorage const& other) const
{
return container_ == other.container_;
return value_ == other.value_;
}
/// \brief Compare two containers for inequality
bool operator!=(TreeContainerStorage const& other) const
{
return container_ != other.container_;
}
private:
Value value_;
};
private:
Container container_;
};
template <class Value>
LeafNodeStorage(Value const&)
-> LeafNodeStorage<Value>;
namespace Impl
{
template <class Value, class Container>
class ValueAndContainer
{
public:
template <class Value, class Container>
class InnerNodeStorage
{
public:
template <class V, class C>
ValueAndContainer(V&& value, C&& container)
InnerNodeStorage(V&& value, C&& container)
: value_(FWD(value))
, container_(FWD(container))
{}
ValueAndContainer()
InnerNodeStorage()
: value_()
, container_()
{}
......@@ -136,89 +76,23 @@ namespace AMDiS
Container& container() { 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_;
}
private:
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, class Container>
InnerNodeStorage(Value const&, Container const&)
-> 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
* 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
......@@ -228,10 +102,10 @@ namespace AMDiS
* \tparam NodeToValue Type of a predicate that determines the stored values at the
* leafs
**/
template <class NodeToValue, bool leafOnly = false>
class ContainerFactory
{
public:
template <class NodeToValue, bool leafOnly = false>
class ContainerFactory
{
public:
/// \brief Create ContainerFactory
/**
* The given predicate will be stored by value.
......@@ -247,46 +121,132 @@ namespace AMDiS
auto operator()(Node const& node) const
{
if constexpr (Node::isLeaf)
return ValueAndContainer{value(node)};
return LeafNodeStorage{nodeToValue_(node)};
else
if constexpr (Node::isPower) {
using TransformedChild = decltype((*this)(node.child(0)));
return ValueAndContainer{
value(node),
std::array<TransformedChild, Node::degree()>()};
return makeInnerNodeStorage(node,
std::array<TransformedChild, Node::degree()>());
}
else
if constexpr (Node::isComposite) {
return ValueAndContainer{
value(node),
return makeInnerNodeStorage(node,
Ranges::applyIndices<Node::degree()>(
[&](auto... ii) { return Dune::makeTupleVector((*this)(node.child(ii))...); })};
[&](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.");
"Node must be one of leaf, power, composite.");
return;
}
}
template <class Node>
decltype(auto) value(Node const& node) const
template <class Node, class Container>
auto makeInnerNodeStorage(Node const& node, Container&& container) const
{
if constexpr(!Node::isLeaf && leafOnly)
return Ignore{};
return FWD(container);
else
return nodeToValue_(node);
return InnerNodeStorage{nodeToValue_(node), FWD(container)};
}
private:
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;
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
* 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
......@@ -294,22 +254,22 @@ namespace AMDiS
* not returned directly. Instead, the returned object stores the container and
* 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 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 factory = Impl::ContainerFactory<decltype(f),leafOnly>(f);
template <bool leafOnly = false, class Tree, class NodeToValue>
auto treeContainer(Tree const& tree, NodeToValue nodeToValue)
{
auto factory = ContainerFactory<NodeToValue,leafOnly>{nodeToValue};
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
* 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
......@@ -323,42 +283,42 @@ namespace AMDiS
*
* \returns A container matching the tree structure
*/
template <class Value, bool leafOnly = false, class Tree>
auto makeTreeContainer(Tree const& tree)
{
return makeTreeContainer<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&>()));
template <class Value, bool leafOnly = false, class Tree>
auto treeContainer(Tree const& tree)
{
return treeContainer<leafOnly>(tree, [](auto&&) { return Value{}; });
}
/// Alias to matrix-container type generated by makeTreeContainer for given tree types
/// and uniform value type
template <class Value, class RowTree, class ColTree = RowTree, bool leafOnly = false>
using UniformTreeMatrix
template <template<class> class NodeData, bool leafOnly = false, class Tree>
auto treeContainer(Tree const& tree)
{
return treeContainer<leafOnly>(tree, [](auto&& node) { return NodeData<TYPEOF(node)>{}; });
}
/// Alias to container type generated by treeContainer for given tree type and
/// uniform value type
template <class Value, class Tree, bool leafOnly = false>
using UniformTreeContainer
= TYPEOF(treeContainer<Value,leafOnly>(std::declval<const Tree&>()));
/// Alias to matrix-container type generated by treeContainer for given tree types
/// and uniform value type
template <class Value, class RowTree, class ColTree = RowTree, bool leafOnly = false>
using UniformTreeMatrix
= UniformTreeContainer<UniformTreeContainer<Value,ColTree,leafOnly>,RowTree,leafOnly>;
/// Alias to container type generated by makeTreeContainer for give tree type and when
/// using NodeToValue to create values
template <template <class Node> class NodeData, class Tree, bool leafOnly = false>
using TreeContainer
= TYPEOF(makeTreeContainer<NodeData,leafOnly>(std::declval<const Tree&>()));
/// Alias to container type generated by treeContainer for give tree type and when
/// using NodeToValue to create values
template <template <class Node> class NodeData, class Tree, bool leafOnly = false>
using TreeContainer
= TYPEOF(treeContainer<NodeData,leafOnly>(std::declval<const Tree&>()));
namespace Impl
{
template <template <class,class> class NodeData, class Tree, bool leafOnly>
struct RowNodeData
{
namespace Impl_ {
template <template <class,class> class NodeData, class Tree, bool leafOnly>
struct RowNodeData
{
template <class RowNode>
struct ColNodeData
{
......@@ -368,14 +328,14 @@ namespace AMDiS
template <class RowNode>
using type = TreeContainer<ColNodeData<RowNode>::template type, Tree, leafOnly>;
};
};
} // end namespace Impl
} // end namespace Impl_
/// Alias to matrix-container type generated by makeTreeContainer for give tree type
/// and when using NodeToValue to create values
template <template <class,class> class NodeData, class RowTree, class ColTree = RowTree, bool leafOnly = false>
using TreeMatrix
= TreeContainer<Impl::RowNodeData<NodeData,ColTree,leafOnly>::template type,RowTree,leafOnly>;
/// Alias to matrix-container type generated by treeContainer for give tree type
/// and when using NodeToValue to create values
template <template <class,class> class NodeData, class RowTree, class ColTree = RowTree, bool leafOnly = false>
using TreeMatrix
= TreeContainer<Impl_::RowNodeData<NodeData,ColTree,leafOnly>::template type,RowTree,leafOnly>;
} //namespace AMDiS
}} //namespace AMDiS::TypeTree
#pragma once
#include <amdis/common/RecursiveForEach.hpp>
#include <amdis/common/RecursiveMap.hpp>
#include <amdis/typetree/TreeContainer.hpp>
namespace AMDiS {
namespace Recursive {
// specializations of recursive utilities for TreeContainer entries
template <class Value>
struct Apply<TypeTree::LeafNodeStorage<Value>>
{
template <class F, class VC>
static auto impl(F&& f, VC const& vc)
{
return TypeTree::LeafNodeStorage{
Recursive::apply(f,vc.value())};
}
};