From f811a69bd088b2fe2fe86912f4bdb8e1665b58a4 Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Fri, 6 Nov 2020 16:51:19 +0100 Subject: [PATCH 1/8] check early for invalid treepaths --- amdis/ProblemStat.hpp | 31 ++++++++++++++++--- amdis/ProblemStat.inc.hpp | 58 ++++++++++++++++++++++------------- amdis/typetree/CMakeLists.txt | 1 + amdis/typetree/Traits.hpp | 24 +++++++++++++++ 4 files changed, 88 insertions(+), 26 deletions(-) create mode 100644 amdis/typetree/Traits.hpp diff --git a/amdis/ProblemStat.hpp b/amdis/ProblemStat.hpp index 494d33a6..06a7c182 100644 --- a/amdis/ProblemStat.hpp +++ b/amdis/ProblemStat.hpp @@ -39,6 +39,7 @@ #include #include #include +#include #include namespace AMDiS @@ -161,7 +162,13 @@ namespace AMDiS template void addMatrixOperator(Operator const& op, RowTreePath row = {}, ColTreePath col = {}) { - systemMatrix_->addOperator(tag::element_operator{}, op, row, col); + using ValidTreePath = std::bool_constant< + Traits::hasChild(globalBasis_->localView().tree(), row) && + Traits::hasChild(globalBasis_->localView().tree(), col)>; + + static_assert(ValidTreePath::value, "Invalid row and/or col treepath passed to addMatrixOperator!"); + if constexpr (ValidTreePath::value) + systemMatrix_->addOperator(tag::element_operator{}, op, row, col); } /// Operator evaluated on the boundary of the domain with boundary index `b` @@ -187,7 +194,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); + using ValidTreePath = std::bool_constant< + Traits::hasChild(globalBasis_->localView().tree(), row) && + Traits::hasChild(globalBasis_->localView().tree(), col)>; + + static_assert(ValidTreePath::value, "Invalid row and/or col treepath passed to addMatrixOperator!"); + if constexpr (ValidTreePath::value) + systemMatrix_->addOperator(tag::boundary_operator{*boundaryManager_,b}, op, row, col); } /** @} */ @@ -212,7 +225,12 @@ namespace AMDiS template void addVectorOperator(Operator const& op, TreePath path = {}) { - rhs_->addOperator(tag::element_operator{}, op, path); + using ValidTreePath = std::bool_constant< + Traits::hasChild(globalBasis_->localView().tree(), path)>; + + static_assert(ValidTreePath::value, "Invalid treepath passed to addVectorOperator!"); + if constexpr (ValidTreePath::value) + rhs_->addOperator(tag::element_operator{}, op, path); } /// Operator evaluated on the boundary of the domain with boundary index `b` @@ -236,7 +254,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); + using ValidTreePath = std::bool_constant< + Traits::hasChild(globalBasis_->localView().tree(), path)>; + + static_assert(ValidTreePath::value, "Invalid treepath passed to addVectorOperator!"); + if constexpr (ValidTreePath::value) + rhs_->addOperator(tag::boundary_operator{*boundaryManager_,b}, op, path); } /** @} */ diff --git a/amdis/ProblemStat.inc.hpp b/amdis/ProblemStat.inc.hpp index af4d67ca..955cce0d 100644 --- a/amdis/ProblemStat.inc.hpp +++ b/amdis/ProblemStat.inc.hpp @@ -296,17 +296,24 @@ addDirichletBC(Predicate const& predicate, RowTreePath row, ColTreePath col, Val 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); - - 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))); + using ValidTreePath = std::bool_constant< + Traits::hasChild(globalBasis_->localView().tree(), row) && + Traits::hasChild(globalBasis_->localView().tree(), col)>; + + static_assert(ValidTreePath::value, "Invalid row and/or col treepath passed to addMatrixOperator!"); + if constexpr (ValidTreePath::value) { + 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), {predicate}, valueGridFct); + boundaryConditions_[i][j].push_back(makeUniquePtr(std::move(bc))); + } } @@ -316,17 +323,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))); + using ValidTreePath = std::bool_constant< + Traits::hasChild(globalBasis_->localView().tree(), row) && + Traits::hasChild(globalBasis_->localView().tree(), col)>; + + static_assert(ValidTreePath::value, "Invalid row and/or col treepath passed to addMatrixOperator!"); + if constexpr (ValidTreePath::value) { + 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 d60bea74..ccabc420 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 00000000..cbec4995 --- /dev/null +++ b/amdis/typetree/Traits.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +namespace AMDiS +{ + namespace Traits + { + template + struct HasChild + { + static constexpr bool value = !std::is_same_v(),std::declval()))>; + }; + + template + constexpr bool hasChild(Tree const&, TreePath const&) + { + return HasChild::value; + } + + } // end namespace AMDiS +} // end namespace AMDiS -- GitLab From fab5eb9977447c9aa185c514853d5940500da582 Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Fri, 6 Nov 2020 21:14:34 +0100 Subject: [PATCH 2/8] Use Traits class for checking whether Tree has Child --- amdis/ProblemStat.hpp | 20 ++++++++++---------- amdis/ProblemStat.inc.hpp | 12 ++++++------ amdis/typetree/Traits.hpp | 6 ------ 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/amdis/ProblemStat.hpp b/amdis/ProblemStat.hpp index 06a7c182..9ec5fac1 100644 --- a/amdis/ProblemStat.hpp +++ b/amdis/ProblemStat.hpp @@ -162,9 +162,9 @@ namespace AMDiS template void addMatrixOperator(Operator const& op, RowTreePath row = {}, ColTreePath col = {}) { - using ValidTreePath = std::bool_constant< - Traits::hasChild(globalBasis_->localView().tree(), row) && - Traits::hasChild(globalBasis_->localView().tree(), col)>; + using ValidTreePath = std::conjunction< + Traits::HasChild, + Traits::HasChild>; static_assert(ValidTreePath::value, "Invalid row and/or col treepath passed to addMatrixOperator!"); if constexpr (ValidTreePath::value) @@ -194,9 +194,9 @@ namespace AMDiS void addMatrixOperator(BoundaryType b, Operator const& op, RowTreePath row = {}, ColTreePath col = {}) { using I = typename GridView::Intersection; - using ValidTreePath = std::bool_constant< - Traits::hasChild(globalBasis_->localView().tree(), row) && - Traits::hasChild(globalBasis_->localView().tree(), col)>; + using ValidTreePath = std::conjunction< + Traits::HasChild, + Traits::HasChild>; static_assert(ValidTreePath::value, "Invalid row and/or col treepath passed to addMatrixOperator!"); if constexpr (ValidTreePath::value) @@ -225,8 +225,8 @@ namespace AMDiS template void addVectorOperator(Operator const& op, TreePath path = {}) { - using ValidTreePath = std::bool_constant< - Traits::hasChild(globalBasis_->localView().tree(), path)>; + using ValidTreePath = + Traits::HasChild; static_assert(ValidTreePath::value, "Invalid treepath passed to addVectorOperator!"); if constexpr (ValidTreePath::value) @@ -254,8 +254,8 @@ namespace AMDiS void addVectorOperator(BoundaryType b, Operator const& op, TreePath path = {}) { using I = typename GridView::Intersection; - using ValidTreePath = std::bool_constant< - Traits::hasChild(globalBasis_->localView().tree(), path)>; + using ValidTreePath = + Traits::HasChild; static_assert(ValidTreePath::value, "Invalid treepath passed to addVectorOperator!"); if constexpr (ValidTreePath::value) diff --git a/amdis/ProblemStat.inc.hpp b/amdis/ProblemStat.inc.hpp index 955cce0d..7afaca16 100644 --- a/amdis/ProblemStat.inc.hpp +++ b/amdis/ProblemStat.inc.hpp @@ -296,9 +296,9 @@ addDirichletBC(Predicate const& predicate, RowTreePath row, ColTreePath col, Val static_assert( Concepts::Functor, "Function passed to addDirichletBC for `predicate` does not model the Functor concept"); - using ValidTreePath = std::bool_constant< - Traits::hasChild(globalBasis_->localView().tree(), row) && - Traits::hasChild(globalBasis_->localView().tree(), col)>; + using ValidTreePath = std::conjunction< + Traits::HasChild, + Traits::HasChild>; static_assert(ValidTreePath::value, "Invalid row and/or col treepath passed to addMatrixOperator!"); if constexpr (ValidTreePath::value) { @@ -323,9 +323,9 @@ template void ProblemStat:: addDirichletBC(BoundaryType id, RowTreePath row, ColTreePath col, Values const& values) { - using ValidTreePath = std::bool_constant< - Traits::hasChild(globalBasis_->localView().tree(), row) && - Traits::hasChild(globalBasis_->localView().tree(), col)>; + using ValidTreePath = std::conjunction< + Traits::HasChild, + Traits::HasChild>; static_assert(ValidTreePath::value, "Invalid row and/or col treepath passed to addMatrixOperator!"); if constexpr (ValidTreePath::value) { diff --git a/amdis/typetree/Traits.hpp b/amdis/typetree/Traits.hpp index cbec4995..b333ac53 100644 --- a/amdis/typetree/Traits.hpp +++ b/amdis/typetree/Traits.hpp @@ -14,11 +14,5 @@ namespace AMDiS TYPEOF(Dune::TypeTree::child(std::declval(),std::declval()))>; }; - template - constexpr bool hasChild(Tree const&, TreePath const&) - { - return HasChild::value; - } - } // end namespace AMDiS } // end namespace AMDiS -- GitLab From 52ad49cecf3b6d9386312d8e6e624e8c8f3a1133 Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Sat, 7 Nov 2020 00:24:16 +0100 Subject: [PATCH 3/8] add test for valid treepaths --- amdis/ProblemStat.hpp | 36 ++++++++++++++++++------------------ amdis/ProblemStat.inc.hpp | 20 ++++++++++---------- amdis/typetree/Traits.hpp | 34 +++++++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/amdis/ProblemStat.hpp b/amdis/ProblemStat.hpp index 9ec5fac1..aa8ed9f2 100644 --- a/amdis/ProblemStat.hpp +++ b/amdis/ProblemStat.hpp @@ -162,12 +162,12 @@ namespace AMDiS template void addMatrixOperator(Operator const& op, RowTreePath row = {}, ColTreePath col = {}) { - using ValidTreePath = std::conjunction< - Traits::HasChild, - Traits::HasChild>; + static constexpr bool isValidTreePath = std::conjunction_v< + AMDiS::Traits::HasChild, + AMDiS::Traits::HasChild>; - static_assert(ValidTreePath::value, "Invalid row and/or col treepath passed to addMatrixOperator!"); - if constexpr (ValidTreePath::value) + static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!"); + if constexpr (isValidTreePath) systemMatrix_->addOperator(tag::element_operator{}, op, row, col); } @@ -194,12 +194,12 @@ namespace AMDiS void addMatrixOperator(BoundaryType b, Operator const& op, RowTreePath row = {}, ColTreePath col = {}) { using I = typename GridView::Intersection; - using ValidTreePath = std::conjunction< - Traits::HasChild, - Traits::HasChild>; + static constexpr bool isValidTreePath = std::conjunction_v< + AMDiS::Traits::HasChild, + AMDiS::Traits::HasChild>; - static_assert(ValidTreePath::value, "Invalid row and/or col treepath passed to addMatrixOperator!"); - if constexpr (ValidTreePath::value) + 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); } /** @} */ @@ -225,11 +225,11 @@ namespace AMDiS template void addVectorOperator(Operator const& op, TreePath path = {}) { - using ValidTreePath = - Traits::HasChild; + static constexpr bool isValidTreePath = + AMDiS::Traits::HasChild::value; - static_assert(ValidTreePath::value, "Invalid treepath passed to addVectorOperator!"); - if constexpr (ValidTreePath::value) + static_assert(isValidTreePath, "Invalid treepath passed to addVectorOperator!"); + if constexpr (isValidTreePath) rhs_->addOperator(tag::element_operator{}, op, path); } @@ -254,11 +254,11 @@ namespace AMDiS void addVectorOperator(BoundaryType b, Operator const& op, TreePath path = {}) { using I = typename GridView::Intersection; - using ValidTreePath = - Traits::HasChild; + static constexpr bool isValidTreePath = + AMDiS::Traits::HasChild::value; - static_assert(ValidTreePath::value, "Invalid treepath passed to addVectorOperator!"); - if constexpr (ValidTreePath::value) + 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 7afaca16..c1f72c4c 100644 --- a/amdis/ProblemStat.inc.hpp +++ b/amdis/ProblemStat.inc.hpp @@ -296,12 +296,12 @@ addDirichletBC(Predicate const& predicate, RowTreePath row, ColTreePath col, Val static_assert( Concepts::Functor, "Function passed to addDirichletBC for `predicate` does not model the Functor concept"); - using ValidTreePath = std::conjunction< - Traits::HasChild, - Traits::HasChild>; + static constexpr bool isValidTreePath = std::conjunction_v< + AMDiS::Traits::HasChild, + AMDiS::Traits::HasChild>; - static_assert(ValidTreePath::value, "Invalid row and/or col treepath passed to addMatrixOperator!"); - if constexpr (ValidTreePath::value) { + static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!"); + if constexpr (isValidTreePath) { auto localView = globalBasis_->localView(); auto i = makeTreePath(row); auto j = makeTreePath(col); @@ -323,12 +323,12 @@ template void ProblemStat:: addDirichletBC(BoundaryType id, RowTreePath row, ColTreePath col, Values const& values) { - using ValidTreePath = std::conjunction< - Traits::HasChild, - Traits::HasChild>; + static constexpr bool isValidTreePath = std::conjunction_v< + AMDiS::Traits::HasChild, + AMDiS::Traits::HasChild>; - static_assert(ValidTreePath::value, "Invalid row and/or col treepath passed to addMatrixOperator!"); - if constexpr (ValidTreePath::value) { + static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!"); + if constexpr (isValidTreePath) { auto localView = globalBasis_->localView(); auto i = makeTreePath(row); auto j = makeTreePath(col); diff --git a/amdis/typetree/Traits.hpp b/amdis/typetree/Traits.hpp index b333ac53..14bf3e99 100644 --- a/amdis/typetree/Traits.hpp +++ b/amdis/typetree/Traits.hpp @@ -1,18 +1,42 @@ #pragma once -#include -#include +#include + +#include namespace AMDiS { namespace Traits { - template + template + struct HasChild; + + // treepath is index type + template struct HasChild { - static constexpr bool value = !std::is_same_v(),std::declval()))>; + static constexpr bool value = !Tree::isLeaf && (std::is_integral_v != Tree::isComposite); }; + // empty treepath + template + struct HasChild, NodeTag> + : std::bool_constant {}; + + // power nodes + template + struct HasChild, Dune::TypeTree::PowerNodeTag> + : HasChild> {}; + + // composite node with integer index + template + struct HasChild, Dune::TypeTree::CompositeNodeTag> + : std::false_type {}; + + // composite node with integral-constant index + template + struct HasChild,II...>, Dune::TypeTree::CompositeNodeTag> + : HasChild::Type, Dune::TypeTree::HybridTreePath> {}; + } // end namespace AMDiS } // end namespace AMDiS -- GitLab From 034b2a12b408eda366beb0e2016871b1c3e8aa1b Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Sat, 7 Nov 2020 11:31:16 +0100 Subject: [PATCH 4/8] Allow inner nodes to be accessed by valid tree path --- amdis/ProblemStat.hpp | 12 ++++++------ amdis/ProblemStat.inc.hpp | 8 ++++---- amdis/typetree/Traits.hpp | 18 +++++++++--------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/amdis/ProblemStat.hpp b/amdis/ProblemStat.hpp index aa8ed9f2..901c1464 100644 --- a/amdis/ProblemStat.hpp +++ b/amdis/ProblemStat.hpp @@ -163,8 +163,8 @@ namespace AMDiS void addMatrixOperator(Operator const& op, RowTreePath row = {}, ColTreePath col = {}) { static constexpr bool isValidTreePath = std::conjunction_v< - AMDiS::Traits::HasChild, - AMDiS::Traits::HasChild>; + AMDiS::Traits::ValidTreePath, + AMDiS::Traits::ValidTreePath>; static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!"); if constexpr (isValidTreePath) @@ -195,8 +195,8 @@ namespace AMDiS { using I = typename GridView::Intersection; static constexpr bool isValidTreePath = std::conjunction_v< - AMDiS::Traits::HasChild, - AMDiS::Traits::HasChild>; + AMDiS::Traits::ValidTreePath, + AMDiS::Traits::ValidTreePath>; static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!"); if constexpr (isValidTreePath) @@ -226,7 +226,7 @@ namespace AMDiS void addVectorOperator(Operator const& op, TreePath path = {}) { static constexpr bool isValidTreePath = - AMDiS::Traits::HasChild::value; + AMDiS::Traits::ValidTreePath::value; static_assert(isValidTreePath, "Invalid treepath passed to addVectorOperator!"); if constexpr (isValidTreePath) @@ -255,7 +255,7 @@ namespace AMDiS { using I = typename GridView::Intersection; static constexpr bool isValidTreePath = - AMDiS::Traits::HasChild::value; + AMDiS::Traits::ValidTreePath::value; static_assert(isValidTreePath, "Invalid treepath passed to addVectorOperator!"); if constexpr (isValidTreePath) diff --git a/amdis/ProblemStat.inc.hpp b/amdis/ProblemStat.inc.hpp index c1f72c4c..e44a268f 100644 --- a/amdis/ProblemStat.inc.hpp +++ b/amdis/ProblemStat.inc.hpp @@ -297,8 +297,8 @@ addDirichletBC(Predicate const& predicate, RowTreePath row, ColTreePath col, Val "Function passed to addDirichletBC for `predicate` does not model the Functor concept"); static constexpr bool isValidTreePath = std::conjunction_v< - AMDiS::Traits::HasChild, - AMDiS::Traits::HasChild>; + AMDiS::Traits::ValidTreePath, + AMDiS::Traits::ValidTreePath>; static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!"); if constexpr (isValidTreePath) { @@ -324,8 +324,8 @@ void ProblemStat:: addDirichletBC(BoundaryType id, RowTreePath row, ColTreePath col, Values const& values) { static constexpr bool isValidTreePath = std::conjunction_v< - AMDiS::Traits::HasChild, - AMDiS::Traits::HasChild>; + AMDiS::Traits::ValidTreePath, + AMDiS::Traits::ValidTreePath>; static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!"); if constexpr (isValidTreePath) { diff --git a/amdis/typetree/Traits.hpp b/amdis/typetree/Traits.hpp index 14bf3e99..1af4d69a 100644 --- a/amdis/typetree/Traits.hpp +++ b/amdis/typetree/Traits.hpp @@ -9,34 +9,34 @@ namespace AMDiS namespace Traits { template - struct HasChild; + struct ValidTreePath; // treepath is index type template - struct HasChild + struct ValidTreePath { static constexpr bool value = !Tree::isLeaf && (std::is_integral_v != Tree::isComposite); }; // empty treepath template - struct HasChild, NodeTag> - : std::bool_constant {}; + struct ValidTreePath, NodeTag> + : std::true_type {}; // power nodes template - struct HasChild, Dune::TypeTree::PowerNodeTag> - : HasChild> {}; + struct ValidTreePath, Dune::TypeTree::PowerNodeTag> + : ValidTreePath> {}; // composite node with integer index template - struct HasChild, Dune::TypeTree::CompositeNodeTag> + struct ValidTreePath, Dune::TypeTree::CompositeNodeTag> : std::false_type {}; // composite node with integral-constant index template - struct HasChild,II...>, Dune::TypeTree::CompositeNodeTag> - : HasChild::Type, Dune::TypeTree::HybridTreePath> {}; + struct ValidTreePath,II...>, Dune::TypeTree::CompositeNodeTag> + : ValidTreePath::Type, Dune::TypeTree::HybridTreePath> {}; } // end namespace AMDiS } // end namespace AMDiS -- GitLab From bf01c253571e29ef8aca8eb136ffb6622eacdacd Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Sat, 7 Nov 2020 12:20:27 +0100 Subject: [PATCH 5/8] add test for ValidTreePath --- amdis/typetree/Traits.hpp | 13 +++++++-- test/CMakeLists.txt | 3 ++ test/ValidTreePathTest.cpp | 58 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 test/ValidTreePathTest.cpp diff --git a/amdis/typetree/Traits.hpp b/amdis/typetree/Traits.hpp index 1af4d69a..5cce84db 100644 --- a/amdis/typetree/Traits.hpp +++ b/amdis/typetree/Traits.hpp @@ -15,7 +15,9 @@ namespace AMDiS template struct ValidTreePath { - static constexpr bool value = !Tree::isLeaf && (std::is_integral_v != Tree::isComposite); + using IndexValue = std::conditional_t, std::integral_constant, Index>; + static constexpr bool value = !Tree::isLeaf && (std::is_integral_v != Tree::isComposite) + && (IndexValue::value >= 0 && IndexValue::value < Tree::degree()); }; // empty treepath @@ -23,6 +25,11 @@ namespace AMDiS struct ValidTreePath, NodeTag> : std::true_type {}; + // leaf nodes + template + struct ValidTreePath, Dune::TypeTree::LeafNodeTag> + : std::false_type {}; + // power nodes template struct ValidTreePath, Dune::TypeTree::PowerNodeTag> @@ -36,7 +43,9 @@ namespace AMDiS // composite node with integral-constant index template struct ValidTreePath,II...>, Dune::TypeTree::CompositeNodeTag> - : ValidTreePath::Type, Dune::TypeTree::HybridTreePath> {}; + : std::conditional_t<(i >= 0 && i < Tree::degree()), + ValidTreePath= 0 && i < Tree::degree()) ? i : 0>::Type, Dune::TypeTree::HybridTreePath>, + std::false_type> {}; } // end namespace AMDiS } // end namespace AMDiS diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9f89e32f..d25f1cd7 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 00000000..3663b006 --- /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 Traits::ValidTreePath::value); + static_assert(not Traits::ValidTreePath::value); + static_assert( Traits::ValidTreePath>::value); + static_assert( Traits::ValidTreePath>::value); + + static_assert(not Traits::ValidTreePath>::value); + static_assert(not Traits::ValidTreePath>::value); + + using namespace Dune::Indices; + + auto tp0 = makeTreePath(0); + auto tp1 = makeTreePath(_0); + static_assert(not Traits::ValidTreePath::value); + static_assert( Traits::ValidTreePath::value); + + auto tp2 = makeTreePath(_0,0); + auto tp3 = makeTreePath(_0,_0); + auto tp4 = makeTreePath(_1,0); + static_assert( Traits::ValidTreePath::value); + static_assert( Traits::ValidTreePath::value); + static_assert(not Traits::ValidTreePath::value); + + auto tp5 = makeTreePath(_0,0,0); + auto tp6 = makeTreePath(_0,0,_0); + static_assert(not Traits::ValidTreePath::value); + static_assert(not Traits::ValidTreePath::value); +} -- GitLab From fe4bb6241571c0789c8eb023dce368ff9951982f Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Sat, 7 Nov 2020 12:52:40 +0100 Subject: [PATCH 6/8] Cleanup the checks for valid tree paths --- amdis/ProblemStat.hpp | 30 ++++++++++++++---------------- amdis/ProblemStat.inc.hpp | 19 ++++++++++--------- amdis/typetree/Traits.hpp | 19 +++++++++---------- amdis/typetree/TreePath.hpp | 12 +----------- 4 files changed, 34 insertions(+), 46 deletions(-) diff --git a/amdis/ProblemStat.hpp b/amdis/ProblemStat.hpp index 901c1464..50a6af4c 100644 --- a/amdis/ProblemStat.hpp +++ b/amdis/ProblemStat.hpp @@ -104,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)) @@ -115,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)) @@ -162,11 +160,11 @@ namespace AMDiS template void addMatrixOperator(Operator const& op, RowTreePath row = {}, ColTreePath col = {}) { - static constexpr bool isValidTreePath = std::conjunction_v< - AMDiS::Traits::ValidTreePath, - AMDiS::Traits::ValidTreePath>; - + 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); } @@ -194,11 +192,11 @@ namespace AMDiS void addMatrixOperator(BoundaryType b, Operator const& op, RowTreePath row = {}, ColTreePath col = {}) { using I = typename GridView::Intersection; - static constexpr bool isValidTreePath = std::conjunction_v< - AMDiS::Traits::ValidTreePath, - AMDiS::Traits::ValidTreePath>; - + 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); } @@ -226,9 +224,9 @@ namespace AMDiS void addVectorOperator(Operator const& op, TreePath path = {}) { static constexpr bool isValidTreePath = - AMDiS::Traits::ValidTreePath::value; - + Concepts::ValidTreePath; static_assert(isValidTreePath, "Invalid treepath passed to addVectorOperator!"); + if constexpr (isValidTreePath) rhs_->addOperator(tag::element_operator{}, op, path); } @@ -255,9 +253,9 @@ namespace AMDiS { using I = typename GridView::Intersection; static constexpr bool isValidTreePath = - AMDiS::Traits::ValidTreePath::value; - + 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 e44a268f..0bb32194 100644 --- a/amdis/ProblemStat.inc.hpp +++ b/amdis/ProblemStat.inc.hpp @@ -293,15 +293,16 @@ 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"); - static constexpr bool isValidTreePath = std::conjunction_v< - AMDiS::Traits::ValidTreePath, - AMDiS::Traits::ValidTreePath>; + static constexpr bool isValidTreePath = + Concepts::ValidTreePath && + Concepts::ValidTreePath; + static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addDirichletBC!"); - static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!"); - if constexpr (isValidTreePath) { + if constexpr (isValidPredicate && isValidTreePath) { auto localView = globalBasis_->localView(); auto i = makeTreePath(row); auto j = makeTreePath(col); @@ -323,11 +324,11 @@ template void ProblemStat:: addDirichletBC(BoundaryType id, RowTreePath row, ColTreePath col, Values const& values) { - static constexpr bool isValidTreePath = std::conjunction_v< - AMDiS::Traits::ValidTreePath, - AMDiS::Traits::ValidTreePath>; + static constexpr bool isValidTreePath = + Concepts::ValidTreePath && + Concepts::ValidTreePath; + static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addDirichletBC!"); - static_assert(isValidTreePath, "Invalid row and/or col treepath passed to addMatrixOperator!"); if constexpr (isValidTreePath) { auto localView = globalBasis_->localView(); auto i = makeTreePath(row); diff --git a/amdis/typetree/Traits.hpp b/amdis/typetree/Traits.hpp index 5cce84db..4d8393e4 100644 --- a/amdis/typetree/Traits.hpp +++ b/amdis/typetree/Traits.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace AMDiS { @@ -11,15 +12,6 @@ namespace AMDiS template struct ValidTreePath; - // treepath is index type - template - struct ValidTreePath - { - using IndexValue = std::conditional_t, std::integral_constant, Index>; - static constexpr bool value = !Tree::isLeaf && (std::is_integral_v != Tree::isComposite) - && (IndexValue::value >= 0 && IndexValue::value < Tree::degree()); - }; - // empty treepath template struct ValidTreePath, NodeTag> @@ -47,5 +39,12 @@ namespace AMDiS ValidTreePath= 0 && i < Tree::degree()) ? i : 0>::Type, Dune::TypeTree::HybridTreePath>, std::false_type> {}; - } // end namespace AMDiS + } // end namespace Traits + + namespace Concepts + { + template + static constexpr bool ValidTreePath = Traits::ValidTreePath()))>::value; + } + } // end namespace AMDiS diff --git a/amdis/typetree/TreePath.hpp b/amdis/typetree/TreePath.hpp index efd66a03..7f6addc1 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) { -- GitLab From 25f440e449a6a6d2dbfca37b8cbdc64d3831b607 Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Sat, 7 Nov 2020 12:53:58 +0100 Subject: [PATCH 7/8] correct ValidTreePathTest to use Concepts instead of Traits --- test/ValidTreePathTest.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/ValidTreePathTest.cpp b/test/ValidTreePathTest.cpp index 3663b006..47cde694 100644 --- a/test/ValidTreePathTest.cpp +++ b/test/ValidTreePathTest.cpp @@ -29,30 +29,30 @@ int main (int argc, char** argv) using Tree = TYPEOF(basis.localView().tree()); // index access of composite node - static_assert(not Traits::ValidTreePath::value); - static_assert(not Traits::ValidTreePath::value); - static_assert( Traits::ValidTreePath>::value); - static_assert( Traits::ValidTreePath>::value); + static_assert(not Concepts::ValidTreePath); + static_assert(not Concepts::ValidTreePath); + static_assert( Concepts::ValidTreePath>); + static_assert( Concepts::ValidTreePath>); - static_assert(not Traits::ValidTreePath>::value); - static_assert(not Traits::ValidTreePath>::value); + 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 Traits::ValidTreePath::value); - static_assert( Traits::ValidTreePath::value); + 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( Traits::ValidTreePath::value); - static_assert( Traits::ValidTreePath::value); - static_assert(not Traits::ValidTreePath::value); + 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 Traits::ValidTreePath::value); - static_assert(not Traits::ValidTreePath::value); + static_assert(not Concepts::ValidTreePath); + static_assert(not Concepts::ValidTreePath); } -- GitLab From f98016a8c614c7f492d4bc9cd5efa1c0e52d9dec Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Sat, 7 Nov 2020 13:39:27 +0100 Subject: [PATCH 8/8] Add documentation of ValieTreePath --- amdis/typetree/Traits.hpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/amdis/typetree/Traits.hpp b/amdis/typetree/Traits.hpp index 4d8393e4..0ca93990 100644 --- a/amdis/typetree/Traits.hpp +++ b/amdis/typetree/Traits.hpp @@ -10,41 +10,42 @@ namespace AMDiS namespace Traits { template - struct ValidTreePath; + struct IsValidTreePath; // empty treepath template - struct ValidTreePath, NodeTag> + struct IsValidTreePath, NodeTag> : std::true_type {}; // leaf nodes template - struct ValidTreePath, Dune::TypeTree::LeafNodeTag> + struct IsValidTreePath, Dune::TypeTree::LeafNodeTag> : std::false_type {}; // power nodes template - struct ValidTreePath, Dune::TypeTree::PowerNodeTag> - : ValidTreePath> {}; + struct IsValidTreePath, Dune::TypeTree::PowerNodeTag> + : IsValidTreePath> {}; // composite node with integer index template - struct ValidTreePath, Dune::TypeTree::CompositeNodeTag> + struct IsValidTreePath, Dune::TypeTree::CompositeNodeTag> : std::false_type {}; // composite node with integral-constant index template - struct ValidTreePath,II...>, Dune::TypeTree::CompositeNodeTag> + struct IsValidTreePath,II...>, Dune::TypeTree::CompositeNodeTag> : std::conditional_t<(i >= 0 && i < Tree::degree()), - ValidTreePath= 0 && i < Tree::degree()) ? i : 0>::Type, Dune::TypeTree::HybridTreePath>, + 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::ValidTreePath()))>::value; + static constexpr bool ValidTreePath = Traits::IsValidTreePath()))>::value; } } // end namespace AMDiS -- GitLab