version 0.4.1
mixin.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2021-2024 The Ikarus Developers mueller@ibb.uni-stuttgart.de
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
10#pragma once
11
12#include <dune/common/tuplevector.hh>
13
15
16namespace Ikarus {
26template <typename PreFE, template <typename, typename> class... Skills>
27struct FEMixin : Skills<PreFE, typename PreFE::template FE<Skills...>>...
28{
34 explicit FEMixin(typename Skills<PreFE, typename PreFE::template FE<Skills...>>::Pre&&... skillsArgs)
35 : Skills<PreFE, typename PreFE::template FE<Skills...>>(
36 std::forward<typename Skills<PreFE, typename PreFE::template FE<Skills...>>::Pre>(skillsArgs))... {}
37
44 template <template <typename, typename> class Skill>
45 static consteval bool hasSkill() {
46 return Ikarus::traits::hasType<Skill<PreFE, typename PreFE::template FE<Skills...>>,
47 std::tuple<Skills<PreFE, typename PreFE::template FE<Skills...>>...>>::value;
48 }
49
50private:
51 template <typename T>
52 consteval static auto computeSupportedResultTypes() {
53 if constexpr (requires { typename T::SupportedResultTypes; })
54 return typename T::SupportedResultTypes();
55 else
56 return std::tuple();
57 }
58
59public:
64 decltype(std::tuple_cat(computeSupportedResultTypes<Skills<PreFE, typename PreFE::template FE<Skills...>>>()...));
65
66 template <bool, typename = void>
68
69 template <typename T>
70 struct RequirementType<false, T>
71 {
73 };
74
75 template <typename T>
76 struct RequirementType<true, T>
77 {
78 using type = std::common_type_t<typename Skills<PreFE, typename PreFE::template FE<Skills...>>::Requirement...>;
79 };
80
81private:
82 static constexpr bool requirementDetected =
83 Dune::Std::is_detected_v<std::common_type_t,
84 typename Skills<PreFE, typename PreFE::template FE<Skills...>>::Requirement...>;
85 static_assert(requirementDetected or sizeof...(Skills) == 0, "The skills must have a common fe requirement type.");
86
87public:
90 using LocalView = typename Traits::LocalView;
91 static constexpr int worldDim = Traits::worlddim;
92
98 static auto createRequirement() { return Requirement(); }
99
107 friend auto calculateScalar(const FEMixin& self, const Requirement& req, ScalarAffordance affordance) {
108 return self.template calculateScalarImpl<double>(req, affordance);
109 }
110
118 friend void calculateVector(const FEMixin& self, const Requirement& req, VectorAffordance affordance,
119 typename Traits::template VectorType<> force) {
120 self.template calculateVectorImpl<double>(req, affordance, force);
121 }
122
130 friend void calculateMatrix(const FEMixin& self, const Requirement& req, MatrixAffordance affordance,
131 typename Traits::template MatrixType<> K) {
132 self.template calculateMatrixImpl<double>(req, affordance, K);
133 }
134
135 using Skills<PreFE, typename PreFE::template FE<Skills...>>::calculateAtImpl...;
136
145 template <template <typename, int, int> class RT>
146 requires requires(FEMixin m, const Requirement& req, const Dune::FieldVector<double, Traits::mydim>& local) {
147 m.template calculateAtImpl<RT>(req, local, Dune::PriorityTag<10>());
148 }
150 return this->template calculateAtImpl<RT>(req, local, Dune::PriorityTag<10>());
151 }
152
153private:
154 template <typename Sk>
155 auto invokeBind() {
156 if constexpr (requires { this->Sk::bindImpl(); })
157 Sk::bindImpl();
158 }
159
160 static constexpr bool implementsCalculateScalarImpl =
161 (requires(FEMixin m, const Requirement& par, ScalarAffordance affordance,
162 const std::optional<std::reference_wrapper<const Eigen::VectorX<double>>>& dx) {
163 m.Skills<PreFE, typename PreFE::template FE<Skills...>>::calculateScalarImpl(par, affordance, dx);
164 } ||
165 ...);
166
167public:
171 void bind() { (invokeBind<Skills<PreFE, typename PreFE::template FE<Skills...>>>(), ...); }
172
181 template <typename ScalarType = double>
182 requires implementsCalculateScalarImpl
184 const Requirement& par, ScalarAffordance affordance,
185 const std::optional<std::reference_wrapper<const Eigen::VectorX<ScalarType>>>& dx = std::nullopt) const {
186 return (Skills<PreFE, typename PreFE::template FE<Skills...>>::template calculateScalarImpl<ScalarType>(
187 par, affordance, dx) +
188 ... + ScalarType{0});
189 }
190
191private:
192 static constexpr bool implementsCalculateVectorImpl =
193 (requires(FEMixin m, const Requirement& par, VectorAffordance affordance,
194 typename Traits::template VectorType<double> force,
195 const std::optional<std::reference_wrapper<const Eigen::VectorX<double>>>& dx) {
196 m.Skills<PreFE, typename PreFE::template FE<Skills...>>::calculateVectorImpl(par, affordance, force, dx);
197 } ||
198 ...);
199
200public:
209 template <typename ScalarType>
210 requires implementsCalculateVectorImpl
212 const Requirement& par, VectorAffordance affordance, typename Traits::template VectorType<ScalarType> force,
213 const std::optional<std::reference_wrapper<const Eigen::VectorX<ScalarType>>>& dx = std::nullopt) const {
214 (Skills<PreFE, typename PreFE::template FE<Skills...>>::template calculateVectorImpl<ScalarType>(par, affordance,
215 force, dx),
216 ...);
217 }
218
219private:
220 static constexpr bool implementsCalculateMatrixImpl =
221 (requires(FEMixin m, const Requirement& par, MatrixAffordance affordance,
222 typename Traits::template MatrixType<double> K,
223 const std::optional<std::reference_wrapper<const Eigen::VectorX<double>>>& dx) {
224 m.Skills<PreFE, typename PreFE::template FE<Skills...>>::calculateMatrixImpl(par, affordance, K, dx);
225 } ||
226 ...);
227
228public:
237 template <typename ScalarType>
238 requires implementsCalculateMatrixImpl
240 const Requirement& par, MatrixAffordance affordance, typename Traits::template MatrixType<ScalarType> K,
241 const std::optional<std::reference_wrapper<const Eigen::VectorX<ScalarType>>>& dx = std::nullopt) const {
242 (Skills<PreFE, typename PreFE::template FE<Skills...>>::template calculateMatrixImpl<ScalarType>(par, affordance, K,
243 dx),
244 ...);
245 }
246
247protected:
253 const auto& underlying() const { return static_cast<const typename PreFE::template FE<Skills...>&>(*this); }
259 auto& underlying() { return static_cast<typename PreFE::template FE<Skills...>&>(*this); }
260};
261
267template <typename... ARGS>
268struct Skills
269{
270 using Args = std::tuple<ARGS...>;
272};
273
281template <typename... Args>
282auto skills(const Args&... args) {
283 return Skills<std::remove_cvref_t<Args>...>{std::forward_as_tuple(std::remove_cvref_t<Args>(args)...)};
284}
285
295template <typename... Args1, typename... Args2>
296auto merge(const Skills<Args1...>& sk1, const Skills<Args2...>& sk2) {
297 return Skills<std::remove_cvref_t<Args1>..., std::remove_cvref_t<Args2>...>{std::tuple_cat(sk1.args, sk2.args)};
298}
299
300} // namespace Ikarus
FETraits template structure for finite element traits.
STL namespace.
Definition: assemblermanipulatorbuildingblocks.hh:22
MatrixAffordance
A strongly typed enum class representing the matrix affordance.
Definition: ferequirements.hh:63
auto merge(const Skills< Args1... > &sk1, const Skills< Args2... > &sk2)
Function to merge two Skills instances.
Definition: mixin.hh:296
VectorAffordance
A strongly typed enum class representing the vector affordance.
Definition: ferequirements.hh:48
auto skills(const Args &... args)
Function to create a Skills instance with the given skills.
Definition: mixin.hh:282
ScalarAffordance
A strongly typed enum class representing the scalar affordance.
Definition: ferequirements.hh:37
FE class is a base class for all finite elements.
Definition: febase.hh:79
PreFE struct acts as a convenient wrapper for the FE class to access different type traits.
Definition: febase.hh:33
FETraits< BH, useEigenRef, useFlat > Traits
Definition: febase.hh:38
Class representing the requirements for finite element calculations.
Definition: ferequirements.hh:252
Traits for handling finite elements.
Definition: fetraits.hh:25
typename Basis::LocalView LocalView
Type of the local view.
Definition: fetraits.hh:42
static constexpr int worlddim
Dimension of the world space.
Definition: fetraits.hh:60
CRTP mixin class for finite elements with additional skills.
Definition: mixin.hh:28
static auto createRequirement()
Create a Requirement object.
Definition: mixin.hh:98
auto calculateScalarImpl(const Requirement &par, ScalarAffordance affordance, const std::optional< std::reference_wrapper< const Eigen::VectorX< ScalarType > > > &dx=std::nullopt) const
Calculate the scalar value in each skill and joins them by +.
Definition: mixin.hh:183
FEMixin(typename Skills< PreFE, typename PreFE::template FE< Skills... > >::Pre &&... skillsArgs)
Constructor for the FEMixin class.
Definition: mixin.hh:34
friend void calculateVector(const FEMixin &self, const Requirement &req, VectorAffordance affordance, typename Traits::template VectorType<> force)
Calculate the vector associated with the given Requirement.
Definition: mixin.hh:118
static constexpr int worldDim
Definition: mixin.hh:91
auto calculateAt(const Requirement &req, const Dune::FieldVector< double, Traits::mydim > &local) const
Calculate the element values at a specific location for a given ResultType.
Definition: mixin.hh:149
friend auto calculateScalar(const FEMixin &self, const Requirement &req, ScalarAffordance affordance)
Calculate the scalar value associated with the given Requirement.
Definition: mixin.hh:107
void calculateVectorImpl(const Requirement &par, VectorAffordance affordance, typename Traits::template VectorType< ScalarType > force, const std::optional< std::reference_wrapper< const Eigen::VectorX< ScalarType > > > &dx=std::nullopt) const
Calculate the vector for each skill.
Definition: mixin.hh:211
void calculateMatrixImpl(const Requirement &par, MatrixAffordance affordance, typename Traits::template MatrixType< ScalarType > K, const std::optional< std::reference_wrapper< const Eigen::VectorX< ScalarType > > > &dx=std::nullopt) const
Calculate the matrix for each skill.
Definition: mixin.hh:239
RequirementType< requirementDetected >::type Requirement
Definition: mixin.hh:89
auto & underlying()
Get a reference to the underlying finite element object.
Definition: mixin.hh:259
friend void calculateMatrix(const FEMixin &self, const Requirement &req, MatrixAffordance affordance, typename Traits::template MatrixType<> K)
Calculate the matrix associated with the given Requirement.
Definition: mixin.hh:130
const auto & underlying() const
Get a reference to the underlying finite element object.
Definition: mixin.hh:253
static consteval bool hasSkill()
Checks if the mixin class has a specific skill.
Definition: mixin.hh:45
void bind()
Call all bind functions if the skill implements it.
Definition: mixin.hh:171
decltype(std::tuple_cat(computeSupportedResultTypes< Skills< PreFE, typename PreFE::template FE< Skills... > > >()...)) SupportedResultTypes
Type alias for the supported result types by the mixin.
Definition: mixin.hh:64
typename Traits::LocalView LocalView
Definition: mixin.hh:90
Definition: mixin.hh:67
std::common_type_t< typename Skills< PreFE, typename PreFE::template FE< Skills... > >::Requirement... > type
Definition: mixin.hh:78
Struct representing a collection of skills.
Definition: mixin.hh:269
std::tuple< ARGS... > Args
Definition: mixin.hh:270
Args args
Definition: mixin.hh:271
Definition: utils/dirichletvalues.hh:32
Type trait to check if a specified type is present in a tuple.
Definition: traits.hh:86