diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LameParameters.cpp b/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LameParameters.cpp
new file mode 100644
index 00000000..313a0460
--- /dev/null
+++ b/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LameParameters.cpp
@@ -0,0 +1,60 @@
+/******************************************************************************
+ * SofaPython3 plugin *
+ * (c) 2021 CNRS, University of Lille, INRIA *
+ * *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as published by *
+ * the Free Software Foundation; either version 2.1 of the License, or (at *
+ * your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, but WITHOUT *
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
+ * for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public License *
+ * along with this program. If not, see . *
+ *******************************************************************************
+ * Contact information: contact@sofa-framework.org *
+ ******************************************************************************/
+
+#include
+
+#include
+#include
+
+namespace sofapython3
+{
+
+void moduleAddLameParameters(pybind11::module &m)
+{
+ using namespace sofa::component::solidmechanics::fem::elastic;
+
+ m.def(
+ "toLameParameters2D",
+ [](SReal youngModulus, SReal poissonRatio) {
+ LameLambda lambda{0};
+ LameMu mu{0};
+ toLameParameters<2>(YoungModulus(youngModulus),
+ PoissonRatio(poissonRatio), lambda, mu);
+ return std::make_pair(mu.get(), lambda.get());
+ },
+ pybind11::arg("youngModulus"), pybind11::arg("poissonRatio"),
+ "Converts Young's modulus and Poisson's ratio to Lamé parameters (mu, "
+ "lambda) for 2D.");
+
+ m.def(
+ "toLameParameters3D",
+ [](SReal youngModulus, SReal poissonRatio) {
+ LameLambda lambda{0};
+ LameMu mu{0};
+ toLameParameters<3>(YoungModulus(youngModulus),
+ PoissonRatio(poissonRatio), lambda, mu);
+ return std::make_pair(mu.get(), lambda.get());
+ },
+ pybind11::arg("youngModulus"), pybind11::arg("poissonRatio"),
+ "Converts Young's modulus and Poisson's ratio to Lamé parameters (mu, "
+ "lambda) for 3D.");
+}
+
+} // namespace sofapython3
diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LameParameters.h b/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LameParameters.h
new file mode 100644
index 00000000..f79835c5
--- /dev/null
+++ b/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LameParameters.h
@@ -0,0 +1,30 @@
+/******************************************************************************
+* SOFA, Simulation Open-Framework Architecture *
+* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
+* *
+* This program is free software; you can redistribute it and/or modify it *
+* under the terms of the GNU Lesser General Public License as published by *
+* the Free Software Foundation; either version 2.1 of the License, or (at *
+* your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, but WITHOUT *
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
+* for more details. *
+* *
+* You should have received a copy of the GNU Lesser General Public License *
+* along with this program. If not, see . *
+*******************************************************************************
+* Contact information: contact@sofa-framework.org *
+******************************************************************************/
+
+#pragma once
+
+#include
+
+namespace sofapython3
+{
+
+void moduleAddLameParameters(pybind11::module& m);
+
+} // namespace sofapython3
diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/CMakeLists.txt b/bindings/Modules/src/SofaPython3/SofaDeformable/CMakeLists.txt
index 5c818b9d..26b5c7eb 100644
--- a/bindings/Modules/src/SofaPython3/SofaDeformable/CMakeLists.txt
+++ b/bindings/Modules/src/SofaPython3/SofaDeformable/CMakeLists.txt
@@ -1,12 +1,14 @@
project(Bindings.Modules.SofaDeformable)
set(SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/Module_SofaDeformable.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LameParameters.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSpring.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_SpringForceField.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Module_SofaDeformable.cpp
)
set(HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LameParameters.h
${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSpring.h
${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSpring_doc.h
${CMAKE_CURRENT_SOURCE_DIR}/Binding_SpringForceField.h
@@ -18,6 +20,7 @@ if (NOT TARGET SofaPython3::Plugin)
endif()
sofa_find_package(Sofa.Component.SolidMechanics.Spring REQUIRED)
+sofa_find_package(Sofa.Component.SolidMechanics.FEM.Elastic REQUIRED)
SP3_add_python_module(
TARGET ${PROJECT_NAME}
@@ -26,6 +29,6 @@ SP3_add_python_module(
DESTINATION Sofa
SOURCES ${SOURCE_FILES}
HEADERS ${HEADER_FILES}
- DEPENDS Sofa.Component.SolidMechanics.Spring SofaPython3::Plugin SofaPython3::Bindings.Sofa.Core
+ DEPENDS Sofa.Component.SolidMechanics.Spring Sofa.Component.SolidMechanics.FEM.Elastic SofaPython3::Plugin SofaPython3::Bindings.Sofa.Core
)
diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/Module_SofaDeformable.cpp b/bindings/Modules/src/SofaPython3/SofaDeformable/Module_SofaDeformable.cpp
index 0fc446e8..c99c636e 100644
--- a/bindings/Modules/src/SofaPython3/SofaDeformable/Module_SofaDeformable.cpp
+++ b/bindings/Modules/src/SofaPython3/SofaDeformable/Module_SofaDeformable.cpp
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
namespace py { using namespace pybind11; }
@@ -34,6 +35,7 @@ PYBIND11_MODULE(SofaDeformable, m)
moduleAddLinearSpring(m);
moduleAddSpringForceField(m);
+ moduleAddLameParameters(m);
}
} // namespace sofapython3
diff --git a/examples/stvenant_kirchhoff.py b/examples/stvenant_kirchhoff.py
new file mode 100644
index 00000000..577652c7
--- /dev/null
+++ b/examples/stvenant_kirchhoff.py
@@ -0,0 +1,83 @@
+import Sofa
+import Sofa.SofaDeformable
+
+from Sofa.Units.Definitions import s, m, cm, N, g, kg, MPa
+from Sofa.Units.UnitSystem import MechanicalUnitSystem
+
+def createScene(root_node):
+
+ plugins = [
+ "Sofa.Component.Constraint.Projective",
+ "Sofa.Component.Engine.Select",
+ "Sofa.Component.LinearSolver.Direct",
+ "Sofa.Component.Mapping.Linear",
+ "Sofa.Component.Mass",
+ "Sofa.Component.ODESolver.Backward",
+ "Sofa.Component.SolidMechanics.FEM.HyperElastic",
+ "Sofa.Component.StateContainer",
+ "Sofa.Component.Topology.Container.Dynamic",
+ "Sofa.Component.Topology.Container.Grid",
+ "Sofa.Component.Topology.Mapping",
+ "Sofa.GL.Component.Rendering3D",
+ "Sofa.Component.SolidMechanics.FEM.Elastic"
+ ]
+ root_node.addObject('RequiredPlugin', pluginName=plugins)
+
+ scene_unit = MechanicalUnitSystem(s, cm, g)
+
+ root_node.gravity = scene_unit([0, -9.81, 0], N / kg)
+ root_node.dt = scene_unit(0.01, s)
+
+ root_node.addObject('EulerImplicitSolver', name="backwardEuler", rayleighStiffness=0.1, rayleighMass=0.1)
+ root_node.addObject('SparseLDLSolver', template="CompressedRowSparseMatrixMat3x3d")
+ root_node.addObject('RegularGridTopology', name="grid", min=[-5, -5, 0], max=[5, 5, 40], n=[5, 5, 20])
+ root_node.addObject('MechanicalObject', template="Vec3", name="state")
+ root_node.addObject('NodalMassDensity', property=scene_unit(1150, kg/m**3))
+ root_node.addObject('FEMMass', template="Vec3,Hexahedron", topology="@grid")
+
+ with root_node.addChild('tetra') as tetra:
+
+ tetra.addObject('TetrahedronSetTopologyContainer', name="Tetra_topo")
+ tetra.addObject('TetrahedronSetTopologyModifier', name="Modifier")
+ tetra.addObject('TetrahedronSetGeometryAlgorithms', template="Vec3", name="GeomAlgo", drawTetrahedra="false")
+ tetra.addObject('Hexa2TetraTopologicalMapping', input="@grid", output="@Tetra_topo")
+
+ young_modulus = scene_unit(0.5, MPa)
+ poisson_ratio = 0.45
+ lame_parameters = Sofa.SofaDeformable.toLameParameters3D(young_modulus, poisson_ratio)
+ tetra.addObject('TetrahedronHyperelasticityFEMForceField', name="FEM", topology="@Tetra_topo",
+ ParameterSet=lame_parameters, materialName="StVenantKirchhoff")
+
+ with tetra.addChild('triangles') as triangles:
+
+ triangles.addObject('TriangleSetTopologyContainer', name="Container")
+ triangles.addObject('TriangleSetTopologyModifier')
+ triangles.addObject('Tetra2TriangleTopologicalMapping', input="@../Tetra_topo", output="@Container")
+
+ with triangles.addChild('Visu') as visu:
+
+ visu.addObject('OglModel', name="Visual", color="red")
+ visu.addObject('IdentityMapping', input="@../../../state", output="@Visual")
+
+ root_node.addObject('BoxROI', template="Vec3", name="box_roi", box=[-6, -6, -1, 6, 6, 0.1])
+ root_node.addObject('FixedProjectiveConstraint', template="Vec3", indices="@box_roi.indices")
+
+
+def main():
+ import Sofa
+ import SofaImGui
+
+ root = Sofa.Core.Node("root")
+ createScene(root)
+ Sofa.Simulation.initRoot(root)
+
+ import Sofa.Gui
+ Sofa.Gui.GUIManager.Init("myscene", "imgui")
+ Sofa.Gui.GUIManager.createGUI(root, __file__)
+ Sofa.Gui.GUIManager.SetDimension(1080, 1080)
+ Sofa.Gui.GUIManager.MainLoop(root)
+ Sofa.Gui.GUIManager.closeGUI()
+
+
+if __name__ == '__main__':
+ main()