version 0.4.7
traversal.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2021-2026 The Ikarus Developers ikarus@ibb.uni-stuttgart.de
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
9#pragma once
11
12namespace Ikarus::utils {
13
30template <class T, class TreePath, class PowerFunc, class LeafFunc>
31void forEachLeafOrPowerLeafNode(T&& tree, TreePath&& treePath, PowerFunc&& powerFunc, LeafFunc&& leafFunc) {
32 using Tree = std::decay_t<T>;
33 if constexpr (Tree::isLeaf) {
34 leafFunc(tree, treePath);
35 } else if constexpr (Tree::isPower) {
36 if constexpr (Tree::template Child<Dune::Indices::_0>::Type::isLeaf) {
37 powerFunc(tree, treePath);
38 } else {
39 for (std::size_t i = 0; i < tree.degree(); ++i) {
40 auto childTreePath = Dune::TypeTree::push_back(treePath, i);
41 forEachLeafOrPowerLeafNode(tree.child(i), childTreePath, powerFunc, leafFunc);
42 }
43 }
44 } else {
45 auto indices = std::make_index_sequence<Tree::degree()>{};
46 Dune::Hybrid::forEach(indices, [&](auto i) {
47 auto childTreePath = Dune::TypeTree::push_back(treePath, i);
48 forEachLeafOrPowerLeafNode(tree.child(i), childTreePath, powerFunc, leafFunc);
49 });
50 }
51}
52
53namespace Impl {
54 template <bool isScalar, typename NT>
55 void checkLagrangeNode(const NT& node) {
56 if constexpr (isScalar) {
57 static_assert(Concepts::LagrangeNode<std::remove_cvref_t<decltype(node)>>, "Only supported for Lagrange basis");
58 } else {
59 static_assert(Concepts::LagrangeNode<std::remove_cvref_t<decltype(node.child(0))>>,
60 "Only supported for Lagrange basis");
61 }
62 }
63} // namespace Impl
64
75template <typename LV, typename F, int myDim = LV::Element::mydimension>
76requires(std::convertible_to<F, std::function<bool(int, Dune::FieldVector<double, myDim> &&)>>)
77void forEachLagrangeNodePosition(const LV& localView, F&& f) {
78 using Tree = LV::Tree;
79 static constexpr bool isScalar = Tree::isLeaf;
80 static constexpr bool isPower = Tree::isPower;
81 const auto& node = [&]() {
82 if constexpr (isScalar or isPower)
83 return localView.tree();
84 else
85 return localView.tree().template child<0>();
86 }();
87
88 Impl::checkLagrangeNode<isScalar>(node);
89 assert(localView.bound() && "The local view must be bound to an element");
90 const auto& localFE = [&]() {
91 if constexpr (isScalar)
92 return node.finiteElement();
93 else
94 return node.child(0).finiteElement();
95 }();
96 std::vector<Dune::FieldVector<double, myDim>> lagrangeNodeCoords;
97 lagrangeNodeCoords.resize(localFE.size());
98 std::vector<double> out;
99 for (int i = 0; i < myDim; i++) {
100 auto ithCoord = [&i](const Dune::FieldVector<double, myDim>& x) { return x[i]; };
101 localFE.localInterpolation().interpolate(ithCoord, out);
102 for (std::size_t j = 0; j < out.size(); j++)
103 lagrangeNodeCoords[j][i] = out[j];
104 }
105 for (int nodeNumber = 0; auto& nCoord : lagrangeNodeCoords)
106 if (f(nodeNumber++, std::move(nCoord)))
107 break;
108}
109} // namespace Ikarus::utils
Definition: algorithms.hh:17
void forEachLeafOrPowerLeafNode(T &&tree, TreePath &&treePath, PowerFunc &&powerFunc, LeafFunc &&leafFunc)
A function which loops over all the nodes of a tree and performs different actions for a power node (...
Definition: traversal.hh:31
void forEachLagrangeNodePosition(const LV &localView, F &&f)
A helper function that helps in traversing over the local coordinates of an element and call a user-d...
Definition: traversal.hh:77
Definition: utils/dirichletvalues.hh:38
Concept to check if a node in a basis tree is a Lagrangian node.
Definition: utils/concepts.hh:92
Several concepts.