Commit 0689eaae authored by Praetorius, Simon's avatar Praetorius, Simon

Reduce errors and compiletime in tree traversal

parent efebae43
#include(CheckIncludeFileCXX)
include(CheckCXXSourceCompiles)
#include(CheckCXXSymbolExists)
# fold expressions (a + ...)
check_cxx_source_compiles("
......@@ -30,4 +28,16 @@ check_cxx_source_compiles("
return f<1>();
}
" AMDIS_HAS_CXX_CONSTEXPR_IF
)
check_cxx_source_compiles("
#include <iostream>
#include <tuple>
int main()
{
auto tup = std::make_tuple(0, 'a', 3.14);
for... (auto elem : tup)
std::cout << elem << std::endl;
}
" AMDIS_HAS_EXPANSION_STATEMENTS
)
\ No newline at end of file
......@@ -49,6 +49,7 @@
/* some detected compiler features may be used in AMDiS */
#cmakedefine AMDIS_HAS_CXX_FOLD_EXPRESSIONS 1
#cmakedefine AMDIS_HAS_CXX_CONSTEXPR_IF 1
#cmakedefine AMDIS_HAS_EXPANSION_STATEMENTS 1
/* end amdis
Everything below here will be overwritten
......
......@@ -24,4 +24,4 @@ add_dependencies(examples
stokes1.2d
stokes3.2d
navier_stokes.2d
convection_diffusion.2d)
\ No newline at end of file
convection_diffusion.2d)
......@@ -146,9 +146,10 @@ namespace AMDiS
if (!segment.boundary())
continue;
auto index = segment.boundarySegmentIndex();
Dune::Hybrid::ifElse(Dune::Std::is_detected<HasBoundaryId, Segment>{},
[&](auto id) { boundaryIds_[index] = id(segment).boundaryId(); });
Dune::Hybrid::ifElse(Dune::Std::is_detected<HasBoundaryId, Segment>{}, [&](auto id) {
auto index = segment.boundarySegmentIndex();
boundaryIds_[index] = id(segment).boundaryId();
});
}
}
}
......
......@@ -22,8 +22,8 @@
#include <amdis/Output.hpp>
#include <amdis/common/ConcurrentCache.hpp>
#include <amdis/typetree/Traversal.hpp>
#include <amdis/typetree/TreeContainer.hpp>
#include <amdis/typetree/Visitor.hpp>
namespace AMDiS
{
......@@ -135,7 +135,7 @@ namespace AMDiS
auto lv = basis_->localView();
auto const& idSet = gv.grid().localIdSet();
forEachLeafNode_(lv.tree(), [&](auto const& node, auto const& tp) {
for_each_leaf_node(lv.tree(), [&](auto const& node, auto const& tp) {
nodeDataTransfer_[tp].preAdaptInit(lv, coeff, node);
});
......@@ -148,7 +148,7 @@ namespace AMDiS
lv.bind(e);
auto& treeContainer = it.first->second;
forEachLeafNode_(lv.tree(), [&](auto const& node, auto const& tp) {
for_each_leaf_node(lv.tree(), [&](auto const& node, auto const& tp) {
nodeDataTransfer_[tp].cacheLocal(treeContainer[tp]);
});
}
......@@ -201,7 +201,7 @@ namespace AMDiS
};
restrictLocalCompleted = true;
forEachLeafNode_(lv.tree(), [&](auto const& node, auto const& tp) {
for_each_leaf_node(lv.tree(), [&](auto const& node, auto const& tp) {
restrictLocalCompleted &=
nodeDataTransfer_[tp].restrictLocal(father, treeContainer[tp], xInChildCached,
childContainer[tp], init);
......@@ -224,7 +224,7 @@ namespace AMDiS
auto gv = basis_->gridView();
auto lv = basis_->localView();
auto const& idSet = gv.grid().localIdSet();
forEachLeafNode_(lv.tree(), [&](auto const& node, auto const& tp) {
for_each_leaf_node(lv.tree(), [&](auto const& node, auto const& tp) {
nodeDataTransfer_[tp].postAdaptInit(lv, coeff, node);
});
......@@ -243,7 +243,7 @@ namespace AMDiS
if (it != persistentContainer_.end()) {
lv.bind(e);
auto const& treeContainer = it->second;
forEachLeafNode_(lv.tree(), [&](auto const& node, auto const& tp) {
for_each_leaf_node(lv.tree(), [&](auto const& node, auto const& tp) {
nodeDataTransfer_[tp].copyLocal(treeContainer[tp]);
});
finished_[index] = true;
......@@ -275,7 +275,7 @@ namespace AMDiS
return fatherGeo.local(childGeo.global(x));
};
forEachLeafNode_(lv.tree(), [&](auto const& node, auto const& tp) {
for_each_leaf_node(lv.tree(), [&](auto const& node, auto const& tp) {
nodeDataTransfer_[tp].prolongLocal(father, treeContainer[tp], xInFather, init);
});
......
......@@ -11,8 +11,8 @@
#include <amdis/BoundaryCondition.hpp>
#include <amdis/common/Concepts.hpp>
#include <amdis/typetree/RangeType.hpp>
#include <amdis/typetree/Traversal.hpp>
#include <amdis/typetree/TreeData.hpp>
#include <amdis/typetree/Visitor.hpp>
namespace AMDiS
{
......
......@@ -196,7 +196,7 @@ std::vector<D> PeriodicBC<D,MI>::
coords(Node const& tree, std::vector<std::size_t> const& localIndices) const
{
std::vector<D> dofCoords(localIndices.size());
AMDiS::forEachLeafNode_(tree, [&](auto const& node, auto const& tp)
for_each_leaf_node(tree, [&](auto const& node, auto const& tp)
{
std::size_t size = node.finiteElement().size();
auto geometry = node.element().geometry();
......
......@@ -177,7 +177,7 @@ void ProblemStat<Traits>::createMatricesAndVectors()
rhs_ = std::make_shared<SystemVector>(*globalBasis_, NO_OPERATION);
auto localView = globalBasis_->localView();
AMDiS::forEachNode_(localView.tree(), [&,this](auto const& node, auto treePath)
for_each_node(localView.tree(), [&,this](auto const& node, auto treePath)
{
std::string i = to_string(treePath);
estimates_[i].resize(globalBasis_->gridView().indexSet().size(0));
......@@ -205,7 +205,7 @@ void ProblemStat<Traits>::createMarker()
{
marker_.clear();
auto localView = globalBasis_->localView();
AMDiS::forEachNode_(localView.tree(), [&,this](auto const& node, auto treePath)
for_each_node(localView.tree(), [&,this](auto const& node, auto treePath)
{
std::string componentName = name_ + "->marker[" + to_string(treePath) + "]";
......@@ -232,7 +232,7 @@ void ProblemStat<Traits>::createFileWriter()
{
filewriter_.clear();
auto localView = globalBasis_->localView();
forEachNode_(localView.tree(), [&,this](auto const& node, auto treePath)
for_each_node(localView.tree(), [&,this](auto const& node, auto treePath)
{
std::string componentName = name_ + "->output[" + to_string(treePath) + "]";
......@@ -428,9 +428,9 @@ buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool as
rhs_->init(asmVector);
auto localView = globalBasis_->localView();
forEachNode_(localView.tree(), [&,this](auto const& rowNode, auto rowTp) {
for_each_node(localView.tree(), [&,this](auto const& rowNode, auto rowTp) {
auto rowBasis = Dune::Functions::subspaceBasis(*globalBasis_, rowTp);
forEachNode_(localView.tree(), [&,this](auto const& colNode, auto colTp) {
for_each_node(localView.tree(), [&,this](auto const& colNode, auto colTp) {
auto colBasis = Dune::Functions::subspaceBasis(*globalBasis_, colTp);
for (auto bc : dirichletBCs_[rowNode][colNode])
bc->init(rowBasis, colBasis);
......@@ -456,8 +456,8 @@ buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool as
systemMatrix_->finish(asmMatrix);
rhs_->finish(asmVector);
forEachNode_(localView.tree(), [&,this](auto const& rowNode, auto) {
forEachNode_(localView.tree(), [&,this](auto const& colNode, auto) {
for_each_node(localView.tree(), [&,this](auto const& rowNode, auto) {
for_each_node(localView.tree(), [&,this](auto const& colNode, auto) {
// finish boundary condition
for (auto bc : dirichletBCs_[rowNode][colNode])
bc->fillBoundaryCondition(*systemMatrix_, *solution_, *rhs_, rowNode, colNode);
......
......@@ -2,7 +2,6 @@
#include <initializer_list>
#include <amdis/common/Apply.hpp>
#include <amdis/common/Index.hpp>
#include <amdis/common/Range.hpp>
......@@ -16,34 +15,52 @@ namespace AMDiS
void ignored_evaluation(std::initializer_list<T>&&) { /* do nothing */ }
}
template <std::size_t... I, class Tuple, class Functor>
constexpr void for_each(std::index_sequence<I...>, Tuple&& tuple, Functor&& f)
{
using std::get;
#if AMDIS_HAS_EXPANSION_STATEMENTS
for... (auto&& t : tuple) { f(FWD(t)); }
#elif AMDIS_HAS_CXX_FOLD_EXPRESSIONS
(f(get<I>(tuple)),...);
#else
Impl_::ignored_evaluation<int>({0, (f(get<I>(tuple)), 0)...});
#endif
}
template <class Tuple, class Functor>
constexpr void for_each(Tuple&& tuple, Functor&& f)
{
#if AMDIS_HAS_CXX_FOLD_EXPRESSIONS
Tools::apply([f=std::move(f)](auto&&... t) { (f(FWD(t)),...); }, tuple);
#else
Tools::apply([f=std::move(f)](auto&&... t) {
Impl_::ignored_evaluation<int>({0, (f(FWD(t)), 0)...});
}, tuple);
#endif
Tools::for_each(std::make_index_sequence<Size_v<std::remove_reference_t<Tuple>>>{}, FWD(tuple), FWD(f));
}
template <std::size_t I0 = 0, std::size_t... I, class Functor>
constexpr void for_range(std::index_sequence<I...>, Functor&& f)
{
#if AMDIS_HAS_CXX_FOLD_EXPRESSIONS
(f(index_t<I0+I>{}),...);
#else
Impl_::ignored_evaluation<int>({0, (f(index_t<I0+I>{}), 0)...});
#endif
}
template <std::size_t I0, std::size_t I1, class Functor>
constexpr void for_range(index_t<I0> i0, index_t<I1> i1, Functor&& f)
{
Tools::for_each(range_t<I0,I1>{}, FWD(f));
Tools::for_range<I0>(std::make_index_sequence<std::size_t(I1-I0)>{}, FWD(f));
}
template <std::size_t N, class Functor>
constexpr void for_range(index_t<N>, Functor&& f)
{
Tools::for_each(range_t<0,N>{}, FWD(f));
Tools::for_range(std::make_index_sequence<N>{}, FWD(f));
}
template <std::size_t I0, std::size_t I1, class Functor>
constexpr void for_range(Functor&& f)
{
Tools::for_each(range_t<I0,I1>{}, FWD(f));
Tools::for_range<I0>(std::make_index_sequence<std::size_t(I1-I0)>{}, FWD(f));
}
} // end namespace Tools
......
......@@ -65,6 +65,12 @@ namespace AMDiS
template <class T>
using owner = T;
/// A functor with no operation
struct NoOp
{
template <class... T>
constexpr void operator()(T&&...) const { /* no nothing */ }
};
/// Create a unique_ptr by copy/move construction
template <class Obj>
......
......@@ -147,7 +147,7 @@ LocalFunction::operator()(Domain const& x) const
auto&& coefficients = *globalFunction_.dofVector_;
auto&& nodeToRangeEntry = globalFunction_.nodeToRangeEntry_;
forEachLeafNode_(*subTree_, [&,this](auto const& node, auto const& tp)
for_each_leaf_node(*subTree_, [&,this](auto const& node, auto const& tp)
{
auto&& fe = node.finiteElement();
auto&& localBasis = fe.localBasis();
......@@ -193,7 +193,7 @@ GradientLocalFunction::operator()(Domain const& x) const
auto&& coefficients = *globalFunction_.dofVector_;
auto&& nodeToRangeEntry = globalFunction_.nodeToRangeEntry_;
forEachLeafNode_(*subTree_, [&,this](auto const& node, auto const& tp)
for_each_leaf_node(*subTree_, [&,this](auto const& node, auto const& tp)
{
// TODO: may DOFVectorView::Range to FieldVector type if necessary
using LocalDerivativeTraits
......
......@@ -2,7 +2,7 @@
#include <amdis/Assembler.hpp>
#include <amdis/LocalOperator.hpp>
#include <amdis/typetree/Visitor.hpp>
#include <amdis/typetree/Traversal.hpp>
#include <amdis/utility/AssembleOperators.hpp>
namespace AMDiS {
......@@ -75,8 +75,8 @@ assemble(RowLocalView const& rowLocalView, ColLocalView const& colLocalView)
auto const& element = rowLocalView.element();
auto geometry = element.geometry();
forEachNode_(rowLocalView.tree(), [&](auto const& rowNode, auto) {
forEachNode_(colLocalView.tree(), [&](auto const& colNode, auto) {
for_each_node(rowLocalView.tree(), [&](auto const& rowNode, auto) {
for_each_node(colLocalView.tree(), [&](auto const& colNode, auto) {
auto& matOp = operators_[rowNode][colNode];
if (matOp) {
matOp.bind(element, geometry);
......
......@@ -2,7 +2,7 @@
#include <amdis/Assembler.hpp>
#include <amdis/LocalOperator.hpp>
#include <amdis/typetree/Visitor.hpp>
#include <amdis/typetree/Traversal.hpp>
#include <amdis/utility/AssembleOperators.hpp>
namespace AMDiS {
......@@ -66,7 +66,7 @@ assemble(LocalView const& localView)
auto const& element = localView.element();
auto geometry = element.geometry();
forEachNode_(localView.tree(), [&](auto const& node, auto) {
for_each_node(localView.tree(), [&](auto const& node, auto) {
auto& rhsOp = operators_[node];
if (rhsOp) {
rhsOp.bind(element, geometry);
......
......@@ -7,5 +7,4 @@ install(FILES
TreeContainer.hpp
TreeData.hpp
TreePath.hpp
Visitor.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/typetree)
This diff is collapsed.
......@@ -6,7 +6,7 @@
#include <vector>
#include <dune/typetree/typetree.hh>
#include <amdis/typetree/Visitor.hpp>
#include <amdis/typetree/Traversal.hpp>
namespace AMDiS
{
......@@ -195,10 +195,10 @@ namespace AMDiS
}
template <class Func>
void applyImpl(Func&& func, std::true_type) { forEachLeafNode_(basis_->localView().tree(), func); }
void applyImpl(Func&& func, std::true_type) { for_each_leaf_node(basis_->localView().tree(), func); }
template <class Func>
void applyImpl(Func&& func, std::false_type) { forEachNode_(basis_->localView().tree(), func); }
void applyImpl(Func&& func, std::false_type) { for_each_node(basis_->localView().tree(), func); }
protected:
Basis const* basis_ = nullptr;
......@@ -238,7 +238,7 @@ namespace AMDiS
void init(RowBasis const& rowBasis, ColBasis const& colBasis)
{
Super::init(rowBasis);
forEachNode_(rowBasis.localView().tree(), [&](auto const& node, auto&&)
for_each_node(rowBasis.localView().tree(), [&](auto const& node, auto&&)
{
(*this)[node].init(colBasis);
});
......
#pragma once
#include <dune/typetree/visitor.hh>
#include <amdis/typetree/Traversal.hpp>
namespace AMDiS
{
// from dune-typetree merge-request !2
namespace Impl
{
template <class PreFunc, class LeafFunc, class PostFunc>
class CallbackVisitor
: public Dune::TypeTree::TreeVisitor
{
public:
CallbackVisitor(PreFunc& preFunc, LeafFunc& leafFunc, PostFunc& postFunc)
: preFunc_(preFunc)
, leafFunc_(leafFunc)
, postFunc_(postFunc)
{}
template <typename Node, typename TreePath>
void pre(Node&& node, TreePath treePath)
{
preFunc_(node, treePath);
}
template <typename Node, typename TreePath>
void leaf(Node&& node, TreePath treePath)
{
leafFunc_(node, treePath);
}
template <typename Node, typename TreePath>
void post(Node&& node, TreePath treePath)
{
postFunc_(node, treePath);
}
private:
PreFunc& preFunc_;
LeafFunc& leafFunc_;
PostFunc& postFunc_;
};
template <class PreFunc, class LeafFunc, class PostFunc>
auto callbackVisitor(PreFunc& preFunc, LeafFunc& leafFunc, PostFunc& postFunc)
{
return CallbackVisitor<PreFunc, LeafFunc, PostFunc>(preFunc, leafFunc, postFunc);
}
} // namespace Impl
/**
* \brief Traverse tree and visit each node
*
* All passed callback functions are called with the
* node and corresponding treepath as arguments.
*
* \param tree The tree to traverse
* \param preFunc This function is called for each inner node before visiting its children
* \param leafFunc This function is called for each leaf node
* \param postFunc This function is called for each inner node after visiting its children
*/
template <class Tree, class PreFunc, class LeafFunc, class PostFunc>
void forEachNode_(Tree&& tree, PreFunc&& preFunc, LeafFunc&& leafFunc, PostFunc&& postFunc)
{
traverseTree(tree, Impl::callbackVisitor(preFunc, leafFunc, postFunc));
}
/**
* \brief Traverse tree and visit each node
*
* All passed callback functions are called with the
* node and corresponding treepath as arguments.
*
* \param tree The tree to traverse
* \param innerFunc This function is called for each inner node before visiting its children
* \param leafFunc This function is called for each leaf node
*/
template <class Tree, class InnerFunc, class LeafFunc>
void forEachNode_(Tree&& tree, InnerFunc&& innerFunc, LeafFunc&& leafFunc)
{
auto nop = [](auto&&... args) {};
forEachNode_(tree, innerFunc, leafFunc, nop);
}
/**
* \brief Traverse tree and visit each node
*
* The passed callback function is called with the
* node and corresponding treepath as arguments.
*
* \param tree The tree to traverse
* \param nodeFunc This function is called for each node
*/
template <class Tree, class NodeFunc>
void forEachNode_(Tree&& tree, NodeFunc&& nodeFunc)
{
forEachNode_(tree, nodeFunc, nodeFunc);
}
/**
* \brief Traverse tree and visit each leaf node
*
* The passed callback function is called with the
* node and corresponding treepath as arguments.
*
* \param tree The tree to traverse
* \param leafFunc This function is called for each leaf node
*/
template <class Tree, class LeafFunc>
void forEachLeafNode_(Tree&& tree, LeafFunc&& leafFunc)
{
auto nop = [](auto&&... args) {};
forEachNode_(tree, nop, leafFunc, nop);
}
} // end namespace AMDiS
......@@ -68,7 +68,7 @@ auto makeProblem(typename BasisCreator::GlobalBasis::GridView::Grid& grid, Fcts
// interpolate given function to initial grid
int k = 0;
AMDiS::forEachLeafNode_(localView.tree(), [&](auto const& node, auto tp)
for_each_leaf_node(localView.tree(), [&](auto const& node, auto tp)
{
interpolate(globalBasis, tp, prob.solution(tp).coefficients(), funcs[k]);
k++;
......@@ -90,7 +90,7 @@ double calcError(Problem const& prob, Fcts const& funcs)
int k = 0;
// interpolate given function onto reference vector
AMDiS::forEachLeafNode_(localView.tree(), [&](auto const& node, auto tp)
for_each_leaf_node(localView.tree(), [&](auto const& node, auto tp)
{
interpolate(globalBasis, tp, ref, funcs[k]);
k++;
......
......@@ -25,7 +25,7 @@ bool operator==(TreeData<Basis,NodeData,false> const& t1, TreeData<Basis,NodeDat
AMDIS_TEST(t1.basis() == t2.basis() && t1.basis() != nullptr);
bool same = true;
AMDiS::forEachNode_(t1.basis()->localView().tree(), [&](auto const& node, auto) {
for_each_node(t1.basis()->localView().tree(), [&](auto const& node, auto) {
same = same && (t1[node] == t2[node]);
});
......@@ -38,7 +38,7 @@ bool operator==(TreeData<Basis,NodeData,true> const& t1, TreeData<Basis,NodeData
AMDIS_TEST(t1.basis() == t2.basis() && t1.basis() != nullptr);
bool same = true;
AMDiS::forEachLeafNode_(t1.basis()->localView().tree(), [&](auto const& node, auto) {
for_each_leaf_node(t1.basis()->localView().tree(), [&](auto const& node, auto) {
same = same && (t1[node] == t2[node]);
});
......@@ -73,7 +73,7 @@ int main ()
TreeData<Basis, NodeData, false> treeData;
treeData.init(basis);
AMDiS::forEachNode_(tree, [&](auto const& node, auto) {
for_each_node(tree, [&](auto const& node, auto) {
treeData[node] = double(node.treeIndex());
});
......@@ -109,7 +109,7 @@ int main ()
TreeData<Basis, NodeData, true> treeData;
treeData.init(basis);
AMDiS::forEachLeafNode_(tree, [&](auto const& node, auto) {
for_each_leaf_node(tree, [&](auto const& node, auto) {
treeData[node] = double(node.treeIndex());
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment