Skip to content

Commit

Permalink
[FEM.HyperElastic] Convert string Data to OptionsGroup (#4651)
Browse files Browse the repository at this point in the history
* [FEM.HyperElastic] Convert string Data to OptionsGroup

* Factorization of drawing

* Missing resize

* Change order of functions

* Add strong test on the value of the material

* Fix wrong name
  • Loading branch information
alxbilger committed May 8, 2024
1 parent 204a38a commit 7dfb651
Show file tree
Hide file tree
Showing 14 changed files with 163 additions and 86 deletions.
4 changes: 4 additions & 0 deletions Sofa/Component/ODESolver/Backward/tests/StaticSolver_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,14 @@ class StaticSolverTest : public sofa::testing::BaseTest
createObject(root, "TetrahedronSetTopologyModifier");
createObject(root, "Hexa2TetraTopologicalMapping", {{"input", "@grid"}, {"output", "@mechanical_topology"}});
createObject(root, "TetrahedronHyperelasticityFEMForceField", {
{"name", "FEM"},
{"materialName", "StVenantKirchhoff"},
{"ParameterSet", std::to_string(mu) + " " + std::to_string(l)},
{"topology", "@mechanical_topology"}
});
ASSERT_NE(root->getObject("FEM"), nullptr);
ASSERT_NE(root->getObject("FEM")->findData("materialName"), nullptr);
ASSERT_EQ(root->getObject("FEM")->findData("materialName")->getValueString(), "StVenantKirchhoff");

createObject(root, "BoxROI", {{"name", "top_roi"}, {"box", "-7.5 -7.5 -0.9 7.5 7.5 0.1"}});
createObject(root, "FixedProjectiveConstraint", {{"indices", "@top_roi.indices"}});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ void StandardTetrahedralFEMForceField<DataTypes>::draw(const core::visual::Visua
if (vparams->displayFlags().getShowWireFrame())
vparams->drawTool()->setPolygonMode(0,true);

drawHyperelasticTets(vparams, x, m_topology, f_materialName.getValue());
drawHyperelasticTets<DataTypes>(vparams, x, m_topology, f_materialName.getValue());

if (vparams->displayFlags().getShowWireFrame())
vparams->drawTool()->setPolygonMode(0,false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,103 @@
#include <sofa/core/topology/BaseMeshTopology.h>
#include <sofa/core/topology/Topology.h>

#include <sofa/component/solidmechanics/fem/hyperelastic/material/BoyceAndArruda.h>
#include <sofa/component/solidmechanics/fem/hyperelastic/material/NeoHookean.h>
#include <sofa/component/solidmechanics/fem/hyperelastic/material/MooneyRivlin.h>
#include <sofa/component/solidmechanics/fem/hyperelastic/material/VerondaWestman.h>
#include <sofa/component/solidmechanics/fem/hyperelastic/material/STVenantKirchhoff.h>
#include <sofa/component/solidmechanics/fem/hyperelastic/material/Costa.h>
#include <sofa/component/solidmechanics/fem/hyperelastic/material/Ogden.h>


namespace sofa::component::solidmechanics::fem::hyperelastic
{

template <class VecCoord>
void drawHyperelasticTets(const core::visual::VisualParams* vparams, const VecCoord& x, core::topology::BaseMeshTopology* topology, const std::string& materialName)
template <class DataTypes>
void selectColors(const std::string& materialName, sofa::type::RGBAColor& color1, sofa::type::RGBAColor& color2, sofa::type::RGBAColor& color3, sofa::type::RGBAColor& color4)
{
if (materialName == material::BoyceAndArruda<DataTypes>::Name)
{
color1 = type::RGBAColor(0.0, 1.0, 0.0, 1.0);
color2 = type::RGBAColor(0.5, 1.0, 0.0, 1.0);
color3 = type::RGBAColor(1.0, 1.0, 0.0, 1.0);
color4 = type::RGBAColor(1.0, 1.0, 0.5, 1.0);
}
else if (materialName == material::STVenantKirchhoff<DataTypes>::Name)
{
color1 = type::RGBAColor(1.0,0.0,0.0,1.0);
color2 = type::RGBAColor(1.0,0.0,0.5,1.0);
color3 = type::RGBAColor(1.0,1.0,0.0,1.0);
color4 = type::RGBAColor(1.0,0.5,1.0,1.0);
}
else if (materialName == material::NeoHookean<DataTypes>::Name)
{
color1 = type::RGBAColor(0.0, 1.0, 1.0, 1.0);
color2 = type::RGBAColor(0.5, 0.0, 1.0, 1.0);
color3 = type::RGBAColor(1.0, 0.0, 1.0, 1.0);
color4 = type::RGBAColor(1.0, 0.5, 1.0, 1.0);
}
else if (materialName == material::MooneyRivlin<DataTypes>::Name)
{
color1 = type::RGBAColor(0.0, 1.0, 0.0, 1.0);
color2 = type::RGBAColor(0.0, 1.0, 0.5, 1.0);
color3 = type::RGBAColor(0.0, 1.0, 1.0, 1.0);
color4 = type::RGBAColor(0.5, 1.0, 1.0, 1.0);
}
else if (materialName == material::VerondaWestman<DataTypes>::Name)
{
color1 = type::RGBAColor(0.0, 1.0, 0.0, 1.0);
color2 = type::RGBAColor(0.5, 1.0, 0.0, 1.0);
color3 = type::RGBAColor(1.0, 1.0, 0.0, 1.0);
color4 = type::RGBAColor(1.0, 1.0, 0.5, 1.0);
}
else if (materialName == material::Costa<DataTypes>::Name)
{
color1 = type::RGBAColor(0.0, 1.0, 0.0, 1.0);
color2 = type::RGBAColor(0.5, 1.0, 0.0, 1.0);
color3 = type::RGBAColor(1.0, 1.0, 0.0, 1.0);
color4 = type::RGBAColor(1.0, 1.0, 0.5, 1.0);
}
else if (materialName == material::Ogden<DataTypes>::Name)
{
color1 = type::RGBAColor(0.0, 1.0, 0.0, 1.0);
color2 = type::RGBAColor(0.5, 1.0, 0.0, 1.0);
color3 = type::RGBAColor(1.0, 1.0, 0.0, 1.0);
color4 = type::RGBAColor(1.0, 1.0, 0.5, 1.0);
}
else
{
color1 = type::RGBAColor(0.0, 1.0, 0.0, 1.0);
color2 = type::RGBAColor(0.5, 1.0, 0.0, 1.0);
color3 = type::RGBAColor(1.0, 1.0, 0.0, 1.0);
color4 = type::RGBAColor(1.0, 1.0, 0.5, 1.0);
}
}

template <class DataTypes>
void drawHyperelasticTets(const core::visual::VisualParams* vparams,
const typename DataTypes::VecCoord& x,
core::topology::BaseMeshTopology* topology,
const std::string& materialName,
const sofa::type::vector<core::topology::Topology::TetrahedronID>& indicesToDraw)
{
std::vector<type::Vec3 > points[4];
for(auto& p : points)
{
p.reserve(3 * topology->getNbTetrahedra());
p.reserve(3 * indicesToDraw.size());
}

for(const auto& t : topology->getTetrahedra())
const auto& tetrahedra = topology->getTetrahedra();

for(const auto i : indicesToDraw)
{
Index a = t[0];
Index b = t[1];
Index c = t[2];
Index d = t[3];
const auto t = tetrahedra[i];

const Index a = t[0];
const Index b = t[1];
const Index c = t[2];
const Index d = t[3];

const auto center = (x[a] + x[b] + x[c] + x[d]) * 0.125;
const auto pa = (x[a] + center) * 0.666667;
const auto pb = (x[b] + center) * 0.666667;
Expand All @@ -67,64 +145,25 @@ void drawHyperelasticTets(const core::visual::VisualParams* vparams, const VecCo
points[3].push_back(pb);
}

sofa::type::RGBAColor color1;
sofa::type::RGBAColor color2;
sofa::type::RGBAColor color3;
sofa::type::RGBAColor color4;
std::array<sofa::type::RGBAColor, 4> colors;
selectColors<DataTypes>(materialName, colors[0], colors[1], colors[2], colors[3]);

if (materialName=="ArrudaBoyce") {
color1 = sofa::type::RGBAColor(0.0,1.0,0.0,1.0);
color2 = sofa::type::RGBAColor(0.5,1.0,0.0,1.0);
color3 = sofa::type::RGBAColor(1.0,1.0,0.0,1.0);
color4 = sofa::type::RGBAColor(1.0,1.0,0.5,1.0);
}
else if (materialName=="StVenantKirchhoff"){
color1 = sofa::type::RGBAColor(1.0,0.0,0.0,1.0);
color2 = sofa::type::RGBAColor(1.0,0.0,0.5,1.0);
color3 = sofa::type::RGBAColor(1.0,1.0,0.0,1.0);
color4 = sofa::type::RGBAColor(1.0,0.5,1.0,1.0);
}
else if (materialName=="NeoHookean"){
color1 = sofa::type::RGBAColor(0.0,1.0,1.0,1.0);
color2 = sofa::type::RGBAColor(0.5,0.0,1.0,1.0);
color3 = sofa::type::RGBAColor(1.0,0.0,1.0,1.0);
color4 = sofa::type::RGBAColor(1.0,0.5,1.0,1.0);
}
else if (materialName=="MooneyRivlin"){
color1 = sofa::type::RGBAColor(0.0,1.0,0.0,1.0);
color2 = sofa::type::RGBAColor(0.0,1.0,0.5,1.0);
color3 = sofa::type::RGBAColor(0.0,1.0,1.0,1.0);
color4 = sofa::type::RGBAColor(0.5,1.0,1.0,1.0);
}
else if (materialName=="VerondaWestman"){
color1 = sofa::type::RGBAColor(0.0,1.0,0.0,1.0);
color2 = sofa::type::RGBAColor(0.5,1.0,0.0,1.0);
color3 = sofa::type::RGBAColor(1.0,1.0,0.0,1.0);
color4 = sofa::type::RGBAColor(1.0,1.0,0.5,1.0);
}
else if (materialName=="Costa"){
color1 = sofa::type::RGBAColor(0.0,1.0,0.0,1.0);
color2 = sofa::type::RGBAColor(0.5,1.0,0.0,1.0);
color3 = sofa::type::RGBAColor(1.0,1.0,0.0,1.0);
color4 = sofa::type::RGBAColor(1.0,1.0,0.5,1.0);
}
else if (materialName=="Ogden"){
color1 = sofa::type::RGBAColor(0.0,1.0,0.0,1.0);
color2 = sofa::type::RGBAColor(0.5,1.0,0.0,1.0);
color3 = sofa::type::RGBAColor(1.0,1.0,0.0,1.0);
color4 = sofa::type::RGBAColor(1.0,1.0,0.5,1.0);
}
else {
color1 = sofa::type::RGBAColor(0.0,1.0,0.0,1.0);
color2 = sofa::type::RGBAColor(0.5,1.0,0.0,1.0);
color3 = sofa::type::RGBAColor(1.0,1.0,0.0,1.0);
color4 = sofa::type::RGBAColor(1.0,1.0,0.5,1.0);
}
vparams->drawTool()->drawTriangles(points[0], colors[0]);
vparams->drawTool()->drawTriangles(points[1], colors[1]);
vparams->drawTool()->drawTriangles(points[2], colors[2]);
vparams->drawTool()->drawTriangles(points[3], colors[3]);
}

vparams->drawTool()->drawTriangles(points[0], color1);
vparams->drawTool()->drawTriangles(points[1], color2);
vparams->drawTool()->drawTriangles(points[2], color3);
vparams->drawTool()->drawTriangles(points[3], color4);
template <class DataTypes>
void drawHyperelasticTets(const core::visual::VisualParams* vparams,
const typename DataTypes::VecCoord& x,
core::topology::BaseMeshTopology* topology,
const std::string& materialName)
{
sofa::type::vector<core::topology::Topology::TetrahedronID> allIndices(topology->getNbTetrahedra());
std::iota(allIndices.begin(), allIndices.end(), static_cast<core::topology::Topology::TetrahedronID>(0));
drawHyperelasticTets<DataTypes>(vparams, x, topology, materialName, allIndices);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include <sofa/type/MatSym.h>
#include <sofa/core/topology/BaseMeshTopology.h>
#include <sofa/core/topology/TopologyData.h>
#include <sofa/helper/OptionsGroup.h>


namespace sofa::component::solidmechanics::fem::hyperelastic
{
Expand Down Expand Up @@ -133,7 +135,7 @@ class TetrahedronHyperelasticityFEMForceField : public core::behavior::ForceFiel

public:
Data<bool> d_stiffnessMatrixRegularizationWeight; ///< Regularization of the Stiffness Matrix (between true or false)
Data<std::string> d_materialName; ///< the name of the material
Data<sofa::helper::OptionsGroup> d_materialName; ///< the name of the material
Data<SetParameterArray> d_parameterSet; ///< The global parameters specifying the material
Data<SetAnisotropyDirectionArray> d_anisotropySet; ///< The global directions of anisotropy of the material

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,24 @@ using namespace sofa::defaulttype;
using namespace core::topology;
using namespace sofa::component::solidmechanics::fem::hyperelastic::material;

template<class DataTypes>
const helper::OptionsGroup materialOptions {
BoyceAndArruda<DataTypes>::Name,
STVenantKirchhoff<DataTypes>::Name,
NeoHookean<DataTypes>::Name,
MooneyRivlin<DataTypes>::Name,
VerondaWestman<DataTypes>::Name,
Costa<DataTypes>::Name,
Ogden<DataTypes>::Name,
StableNeoHookean<DataTypes>::Name
};

template <class DataTypes> TetrahedronHyperelasticityFEMForceField<DataTypes>::TetrahedronHyperelasticityFEMForceField()
: m_topology(nullptr)
, m_initialPoints(0)
, m_updateMatrix(true)
, d_stiffnessMatrixRegularizationWeight(initData(&d_stiffnessMatrixRegularizationWeight, (bool)false,"matrixRegularization","Regularization of the Stiffness Matrix (between true or false)"))
, d_materialName(initData(&d_materialName,std::string("ArrudaBoyce"),"materialName","the name of the material to be used"))
, d_materialName(initData(&d_materialName, materialOptions<DataTypes>, "materialName","the name of the material to be used"))
, d_parameterSet(initData(&d_parameterSet,"ParameterSet","The global parameters specifying the material"))
, d_anisotropySet(initData(&d_anisotropySet,"AnisotropyDirections","The global directions of anisotropy of the material"))
, m_tetrahedronInfo(initData(&m_tetrahedronInfo, "tetrahedronInfo", "Internal tetrahedron data"))
Expand All @@ -67,44 +78,43 @@ template <class DataTypes> TetrahedronHyperelasticityFEMForceField<DataTypes>::~
template <class DataTypes>
void TetrahedronHyperelasticityFEMForceField<DataTypes>::instantiateMaterial()
{
const std::string& material = d_materialName.getValue();
const std::string& material = d_materialName.getValue().getSelectedItem();

if (material == "ArrudaBoyce")
if (material == BoyceAndArruda<DataTypes>::Name)
{
m_myMaterial = std::make_unique<BoyceAndArruda<DataTypes>>();
}
else if (material == "StVenantKirchhoff")
else if (material == STVenantKirchhoff<DataTypes>::Name)
{
m_myMaterial = std::make_unique<STVenantKirchhoff<DataTypes>>();
}
else if (material == "NeoHookean")
else if (material == NeoHookean<DataTypes>::Name)
{
m_myMaterial = std::make_unique<NeoHookean<DataTypes>>();
}
else if (material == "MooneyRivlin")
else if (material == MooneyRivlin<DataTypes>::Name)
{
m_myMaterial = std::make_unique<MooneyRivlin<DataTypes>>();
}
else if (material == "VerondaWestman")
else if (material == VerondaWestman<DataTypes>::Name)
{
m_myMaterial = std::make_unique<VerondaWestman<DataTypes>>();
}
else if (material == "Costa")
else if (material == Costa<DataTypes>::Name)
{
m_myMaterial = std::make_unique<Costa<DataTypes>>();
}
else if (material == "Ogden")
else if (material == Ogden<DataTypes>::Name)
{
m_myMaterial = std::make_unique<Ogden<DataTypes>>();
}
else if (material == "StableNeoHookean")
else if (material == StableNeoHookean<DataTypes>::Name)
{
m_myMaterial = std::make_unique<StableNeoHookean<DataTypes>>();
}
else
{
msg_error() << "material name " << material <<
" is not valid (should be ArrudaBoyce, StVenantKirchhoff, NeoHookean, MooneyRivlin, VerondaWestman, Costa, Ogden or StableNeoHookean)";
msg_error() << "material name " << material << " is not valid";
}

if (m_myMaterial)
Expand Down Expand Up @@ -204,7 +214,7 @@ template <class DataTypes>
void TetrahedronHyperelasticityFEMForceField<DataTypes>::setMaterialName(
const std::string materialName)
{
d_materialName.setValue(materialName);
sofa::helper::getWriteAccessor(d_materialName)->setSelectedItem(materialName);
}

template <class DataTypes>
Expand Down Expand Up @@ -747,7 +757,7 @@ void TetrahedronHyperelasticityFEMForceField<DataTypes>::draw(const core::visual
if (vparams->displayFlags().getShowWireFrame())
vparams->drawTool()->setPolygonMode(0,true);

drawHyperelasticTets(vparams, x, m_topology, d_materialName.getValue());
drawHyperelasticTets<DataTypes>(vparams, x, m_topology, d_materialName.getValue().getSelectedItem());

if (vparams->displayFlags().getShowWireFrame())
vparams->drawTool()->setPolygonMode(0,false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ the determinant of the deformation gradient J and the right Cauchy Green deforma
template<class DataTypes>
class BoyceAndArruda : public HyperelasticMaterial<DataTypes>{

public:
static constexpr std::string_view Name = "ArrudaBoyce";

typedef typename DataTypes::Coord::value_type Real;
typedef type::Mat<3,3,Real> Matrix3;
typedef type::Mat<6,6,Real> Matrix6;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ the determinant of the deformation gradient J and the right Cauchy Green deforma


template<class DataTypes>
class Costa: public HyperelasticMaterial<DataTypes>{
class Costa: public HyperelasticMaterial<DataTypes>
{
public:
static constexpr std::string_view Name = "Costa";

typedef typename DataTypes::Coord::value_type Real;
typedef type::Mat<3,3,Real> Matrix3;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ the determinant of the deformation gradient J and the right Cauchy Green deforma
template <class DataTypes>
class MooneyRivlin : public HyperelasticMaterial<DataTypes>
{
public:
static constexpr std::string_view Name = "MooneyRivlin";

typedef typename DataTypes::Coord::value_type Real;
typedef type::Mat<3, 3, Real> Matrix3;
typedef type::Mat<6, 6, Real> Matrix6;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ template <class DataTypes>
class NeoHookean : public HyperelasticMaterial<DataTypes>
{
public:
static constexpr std::string_view Name = "NeoHookean";

typedef typename DataTypes::Coord::value_type Real;
typedef type::Mat<3, 3, Real> Matrix3;
typedef type::Mat<6, 6, Real> Matrix6;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ the determinant of the deformation gradient J and the right Cauchy Green deforma
template<class DataTypes>
class Ogden: public HyperelasticMaterial<DataTypes>
{
public:
static constexpr std::string_view Name = "Ogden";

typedef typename DataTypes::Coord::value_type Real;
typedef type::Mat<3,3,Real> Matrix3;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class STVenantKirchhoff : public HyperelasticMaterial<DataTypes>
typedef type::MatSym<3, Real> MatrixSym;

public:
static constexpr std::string_view Name = "StVenantKirchhoff";

Real getStrainEnergy(StrainInformation<DataTypes>* sinfo,
const MaterialParameters<DataTypes>& param) override
{
Expand Down

0 comments on commit 7dfb651

Please sign in to comment.