Skip to content

Commit d11d313

Browse files
committed
[HyperElastic] Clean up the ElasticityTensor
1 parent 226cb89 commit d11d313

File tree

1 file changed

+103
-99
lines changed
  • Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/material

1 file changed

+103
-99
lines changed

Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/material/Ogden.h

Lines changed: 103 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,20 @@ the determinant of the deformation gradient J and the right Cauchy Green deforma
4848
template<class DataTypes>
4949
class Ogden: public HyperelasticMaterial<DataTypes>
5050
{
51+
private:
52+
// In SOFA Voigt order for 3D symmetric tensors is non-standard: xx, xy, yy, xz, yz, zz
53+
const std::array<sofa::Index, 3*3> toVoigt = {0, 1, 3, 1, 2, 4, 3, 4, 5};
54+
inline sofa::Index vId(sofa::Index i, sofa::Index j) {return toVoigt[i * 3 + j];}
55+
const std::array<std::tuple<sofa::Index, sofa::Index>, 6> fromVoigt =
56+
{
57+
std::make_tuple(0,0),
58+
std::make_tuple(0,1),
59+
std::make_tuple(1,1),
60+
std::make_tuple(0,2),
61+
std::make_tuple(1,2),
62+
std::make_tuple(2,2)
63+
};
64+
5165
public:
5266
static constexpr std::string_view Name = "Ogden";
5367

@@ -70,8 +84,8 @@ class Ogden: public HyperelasticMaterial<DataTypes>
7084

7185
// Solve eigen problem for C
7286
Eigen::Matrix<Real, 3, 3> CEigen;
73-
CEigen(0,0)=C[0]; CEigen(0,1)=C[1]; CEigen(1,0)=C[1]; CEigen(1,1)=C[2];
74-
CEigen(1,2)=C[4]; CEigen(2,1)=C[4]; CEigen(2,0)=C[3]; CEigen(0,2)=C[3]; CEigen(2,2)=C[5];
87+
for (sofa::Index i = 0; i < 3; ++i)
88+
for (sofa::Index j = 0; j < 3; ++j) CEigen(i, j) = C[vId(i, j)];
7589

7690
// Disable temporarilly until fixed /*Eigen::SelfAdjointEigenSolver<EigenMatrix>*/
7791
Eigen::EigenSolver<Eigen::Matrix<Real, 3, 3> > EigenProblemSolver(CEigen, true);
@@ -103,9 +117,9 @@ class Ogden: public HyperelasticMaterial<DataTypes>
103117
const Real fj = pow(sinfo->J, -alpha1/3.0_sreal);
104118

105119
// Solve eigen problem for C
106-
Eigen::Matrix<Real,3,3> CEigen;
107-
CEigen(0,0)=C[0]; CEigen(0,1)=C[1]; CEigen(1,0)=C[1]; CEigen(1,1)=C[2]; CEigen(1,2)=C[4]; CEigen(2,1)=C[4];
108-
CEigen(2,0)=C[3]; CEigen(0,2)=C[3]; CEigen(2,2)=C[5];
120+
Eigen::Matrix<Real, 3, 3> CEigen;
121+
for (sofa::Index i = 0; i < 3; ++i)
122+
for (sofa::Index j = 0; j < 3; ++j) CEigen(i, j) = C[vId(i, j)];
109123

110124
// Disable temporarilly until fixed /*Eigen::SelfAdjointEigenSolver<EigenMatrix>*/
111125
Eigen::EigenSolver<Eigen::Matrix<Real, 3, 3> > EigenProblemSolver(CEigen, true);
@@ -140,7 +154,6 @@ class Ogden: public HyperelasticMaterial<DataTypes>
140154
SPKTensorGeneral = fj * mu1 / alpha1 * (CaBy2Minus1 + -1_sreal/3_sreal * trCaBy2 * invC) + k0*log(sinfo->J)*invC;
141155
}
142156

