Liebe Gitlab-Nutzerin, lieber Gitlab-Nutzer,
es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Die Konten der externen Nutzer:innen sind über den Reiter "Standard" erreichbar.
Die Administratoren


Dear Gitlab user,
it is now possible to log in to our service using the ZIH login/LDAP. The accounts of external users can be accessed via the "Standard" tab.
The administrators

Commit 98d84228 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Merge branch 'feature/tree_container' into 'master'

add extended TreeContainer implementation and replace TreeData

See merge request !193
parents 1f3895e9 a7a4301c
Pipeline #4517 failed with stage
in 15 seconds
......@@ -57,8 +57,6 @@ namespace AMDiS
, colBasis_(colBasis)
, updatePattern_(true)
{
operators_.init(*rowBasis_, *colBasis_);
auto const rowSize = rowBasis_->localView().maxSize();
auto const colSize = colBasis_->localView().maxSize();
elementMatrix_.resize(rowSize, colSize);
......
......@@ -20,13 +20,15 @@ addOperator(ContextTag contextTag, Expr const& expr,
static_assert( Concepts::PreTreePath<ColTreePath>,
"col must be a valid treepath, or an integer/index-constant");
auto i = child(this->rowBasis()->localView().tree(), makeTreePath(row));
auto j = child(this->colBasis()->localView().tree(), makeTreePath(col));
auto i = makeTreePath(row);
auto node_i = child(this->rowBasis()->localView().tree(), i);
auto j = makeTreePath(col);
auto node_j = child(this->colBasis()->localView().tree(), j);
using LocalContext = typename ContextTag::type;
using Tr = DefaultAssemblerTraits<LocalContext, ElementMatrix>;
auto op = makeLocalOperator<LocalContext>(expr, this->rowBasis()->gridView());
auto localAssembler = makeUniquePtr(makeAssembler<Tr>(std::move(op), i, j));
auto localAssembler = makeUniquePtr(makeAssembler<Tr>(std::move(op), node_i, node_j));
operators_[i][j].push(contextTag, std::move(localAssembler));
updatePattern_ = true;
......@@ -47,9 +49,9 @@ assemble(RowLocalView const& rowLocalView, ColLocalView const& colLocalView)
auto const& element = rowLocalView.element();
auto geometry = element.geometry();
for_each_node(rowLocalView.tree(), [&](auto const& rowNode, auto) {
for_each_node(colLocalView.tree(), [&](auto const& colNode, auto) {
auto& matOp = operators_[rowNode][colNode];
for_each_node(rowLocalView.tree(), [&](auto const& rowNode, auto rowTp) {
for_each_node(colLocalView.tree(), [&](auto const& colNode, auto colTp) {
auto& matOp = operators_[rowTp][colTp];
if (matOp) {
matOp.bind(element, geometry);
assembleOperators(gv, element, matOp, makeMatrixAssembler(rowNode, colNode, elementMatrix_));
......
......@@ -3,7 +3,7 @@
#include <list>
#include <memory>
#include <amdis/typetree/TreeData.hpp>
#include <amdis/typetree/TreeContainer.hpp>
namespace AMDiS
{
......@@ -48,6 +48,8 @@ namespace AMDiS
/// Container for storing shared pointers to boundary conditions indexed by their position in
/// the basis tree, see \ref MatrixData.
template <class Mat, class Sol, class Rhs, class RB, class CB>
using BoundaryConditions = MatrixData<RB, CB, BCData<Mat, Sol, Rhs>::template type>;
using BoundaryConditions
= TreeMatrix<BCData<Mat, Sol, Rhs>::template type,
typename RB::LocalView::Tree, typename CB::LocalView::Tree>;
} // end namespace AMDiS
......@@ -94,7 +94,7 @@ namespace AMDiS
template <class Node>
using NodeElementData = typename NodeDataTransfer<Node, Container, Basis>::NodeElementData;
using ElementData = TYPEOF(makeTreeContainer<NodeElementData>(std::declval<const Tree&>()));
using ElementData = 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 = TYPEOF(makeTreeContainer<NDT>(std::declval<const Tree&>()));
using NodeDataTransferContainer = TreeContainer<NDT,Tree,true>;
NodeDataTransferContainer nodeDataTransfer_;
};
......
......@@ -46,7 +46,7 @@ template <class C, class B>
DataTransfer<C,B>::DataTransfer(std::shared_ptr<B const> basis)
: basis_(std::move(basis))
, mapper_(basis_->gridView().grid(), Dune::mcmgElementLayout())
, nodeDataTransfer_(makeTreeContainer<NDT>(basis_->localView().tree()))
, 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>(lv.tree()));
auto it = persistentContainer_.emplace(idSet.id(e), makeTreeContainer<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>(lv.tree()));
auto it = persistentContainer_.emplace(idSet.id(father), makeTreeContainer<NodeElementData,true>(lv.tree()));
if (!it.second)
continue;
......
......@@ -44,8 +44,6 @@ namespace AMDiS
: Super(*basis)
, basis_(basis)
{
operators_.init(*basis);
auto const localSize = basis->localView().maxSize();
elementVector_.resize(localSize);
}
......
......@@ -18,12 +18,13 @@ addOperator(ContextTag contextTag, Expr const& expr, TreePath path)
static_assert( Concepts::PreTreePath<TreePath>,
"path must be a valid treepath, or an integer/index-constant");
auto i = child(this->basis()->localView().tree(), makeTreePath(path));
auto i = makeTreePath(path);
auto node = child(this->basis()->localView().tree(), i);
using LocalContext = typename ContextTag::type;
using Tr = DefaultAssemblerTraits<LocalContext, ElementVector>;
auto op = makeLocalOperator<LocalContext>(expr, this->basis()->gridView());
auto localAssembler = makeUniquePtr(makeAssembler<Tr>(std::move(op), i));
auto localAssembler = makeUniquePtr(makeAssembler<Tr>(std::move(op), node));
operators_[i].push(contextTag, std::move(localAssembler));
}
......@@ -41,8 +42,8 @@ assemble(LocalView const& localView)
auto const& element = localView.element();
auto geometry = element.geometry();
for_each_node(localView.tree(), [&](auto const& node, auto) {
auto& rhsOp = operators_[node];
for_each_node(localView.tree(), [&](auto const& node, auto tp) {
auto& rhsOp = operators_[tp];
if (rhsOp) {
rhsOp.bind(element, geometry);
assembleOperators(gv, element, rhsOp, makeVectorAssembler(node, elementVector_));
......
......@@ -5,7 +5,7 @@
#include <amdis/BoundarySubset.hpp>
#include <amdis/AssemblerInterface.hpp>
#include <amdis/typetree/TreeData.hpp>
#include <amdis/typetree/TreeContainer.hpp>
namespace AMDiS
{
......@@ -141,10 +141,15 @@ namespace AMDiS
template <class RowBasis, class ColBasis, class ElementMatrix>
using MatrixOperators
= MatrixData<RowBasis, ColBasis, OperatorLists<typename RowBasis::GridView,ElementMatrix>::template MatData>;
= TreeMatrix<
OperatorLists<typename RowBasis::GridView,ElementMatrix>::template MatData,
typename RowBasis::LocalView::Tree,
typename ColBasis::LocalView::Tree>;
template <class GlobalBasis, class ElementVector>
template <class Basis, class ElementVector>
using VectorOperators
= VectorData<GlobalBasis, OperatorLists<typename GlobalBasis::GridView,ElementVector>::template VecData>;
= TreeContainer<
OperatorLists<typename Basis::GridView,ElementVector>::template VecData,
typename Basis::LocalView::Tree>;
} // end namespace AMDiS
......@@ -197,7 +197,7 @@ auto PeriodicBC<Mat, Sol, Rhs, Basis, TP>::
coords(Node const& tree, std::vector<std::size_t> const& localIndices) const
{
std::vector<Domain> dofCoords(localIndices.size());
for_each_leaf_node(tree, [&](auto const& node, auto const& tp)
for_each_leaf_node(tree, [&](auto const& node, auto&&)
{
std::size_t size = node.finiteElement().size();
auto geometry = node.element().geometry();
......
......@@ -33,17 +33,12 @@
#include <amdis/ProblemStatBase.hpp>
#include <amdis/ProblemStatTraits.hpp>
#include <amdis/StandardProblemIteration.hpp>
#include <amdis/common/SharedPtr.hpp>
#include <amdis/common/TupleUtility.hpp>
#include <amdis/common/TypeTraits.hpp>
#include <amdis/GridFunctions.hpp>
#include <amdis/gridfunctions/DiscreteFunction.hpp>
#include <amdis/io/FileWriterBase.hpp>
#include <amdis/typetree/TreeData.hpp>
#include <amdis/typetree/TreePath.hpp>
namespace AMDiS
......@@ -305,7 +300,7 @@ namespace AMDiS
bool storeMatrixData = false) override;
/// Implementation of \ref ProblemStatBase::estimate.
void estimate(AdaptInfo& adaptInfo) override { /* do nothing. */ }
void estimate(AdaptInfo& /*adaptInfo*/) override { /* do nothing. */ }
/// Implementation of \ref ProblemStatBase::refineMesh.
Flag adaptGrid(AdaptInfo& adaptInfo) override;
......
......@@ -209,10 +209,7 @@ void ProblemStat<Traits>::createGlobalBasisImpl(std::false_type)
template <class Traits>
void ProblemStat<Traits>::initGlobalBasis()
{
boundaryConditions_.init(*globalBasis_, *globalBasis_);
}
void ProblemStat<Traits>::initGlobalBasis() {}
template <class Traits>
......@@ -227,7 +224,7 @@ void ProblemStat<Traits>::createMatricesAndVectors()
rhs_ = std::make_shared<SystemVector>(globalBasis_);
auto localView = globalBasis_->localView();
for_each_node(localView.tree(), [&,this](auto const& node, auto treePath) -> void
for_each_node(localView.tree(), [&,this](auto&&, auto treePath) -> void
{
std::string i = to_string(treePath);
estimates_[i].resize(globalBasis_->gridView().indexSet().size(0));
......@@ -255,7 +252,7 @@ void ProblemStat<Traits>::createMarker()
{
marker_.clear();
auto localView = globalBasis_->localView();
for_each_node(localView.tree(), [&,this](auto const& node, auto treePath) -> void
for_each_node(localView.tree(), [&,this](auto&&, auto treePath) -> void
{
std::string componentName = name_ + "->marker[" + to_string(treePath) + "]";
......@@ -358,7 +355,7 @@ addPeriodicBC(BoundaryType id, WorldMatrix const& matrix, WorldVector const& vec
template <class Traits>
void ProblemStat<Traits>::
solve(AdaptInfo& adaptInfo, bool createMatrixData, bool storeMatrixData)
solve(AdaptInfo& /*adaptInfo*/, bool createMatrixData, bool storeMatrixData)
{
Dune::Timer t;
......@@ -449,7 +446,7 @@ globalRefine(int n)
template <class Traits>
Flag ProblemStat<Traits>::
adaptGrid(AdaptInfo& adaptInfo)
adaptGrid(AdaptInfo& /*adaptInfo*/)
{
Dune::Timer t;
......@@ -470,9 +467,9 @@ buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool as
Dune::Timer t2;
auto localView = globalBasis_->localView();
for_each_node(localView.tree(), [&,this](auto const& rowNode, auto rowTp) -> void {
for_each_node(localView.tree(), [&,this](auto const& colNode, auto colTp) -> void {
for (auto bc : boundaryConditions_[rowNode][colNode])
for_each_node(localView.tree(), [&](auto&&, auto rowTp) -> void {
for_each_node(localView.tree(), [&](auto&&, auto colTp) -> void {
for (auto bc : boundaryConditions_[rowTp][colTp])
bc->init();
});
});
......@@ -509,10 +506,10 @@ buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool as
t2.reset();
solution_->resize(sizeInfo(*globalBasis_));
for_each_node(localView.tree(), [&,this](auto const& rowNode, auto row_tp) -> void {
for_each_node(localView.tree(), [&,this](auto const& colNode, auto col_tp) -> void {
for_each_node(localView.tree(), [&](auto&&, auto rowTp) -> void {
for_each_node(localView.tree(), [&](auto&&, auto colTp) -> void {
// finish boundary condition
for (auto bc : boundaryConditions_[rowNode][colNode])
for (auto bc : boundaryConditions_[rowTp][colTp])
bc->apply(*systemMatrix_, *solution_, *rhs_);
});
});
......
......@@ -5,6 +5,5 @@ install(FILES
RangeType.hpp
Traversal.hpp
TreeContainer.hpp
TreeData.hpp
TreePath.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/typetree)
......@@ -18,20 +18,217 @@
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_()
{}
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_;
};
namespace Impl
{
template <class Value, class Container>
class ValueAndContainer
{
public:
template <class V, class C>
ValueAndContainer(V&& value, C&& container)
: 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 LeafToValue Type of a predicate that determines the stored values at the leafs
*/
template <class LeafToValue>
* 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:
......@@ -41,25 +238,29 @@ namespace AMDiS
*
* \param A predicate used to generate the stored values for the leaves
*/
ContainerFactory(LeafToValue leafToValue)
: leafToValue_(std::move(leafToValue))
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
auto operator()(Node const& node) const
{
if constexpr (Node::isLeaf)
return leafToValue_(node);
return ValueAndContainer{value(node)};
else
if constexpr (Node::isPower) {
using TransformedChild = decltype((*this)(node.child(0)));
return std::array<TransformedChild, Node::degree()>();
return ValueAndContainer{
value(node),
std::array<TransformedChild, Node::degree()>()};
}
else
if constexpr (Node::isComposite) {
return Tools::apply_indices<Node::degree()>(
[&](auto... i) { return Dune::makeTupleVector((*this)(node.child(i))...); });
return ValueAndContainer{
value(node),
Tools::apply_indices<Node::degree()>(
[&](auto... i) { return Dune::makeTupleVector((*this)(node.child(i))...); })};
}
else {
static_assert(Node::isLeaf || Node::isPower || Node::isComposite,
......@@ -68,93 +269,23 @@ namespace AMDiS
}
}
private:
LeafToValue leafToValue_;
};
/// \brief Wrap nested container to provide a VectorBackend
template <class Container>
class TreeContainerVectorBackend
{
using Self = TreeContainerVectorBackend;
template <class C>
static constexpr decltype(auto) accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<> const& path)
{
return container;
}
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
TreeContainerVectorBackend()
: container_()
{}
/// \brief Construct the tree-container from a given container storage
TreeContainerVectorBackend(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