version 0.4.1
mixin.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
12#include <dune/common/tuplevector.hh>
13
20
21namespace Ikarus {
31template <typename PreFE, template <typename, typename> class... Skills>
32struct FEMixin : public Listener, Skills<PreFE, typename PreFE::template FE<Skills...>>...
33{
39 explicit FEMixin(typename Skills<PreFE, typename PreFE::template FE<Skills...>>::Pre&&... skillsArgs)
40 : Skills<PreFE, typename PreFE::template FE<Skills...>>(
41 std::forward<typename Skills<PreFE, typename PreFE::template FE<Skills...>>::Pre>(skillsArgs))... {}
42
49 template <template <typename, typename> class Skill>
50 static consteval bool hasSkill() {
51 return Ikarus::traits::hasType<Skill<PreFE, typename PreFE::template FE<Skills...>>,
52 std::tuple<Skills<PreFE, typename PreFE::template FE<Skills...>>...>>::value;
53 }
54
55private:
56 template <typename T>
57 consteval static auto computeSupportedResultTypes() {
58 if constexpr (requires { typename T::SupportedResultTypes; })
59 return typename T::SupportedResultTypes();
60 else
61 return std::tuple();
62 }
63
64public:
69 decltype(std::tuple_cat(computeSupportedResultTypes<Skills<PreFE, typename PreFE::template FE<Skills...>>>()...));
70
71 template <bool, typename = void>
73
74 template <typename T>
75 struct RequirementType<false, T>
76 {
78 };
79
80 template <typename T>
81 struct RequirementType<true, T>
82 {
83 using type = std::common_type_t<typename Skills<PreFE, typename PreFE::template FE<Skills...>>::Requirement...>;
84 };
85
86private:
87 static constexpr bool requirementDetected =
88 Dune::Std::is_detected_v<std::common_type_t,
89 typename Skills<PreFE, typename PreFE::template FE<Skills...>>::Requirement...>;
90 static_assert(requirementDetected or sizeof...(Skills) == 0, "The skills must have a common fe requirement type.");
91
92public:
95 using LocalView = typename Traits::LocalView;
96 static constexpr int worldDim = Traits::worlddim;
97
98private:
99 template <typename ES>
100 static constexpr bool hasEASImpl = hasSkill<EnhancedAssumedStrainsPre<ES>::template Skill>();
101 template <typename PS>
102 static constexpr bool hasASImpl = hasSkill<AssumedStressPre<PS>::template Skill>();
103
104public:
105 static constexpr bool hasEAS() {
106 return hasEASImpl<EAS::LinearStrain> or hasEASImpl<EAS::GreenLagrangeStrain> or
107 hasEASImpl<EAS::DisplacementGradient> or hasEASImpl<EAS::DisplacementGradientTransposed>;
108 }
109 static constexpr bool hasAssumedStress() { return hasASImpl<PS::LinearStress> or hasASImpl<PS::PK2Stress>; }
110 static constexpr bool isMixed() { return hasAssumedStress() or hasEAS(); }
111
117 static auto createRequirement() { return Requirement(); }
118
126 friend auto calculateScalar(const FEMixin& self, const Requirement& req, ScalarAffordance affordance) {
127 return self.template calculateScalarImpl<double>(req, affordance);
128 }
129
137 friend void calculateVector(const FEMixin& self, const Requirement& req, VectorAffordance affordance,
138 typename Traits::template VectorType<> force) {
139 self.template calculateVectorImpl<double>(req, affordance, force);
140 }
141
149 friend void calculateMatrix(const FEMixin& self, const Requirement& req, MatrixAffordance affordance,
150 typename Traits::template MatrixType<> K) {
151 self.template calculateMatrixImpl<double>(req, affordance, K);
152 }
153
154 using Skills<PreFE, typename PreFE::template FE<Skills...>>::calculateAtImpl...;
155
164 template <template <typename, int, int> class RT>
165 requires requires(FEMixin m, const Requirement& req, const Dune::FieldVector<double, Traits::mydim>& local) {
166 m.template calculateAtImpl<RT>(req, local, Dune::PriorityTag<10>());
167 }
169 return this->template calculateAtImpl<RT>(req, local, Dune::PriorityTag<10>());
170 }
171
172private:
173 template <typename Sk>
174 auto invokeBind() {
175 if constexpr (requires { this->Sk::bindImpl(); })
176 Sk::bindImpl();
177 }
178
179 static constexpr bool implementsCalculateScalarImpl =
180 (requires(FEMixin m, const Requirement& par, ScalarAffordance affordance,
181 const std::optional<std::reference_wrapper<const Eigen::VectorX<double>>>& dx) {
182 m.Skills<PreFE, typename PreFE::template FE<Skills...>>::calculateScalarImpl(par, affordance, dx);
183 } ||
184 ...);
185
186public:
190 void bind() { (invokeBind<Skills<PreFE, typename PreFE::template FE<Skills...>>>(), ...); }
191
200 template <typename ScalarType = double>
201 requires implementsCalculateScalarImpl
203 const Requirement& par, ScalarAffordance affordance,
204 const std::optional<std::reference_wrapper<const Eigen::VectorX<ScalarType>>>& dx = std::nullopt) const {
205 return (Skills<PreFE, typename PreFE::template FE<Skills...>>::template calculateScalarImpl<ScalarType>(
206 par, affordance, dx) +
207 ... + ScalarType{0});
208 }
209
210private:
211 static constexpr bool implementsCalculateVectorImpl =
212 (requires(FEMixin m, const Requirement& par, VectorAffordance affordance,
213 typename Traits::template VectorType<double> force,
214 const std::optional<std::reference_wrapper<const Eigen::VectorX<double>>>& dx) {
215 m.Skills<PreFE, typename PreFE::template FE<Skills...>>::calculateVectorImpl(par, affordance, force, dx);
216 } ||
217 ...);
218
219public:
228 template <typename ScalarType>
229 requires implementsCalculateVectorImpl
231 const Requirement& par, VectorAffordance affordance, typename Traits::template VectorType<ScalarType> force,
232 const std::optional<std::reference_wrapper<const Eigen::VectorX<ScalarType>>>& dx = std::nullopt) const {
233 (Skills<PreFE, typename PreFE::template FE<Skills...>>::template calculateVectorImpl<ScalarType>(par, affordance,
234 force, dx),
235 ...);
236 }
237
238private:
239 static constexpr bool implementsCalculateMatrixImpl =
240 (requires(FEMixin m, const Requirement& par, MatrixAffordance affordance,
241 typename Traits::template MatrixType<double> K,
242 const std::optional<std::reference_wrapper<const Eigen::VectorX<double>>>& dx) {
243 m.Skills<PreFE, typename PreFE::template FE<Skills...>>::calculateMatrixImpl(par, affordance, K, dx);
244 } ||
245 ...);
246
247public:
256 template <typename ScalarType>
257 requires implementsCalculateMatrixImpl
259 const Requirement& par, MatrixAffordance affordance, typename Traits::template MatrixType<ScalarType> K,
260 const std::optional<std::reference_wrapper<const Eigen::VectorX<ScalarType>>>& dx = std::nullopt) const {
261 (Skills<PreFE, typename PreFE::template FE<Skills...>>::template calculateMatrixImpl<ScalarType>(par, affordance, K,
262 dx),
263 ...);
264 }
265
266private:
267 template <typename Sk>
268 auto invokeUpdateState(const Requirement& par,
269 const std::remove_reference_t<typename Traits::template VectorType<>>& correction) {
270 if constexpr (requires { Sk::updateStateImpl(par, correction); })
271 Sk::updateStateImpl(par, correction);
272 }
273
274public:
284 void updateState(const Requirement& par,
285 const std::remove_reference_t<typename Traits::template VectorType<>>& correction) {
286 (invokeUpdateState<Skills<PreFE, typename PreFE::template FE<Skills...>>>(par, correction), ...);
287 }
288
289private:
290 template <typename Sk, typename BC, typename MT>
291 auto invokeSubscribeTo(BC& bc) {
292 // For Clang-16: we need the this-> otherwise the code in the if clause will never be called. For Gcc-12.2: with
293 // the this-> it throws a compiler error in certain cases
294#if defined(__clang__)
295 if constexpr (requires { this->Sk::template subscribeToImpl<MT>(bc); }) {
296#else
297 if constexpr (requires { Sk::template subscribeToImpl<MT>(bc); }) {
298#endif
299 Sk::template subscribeToImpl<MT>(bc);
300 }
301 }
302
303public:
312 template <typename MT, typename BC>
313 auto subscribeTo(BC& bc) {
314 (invokeSubscribeTo<Skills<PreFE, typename PreFE::template FE<Skills...>>, traits::MaybeDereferencedType<BC>, MT>(
316 ...);
317 return *this;
318 }
319
320protected:
326 const auto& underlying() const { return static_cast<const typename PreFE::template FE<Skills...>&>(*this); }
332 auto& underlying() { return static_cast<typename PreFE::template FE<Skills...>&>(*this); }
333};
334
340template <typename... ARGS>
341struct Skills
342{
343 using Args = std::tuple<ARGS...>;
345};
346
354template <typename... Args>
355auto skills(const Args&... args) {
356 return Skills<std::remove_cvref_t<Args>...>{std::forward_as_tuple(std::remove_cvref_t<Args>(args)...)};
357}
358
368template <typename... Args1, typename... Args2>
369auto merge(const Skills<Args1...>& sk1, const Skills<Args2...>& sk2) {
370 return Skills<std::remove_cvref_t<Args1>..., std::remove_cvref_t<Args2>...>{std::tuple_cat(sk1.args, sk2.args)};
371}
372
373} // namespace Ikarus
Helper for dune-functions.
Definition of the EAS class.
Definition of the AssumedStress class.
FETraits template structure for finite element traits.
Implementation of the observer design pattern with broadcasters.
Enums for observer messages.
Definition: assemblermanipulatorbuildingblocks.hh:22
MatrixAffordance
A strongly typed enum class representing the matrix affordance.
Definition: ferequirements.hh:64
auto merge(const Skills< Args1... > &sk1, const Skills< Args2... > &sk2)
Function to merge two Skills instances.
Definition: mixin.hh:369
VectorAffordance
A strongly typed enum class representing the vector affordance.
Definition: ferequirements.hh:49
auto skills(const Args &... args)
Function to create a Skills instance with the given skills.
Definition: mixin.hh:355
ScalarAffordance
A strongly typed enum class representing the scalar affordance.
Definition: ferequirements.hh:38
decltype(auto) maybeDeref(T &t)
if T is a pointer type, return the dereferenced value, otherwise return the value itself.
Definition: functionhelper.hh:118
typename MaybeDereference< T >::type MaybeDereferencedType
Definition: utils/concepts.hh:754
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:223
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:33
auto subscribeTo(BC &bc)
Subscribes the elements to listen to functions provided from the skills emitted by the given broadcas...
Definition: mixin.hh:313
static auto createRequirement()
Create a Requirement object.
Definition: mixin.hh:117
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:202
static constexpr bool hasEAS()
Definition: mixin.hh:105
FEMixin(typename Skills< PreFE, typename PreFE::template FE< Skills... > >::Pre &&... skillsArgs)
Constructor for the FEMixin class.
Definition: mixin.hh:39
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:137
static constexpr int worldDim
Definition: mixin.hh:96
static constexpr bool hasAssumedStress()
Definition: mixin.hh:109
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:168
void updateState(const Requirement &par, const std::remove_reference_t< typename Traits::template VectorType<> > &correction)
Call all updateStateImpl functions if the skill implements it.
Definition: mixin.hh:284
friend auto calculateScalar(const FEMixin &self, const Requirement &req, ScalarAffordance affordance)
Calculate the scalar value associated with the given Requirement.
Definition: mixin.hh:126
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:230
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:258
RequirementType< requirementDetected >::type Requirement
Definition: mixin.hh:94
auto & underlying()
Get a reference to the underlying finite element object.
Definition: mixin.hh:332
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:149
const auto & underlying() const
Get a reference to the underlying finite element object.
Definition: mixin.hh:326
static consteval bool hasSkill()
Checks if the mixin class has a specific skill.
Definition: mixin.hh:50
void bind()
Call all bind functions if the skill implements it.
Definition: mixin.hh:190
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:69
static constexpr bool isMixed()
Definition: mixin.hh:110
typename Traits::LocalView LocalView
Definition: mixin.hh:95
Definition: mixin.hh:72
std::common_type_t< typename Skills< PreFE, typename PreFE::template FE< Skills... > >::Requirement... > type
Definition: mixin.hh:83
Struct representing a collection of skills.
Definition: mixin.hh:342
std::tuple< ARGS... > Args
Definition: mixin.hh:343
Args args
Definition: mixin.hh:344
Definition: utils/dirichletvalues.hh:32
Definition: listener.hh:27
Type trait to check if a specified type is present in a tuple.
Definition: traits.hh:88