143-
144157
void applyElasticityTensor_old(StrainInformation<DataTypes> *sinfo, const MaterialParameters<DataTypes> &param,
145158
const MatrixSym& inputTensor, MatrixSym& outputTensor)
146159
{
@@ -272,139 +285,130 @@ class Ogden: public HyperelasticMaterial<DataTypes>
272285

273286
void ElasticityTensor(StrainInformation<DataTypes> *sinfo, const MaterialParameters<DataTypes> &param, Matrix6& outputTensor) override
274287
{
275-
Real k0=param.parameterArray[0];
276-
Real mu1=param.parameterArray[1];
277-
Real alpha1=param.parameterArray[2];
278-
MatrixSym C=sinfo->deformationTensor;
279-
Eigen::Matrix<Real,3,3> CEigen;
280-
CEigen(0,0)=C[0]; CEigen(0,1)=C[1]; CEigen(1,0)=C[1]; CEigen(1,1)=C[2]; CEigen(1,2)=C[4]; CEigen(2,1)=C[4];
281-
CEigen(2,0)=C[3]; CEigen(0,2)=C[3]; CEigen(2,2)=C[5];
288+
const MatrixSym& C = sinfo->deformationTensor;
289+
const Real k0 = param.parameterArray[0];
290+
const Real mu1 = param.parameterArray[1];
291+
const Real alpha1 = param.parameterArray[2];
292+
const Real fj = pow(sinfo->J, -alpha1/3.0_sreal);
282293

283-
/*Eigen::SelfAdjointEigenSolver<EigenMatrix>*/Eigen::EigenSolver<Eigen::Matrix<Real, 3, 3> > EigenProblemSolver(CEigen,true);
294+
// Solve eigen problem for C
295+
Eigen::Matrix<Real, 3, 3> CEigen;
296+
for (sofa::Index i = 0; i < 3; ++i)
297+
for (sofa::Index j = 0; j < 3; ++j) CEigen(i, j) = C[vId(i, j)];
298+
299+
// Disable temporarilly until fixed /*Eigen::SelfAdjointEigenSolver<EigenMatrix>*/
300+
Eigen::EigenSolver<Eigen::Matrix<Real, 3, 3> > EigenProblemSolver(CEigen, true);
284301
if (EigenProblemSolver.info() != Eigen::Success)
285302
{
286303
dmsg_warning("Ogden") << "SelfAdjointEigenSolver iterations failed to converge";
287304
return;
288305
}
289-
EigenMatrix Evect=EigenProblemSolver.eigenvectors().real();
290-
CoordEigen Evalue=EigenProblemSolver.eigenvalues().real();
306+
const EigenMatrix Evect = EigenProblemSolver.eigenvectors().real();
307+
const CoordEigen Evalue = EigenProblemSolver.eigenvalues().real();
291308

292-
Real trCalpha=pow(Evalue[0],alpha1/(Real)2)+pow(Evalue[1],alpha1/(Real)2)+pow(Evalue[2],alpha1/(Real)2);
293-
Matrix3 Pinverse;
294-
Pinverse(0,0)=Evect(0,0); Pinverse(1,1)=Evect(1,1); Pinverse(2,2)=Evect(2,2); Pinverse(0,1)=Evect(1,0); Pinverse(1,0)=Evect(0,1); Pinverse(2,0)=Evect(0,2);
295-
Pinverse(0,2)=Evect(2,0); Pinverse(2,1)=Evect(1,2); Pinverse(1,2)=Evect(2,1);
309+
// trace of C^(alpha1/2)
310+
const Real aBy2 = alpha1*0.5_sreal;
311+
const Real trCaBy2 = pow(Evalue[0], aBy2) + pow(Evalue[1], aBy2) + pow(Evalue[2], aBy2);
296312

297-
MatrixSym Dalpha_1(
298-
pow(Evalue[0], alpha1/2.0 - 1.0), 0,
299-
pow(Evalue[1], alpha1/2.0 - 1.0), 0, 0,
300-
pow(Evalue[2], alpha1/2.0 - 1.0)
301-
);
302-
MatrixSym Calpha_1;
303-
Calpha_1.Mat2Sym(Pinverse.transposed()*Dalpha_1.SymMatMultiply(Pinverse),Calpha_1);
304-
305-
MatrixSym Dalpha_2(
306-
pow(Evalue[0], alpha1/2.0 - 2.0), 0,
307-
pow(Evalue[1], alpha1/2.0 - 2.0), 0, 0,
308-
pow(Evalue[2], alpha1/2.0 - 2.0)
309-
);
310-
MatrixSym Calpha_2;
311-
Calpha_2.Mat2Sym(Pinverse.transposed() * Dalpha_2.SymMatMultiply(Pinverse), Calpha_2);
313+
// Transpose (also inverse) of the eigenvector matrix
314+
Matrix3 EigenBasis;
315+
for (auto m = 0; m < Evect.rows(); ++m)
316+
for (auto n = 0; n < Evect.cols(); ++n) EigenBasis(m, n) = Evect(m, n);
312317

313-
MatrixSym inversematrix;
314-
invertMatrix(inversematrix,sinfo->deformationTensor);
318+
// Construct C^(alpha1/2 - 1) from eigenbasis: V * D * V^T; D_i = lambda_i^(alpha1/2 - 1)
319+
const Real aBy2Minus1 = aBy2 - 1_sreal;
320+
MatrixSym D(pow(Evalue[0], aBy2Minus1), 0, pow(Evalue[1], aBy2Minus1), 0, 0, pow(Evalue[2], aBy2Minus1));
321+
MatrixSym CaBy2Minus1;
322+
sofa::type::MatSym<3>::Mat2Sym(EigenBasis*D.SymMatMultiply(EigenBasis.transposed()), CaBy2Minus1);
315323

316-
// build 4th-order tensor contribution in Voigt notation
324+
// Invert deformation tensor
325+
MatrixSym invC;
326+
invertMatrix(invC, C);
327+
328+
// Build the 4th-order tensor contribution in Voigt notation
317329
Matrix6 elasticityTensor;
318330

319-
// diagonal entries
320-
const Real coef = 0.5 * alpha1 - 1.;
321-
Real fj= (Real)(pow(sinfo->J,(Real)(-alpha1/3.0)));
322-
for (int n = 0; n < 6; n++)
331+
const Real aBy2Minus2 = aBy2 - 2_sreal;
332+
for (sofa::Index m = 0; m < 6; m++)
323333
{
324-
int i, j;
325-
switch(n)
326-
{
327-
case 0: i=0; j=0; break;
328-
case 1: i=0; j=1; break;
329-
case 2: i=1; j=1; break;
330-
case 3: i=0; j=2; break;
331-
case 4: i=1; j=2; break;
332-
case 5: i=2; j=2; break;
333-
}
334-
for (int m = 0; m < 6; m++)
334+
sofa::Index i, j;
335+
std::tie(i, j) = fromVoigt[m];
336+
337+
for (sofa::Index n = 0; n < 6; n++)
335338
{
336-
int k, l;
337-
switch(m)
338-
{
339-
case 0: k=0; l=0; break;
340-
case 1: k=0; l=1; break;
341-
case 2: k=1; l=1; break;
342-
case 3: k=0; l=2; break;
343-
case 4: k=1; l=2; break;
344-
case 5: k=2; l=2; break;
345-
}
346-
// Simple Ogden summation
347-
for (int ii = 0 ; ii < 3; ii++)
348-
{
349-
Real eigenTerm = pow(Evalue[ii], alpha1/2. - 2.);
350-
elasticityTensor(n, m) += coef * eigenTerm
351-
* Evect(i, ii) * Evect(j, ii) * Evect(k, ii) * Evect(l, ii);
339+
sofa::Index k, l;
340+
std::tie(k, l) = fromVoigt[n];
352341

353-
const Real eigenTerm_ii = pow(Evalue[ii], alpha1/2. - 1.);
354-
for (int jj = 0 ; jj < 3; jj++)
342+
// SPK derivative contribution from spectral part
343+
for (sofa::Index eI = 0 ; eI < 3; eI++)
344+
{
345+
// Distortion term from differenting of eigenvalues
346+
const Real evalPowI2 = pow(Evalue[eI], aBy2Minus2);
347+
elasticityTensor(m, n) += aBy2Minus1 * evalPowI2
348+
* Evect(i, eI) * Evect(j, eI) * Evect(k, eI) * Evect(l, eI);
349+
350+
// Rotational part from differenting of eigenvectors
351+
const Real evalPowI = pow(Evalue[eI], aBy2Minus1);
352+
for (sofa::Index eJ = 0 ; eJ < 3; eJ++)
355353
{
356-
if (jj == ii) continue;
354+
if (eJ == eI) continue;
357355

358356
Real coefRot{0};
359-
if (std::fabs(Evalue[ii] - Evalue[jj]) < std::numeric_limits<Real>::epsilon())
360-
coefRot = (alpha1 / 2. - 1.) * pow(Evalue[ii], alpha1 / 2. - 2.);
357+
358+
if (std::fabs(Evalue[eI] - Evalue[eJ]) < std::numeric_limits<Real>::epsilon())
359+
coefRot = aBy2Minus1 * evalPowI2;
361360
else
362361
{
363-
const Real eigenTerm_jj = pow(Evalue[jj], alpha1/2. - 1.);
364-
coefRot = (eigenTerm_ii - eigenTerm_jj)/(Evalue[ii] - Evalue[jj]);
362+
const Real evalPowJ = pow(Evalue[eJ], aBy2Minus1);
363+
coefRot = (evalPowI - evalPowJ)/(Evalue[eI] - Evalue[eJ]);
365364
}
366-
elasticityTensor(n, m) += coefRot * 0.5 *
365+
366+
elasticityTensor(m, n) += coefRot * 0.5_sreal *
367367
(
368-
Evect(i, ii) * Evect(j, jj) * Evect(k, jj) * Evect(l, ii) +
369-
Evect(i, ii) * Evect(j, jj) * Evect(k, ii) * Evect(l, jj)
368+
Evect(i, eI) * Evect(j, eJ) * Evect(k, eJ) * Evect(l, eI) +
369+
Evect(i, eI) * Evect(j, eJ) * Evect(k, eI) * Evect(l, eJ)
370370
);
371371
}
372372
}
373-
// F(J) term
374-
elasticityTensor(n, m) -= alpha1/6. * (inversematrix(i,j) * Calpha_1(k,l)
375-
- trCalpha / 3. * inversematrix(i,j) * inversematrix(k,l));
376373

377-
// T22 term 1
378-
elasticityTensor(n, m) -= alpha1/6. * Calpha_1(i,j) * inversematrix(k,l);
374+
// SPK derivative contributions from isochoric part; product rule applies
375+
// Factor 1 - Directly differentiate F(J)
376+
elasticityTensor(m, n) -= alpha1/6_sreal * (invC(i,j) * CaBy2Minus1(k,l)
377+
- trCaBy2 / 3_sreal * invC(i,j) * invC(k,l));
378+
379+
// Factor 2 - 1st term - trace(C^(alpha1/2)) contribution
380+
elasticityTensor(m, n) -= alpha1/6_sreal * CaBy2Minus1(i,j) * invC(k,l);
379381

380-
// T22 term 2
381-
elasticityTensor(n, m) += alpha1/3. * trCalpha * 0.5 * (
382-
inversematrix(i,k) * inversematrix(j,l)
383-
+ inversematrix(i,l) * inversematrix(j,k));
382+
// Factor 2 - 2nd term - C inverse contribution
383+
elasticityTensor(m, n) += alpha1/3_sreal * trCaBy2 * 0.5_sreal * (
384+
invC(i,k) * invC(j,l)
385+
+ invC(i,l) * invC(j,k));
384386

385-
elasticityTensor(n, m) += 0.5 * alpha1 / mu1 / fj *
387+
// SPK derivative contribution from the volumetric part
388+
elasticityTensor(m, n) += 0.5_sreal * alpha1 / mu1 / fj *
386389
(
387-
k0 * inversematrix(i,j) * inversematrix(k,l)
388-
- k0*log(sinfo->J) *(inversematrix(i,k) * inversematrix(j,l)
389-
+ inversematrix(i,l) * inversematrix(j,k))
390+
k0 * invC(i,j) * invC(k,l)
391+
- k0*log(sinfo->J) *(invC(i,k) * invC(j,l)
392+
+ invC(i,l) * invC(j,k))
390393
) ;
391394
}
392395
}
393396

394-
// multiply by scalar factor
395-
outputTensor = 2.0 * fj * mu1 / alpha1 * elasticityTensor ;
396-
for (int n = 0; n < 6; n++)
397+
outputTensor = 2_sreal * fj * mu1 / alpha1 * elasticityTensor ;
398+
399+
// Adjust for Voigt notation using 2x factor on the off-diagonal
400+
for (sofa::Index m = 0; m < 6; m++)
397401
{
398-
outputTensor(n,1) *= 2.;
399-
outputTensor(n,3) *= 2.;
400-
outputTensor(n,4) *= 2.;
402+
outputTensor(m,1) *= 2_sreal;
403+
outputTensor(m,3) *= 2_sreal;
404+
outputTensor(m,4) *= 2_sreal;
401405
}
402406
}
403407

404408
void applyElasticityTensor(StrainInformation<DataTypes> *sinfo, const MaterialParameters<DataTypes> &param,
405409
const MatrixSym& inputTensor, MatrixSym& outputTensor) override
406410
{
407-
// For now, let's just multiply matrices using the ElasticityTensor explicitely
411+
// For now, let's just multiply matrices using the ElasticityTensor explicitly
408412
Matrix6 elasticityTensor;
409413
this->ElasticityTensor(sinfo, param, elasticityTensor);
410414
auto temp = elasticityTensor * inputTensor;

0 commit comments

Comments
 (0)