Commit a090eb81 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Introduce Traits class for checking whether Tree can be accessed by given TreePath

parent 1aae0253
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <amdis/GridFunctions.hpp> #include <amdis/GridFunctions.hpp>
#include <amdis/gridfunctions/DiscreteFunction.hpp> #include <amdis/gridfunctions/DiscreteFunction.hpp>
#include <amdis/io/FileWriterBase.hpp> #include <amdis/io/FileWriterBase.hpp>
#include <amdis/typetree/Traits.hpp>
#include <amdis/typetree/TreePath.hpp> #include <amdis/typetree/TreePath.hpp>
namespace AMDiS namespace AMDiS
...@@ -103,8 +104,7 @@ namespace AMDiS ...@@ -103,8 +104,7 @@ namespace AMDiS
/// \brief Constructor taking a grid and basis. /// \brief Constructor taking a grid and basis.
/// Wraps both in shared pointers. /// Wraps both in shared pointers.
template <class Grid_, class Basis_, template <class Grid_, class Basis_, class B_ = Underlying_t<Basis_>,
class B_ = Underlying_t<Basis_>,
REQUIRES(Concepts::GlobalBasis<B_>)> REQUIRES(Concepts::GlobalBasis<B_>)>
ProblemStat(std::string const& name, Grid_&& grid, Basis_&& globalBasis) ProblemStat(std::string const& name, Grid_&& grid, Basis_&& globalBasis)
: ProblemStat(name, FWD(grid)) : ProblemStat(name, FWD(grid))
...@@ -114,8 +114,7 @@ namespace AMDiS ...@@ -114,8 +114,7 @@ namespace AMDiS
/// \brief Constructor taking a grid and pre-basis factory to create a global basis /// \brief Constructor taking a grid and pre-basis factory to create a global basis
/// on the fly. /// on the fly.
template <class Grid_, class PBF_, template <class Grid_, class PBF_, class GV_ = typename Underlying_t<Grid_>::LeafGridView,
class GV_ = typename Underlying_t<Grid_>::LeafGridView,
REQUIRES(Concepts::PreBasisFactory<PBF_, GV_, MultiIndex_t<PBF_>>)> REQUIRES(Concepts::PreBasisFactory<PBF_, GV_, MultiIndex_t<PBF_>>)>
ProblemStat(std::string const& name, Grid_&& grid, PBF_ const& preBasisFactory) ProblemStat(std::string const& name, Grid_&& grid, PBF_ const& preBasisFactory)
: ProblemStat(name, FWD(grid)) : ProblemStat(name, FWD(grid))
...@@ -161,7 +160,13 @@ namespace AMDiS ...@@ -161,7 +160,13 @@ namespace AMDiS
template <class Operator, class RowTreePath = RootTreePath, class ColTreePath = RootTreePath> template <class Operator, class RowTreePath = RootTreePath, class ColTreePath = RootTreePath>
void addMatrixOperator(Operator const& op, RowTreePath row = {}, ColTreePath col = {}) void addMatrixOperator(Operator const& op, RowTreePath row = {}, ColTreePath col = {})
{ {
systemMatrix_->addOperator(tag::element_operator<Element>{}, op, row, col); static constexpr bool isValidTreePath =
Concepts::ValidTreePath<typename GlobalBasis::LocalView::Tree, RowTreePath> &&
Concepts::ValidTreePath<typename GlobalBasis::LocalView::Tree, ColTreePath>;
static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!");
if constexpr (isValidTreePath)
systemMatrix_->addOperator(tag::element_operator<Element>{}, op, row, col);
} }
/// Operator evaluated on the boundary of the domain with boundary index `b` /// Operator evaluated on the boundary of the domain with boundary index `b`
...@@ -187,7 +192,13 @@ namespace AMDiS ...@@ -187,7 +192,13 @@ namespace AMDiS
void addMatrixOperator(BoundaryType b, Operator const& op, RowTreePath row = {}, ColTreePath col = {}) void addMatrixOperator(BoundaryType b, Operator const& op, RowTreePath row = {}, ColTreePath col = {})
{ {
using I = typename GridView::Intersection; using I = typename GridView::Intersection;
systemMatrix_->addOperator(tag::boundary_operator<I>{*boundaryManager_,b}, op, row, col); static constexpr bool isValidTreePath =
Concepts::ValidTreePath<typename GlobalBasis::LocalView::Tree, RowTreePath> &&
Concepts::ValidTreePath<typename GlobalBasis::LocalView::Tree, ColTreePath>;
static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!");
if constexpr (isValidTreePath)
systemMatrix_->addOperator(tag::boundary_operator<I>{*boundaryManager_,b}, op, row, col);
} }
/** @} */ /** @} */
...@@ -212,7 +223,12 @@ namespace AMDiS ...@@ -212,7 +223,12 @@ namespace AMDiS
template <class Operator, class TreePath = RootTreePath> template <class Operator, class TreePath = RootTreePath>
void addVectorOperator(Operator const& op, TreePath path = {}) void addVectorOperator(Operator const& op, TreePath path = {})
{ {
rhs_->addOperator(tag::element_operator<Element>{}, op, path); static constexpr bool isValidTreePath =
Concepts::ValidTreePath<typename GlobalBasis::LocalView::Tree, TreePath>;
static_assert(isValidTreePath, "Invalid treepath passed to addVectorOperator!");
if constexpr (isValidTreePath)
rhs_->addOperator(tag::element_operator<Element>{}, op, path);
} }
/// Operator evaluated on the boundary of the domain with boundary index `b` /// Operator evaluated on the boundary of the domain with boundary index `b`
...@@ -236,7 +252,12 @@ namespace AMDiS ...@@ -236,7 +252,12 @@ namespace AMDiS
void addVectorOperator(BoundaryType b, Operator const& op, TreePath path = {}) void addVectorOperator(BoundaryType b, Operator const& op, TreePath path = {})
{ {
using I = typename GridView::Intersection; using I = typename GridView::Intersection;
rhs_->addOperator(tag::boundary_operator<I>{*boundaryManager_,b}, op, path); static constexpr bool isValidTreePath =
Concepts::ValidTreePath<typename GlobalBasis::LocalView::Tree, TreePath>;
static_assert(isValidTreePath, "Invalid treepath passed to addVectorOperator!");
if constexpr (isValidTreePath)
rhs_->addOperator(tag::boundary_operator<I>{*boundaryManager_,b}, op, path);
} }
/** @} */ /** @} */
......
...@@ -293,20 +293,28 @@ template <class Traits> ...@@ -293,20 +293,28 @@ template <class Traits>
void ProblemStat<Traits>:: void ProblemStat<Traits>::
addDirichletBC(Predicate const& predicate, RowTreePath row, ColTreePath col, Values const& values) addDirichletBC(Predicate const& predicate, RowTreePath row, ColTreePath col, Values const& values)
{ {
static constexpr bool isValidPredicate = Concepts::Functor<Predicate, bool(WorldVector)>;
static_assert( Concepts::Functor<Predicate, bool(WorldVector)>, static_assert( Concepts::Functor<Predicate, bool(WorldVector)>,
"Function passed to addDirichletBC for `predicate` does not model the Functor<bool(WorldVector)> concept"); "Function passed to addDirichletBC for `predicate` does not model the Functor<bool(WorldVector)> concept");
auto localView = globalBasis_->localView(); static constexpr bool isValidTreePath =
auto i = makeTreePath(row); Concepts::ValidTreePath<typename GlobalBasis::LocalView::Tree, RowTreePath> &&
auto j = makeTreePath(col); Concepts::ValidTreePath<typename GlobalBasis::LocalView::Tree, ColTreePath>;
auto rowBasis = Dune::Functions::subspaceBasis(*globalBasis_, i); static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addDirichletBC!");
auto colBasis = Dune::Functions::subspaceBasis(*globalBasis_, j);
if constexpr (isValidPredicate && isValidTreePath) {
auto localView = globalBasis_->localView();
auto i = makeTreePath(row);
auto j = makeTreePath(col);
auto rowBasis = Dune::Functions::subspaceBasis(*globalBasis_, i);
auto colBasis = Dune::Functions::subspaceBasis(*globalBasis_, j);
auto valueGridFct = makeGridFunction(values, this->gridView()); auto valueGridFct = makeGridFunction(values, this->gridView());
auto bc = makeDirichletBC<SystemMatrix, SolutionVector, SystemVector>( auto bc = makeDirichletBC<SystemMatrix, SolutionVector, SystemVector>(
std::move(rowBasis), std::move(colBasis), {predicate}, valueGridFct); std::move(rowBasis), std::move(colBasis), {predicate}, valueGridFct);
boundaryConditions_[i][j].push_back(makeUniquePtr(std::move(bc))); boundaryConditions_[i][j].push_back(makeUniquePtr(std::move(bc)));
}
} }
...@@ -316,17 +324,24 @@ template <class Traits> ...@@ -316,17 +324,24 @@ template <class Traits>
void ProblemStat<Traits>:: void ProblemStat<Traits>::
addDirichletBC(BoundaryType id, RowTreePath row, ColTreePath col, Values const& values) addDirichletBC(BoundaryType id, RowTreePath row, ColTreePath col, Values const& values)
{ {
auto localView = globalBasis_->localView(); static constexpr bool isValidTreePath =
auto i = makeTreePath(row); Concepts::ValidTreePath<typename GlobalBasis::LocalView::Tree, RowTreePath> &&
auto j = makeTreePath(col); Concepts::ValidTreePath<typename GlobalBasis::LocalView::Tree, ColTreePath>;
auto rowBasis = Dune::Functions::subspaceBasis(*globalBasis_, i); static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addDirichletBC!");
auto colBasis = Dune::Functions::subspaceBasis(*globalBasis_, j);
if constexpr (isValidTreePath) {
auto valueGridFct = makeGridFunction(values, this->gridView()); auto localView = globalBasis_->localView();
auto i = makeTreePath(row);
auto bc = makeDirichletBC<SystemMatrix, SolutionVector, SystemVector>( auto j = makeTreePath(col);
std::move(rowBasis), std::move(colBasis), {*boundaryManager_, id}, valueGridFct); auto rowBasis = Dune::Functions::subspaceBasis(*globalBasis_, i);
boundaryConditions_[i][j].push_back(makeUniquePtr(std::move(bc))); auto colBasis = Dune::Functions::subspaceBasis(*globalBasis_, j);
auto valueGridFct = makeGridFunction(values, this->gridView());
auto bc = makeDirichletBC<SystemMatrix, SolutionVector, SystemVector>(
std::move(rowBasis), std::move(colBasis), {*boundaryManager_, id}, valueGridFct);
boundaryConditions_[i][j].push_back(makeUniquePtr(std::move(bc)));
}
} }
......
...@@ -3,6 +3,7 @@ install(FILES ...@@ -3,6 +3,7 @@ install(FILES
FiniteElementType.hpp FiniteElementType.hpp
MultiIndex.hpp MultiIndex.hpp
RangeType.hpp RangeType.hpp
Traits.hpp
Traversal.hpp Traversal.hpp
TreeContainer.hpp TreeContainer.hpp
TreePath.hpp TreePath.hpp
......
#pragma once
#include <type_traits>
#include <dune/typetree/treepath.hh>
#include <amdis/typetree/TreePath.hpp>
namespace AMDiS
{
namespace Traits
{
template <class Tree, class TreePath, class NodeTag = typename Tree::NodeTag>
struct IsValidTreePath;
// empty treepath
template <class Tree, class NodeTag>
struct IsValidTreePath<Tree, Dune::TypeTree::HybridTreePath<>, NodeTag>
: std::true_type {};
// leaf nodes
template <class Tree, class I0, class... II>
struct IsValidTreePath<Tree, Dune::TypeTree::HybridTreePath<I0,II...>, Dune::TypeTree::LeafNodeTag>
: std::false_type {};
// power nodes
template <class Tree, class I0, class... II>
struct IsValidTreePath<Tree, Dune::TypeTree::HybridTreePath<I0,II...>, Dune::TypeTree::PowerNodeTag>
: IsValidTreePath<typename Tree::ChildType, Dune::TypeTree::HybridTreePath<II...>> {};
// composite node with integer index
template <class Tree, class I0, class... II>
struct IsValidTreePath<Tree, Dune::TypeTree::HybridTreePath<I0,II...>, Dune::TypeTree::CompositeNodeTag>
: std::false_type {};
// composite node with integral-constant index
template <class Tree, class Int, Int i, class... II>
struct IsValidTreePath<Tree, Dune::TypeTree::HybridTreePath<std::integral_constant<Int,i>,II...>, Dune::TypeTree::CompositeNodeTag>
: std::conditional_t<(i >= 0 && i < Tree::degree()),
IsValidTreePath<typename Tree::template Child<(i >= 0 && i < Tree::degree()) ? i : 0>::Type, Dune::TypeTree::HybridTreePath<II...>>,
std::false_type> {};
} // end namespace Traits
namespace Concepts
{
/// \brief Check whether `Path` is a valid index of treepath for the given typetree `Tree`
template <class Tree, class Path>
static constexpr bool ValidTreePath = Traits::IsValidTreePath<Tree,TYPEOF(makeTreePath(std::declval<Path>()))>::value;
}
} // end namespace AMDiS
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
namespace AMDiS namespace AMDiS
{ {
struct RootTreePath {}; using RootTreePath = Dune::TypeTree::HybridTreePath<>;
namespace Concepts namespace Concepts
{ {
...@@ -43,11 +43,6 @@ namespace AMDiS ...@@ -43,11 +43,6 @@ namespace AMDiS
: std::conjunction<std::is_integral<Indices>...> : std::conjunction<std::is_integral<Indices>...>
{}; {};
template <>
struct IsPreTreePath<RootTreePath>
: std::true_type
{};
} // end namespace Definition } // end namespace Definition
template <class TP> template <class TP>
...@@ -119,11 +114,6 @@ namespace AMDiS ...@@ -119,11 +114,6 @@ namespace AMDiS
return Dune::TypeTree::hybridTreePath(); return Dune::TypeTree::hybridTreePath();
} }
inline auto makeTreePath(RootTreePath)
{
return makeTreePath();
}
template <class Index, Index... I> template <class Index, Index... I>
auto makeTreePath(std::integer_sequence<Index, I...>) auto makeTreePath(std::integer_sequence<Index, I...>)
{ {
......
...@@ -160,3 +160,6 @@ dune_add_test(SOURCES UniqueBorderPartitionTest.cpp ...@@ -160,3 +160,6 @@ dune_add_test(SOURCES UniqueBorderPartitionTest.cpp
MPI_RANKS 2 MPI_RANKS 2
TIMEOUT 300 TIMEOUT 300
CMAKE_GUARD MPI_FOUND) CMAKE_GUARD MPI_FOUND)
dune_add_test(SOURCES ValidTreePathTest.cpp
LINK_LIBRARIES amdis)
#include <config.h>
#include <dune/grid/yaspgrid.hh>
#include <dune/functions/functionspacebases/compositebasis.hh>
#include <dune/functions/functionspacebases/lagrangebasis.hh>
#include <dune/functions/functionspacebases/powerbasis.hh>
#include <amdis/Environment.hpp>
#include <amdis/common/TypeTraits.hpp>
#include <amdis/typetree/Traits.hpp>
#include <amdis/typetree/TreePath.hpp>
using namespace AMDiS;
int main (int argc, char** argv)
{
Environment env(argc, argv);
Dune::YaspGrid<2> grid({1.0,1.0}, {1,1});
using namespace Dune::Functions::BasisFactory;
auto basis = makeBasis(grid.leafGridView(),
composite(
power<2>(lagrange<2>()),
lagrange<1>()
));
using Tree = TYPEOF(basis.localView().tree());
// index access of composite node
static_assert(not Concepts::ValidTreePath<Tree,int>);
static_assert(not Concepts::ValidTreePath<Tree,std::size_t>);
static_assert( Concepts::ValidTreePath<Tree,std::integral_constant<int,0>>);
static_assert( Concepts::ValidTreePath<Tree,std::integral_constant<std::size_t,0>>);
static_assert(not Concepts::ValidTreePath<Tree,std::integral_constant<int,2>>);
static_assert(not Concepts::ValidTreePath<Tree,std::integral_constant<std::size_t,2>>);
using namespace Dune::Indices;
auto tp0 = makeTreePath(0);
auto tp1 = makeTreePath(_0);
static_assert(not Concepts::ValidTreePath<Tree,TYPEOF(tp0)>);
static_assert( Concepts::ValidTreePath<Tree,TYPEOF(tp1)>);
auto tp2 = makeTreePath(_0,0);
auto tp3 = makeTreePath(_0,_0);
auto tp4 = makeTreePath(_1,0);
static_assert( Concepts::ValidTreePath<Tree,TYPEOF(tp2)>);
static_assert( Concepts::ValidTreePath<Tree,TYPEOF(tp3)>);
static_assert(not Concepts::ValidTreePath<Tree,TYPEOF(tp4)>);
auto tp5 = makeTreePath(_0,0,0);
auto tp6 = makeTreePath(_0,0,_0);
static_assert(not Concepts::ValidTreePath<Tree,TYPEOF(tp5)>);
static_assert(not Concepts::ValidTreePath<Tree,TYPEOF(tp6)>);
}
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