11#include <dune/common/classname.hh>
12#include <dune/python/common/typeregistry.hh>
13#include <dune/python/pybind11/eigen.h>
14#include <dune/python/pybind11/pybind11.h>
15#include <dune/python/pybind11/stl.h>
23#define MAKE_MaterialFunction(clsName, materialName, functionname, vecSize) \
26 [](materialName& self, StrainTags straintag, Eigen::Ref<const Eigen::Vector<double, vecSize>> eVoigt_) { \
27 if constexpr (not(materialName::strainTag == StrainTags::linear)) { \
28 Eigen::Vector<double, vecSize> eVoigt = eVoigt_; \
29 if (straintag == StrainTags::rightCauchyGreenTensor) \
30 return self.template functionname<StrainTags::rightCauchyGreenTensor>(eVoigt); \
31 else if (straintag == StrainTags::greenLagrangian) \
32 return self.template functionname<StrainTags::greenLagrangian>(eVoigt); \
33 else if (straintag == StrainTags::linear) \
34 DUNE_THROW(Dune::MathError, "Passing linear strain to " + std::string(#materialName) + \
35 " does not makes sense use LinearElastic class"); \
36 else if (straintag == StrainTags::displacementGradient) \
37 DUNE_THROW(Dune::MathError, \
38 "Passing displacementGradient strain in 6d Voigt notation does not make any sense!"); \
39 else if (straintag == StrainTags::deformationGradient) \
40 DUNE_THROW(Dune::MathError, \
41 "Passing deformationGradient strain in 6d Voigt notation does not make any sense!"); \
43 DUNE_THROW(Dune::MathError, toString(straintag) + "is not a valid strain tag."); \
45 Eigen::Vector<double, vecSize> eVoigt = eVoigt_;
\
46 if (straintag == StrainTags::linear) \
47 return self.template functionname<StrainTags::linear>(eVoigt); \
49 DUNE_THROW(Dune::MathError, "Linear elastic material only accepts linear strains!"); \
51 __builtin_unreachable(); \
53 "StrainName"_a, "strainVector"_a);
59 LamesFirstParameterAndShearModulus convertMaterialParameters(
const pybind11::kwargs& kwargs,
60 const std::string& param1,
const std::string& param2) {
62 convertLameConstants(T{kwargs[param1.c_str()].cast<double>(), kwargs[param2.c_str()].cast<
double>()});
63 return {converter.toLamesFirstParameter(), converter.toShearModulus()};
68 static const std::map<std::array<std::string, 2>, std::function<LamesFirstParameterAndShearModulus(
const pybind11::kwargs&)>> conversionMap = {
69 {{
"E",
"nu"}, [](
const auto& kw){
return convertMaterialParameters<YoungsModulusAndPoissonsRatio>(kw,
"E",
"nu"); }},
70 {{
"E",
"mu"}, [](
const auto& kw){
return convertMaterialParameters<YoungsModulusAndShearModulus>(kw,
"E",
"mu"); }},
71 {{
"E",
"K"}, [](
const auto& kw){
return convertMaterialParameters<YoungsModulusAndBulkModulus>(kw,
"E",
"K"); }},
72 {{
"E",
"Lambda"}, [](
const auto& kw){
return convertMaterialParameters<YoungsModulusAndLamesFirstParameter>(kw,
"E",
"Lambda"); }},
73 {{
"K",
"Lambda"}, [](
const auto& kw){
return convertMaterialParameters<BulkModulusAndLamesFirstParameter>(kw,
"K",
"Lambda"); }},
74 {{
"Lambda",
"mu"}, [](
const auto& kw){
return LamesFirstParameterAndShearModulus{kw[
"Lambda"].template cast<double>(), kw[
"mu"].template cast<double>()}; }}
78 if (kwargs.size() != 2)
79 DUNE_THROW(Dune::IOError,
"The number of material parameters passed to the material should be 2");
81 for (
const auto& [materialParameters, parameterConverter] : conversionMap) {
82 const auto [firstPar, secondPar] = materialParameters;
83 if (kwargs.contains(firstPar) && kwargs.contains(secondPar)) {
84 return parameterConverter(kwargs);
88 DUNE_THROW(Dune::IOError,
89 "No suitable combination of material parameters found, valid combinations are: (E, nu), (E, mu), (E, "
90 "K), (E, Lambda), (K, Lambda), (Lambda, nu)");
94template <
class Material,
size_t vecSize,
bool registerConstructor,
class... options>
95void registerMaterial(pybind11::handle scope, pybind11::class_<Material, options...> cls) {
96 using pybind11::operator
""_a;
97 namespace py = pybind11;
99 if constexpr (registerConstructor)
101 auto matParameter = Impl::extractMaterialParameters(kwargs);
102 return new Material(matParameter);
105 std::string materialname = Material::name();
112 auto includes = Dune::Python::IncludeFiles{
"ikarus/finiteelements/mechanics/materials.hh"};
113 auto pS = Dune::Python::insertClass<PlaneStressClass>(
114 scope, std::string(
"PlaneStress_") + materialname,
115 Dune::Python::GenerateTypeName(
116 "Ikarus::Materials::VanishingStress<std::array<Ikarus::Materials::MatrixIndexPair, 3ul >"
118 "{Ikarus::Materials::MatrixIndexPair{2ul, 1ul}, Ikarus::Materials::MatrixIndexPair{2ul, 0ul},"
119 "Ikarus::Materials::MatrixIndexPair{2ul, 2ul}}}," +
120 Dune::className<Material>() +
">"),
132 py::arg(
"tol") = 1e-12);
135 auto pStrain = Dune::Python::insertClass<PlaneStrainClass>(
136 scope, std::string(
"PlaneStrain_") + materialname,
137 Dune::Python::GenerateTypeName(
138 "Ikarus::Materials::VanishingStrain<std::array<Ikarus::Materials::MatrixIndexPair, "
139 "3ul>{{Ikarus::Materials::MatrixIndexPair{2ul, 1ul},"
140 "Ikarus::Materials::MatrixIndexPair{2ul,0ul}, Ikarus::Materials::MatrixIndexPair{"
142 Dune::className<Material>() +
">"),
152 cls.def(
"asPlaneStrain", [](
Material& self) {
156 auto shellmaterial = Dune::Python::insertClass<ShellMaterialClass>(
157 scope, std::string(
"Shell_") + materialname,
158 Dune::Python::GenerateTypeName(
159 "Ikarus::Materials::VanishingStress<std::array<Ikarus::Materials::MatrixIndexPair,"
160 "1ul>{{Ikarus::Materials::MatrixIndexPair{2ul, 2ul}}}," +
161 Dune::className<Material>() +
">"),
173 py::arg(
"tol") = 1e-12);
175 auto beammaterial = Dune::Python::insertClass<BeamMaterialClass>(
176 scope, std::string(
"Beam_") + materialname,
177 Dune::Python::GenerateTypeName(
178 "Ikarus::Materials::VanishingStress<std::array<Ikarus::Materials::MatrixIndexPair, "
179 "2ul>{{Materials::MatrixIndexPair{1, 1},Ikarus::Materials::MatrixIndexPair{2ul, 2ul}}}," +
180 Dune::className<Material>() +
">"),
191 py::arg(
"tol") = 1e-12);
194#define MAKE_MATERIAL_REGISTRY_FUNCTION(name, vecSize) \
195 template <class Material, class... options> \
196 void register##name(pybind11::handle scope, pybind11::class_<Material, options...> cls) { \
197 Ikarus::Python::registerMaterial<Material, vecSize, true>(scope, cls); \
206template <
class MuesliMaterial,
class... options>
207void registerMuesliMaterial(pybind11::handle scope, pybind11::class_<MuesliMaterial, options...> cls) {
208 Ikarus::Python::registerMaterial<MuesliMaterial, 6, false>(scope, cls);
211 if constexpr (std::same_as<typename MuesliMaterial::MaterialModel, muesli::neohookeanMaterial> or
212 std::same_as<typename MuesliMaterial::MaterialModel, muesli::svkMaterial> or
213 std::same_as<typename MuesliMaterial::MaterialModel, muesli::elasticIsotropicMaterial>) {
214 auto matParameter = Impl::extractMaterialParameters(kwargs);
215 auto muesliParameters = Ikarus::Materials::propertiesFromIkarusMaterialParameters(matParameter);
216 return new MuesliMaterial(muesliParameters);
217 }
else if constexpr (std::same_as<typename MuesliMaterial::MaterialModel, muesli::arrudaboyceMaterial>) {
218 bool compressible = kwargs.contains(
"compressible") ? kwargs[
"compressible"].cast<
bool>() :
true;
219 return Materials::makeMuesliArrudaBoyce(kwargs[
"C1"].cast<double>(), kwargs[
"lambda_m"].cast<double>(),
220 kwargs[
"K"].cast<double>(),
true);
221 }
else if constexpr (std::same_as<typename MuesliMaterial::MaterialModel, muesli::yeohMaterial>) {
222 bool compressible = kwargs.contains(
"compressible") ? kwargs[
"compressible"].cast<
bool>() :
true;
223 return Materials::makeMuesliYeoh(kwargs[
"C"].cast<std::array<double, 3>>(), kwargs[
"K"].cast<double>(),
true);
224 }
else if constexpr (std::same_as<typename MuesliMaterial::MaterialModel, muesli::mooneyMaterial>) {
225 bool incompressible = kwargs.contains(
"incompressible") ? kwargs[
"incompressible"].cast<
bool>() :
false;
228 DUNE_THROW(Dune::NotImplemented,
"No known constructor for the specified Muesli material mode");
232 cls.def(
"printDescription", [](MuesliMaterial& self) { self.material().print(std::cout); });
#define MAKE_MaterialFunction(clsName, materialName, functionname, vecSize)
Definition: material.hh:23
ConvertLameConstants< YoungsModulusAndPoissonsRatio > convertLameConstants(const YoungsModulusAndPoissonsRatio &valuePair)
Definition: physicshelper.hh:245
void init(int argc, char **argv, bool enableFileLogger=true)
Initializes the Ikarus framework.
Definition: init.hh:82
NeoHookeT< double > NeoHooke
Alias for NeoHookeT with double as the default scalar type.
Definition: neohooke.hh:160
auto planeStrain(const MaterialImpl &mat)
Factory function to create a VanishingStrain material for plane strain conditions.
Definition: vanishingstrain.hh:197
StVenantKirchhoffT< double > StVenantKirchhoff
Alias for StVenantKirchhoffT with double as the default scalar type.
Definition: svk.hh:182
auto makeMooneyRivlin(const typename InvariantBased< 2 >::MaterialParameters &mu, double K=0.0, const VolumetricFunction &vf=VolumetricFunction{})
A helper function to create a hyperelastic material model, where the deviatoric part is according to ...
Definition: factory.hh:105
auto shellMaterial(const MaterialImpl &mat, typename MaterialImpl::ScalarType tol=1e-8)
Factory function to create a VanishingStress material for a shell material with zero normal stress co...
Definition: vanishingstress.hh:253
LinearElasticityT< double > LinearElasticity
Convenience typedef for LinearElasticity with double as ScalarType.
Definition: linearelasticity.hh:129
auto planeStress(const MaterialImpl &mat, typename MaterialImpl::ScalarType tol=1e-8)
Factory function to create a VanishingStress material for plane stress conditions.
Definition: vanishingstress.hh:240
auto beamMaterial(const MaterialImpl &mat, typename MaterialImpl::ScalarType tol=1e-8)
Factory function to create a VanishingStress material for a beam material with two zero normal stress...
Definition: vanishingstress.hh:266
Definition: flatassembler.hh:21
void registerMaterial(pybind11::handle scope, pybind11::class_< Material, options... > cls)
Definition: material.hh:95
MAKE_MATERIAL_REGISTRY_FUNCTION(LinearElasticity, 6)
Definition: physicshelper.hh:54
Header file for material models in Ikarus finite element mechanics.