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 @@
#include <amdis/GridFunctions.hpp>
#include <amdis/gridfunctions/DiscreteFunction.hpp>
#include <amdis/io/FileWriterBase.hpp>
#include <amdis/typetree/Traits.hpp>
#include <amdis/typetree/TreePath.hpp>
namespace AMDiS
......@@ -103,8 +104,7 @@ namespace AMDiS
/// \brief Constructor taking a grid and basis.
/// Wraps both in shared pointers.
template <class Grid_, class Basis_,
class B_ = Underlying_t<Basis_>,
template <class Grid_, class Basis_, class B_ = Underlying_t<Basis_>,
REQUIRES(Concepts::GlobalBasis<B_>)>
ProblemStat(std::string const& name, Grid_&& grid, Basis_&& globalBasis)
: ProblemStat(name, FWD(grid))
......@@ -114,8 +114,7 @@ namespace AMDiS
/// \brief Constructor taking a grid and pre-basis factory to create a global basis
/// on the fly.
template <class Grid_, class PBF_,
class GV_ = typename Underlying_t<Grid_>::LeafGridView,
template <class Grid_, class PBF_, class GV_ = typename Underlying_t<Grid_>::LeafGridView,
REQUIRES(Concepts::PreBasisFactory<PBF_, GV_, MultiIndex_t<PBF_>>)>
ProblemStat(std::string const& name, Grid_&& grid, PBF_ const& preBasisFactory)
: ProblemStat(name, FWD(grid))
......@@ -161,7 +160,13 @@ namespace AMDiS
template <class Operator, class RowTreePath = RootTreePath, class ColTreePath = RootTreePath>
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`
......@@ -187,7 +192,13 @@ namespace AMDiS
void addMatrixOperator(BoundaryType b, Operator const& op, RowTreePath row = {}, ColTreePath col = {})
{
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
template <class Operator, class TreePath = RootTreePath>
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`
......@@ -236,7 +252,12 @@ namespace AMDiS
void addVectorOperator(BoundaryType b, Operator const& op, TreePath path = {})
{
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>
void ProblemStat<Traits>::
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)>,
"Function passed to addDirichletBC for `predicate` does not model the Functor<bool(WorldVector)> concept");
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);
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 addDirichletBC!");
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>(
std::move(rowBasis), std::move(colBasis), {predicate}, valueGridFct);
boundaryConditions_[i][j].push_back(makeUniquePtr(std::move(bc)));
auto bc = makeDirichletBC<SystemMatrix, SolutionVector, SystemVector>(
std::move(rowBasis), std::move(colBasis), {predicate}, valueGridFct);
boundaryConditions_[i][j].push_back(makeUniquePtr(std::move(bc)));
}
}
......@@ -316,17 +324,24 @@ template <class Traits>
void ProblemStat<Traits>::
addDirichletBC(BoundaryType id, RowTreePath row, ColTreePath col, Values const& values)
{
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 bc = makeDirichletBC<SystemMatrix, SolutionVector, SystemVector>(
std::move(rowBasis), std::move(colBasis), {*boundaryManager_, id}, valueGridFct);
boundaryConditions_[i][j].push_back(makeUniquePtr(std::move(bc)));
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 addDirichletBC!");
if constexpr (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 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
FiniteElementType.hpp
MultiIndex.hpp
RangeType.hpp
Traits.hpp
Traversal.hpp
TreeContainer.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 @@
namespace AMDiS
{
struct RootTreePath {};
using RootTreePath = Dune::TypeTree::HybridTreePath<>;
namespace Concepts
{
......@@ -43,11 +43,6 @@ namespace AMDiS
: std::conjunction<std::is_integral<Indices>...>
{};
template <>
struct IsPreTreePath<RootTreePath>
: std::true_type
{};
} // end namespace Definition
template <class TP>
......@@ -119,11 +114,6 @@ namespace AMDiS
return Dune::TypeTree::hybridTreePath();
}
inline auto makeTreePath(RootTreePath)
{
return makeTreePath();
}
template <class Index, Index... I>
auto makeTreePath(std::integer_sequence<Index, I...>)
{
......
......@@ -160,3 +160,6 @@ dune_add_test(SOURCES UniqueBorderPartitionTest.cpp
MPI_RANKS 2
TIMEOUT 300
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