Function Repository Resource:

TensorCoordinateTransform

Source Notebook

Transform components of tensors with arbitrary rank with regard to their transformation behavior under any given mapping

Contributed by: Lars Ulke-Winter

ResourceFunction["TensorCoordinateTransform"][tensor,mat]

transform tensor components according to their transformation behavior matrix mat. All tensor slots are considered to be contravariant and not normalized.

Details and Options

Generally tensor components (with mixed n×m-rank) transform from one system to another (ii') according to .
The mapping from the old system to the new one is described in the matrix for covariant transformation behavior (tensor components with lower indices) and for so-called contravariant tensor components (depicted with superscript indices).
Summation must be done for the same but opposing indices about the dimensions of the tensor coordinates. The fundamental relationship of the contrary transformation behavior ensures invariance of the tensor object T in all systems after contracting all opposing indices (e.g. ). Due to this fact, a distinction of covariant and contravariant transformation behavior is not required in transformation relations with , e.g. in transformations between orthonormal reference systems.
The input tensor can be of any rank and should be a List or an object of StructuredArray.
The resulting format is always a normal List.
Unlike TransformedField, the ResourceFunction["TensorCoordinateTransform"] result is not given with respect to a normalized basis by default. Using the option Normalize True forces a normalized basis.
The matrix mat defines the mapping between two coordinate systems (often their transposed Jacobian).
The following options are supported:
"TransformationBehavior""AllContravariant"transformation behavior of individual components
"Normalize"Falsewhether the components are represented with respect to a normalized basis
Values allowed by the option "TransformationBehavior" include "AllContravariant", "AllCovariant" and {"Con","Cov",}.

Examples

Basic Examples (1) 

Apply a rotation transformation to a tensor:

In[1]:=
ResourceFunction[
 "TensorCoordinateTransform"][{Subscript[v, 1], Subscript[v, 2], Subscript[v, 3]}, ( {
   {Cos[\[Phi]], -Sin[\[Phi]], 0},
   {Sin[\[Phi]], Cos[\[Phi]], 0},
   {0, 0, 1}
  } )]
Out[1]=

Scope (13) 

Tensor Components with Respect to Rotated Base Vectors (4) 

Rotate vector components about the three axes counterclockwise:

In[2]:=
ResourceFunction[
   "TensorCoordinateTransform"][{Subscript[v, 1], Subscript[v, 2], Subscript[v, 3]}, ( {
     {Cos[\[Phi]], -Sin[\[Phi]], 0},
     {Sin[\[Phi]], Cos[\[Phi]], 0},
     {0, 0, 1}
    } )] // Simplify // MatrixForm
Out[2]=

Change the axis:

In[3]:=
ResourceFunction[
  "TensorCoordinateTransform"][{Subscript[v, 1], Subscript[v, 2], Subscript[v, 3]}, ( {
    {0, 1, 0},
    {0, 0, 1},
    {1, 0, 0}
   } )] // MatrixForm
Out[3]=

Rotate the rank-2 tensor about the three axes counterclockwise:

In[4]:=
ResourceFunction["TensorCoordinateTransform"][( {
     {Subscript[\[Sigma], 11], Subscript[\[Sigma], 12], Subscript[\[Sigma], 13]},
     {Subscript[\[Sigma], 21], Subscript[\[Sigma], 22], Subscript[\[Sigma], 23]},
     {Subscript[\[Sigma], 31], Subscript[\[Sigma], 32], Subscript[\[Sigma], 33]}
    } ), RotationMatrix[\[Theta], {0, 0, 1}]] // Simplify // MatrixForm
Out[4]=

Rotate a rank-4 tensor with three symmetries about the three axes counterclockwise:

In[5]:=
SeedRandom[314];

t = SymmetrizedArray[
   pos_ :> RandomInteger[10], {3, 3, 3, 3}, {{{2, 1, 3, 4}, 1}, {{1, 2, 4, 3}, 1}, {{3, 4, 1, 2}, 1}}];
tRot = ResourceFunction["TensorCoordinateTransform"][t, RotationMatrix[45 °, {0, 0, 1}]];
tRot // Simplify // MatrixForm
Out[6]=

Transform Vector Components Regarding Another Affine Frame of Reference (2) 

The contravariant vector components with respect to covariant bases are a=vjbj=vi'bi'. The old system is Cartesian (aj=vj):

In[7]:=
a = {2, 8, 7};

Consider a transformation between new ei' and old ej covariant base vectors e1'=2e1+3e2+1e3, e2'=1e1+2e2+2e3 and e3'=1e1+2e3. Here are the contravariant components vi' of the new system:

In[8]:=
vNewCon = ResourceFunction["TensorCoordinateTransform"][vOld = {2, 8, 7}, mappingToNew = ( {
     {2, 3, 1},
     {1, 2, 2},
     {1, 0, 1}
    } )]
Out[8]=

They should be the same vector:

In[9]:=
bNewCov = mappingToNew;
In[10]:=
(\!\(
\*UnderoverscriptBox[\(\[Sum]\), \(i = 1\), \(3\)]\(vNewCon[\([\)\(i\)\(]\)] bNewCov[\([\)\(i\)\(]\)]\)\))
Out[10]=
In[11]:=
a == %
Out[11]=

The covariant vector components with respect to contravariant bases are a=vjbj=vi'bj'

In[12]:=
vNewCov = ResourceFunction["TensorCoordinateTransform"][{2, 8, 7}, ( {
    {2, 3, 1},
    {1, 2, 2},
    {1, 0, 1}
   } ), "TransformationBehavior" -> "AllCovariant"]
Out[12]=

Find related contravariant base vectors bi' by transforming the covariant base in contravariant sense (index juggling bi'bi'):

In[13]:=
bNewCon = ResourceFunction["TensorCoordinateTransform"][( {
    {2, 3, 1},
    {1, 2, 2},
    {1, 0, 1}
   } ), ( {
    {2, 3, 1},
    {1, 2, 2},
    {1, 0, 1}
   } ), "TransformationBehavior" -> "AllContravariant"]
Out[13]=
In[14]:=
(\!\(
\*UnderoverscriptBox[\(\[Sum]\), \(i = 1\), \(3\)]\(vNewCov[\([\)\(i\)\(]\)] bNewCon[\([\)\(i\)\(]\)]\)\))
Out[14]=
In[15]:=
a == %
Out[15]=

Note that covariant and contravariant base vectors are inverse to each other bi'bj'=δi'j':

In[16]:=
(bNewCon . bNewCov\[Transpose]) // MatrixForm
Out[16]=

A Local Base on the Manifold of a Torus Surface (Curvilinear Coordinate System) (7) 

Consider the aibicijklskltjbi=ci'j'k'l'sk'l'tj'bi'ai'bi'-invariant tensors in Cartesian frame:

In[17]:=
cFourRankOld = RandomInteger[{-5, 5}, {3, 3, 3, 3}];
sTwoRankOld = RandomInteger[{-5, 5}, {3, 3}];
tOneRankOld = RandomInteger[{-5, 5}, {3}];

The transformation from Cartesian to local torus coordinates (ii'):

In[18]:=
x[r_, \[Alpha]_, \[Beta]_] := (R + r Cos[\[Beta]]) Cos[\[Alpha]]
y[r_, \[Alpha]_, \[Beta]_] := (R + r Cos[\[Beta]]) Sin[\[Alpha]]
z[r_, \[Alpha]_, \[Beta]_] := r Sin[\[Beta]]

The torus surface at α=β=02π, with R and r constant:

In[19]:=
ParametricPlot3D[({x[r, \[Alpha], \[Beta]], y[r, \[Alpha], \[Beta]], z[r, \[Alpha], \[Beta]]} /. {r -> 1, R -> 3}), {\[Alpha], 0, 2 \[Pi]}, {\[Beta], 0, 2 \[Pi]}]
Out[19]=

Transform tensors' different ranks regarding the local torus base with respect to transformation behavior. This is faster than transformation of an entire assembled rank-7 tensor):

In[20]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/c5b72640-60b8-42a2-b25d-6392bd8b8098"]

Local covariant base vector bi':

In[21]:=
bNew = Transpose@jacobianTorus;

Assemble the tensor term by contracting the right indices ci'j'k'l'sk'l'tj'biai'bi':

In[22]:=
aNew = TensorContract[
   cFourRankNew\[TensorProduct]sTwoRankNew\[TensorProduct]tOneRankNew, {{2, 7}, {3, 5}, {4, 6}}] // Simplify
Out[22]=
In[23]:=
((\!\(
\*UnderoverscriptBox[\(\[Sum]\), \(i = 1\), \(3\)]\(aNew[\([\)\(i\)\(]\)] bNew[\([\)\(i\)\(]\)]\)\))) // Simplify
Out[23]=

The result should be the same in the Cartesian system:

In[24]:=
TensorContract[
 cFourRankOld\[TensorProduct]sTwoRankOld\[TensorProduct]tOneRankOld, {{2, 7}, {3, 5}, {4, 6}}]
Out[24]=

Options (7) 

TransformationBehavior (2) 

If the base vectors are not normalized ("Normalize"False), i.e. if they have local-dependent lengths (and are not orthogonal in general reference systems either), the corresponding tensor components are transformed according to their co- and contravariant transformation behaviors. This leads to different representations of the same tensor object.

Here is an example of all four transforming possibilities of a rank-2 tensor to a local, non-normalized cylindrical system:

In[25]:=
jacobianCylTransposed = Transpose@(CoordinateTransformData["Cylindrical" -> "Cartesian", "MappingJacobian", {r, \[Phi], z}]);

All coordinates transform the contravariant tij (default):

In[26]:=
tConCon = ResourceFunction["TensorCoordinateTransform"][( {
      {Subscript[\[Sigma], 11], Subscript[\[Sigma], 12], Subscript[\[Sigma], 13]},
      {Subscript[\[Sigma], 21], Subscript[\[Sigma], 22], Subscript[\[Sigma], 23]},
      {Subscript[\[Sigma], 31], Subscript[\[Sigma], 32], Subscript[\[Sigma], 33]}
     } ), jacobianCylTransposed] // Simplify[#, r > 0] & // TraditionalForm
Out[26]=

All coordinates transform the covariant tij:

In[27]:=
tCovCov = ResourceFunction["TensorCoordinateTransform"][( {
      {Subscript[\[Sigma], 11], Subscript[\[Sigma], 12], Subscript[\[Sigma], 13]},
      {Subscript[\[Sigma], 21], Subscript[\[Sigma], 22], Subscript[\[Sigma], 23]},
      {Subscript[\[Sigma], 31], Subscript[\[Sigma], 32], Subscript[\[Sigma], 33]}
     } ), jacobianCylTransposed, "TransformationBehavior" -> "AllCovariant"] // Simplify[#, r > 0] & // TraditionalForm
Out[27]=

A tensor object with coordinates of mixed-transformation behavior tij:

In[28]:=
tConCov = ResourceFunction["TensorCoordinateTransform"][( {
      {Subscript[\[Sigma], 11], Subscript[\[Sigma], 12], Subscript[\[Sigma], 13]},
      {Subscript[\[Sigma], 21], Subscript[\[Sigma], 22], Subscript[\[Sigma], 23]},
      {Subscript[\[Sigma], 31], Subscript[\[Sigma], 32], Subscript[\[Sigma], 33]}
     } ), jacobianCylTransposed, "TransformationBehavior" -> {"Cov", "Con"}] // Simplify[#, r > 0] & // TraditionalForm
Out[28]=

A tensor object with coordinates of opposite mixed-transformation behavior tji:

In[29]:=
tCovCon = ResourceFunction["TensorCoordinateTransform"][( {
      {Subscript[\[Sigma], 11], Subscript[\[Sigma], 12], Subscript[\[Sigma], 13]},
      {Subscript[\[Sigma], 21], Subscript[\[Sigma], 22], Subscript[\[Sigma], 23]},
      {Subscript[\[Sigma], 31], Subscript[\[Sigma], 32], Subscript[\[Sigma], 33]}
     } ), jacobianCylTransposed, "TransformationBehavior" -> {"Con", "Cov"}] // Simplify[#, r > 0] & // TraditionalForm
Out[29]=

Nomenclature referencing all indices together or each index separately is interchangeable:

In[30]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/d0a5cd74-97e8-4a67-a3da-b8d6dadf7f50"]
Out[30]=

This is analogous for the covariant transformation:

In[31]:=
(ResourceFunction["TensorCoordinateTransform"][( {
      {Subscript[\[Sigma], 11], Subscript[\[Sigma], 12], Subscript[\[Sigma], 13]},
      {Subscript[\[Sigma], 21], Subscript[\[Sigma], 22], Subscript[\[Sigma], 23]},
      {Subscript[\[Sigma], 31], Subscript[\[Sigma], 32], Subscript[\[Sigma], 33]}
     } ), jacobianCylTransposed, "TransformationBehavior" -> {"Cov", "Cov"}] == ResourceFunction["TensorCoordinateTransform"][( {
      {Subscript[\[Sigma], 11], Subscript[\[Sigma], 12], Subscript[\[Sigma], 13]},
      {Subscript[\[Sigma], 21], Subscript[\[Sigma], 22], Subscript[\[Sigma], 23]},
      {Subscript[\[Sigma], 31], Subscript[\[Sigma], 32], Subscript[\[Sigma], 33]}
     } ), jacobianCylTransposed, "TransformationBehavior" -> "AllCovariant"]) // Simplify[#, r > 0] &
Out[31]=

Normalize (5) 

Transformed contravariant vector components with respect to normalized base vectors:

In[32]:=
vNewConN = ResourceFunction["TensorCoordinateTransform"][vOld = {2, 8, 7}, mappingToNew = ( {
     {2, 3, 1},
     {1, 2, 2},
     {1, 0, 1}
    } ), "Normalize" -> True]
Out[32]=

The same transformed contravariant vector components with respect to non-normalized base vectors (default):

In[33]:=
ResourceFunction["TensorCoordinateTransform"][vOld, mappingToNew, "Normalize" -> False]
Out[33]=

Transformed covariant normalized base vectors:

In[34]:=
bNewCovN = ResourceFunction["TensorCoordinateTransform"][{e1, e2, e3}, mappingToNew, "TransformationBehavior" -> "AllCovariant", "Normalize" -> True] /. {e1 -> {1, 0, 0}, e2 -> {0, 1, 0}, e3 -> {0, 0, 1}}
Out[34]=

The contraction of the assigned tensors should be produce invariance:

In[35]:=
(\!\(
\*UnderoverscriptBox[\(\[Sum]\), \(i = 1\), \(3\)]\(vNewConN[\([\)\(i\)\(]\)] bNewCovN[\([\)\(i\)\(]\)]\)\)) == vOld
Out[35]=

Tensor components with respect to an orthonormal cylindrical system:

In[36]:=
tCylConCon = ResourceFunction["TensorCoordinateTransform"][( {
      {Subscript[\[Sigma], 11], Subscript[\[Sigma], 12], Subscript[\[Sigma], 13]},
      {Subscript[\[Sigma], 21], Subscript[\[Sigma], 22], Subscript[\[Sigma], 23]},
      {Subscript[\[Sigma], 31], Subscript[\[Sigma], 32], Subscript[\[Sigma], 33]}
     } ), Transpose@
     CoordinateTransformData["Cylindrical" -> "Cartesian", "MappingJacobian", {r, \[Phi], z}], "Normalize" -> True] // Simplify[#, r > 0] &;
tCylConCon // TraditionalForm
Out[35]=

TransformedField also assumes a normalized base:

In[37]:=
TransformedField["Cartesian" -> "Cylindrical", ( {
     {Subscript[\[Sigma], 11], Subscript[\[Sigma], 12], Subscript[\[Sigma], 13]},
     {Subscript[\[Sigma], 21], Subscript[\[Sigma], 22], Subscript[\[Sigma], 23]},
     {Subscript[\[Sigma], 31], Subscript[\[Sigma], 32], Subscript[\[Sigma], 33]}
    } ),  {x1, x2, x3} -> {r, \[Phi], z}] // Simplify // TraditionalForm
Out[37]=
In[38]:=
(tCylConCon == TransformedField["Cartesian" -> "Cylindrical", ( {
      {Subscript[\[Sigma], 11], Subscript[\[Sigma], 12], Subscript[\[Sigma], 13]},
      {Subscript[\[Sigma], 21], Subscript[\[Sigma], 22], Subscript[\[Sigma], 23]},
      {Subscript[\[Sigma], 31], Subscript[\[Sigma], 32], Subscript[\[Sigma], 33]}
     } ),  {x1, x2, x3} -> {r, \[Phi], z}]) // Simplify
Out[38]=

With orthonormal reference systems (e.g. normalized cylindrical systems), no distinction between co- and contravariant transformation behavior is required:

In[39]:=
(tCylConCon ==
   ResourceFunction["TensorCoordinateTransform"][( {
      {Subscript[\[Sigma], 11], Subscript[\[Sigma], 12], Subscript[\[Sigma], 13]},
      {Subscript[\[Sigma], 21], Subscript[\[Sigma], 22], Subscript[\[Sigma], 23]},
      {Subscript[\[Sigma], 31], Subscript[\[Sigma], 32], Subscript[\[Sigma], 33]}
     } ), Transpose@
     CoordinateTransformData["Cylindrical" -> "Cartesian", "MappingJacobian", {r, \[Phi], z}], "TransformationBehavior" -> "AllCovariant", "Normalize" -> True]) // Simplify[#, r > 0] &
Out[39]=

Applications (6) 

Stiffness Components of the Rank-4 Elasticity Tensor with Different Material Symmetries (6) 

In[40]:=
ClearAll[c]

Hook's general law describes a linear relationship between the components of the rank-2 stress tensor σ and the two-stage strain tensor ε using the rank-4 tensor C: σij=Cijklεkl with the symmetries σij=σji, εkl=εlk and Eijkl=Ejikl=Eijlk=Eklij.

Components of the general, fully anisotropic stiffness tensor with initial symmetries:

In[41]:=
cFull = Normal@
   SymmetrizedArray[
    pos_ :> Subscript[c, pos], {3, 3, 3, 3}, {{{2, 1, 3, 4}, 1}, {{1, 2, 4, 3}, 1}, {{3, 4, 1, 2}, 1}}];
cFull // MatrixForm
Out[37]=

The number of independent components:

In[42]:=
SymmetrizedIndependentComponents[{3, 3, 3, 3}, TensorSymmetry[cFull]] // Length
Out[42]=

One plane of symmetry, rotated by 180 degrees, results in the same stiffness:

In[43]:=
rot3 = RotationMatrix[180 °, {0, 0, 1}];
rot3 // MatrixForm
Out[44]=

This results in a stiffness tensor with fewer independent components:

In[45]:=
monoclinic = cFull /. (Flatten@(Solve[Thread@( Flatten@cFull == Flatten@ResourceFunction["TensorCoordinateTransform"][cFull,
             rot3, "TransformationBehavior" -> "AllCovariant"])]));
monoclinic // MatrixForm
Out[20]=

Determination and comparison of different material symmetries:

In[46]:=
orthotrop = Fold[cFull /. (Solve[
        Thread@(Flatten@cFull == Flatten@ResourceFunction[
             "TensorCoordinateTransform"][#1, #2, "TransformationBehavior" -> "AllCovariant"])] // Flatten) &, cFull, {RotationMatrix[180 °, {0, 0, 1}], RotationMatrix[180 °, {0, 1, 0}]}];
In[47]:=
transversalIso = Fold[cFull /. Quiet@ (* \[Alpha] only between 0° and 360° *)(Solve[
         Thread@(Flatten@cFull == Flatten@ResourceFunction[
              "TensorCoordinateTransform"][#1, #2, "TransformationBehavior" -> "AllCovariant"])] // Flatten) &, cFull, {RotationMatrix[180 °, {0, 0, 1}], RotationMatrix[180 °, {0, 1, 0}], RotationMatrix[\[Alpha], {1, 0, 0}]}];
In[48]:=
isotropic = Fold[cFull /. Quiet@(Solve[
         Thread@(Flatten@cFull == Flatten@ResourceFunction[
              "TensorCoordinateTransform"][#1, #2, "TransformationBehavior" -> "AllCovariant"])] // Flatten) &, cFull, {RotationMatrix[\[Alpha]1, {1, 0, 0}], RotationMatrix[\[Alpha]2, {0, 1, 0}], RotationMatrix[\[Alpha]3, {0, 0, 1}]}];

Summary:

In[49]:=
(<|"Material behaviour" -> #2, "Stiffness Tensor" -> (#1 // MatrixForm), "Independent Components" -> (Cases[#1, _Subscript, \[Infinity]] //
         Union), "Number of independent components" -> Length[Cases[#1, _Subscript, \[Infinity]] // Union], "Description" -> #3|>) & @@@ {{monoclinic, "Monoclinic", "One symmetric plane"},
   {orthotrop, "Orthotropic", "Two (three) symmetric planes"},
   {transversalIso, "Transversal isotropic", "Two symmetric planes transversal isometric"},
   {isotropic, "Isotropic", "All planes isometric"}} // Dataset
Out[49]=

Publisher

Lars Ulke-Winter

Version History

  • 1.0.0 – 29 August 2019

Source Metadata

Related Resources

License Information