Computing or

To compute the derivative of with respect to , we leverage the rotational invariance property discussed earlier for . Consider two arbitrary rotation matrices and . From the rotational properties of , we have:

Define , then:

Taking the differential of , while treating and as constants, gives:

By setting and , where , the differential expression simplifies to:

The tensorial derivative is then expressed in index notation as:

These expressions must hold for any , leading to the relationship:

So the remaining task is computing . We show how to do it in 3D.

First, let's introduce Rodrigues' rotation formula, which provides a method for expressing any rotation matrix in terms of a unit vector and a rotation angle . The formula is given by: where is the skew-symmetric cross-product matrix associated with . This formula shows that any rotation matrix is characterized by just three degrees of freedom, denoted as . These components are used to define the rotation vector , from which and are derived as follows:

Using this parameterization, rotation matrices and can each be described by three parameters.

Now we have the following code for defining in terms of , , , , , , , , , where and are defined by and with Rodrigues' rotation formula, are the singular values from .

id=IdentityMatrix[3];
var={s1,s2,s3,u1,u2,u3,v1,v2,v3};
Sigma=DiagonalMatrix[{s1,s2,s3}];
cp[k1_,k2_,k3_]={{0,-k3,k2},{k3,0,-k1},{-k2,k1,0}};
vV={v1,v2,v3};
vU={u1,u2,u3};
nv=Sqrt[Dot[vV,vV]];
nu=Sqrt[Dot[vU,vU]];
UU=cp[u1,u2,u3]/nu;
VV=cp[v1,v2,v3]/nv;
U=id+Sin[nu]*UU+(1-Cos[nu])*UU.UU;
V=id+Sin[nv]*VV+(1-Cos[nv])*VV.VV;
F=U.Sigma.Transpose[V];

where cp is a function for generating the cross-product matrix (corresponding to computing in Equation (14.3.1)).

From now on, we write the tensor and any other such tensors to matrices. That means each matrix is now a size- vector. It is easy to see the old is now . We further call vector being the parametrization of . Then we can apply the chain rule

Here are the Mathematica code for computing them. Note that we achieve by taking the limit , which correspond to nearly zero rotations.

dFdS=D[Flatten[F],{var}];
dFdS0=dFdS/.{u1->e,u2->e,u3->e,v1->e,v2->e,v3->e};
dFdS1=Limit[dFdS0,e->0,Direction->-1];
dSdF0=Inverse[dFdS1];
Phat=DiagonalMatrix[{t1[s1,s2,s3],t2[s1,s2,s3],t3[s1,s2,s3]}];
P=U.Phat.Transpose[V];
dPdS=D[Flatten[P],{var}];
dPdS0=dPdS/.{u1->e,u2->e,u3->e,v1->e,v2->e,v3->e};
dPdS1=Limit[dPdS0,e->0,Direction->-1];
dPdF=Simplify[dPdS1.dSdF0];

Note 'Direction->-1' in Mathematica means taking the limit from large values to the small limit value. The Mathematica computation result will be given in terms of the singular values and . One can then take the formula for implementing them in the code. [Stomakhin et al. 2012] gives the result where (size matrix) is permuted to be a block diagonal matrix with diagonal blocks , where and Denominator clamping is needed for terms in that may introduce division-by-zero (after fully simplifying them). Here we denote and as and respectively. The division by is problematic when two singular values are nearly equal or when two singular values nearly sum to zero. The latter is possible with a convention for permitting negative singular values (as in invertible elasticity [Irving et al. 2004] [Stomakhin et al. 2012]).

Expanding in terms of partial fractions yields the useful decomposition Note that if is invariant under permutation of the singular values, then as . Thus, the first term can normally be computed robustly for an isotropic model if implemented carefully. The other fraction can be computed robustly if as . But this usually does not hold as it means the constitutive model will have difficulty recovering from degenerate or inverted configurations. Thus, this term will be unbounded under some circumstances. We address this by clamping the magnitude of the denominator to not be smaller than before division to bound the derivatives.

For 2D, a rotation matrix is now simply paremetrized with a single where the reconstruction is

The 2D version of the whole Mathematica code is

id=IdentityMatrix[2];
var={s1,s2,u1,v1};
S=DiagonalMatrix[{s1,s2}];
U={{Cos[u1],-Sin[u1]

},{Sin[u1],Cos[u1]}};
V={{Cos[v1],-Sin[v1]},{Sin[v1],Cos[v1]}};
F=U.S.Transpose[V];
dFdS=D[Flatten[F],{var}];
dFdS0=dFdS/.{u1->e,v1->e};
dFdS1=Limit[dFdS0,e->0,Direction->-1};
dSdF0=Inverse[dFdS1];
Phat=DiagonalMatrix[{t1[s1,s2],t2[s1,s2]}];
P=U.Phat.Transpose[V];
dPdS=D[Flatten[P],{var}];
dPdS0=dPdS/.{u1->e,v1->e};
dPdS1=Limit[dPdS0,e->0,Direction->-1];
dPdF=Simplify[dPdS1.dSdF0];

where is now also and there is only one .