diff --git a/amdis/DataTransfer.hpp b/amdis/DataTransfer.hpp index 468a73d24ae24f0216d86d1923b7708b2fb121d6..141a5f8c2ff33c1fcceece7c0f92187a03c8ec74 100644 --- a/amdis/DataTransfer.hpp +++ b/amdis/DataTransfer.hpp @@ -94,7 +94,7 @@ namespace AMDiS template using NodeElementData = typename NodeDataTransfer::NodeElementData; - using ElementData = TreeContainer; + using ElementData = TypeTree::TreeContainer; using Interface = DataTransferInterface; @@ -138,7 +138,7 @@ namespace AMDiS /// Data transfer on a single basis node template using NDT = NodeDataTransfer; - using NodeDataTransferContainer = TreeContainer; + using NodeDataTransferContainer = TypeTree::TreeContainer; NodeDataTransferContainer nodeDataTransfer_; }; diff --git a/amdis/DataTransfer.inc.hpp b/amdis/DataTransfer.inc.hpp index db0dab3d8cb2ea800e8769146f8b1f0ab1b40ccb..5e69a8c0b3ef96871a4fe0cdde4acdea31630058 100644 --- a/amdis/DataTransfer.inc.hpp +++ b/amdis/DataTransfer.inc.hpp @@ -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(lv.tree())); + auto it = persistentContainer_.emplace(idSet.id(e), TypeTree::treeContainer(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(lv.tree())); + auto it = persistentContainer_.emplace(idSet.id(father), TypeTree::treeContainer(lv.tree())); if (!it.second) continue; diff --git a/amdis/OperatorList.hpp b/amdis/OperatorList.hpp index 8d8af1c6c8491ff971f824b4e06668e5667e3ea6..8ea60b469b94eb3fa2b529f931c831540b65c79a 100644 --- a/amdis/OperatorList.hpp +++ b/amdis/OperatorList.hpp @@ -141,14 +141,14 @@ namespace AMDiS template using MatrixOperators - = TreeMatrix< + = TypeTree::TreeMatrix< OperatorLists::template MatData, typename RowBasis::LocalView::TreeCache, typename ColBasis::LocalView::TreeCache>; template using VectorOperators - = TreeContainer< + = TypeTree::TreeContainer< OperatorLists::template VecData, typename Basis::LocalView::TreeCache>; diff --git a/amdis/typetree/CMakeLists.txt b/amdis/typetree/CMakeLists.txt index fd487042785e6b0e0d82116fc63eb6b882f1c096..84a8cbf995b2a94259ac01993dce4b8452d01d2e 100644 --- a/amdis/typetree/CMakeLists.txt +++ b/amdis/typetree/CMakeLists.txt @@ -6,6 +6,6 @@ install(FILES Traits.hpp Traversal.hpp TreeContainer.hpp - TreeContainerTransformation.hpp + TreeContainerTrafo.hpp TreePath.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/typetree) diff --git a/amdis/typetree/TreeContainer.hpp b/amdis/typetree/TreeContainer.hpp index c0accf758c504f5642a06ffdeaf4bf178cd7ba23..2720580a097b57112e6ad251c494bdbb8568f87f 100644 --- a/amdis/typetree/TreeContainer.hpp +++ b/amdis/typetree/TreeContainer.hpp @@ -16,366 +16,326 @@ // NOTE: backport of dune/typetree/treecontainer.hh -namespace AMDiS +namespace AMDiS { +namespace TypeTree { + +template +class LeafNodeStorage { - /// \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 TreeContainerStorage +public: + template + LeafNodeStorage(V&& value) + : value_(FWD(value)) + {} + + LeafNodeStorage() + : value_() + {} + + Value& value() { return value_; } + Value const& value() const { return value_; } + + bool operator==(LeafNodeStorage const& other) const { - using Self = TreeContainerStorage; + return value_ == other.value_; + } - template - static constexpr decltype(auto) - accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<> const&) - { - return container.value(); - } +private: + Value value_; +}; - template - static constexpr decltype(auto) - accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath const& path) - { - auto head = Dune::TypeTree::treePathEntry(path,Dune::Indices::_0); - return accessByTreePath(container[head], pop_front(path)); - } +template +LeafNodeStorage(Value const&) + -> LeafNodeStorage; - 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 - decltype(auto) operator[](Dune::TypeTree::HybridTreePath const& path) const - { - return accessByTreePath(container_, path); - } - /// \brief Access a (mutable) element of the container by treepath - template - decltype(auto) operator[](Dune::TypeTree::HybridTreePath const& path) - { - return accessByTreePath(container_, path); - } +template +class InnerNodeStorage +{ +public: + template + InnerNodeStorage(V&& value, C&& container) + : value_(FWD(value)) + , container_(FWD(container)) + {} - /// \brief Obtain the container (const) - Container const& data() const - { - return container_; - } + InnerNodeStorage() + : value_() + , container_() + {} - /// \brief Obtain the container (mutable) - Container& data() - { - return container_; - } + template + auto& operator[](I const& i) { return container_[i]; } - /// \brief Compare two containers for equality - bool operator==(TreeContainerStorage const& other) const - { - return container_ == other.container_; - } + template + auto const& operator[](I const& i) const { return container_[i]; } - /// \brief Compare two containers for inequality - bool operator!=(TreeContainerStorage const& other) const - { - return container_ != other.container_; + Value& value() { return value_; } + Value const& value() const { return value_; } + + 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 +InnerNodeStorage(Value const&, Container const&) + -> InnerNodeStorage; + + +/// \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 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 + 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()); + } + else + if constexpr (Node::isComposite) { + return makeInnerNodeStorage(node, + Ranges::applyIndices( + [&](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: - Container container_; - }; + template + 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 TreeContainerStorage +{ + using Self = TreeContainerStorage; - namespace Impl + template + static constexpr auto + accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<>) -> decltype(container.value()) { - template - class ValueAndContainer - { - public: - template - ValueAndContainer(V&& value, C&& container) - : value_(FWD(value)) - , container_(FWD(container)) - {} - - ValueAndContainer() - : value_() - , container_() - {} - - template - auto& operator[](I const& i) { return container_[i]; } - - template - 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 ValueAndContainer - { - public: - template = 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 ValueAndContainer - { - public: - template - ValueAndContainer(Ignore, C&& container) - : container_(FWD(container)) - {} - - ValueAndContainer() - : container_() - {} - - template - auto& operator[](I const& i) { return container_[i]; } - - template - 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 - ValueAndContainer(Value const&, Container const&) - -> ValueAndContainer; - - template - ValueAndContainer(Value const&) - -> ValueAndContainer; - - - /// \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 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 - 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()}; - } - else - if constexpr (Node::isComposite) { - return ValueAndContainer{ - value(node), - Ranges::applyIndices( - [&](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 - 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 - auto makeTreeContainer(Tree const& tree, NodeToValue&& nodeToValue) + return container.value(); + } + + template + static constexpr decltype(auto) + accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath const& path) { - auto f = std::ref(nodeToValue); - auto factory = Impl::ContainerFactory(f); - return TreeContainerStorage{factory(tree)}; + 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 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 + decltype(auto) operator[](Dune::TypeTree::HybridTreePath const& path) const + { + return accessByTreePath(container_, path); + } - /// \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 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. - * - * \tparam Value Type of the values to be stored for the leafs. Should be default - * constructible. - * \param nodeToValue A predicate used to generate the stored values for the nodes - * - * \returns A container matching the tree structure - */ - template - auto makeTreeContainer(Tree const& tree) + /// \brief Access a (mutable) element of the container by treepath + template + decltype(auto) operator[](Dune::TypeTree::HybridTreePath 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 makeTreeContainer(tree, [](auto&&) { return Value{}; }); + return container_ == other.container_; } - template class NodeData, bool leafOnly = false, class Tree> - auto makeTreeContainer(Tree const& tree) + /// \brief Compare two containers for inequality + bool operator!=(TreeContainerStorage const& other) const { - return makeTreeContainer(tree, [](auto&& node) { return NodeData{}; }); + return container_ != other.container_; } - /// Alias to container type generated by makeTreeContainer for given tree type and - /// uniform value type - template - using UniformTreeContainer - = TYPEOF(makeTreeContainer(std::declval())); +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 + * 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. + * + * \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 +auto treeContainer(Tree const& tree, NodeToValue nodeToValue) +{ + auto factory = ContainerFactory{nodeToValue}; + return TreeContainerStorage{factory(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 + * 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. + * + * \tparam Value Type of the values to be stored for the leafs. Should be default + * constructible. + * \param nodeToValue A predicate used to generate the stored values for the nodes + * + * \returns A container matching the tree structure + */ +template +auto treeContainer(Tree const& tree) +{ + return treeContainer(tree, [](auto&&) { return Value{}; }); +} + +template class NodeData, bool leafOnly = false, class Tree> +auto treeContainer(Tree const& tree) +{ + return treeContainer(tree, [](auto&& node) { return NodeData{}; }); +} + +/// Alias to container type generated by treeContainer for given tree type and +/// uniform value type +template +using UniformTreeContainer + = TYPEOF(treeContainer(std::declval())); - /// Alias to matrix-container type generated by makeTreeContainer for given tree types - /// and uniform value type - template - using UniformTreeMatrix - = UniformTreeContainer,RowTree,leafOnly>; +/// Alias to matrix-container type generated by treeContainer for given tree types +/// and uniform value type +template +using UniformTreeMatrix + = UniformTreeContainer,RowTree,leafOnly>; - /// Alias to container type generated by makeTreeContainer for give tree type and when - /// using NodeToValue to create values - template