version 0.4.7
utils/dirichletvalues.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2021-2025 The Ikarus Developers ikarus@ibb.uni-stuttgart.de
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
10#pragma once
11#include <algorithm>
12#include <concepts>
13#include <cstddef>
14#include <functional>
15#include <type_traits>
16#include <utility>
17#include <vector>
18
19#include <dune/common/float_cmp.hh>
20#include <dune/common/hybridutilities.hh>
21#include <dune/common/indices.hh>
22#include <dune/functions/backends/istlvectorbackend.hh>
23#include <dune/functions/functionspacebases/boundarydofs.hh>
24#include <dune/functions/functionspacebases/compositebasis.hh>
25#include <dune/functions/functionspacebases/flatmultiindex.hh>
26#include <dune/functions/functionspacebases/interpolate.hh>
27#include <dune/functions/functionspacebases/subspacebasis.hh>
28
29#include <Eigen/Core>
30
31#include <autodiff/forward/real/real.hpp>
32
34
35namespace Dune {
36template <class K, int N>
38}
39
40namespace Ikarus {
41
45template <class>
47
48template <Concepts::EigenVector T>
50{
51 using SizeType = Eigen::Index;
52};
53
54template <>
55struct DeriveSizeType<std::vector<bool>>
56{
57 using SizeType = std::vector<bool>::size_type;
58};
59
60namespace Impl {
61 template <typename Tree>
62 struct PreBasisInfo
63 {
64 };
65
66 template <typename Tree>
67 requires(Tree::isLeaf)
68 struct PreBasisInfo<Tree>
69 {
70 static constexpr std::size_t size = 0;
71 using NodalSolutionType = double;
72 };
73
74 template <typename Tree>
75 requires(Tree::isPower)
76 struct PreBasisInfo<Tree>
77 {
78 static constexpr std::size_t size = Tree::degree();
79 using NodalSolutionType = Eigen::Vector<double, size>;
80 };
81
82 template <typename Tree>
83 requires(Tree::isComposite)
84 struct PreBasisInfo<Tree>
85 {
86 using ChildTreeType = Tree::template Child<0>::Type;
87 static_assert(not ChildTreeType::isComposite,
88 "DirichletValues is not implemented to handle a composite basis within a composite basis.");
89
90 static constexpr std::size_t size = PreBasisInfo<ChildTreeType>::size;
91 using NodalSolutionType = PreBasisInfo<ChildTreeType>::NodalSolutionType;
92 };
93} // namespace Impl
94
107template <typename B, typename FC = std::vector<bool>>
109{
110public:
111 using Basis = std::remove_cvref_t<B>;
112 using FlagsType = FC;
113 using BackendType = decltype(Dune::Functions::istlVectorBackend(std::declval<FlagsType&>()));
115 static constexpr int worldDimension = Basis::GridView::dimensionworld;
116 using LocalView = Basis::LocalView;
117 using Tree = LocalView::Tree;
118 using NodalSolutionType = typename Impl::PreBasisInfo<Tree>::NodalSolutionType;
119 static constexpr std::size_t numberOfChildrenAtNode = Impl::PreBasisInfo<Tree>::size;
120 explicit DirichletValues(const B& basis)
121 : basis_{basis},
122 dirichletFlagsBackend_{dirichletFlags_} {
123 dirichletFlagsBackend_.resize(basis_);
124 std::fill(dirichletFlags_.begin(), dirichletFlags_.end(), false);
125 if constexpr (Tree::isComposite) {
126 Dune::Hybrid::forEach(
127 Dune::Hybrid::integralRange(Dune::index_constant<std::tuple_size_v<typename Basis::PreBasis::SubPreBases>>()),
128 [&](const auto i) {
129 static_assert(not Tree::template Child<i>::Type::isComposite,
130 "DirichletValues is not implemented to handle a composite basis within a composite basis.");
131 });
132 }
133 }
134
144 template <typename F, typename TreePath = Dune::TypeTree::HybridTreePath<>>
145 void fixBoundaryDOFs(F&& f, TreePath&& treePath = {}) {
146 using namespace Dune::Functions;
147 using SubSpaceLocalView =
148 typename std::remove_cvref_t<decltype(subspaceBasis(basis_, std::forward<TreePath>(treePath)))>::LocalView;
149
151 auto lambda = [&](auto&& indexGlobal) { f(dirichletFlagsBackend_, indexGlobal); };
152 Dune::Functions::forEachBoundaryDOF(subspaceBasis(basis_, std::forward<TreePath>(treePath)), lambda);
153 } else if constexpr (Concepts::IsFunctorWithArgs<F, BackendType, int, SubSpaceLocalView>) {
154 auto lambda = [&](auto&& localIndex, auto&& localView) { f(dirichletFlagsBackend_, localIndex, localView); };
155 Dune::Functions::forEachBoundaryDOF(subspaceBasis(basis_, std::forward<TreePath>(treePath)), lambda);
156 } else if constexpr (Concepts::IsFunctorWithArgs<F, BackendType, int, SubSpaceLocalView,
157 typename Basis::GridView::Intersection>) {
158 auto lambda = [&](auto&& localIndex, auto&& localView, auto&& intersection) {
159 f(dirichletFlagsBackend_, localIndex, localView, intersection);
160 };
161 Dune::Functions::forEachBoundaryDOF(subspaceBasis(basis_, std::forward<TreePath>(treePath)), lambda);
162 } else {
163 static_assert(Dune::AlwaysFalse<F>(), "fixBoundaryDOFs: A function with this signature is not supported");
164 }
165 }
166
175 template <typename F>
176 void fixDOFs(F&& f) {
177 f(basis_, dirichletFlagsBackend_);
178 }
179
186 template <typename MultiIndex>
187 requires(not std::integral<MultiIndex>)
188 void setSingleDOF(const MultiIndex i, bool flag) {
189 dirichletFlagsBackend_[i] = flag;
190 }
191
199 void setSingleDOF(std::size_t i, bool flag)
200 requires(std::same_as<typename Basis::MultiIndex, Dune::Functions::FlatMultiIndex<size_t>>)
201 {
202 dirichletFlags_[i] = flag;
203 }
204
208 void reset() { std::fill(dirichletFlags_.begin(), dirichletFlags_.end(), false); }
209
210 /* \brief Returns the local basis object */
211 const auto& basis() const { return basis_; }
212
213 /* \brief Returns a boolean values, if the give multiIndex is constrained */
214 template <typename MultiIndex>
215 requires(not std::integral<MultiIndex>)
216 [[nodiscard]] bool isConstrained(const MultiIndex& multiIndex) const {
217 return dirichletFlagsBackend_[multiIndex];
218 }
219
220 /* \brief Returns a boolean values, if the i-th degree of freedom is constrained */
221 [[nodiscard]] bool isConstrained(std::size_t i) const
222 requires(std::same_as<typename Basis::MultiIndex, Dune::Functions::FlatMultiIndex<size_t>>)
223 {
224 return dirichletFlags_[i];
225 }
226
227 /* \brief Returns how many degrees of freedoms are fixed */
228 auto fixedDOFsize() const { return std::ranges::count(dirichletFlags_, true); }
229
230 /* \brief Returns how many degrees of freedom there are */
231 auto size() const { return dirichletFlags_.size(); }
232
233 /* \brief Returns the underlying dof flag container */
234 auto& container() const { return dirichletFlags_; }
235
247 template <typename F>
248 void storeInhomogeneousBoundaryCondition(F&& f, double lambda = 1.0) {
249 auto derivativeLambda = [&](const auto& globalCoord, const double& lambda) {
250 autodiff::real lambdaDual = lambda;
251 lambdaDual[1] = 1; // Setting the derivative in lambda direction to 1
252 return derivative(f(globalCoord, lambdaDual));
253 };
254 dirichletFunctions_.push_back({f, derivativeLambda});
255 setInhomogeneousBoundaryConditionFlag(lambda);
256 }
257
263 void setZeroAtConstrainedDofs(Eigen::VectorXd& xIh) const {
264 for (Eigen::Index i = 0; i < xIh.size(); ++i)
265 if (this->isConstrained(i))
266 xIh[i] = 0.0;
267 }
268
278 void evaluateInhomogeneousBoundaryCondition(Eigen::VectorXd& xIh, const double& lambda) const {
279 Eigen::VectorXd inhomogeneousBoundaryVectorDummy;
280 inhomogeneousBoundaryVectorDummy.setZero(this->size());
281 xIh.resizeLike(inhomogeneousBoundaryVectorDummy);
282 xIh.setZero();
283 auto runInterpolateImpl = [&](const auto& basis) {
284 for (auto& f : dirichletFunctions_) {
285 interpolate(basis, inhomogeneousBoundaryVectorDummy,
286 [&](const auto& globalCoord) { return f.value(globalCoord, lambda); });
287 xIh += inhomogeneousBoundaryVectorDummy;
288 }
289 };
290 runInterpolate(runInterpolateImpl);
291 }
292
302 void evaluateInhomogeneousBoundaryConditionDerivative(Eigen::VectorXd& xIh, const double& lambda) const {
303 Eigen::VectorXd inhomogeneousBoundaryVectorDummy;
304 inhomogeneousBoundaryVectorDummy.setZero(this->size());
305 xIh.resizeLike(inhomogeneousBoundaryVectorDummy);
306 xIh.setZero();
307 auto runInterpolateImpl = [&](const auto& basis) {
308 for (auto& f : dirichletFunctions_) {
309 interpolate(basis, inhomogeneousBoundaryVectorDummy,
310 [&](const auto& globalCoord) { return f.derivative(globalCoord, lambda); });
311 xIh += inhomogeneousBoundaryVectorDummy;
312 }
313 };
314 runInterpolate(runInterpolateImpl);
315 }
316
317private:
318 Basis basis_;
319 FlagsType dirichletFlags_;
320 BackendType dirichletFlagsBackend_;
321 struct DirichletFunctions
322 {
323 using Signature = std::function<NodalSolutionType(const Dune::FieldVector<double, worldDimension>&, const double&)>;
324 Signature value;
325 Signature derivative;
326 };
327 std::vector<DirichletFunctions> dirichletFunctions_;
328
329 void setInhomogeneousBoundaryConditionFlag(double lambda) {
330 Eigen::VectorXd inhomogeneousBoundaryVectorDummy;
331 inhomogeneousBoundaryVectorDummy.setZero(this->size());
332 this->evaluateInhomogeneousBoundaryCondition(inhomogeneousBoundaryVectorDummy, lambda);
333 for (const std::size_t i : Dune::range(this->size()))
334 if (Dune::FloatCmp::ne(inhomogeneousBoundaryVectorDummy[i], 0.0))
335 this->setSingleDOF(i, true);
336 }
337
338 template <typename F>
339 void runInterpolate(F&& f) const {
340 if constexpr (Tree::isComposite)
341 f(subspaceBasis(basis_, Dune::Indices::_0));
342 else
343 f(basis_);
344 }
345};
346
347} // namespace Ikarus
Definition: assemblermanipulatorbuildingblocks.hh:22
Definition: utils/dirichletvalues.hh:35
Definition: utils/dirichletvalues.hh:37
A helper struct to derive the SizeType of the underlying container.
Definition: utils/dirichletvalues.hh:46
Eigen::Index SizeType
Definition: utils/dirichletvalues.hh:51
std::vector< bool >::size_type SizeType
Definition: utils/dirichletvalues.hh:57
Class for handling Dirichlet boundary conditions in Ikarus.
Definition: utils/dirichletvalues.hh:109
auto size() const
Definition: utils/dirichletvalues.hh:231
void setZeroAtConstrainedDofs(Eigen::VectorXd &xIh) const
Function to write zeros at constrained Dirichlet entries.
Definition: utils/dirichletvalues.hh:263
void setSingleDOF(const MultiIndex i, bool flag)
Fixes and unfixes (set boolean value to true or false) a specific degree of freedom.
Definition: utils/dirichletvalues.hh:188
bool isConstrained(const MultiIndex &multiIndex) const
Definition: utils/dirichletvalues.hh:216
bool isConstrained(std::size_t i) const
Definition: utils/dirichletvalues.hh:221
void setSingleDOF(std::size_t i, bool flag)
Fixes or unfixes (set boolean value to true or false) a specific degree of freedom.
Definition: utils/dirichletvalues.hh:199
std::remove_cvref_t< B > Basis
Definition: utils/dirichletvalues.hh:111
void fixBoundaryDOFs(F &&f, TreePath &&treePath={})
Function to fix (set boolean values to true or false) degrees of freedom on the boundary.
Definition: utils/dirichletvalues.hh:145
decltype(Dune::Functions::istlVectorBackend(std::declval< FlagsType & >())) BackendType
Definition: utils/dirichletvalues.hh:113
void evaluateInhomogeneousBoundaryConditionDerivative(Eigen::VectorXd &xIh, const double &lambda) const
Function to evaluate all stored inhomogeneous Dirichlet boundary derivative functions.
Definition: utils/dirichletvalues.hh:302
void storeInhomogeneousBoundaryCondition(F &&f, double lambda=1.0)
Function to insert a function for inhomogeneous Dirichlet boundary conditions.
Definition: utils/dirichletvalues.hh:248
LocalView::Tree Tree
Definition: utils/dirichletvalues.hh:117
static constexpr int worldDimension
Definition: utils/dirichletvalues.hh:115
void fixDOFs(F &&f)
Function to fix (set boolean values to true or false) degrees of freedom.
Definition: utils/dirichletvalues.hh:176
FC FlagsType
Definition: utils/dirichletvalues.hh:112
void evaluateInhomogeneousBoundaryCondition(Eigen::VectorXd &xIh, const double &lambda) const
Function to evaluate all stored inhomogeneous Dirichlet boundary functions.
Definition: utils/dirichletvalues.hh:278
Basis::LocalView LocalView
Definition: utils/dirichletvalues.hh:116
void reset()
Resets all degrees of freedom.
Definition: utils/dirichletvalues.hh:208
typename DeriveSizeType< FlagsType >::SizeType SizeType
Definition: utils/dirichletvalues.hh:114
const auto & basis() const
Definition: utils/dirichletvalues.hh:211
auto fixedDOFsize() const
Definition: utils/dirichletvalues.hh:228
DirichletValues(const B &basis)
Definition: utils/dirichletvalues.hh:120
static constexpr std::size_t numberOfChildrenAtNode
Definition: utils/dirichletvalues.hh:119
auto & container() const
Definition: utils/dirichletvalues.hh:234
typename Impl::PreBasisInfo< Tree >::NodalSolutionType NodalSolutionType
Definition: utils/dirichletvalues.hh:118
Concept defining the requirements for functors with arguments.
Definition: utils/concepts.hh:357
Several concepts.