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()