diff --git a/amdis/ProblemStat.hpp b/amdis/ProblemStat.hpp index 494d33a617614b4863ed986fdb601ec772939606..50a6af4ca463a960bfe06b7724dff3f493c2e678 100644 --- a/amdis/ProblemStat.hpp +++ b/amdis/ProblemStat.hpp @@ -39,6 +39,7 @@ #include #include #include +#include #include namespace AMDiS @@ -103,8 +104,7 @@ namespace AMDiS /// \brief Constructor taking a grid and basis. /// Wraps both in shared pointers. - template , + template , REQUIRES(Concepts::GlobalBasis)> 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 ::LeafGridView, + template ::LeafGridView, REQUIRES(Concepts::PreBasisFactory>)> ProblemStat(std::string const& name, Grid_&& grid, PBF_ const& preBasisFactory) : ProblemStat(name, FWD(grid)) @@ -161,7 +160,13 @@ namespace AMDiS template void addMatrixOperator(Operator const& op, RowTreePath row = {}, ColTreePath col = {}) { - systemMatrix_->addOperator(tag::element_operator{}, op, row, col); + static constexpr bool isValidTreePath = + Concepts::ValidTreePath && + Concepts::ValidTreePath; + static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!"); + + if constexpr (isValidTreePath) + systemMatrix_->addOperator(tag::element_operator{}, 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{*boundaryManager_,b}, op, row, col); + static constexpr bool isValidTreePath = + Concepts::ValidTreePath && + Concepts::ValidTreePath; + static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!"); + + if constexpr (isValidTreePath) + systemMatrix_->addOperator(tag::boundary_operator{*boundaryManager_,b}, op, row, col); } /** @} */ @@ -212,7 +223,12 @@ namespace AMDiS template void addVectorOperator(Operator const& op, TreePath path = {}) { - rhs_->addOperator(tag::element_operator{}, op, path); + static constexpr bool isValidTreePath = + Concepts::ValidTreePath; + static_assert(isValidTreePath, "Invalid treepath passed to addVectorOperator!"); + + if constexpr (isValidTreePath) + rhs_->addOperator(tag::element_operator{}, 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{*boundaryManager_,b}, op, path); + static constexpr bool isValidTreePath = + Concepts::ValidTreePath; + static_assert(isValidTreePath, "Invalid treepath passed to addVectorOperator!"); + + if constexpr (isValidTreePath) + rhs_->addOperator(tag::boundary_operator{*boundaryManager_,b}, op, path); } /** @} */ diff --git a/amdis/ProblemStat.inc.hpp b/amdis/ProblemStat.inc.hpp index af4d67cafd777fb328f66602e96a6a95102b423e..0bb32194acebc9031e38790bfdfbf52e14e414d0 100644 --- a/amdis/ProblemStat.inc.hpp +++ b/amdis/ProblemStat.inc.hpp @@ -293,20 +293,28 @@ template void ProblemStat:: addDirichletBC(Predicate const& predicate, RowTreePath row, ColTreePath col, Values const& values) { + static constexpr bool isValidPredicate = Concepts::Functor; static_assert( Concepts::Functor, "Function passed to addDirichletBC for `predicate` does not model the Functor 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 && + Concepts::ValidTreePath; + 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( - std::move(rowBasis), std::move(colBasis), {predicate}, valueGridFct); - boundaryConditions_[i][j].push_back(makeUniquePtr(std::move(bc))); + auto bc = makeDirichletBC( + std::move(rowBasis), std::move(colBasis), {predicate}, valueGridFct); + boundaryConditions_[i][j].push_back(makeUniquePtr(std::move(bc))); + } } @@ -316,17 +324,24 @@ template void ProblemStat:: 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( - std::move(rowBasis), std::move(colBasis), {*boundaryManager_, id}, valueGridFct); - boundaryConditions_[i][j].push_back(makeUniquePtr(std::move(bc))); + static constexpr bool isValidTreePath = + Concepts::ValidTreePath && + Concepts::ValidTreePath; + 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( + std::move(rowBasis), std::move(colBasis), {*boundaryManager_, id}, valueGridFct); + boundaryConditions_[i][j].push_back(makeUniquePtr(std::move(bc))); + } } diff --git a/amdis/typetree/CMakeLists.txt b/amdis/typetree/CMakeLists.txt index d60bea745664cb6f826c94c3793b01e45422c50c..ccabc420345261ea015a9158085de957e07bf5d4 100644 --- a/amdis/typetree/CMakeLists.txt +++ b/amdis/typetree/CMakeLists.txt @@ -3,6 +3,7 @@ install(FILES FiniteElementType.hpp MultiIndex.hpp RangeType.hpp + Traits.hpp Traversal.hpp TreeContainer.hpp TreePath.hpp diff --git a/amdis/typetree/Traits.hpp b/amdis/typetree/Traits.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0ca9399022e9ab6564f0bff87c488b122900ee20 --- /dev/null +++ b/amdis/typetree/Traits.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include + +#include +#include + +namespace AMDiS +{ + namespace Traits + { + template + struct IsValidTreePath; + + // empty treepath + template + struct IsValidTreePath, NodeTag> + : std::true_type {}; + + // leaf nodes + template + struct IsValidTreePath, Dune::TypeTree::LeafNodeTag> + : std::false_type {}; + + // power nodes + template + struct IsValidTreePath, Dune::TypeTree::PowerNodeTag> + : IsValidTreePath> {}; + + // composite node with integer index + template + struct IsValidTreePath, Dune::TypeTree::CompositeNodeTag> + : std::false_type {}; + + // composite node with integral-constant index + template + struct IsValidTreePath,II...>, Dune::TypeTree::CompositeNodeTag> + : std::conditional_t<(i >= 0 && i < Tree::degree()), + IsValidTreePath= 0 && i < Tree::degree()) ? i : 0>::Type, Dune::TypeTree::HybridTreePath>, + std::false_type> {}; + + } // end namespace Traits + + namespace Concepts + { + /// \brief Check whether `Path` is a valid index of treepath for the given typetree `Tree` + template + static constexpr bool ValidTreePath = Traits::IsValidTreePath()))>::value; + } + +} // end namespace AMDiS diff --git a/amdis/typetree/TreePath.hpp b/amdis/typetree/TreePath.hpp index efd66a03f3b2fa4508970bcac35188ad87916946..7f6addc15412108d8b783dd4112e830e866490d8 100644 --- a/amdis/typetree/TreePath.hpp +++ b/amdis/typetree/TreePath.hpp @@ -13,7 +13,7 @@ namespace AMDiS { - struct RootTreePath {}; + using RootTreePath = Dune::TypeTree::HybridTreePath<>; namespace Concepts { @@ -43,11 +43,6 @@ namespace AMDiS : std::conjunction...> {}; - template <> - struct IsPreTreePath - : std::true_type - {}; - } // end namespace Definition template @@ -119,11 +114,6 @@ namespace AMDiS return Dune::TypeTree::hybridTreePath(); } - inline auto makeTreePath(RootTreePath) - { - return makeTreePath(); - } - template auto makeTreePath(std::integer_sequence) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9f89e32f8f267e7fe99d18d2d8767e50f0b8f45b..d25f1cd74da68fda75934c3593b84d3e1f29a953 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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) diff --git a/test/ValidTreePathTest.cpp b/test/ValidTreePathTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..47cde694d56c54991f3fef4d46450c5c9143a21e --- /dev/null +++ b/test/ValidTreePathTest.cpp @@ -0,0 +1,58 @@ +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +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); + static_assert(not Concepts::ValidTreePath); + static_assert( Concepts::ValidTreePath>); + static_assert( Concepts::ValidTreePath>); + + static_assert(not Concepts::ValidTreePath>); + static_assert(not Concepts::ValidTreePath>); + + using namespace Dune::Indices; + + auto tp0 = makeTreePath(0); + auto tp1 = makeTreePath(_0); + static_assert(not Concepts::ValidTreePath); + static_assert( Concepts::ValidTreePath); + + auto tp2 = makeTreePath(_0,0); + auto tp3 = makeTreePath(_0,_0); + auto tp4 = makeTreePath(_1,0); + static_assert( Concepts::ValidTreePath); + static_assert( Concepts::ValidTreePath); + static_assert(not Concepts::ValidTreePath); + + auto tp5 = makeTreePath(_0,0,0); + auto tp6 = makeTreePath(_0,0,_0); + static_assert(not Concepts::ValidTreePath); + static_assert(not Concepts::ValidTreePath); +}