Lesson 9: Tensor Algebra - Maple Help
For the best experience, we recommend viewing online help using Google Chrome or Microsoft Edge.

Online Help

All Products    Maple    MapleSim


DifferentialGeometry Lessons

 

Lesson 9: Tensor Algebra

 

 

Overview

Rearrange the indices of a tensor

Symmetrize and skew-symmetrize a list of indices

Contract the indices of a tensor or contract the indices between two tensors

Find the inverse of a metric tensor

Raise and lower indices

Generating lists of tensors

Tensor algebra on vector bundles

PushPullTensor

Exercises

Overview

 

In this lesson, you will learn to do the following:

– 

Rearrange the indices in a tensor.

– 

Symmetrize and skew-symmetrize the indices of a tensor.

– 

Contract the indices of a tensor.

– 

Find the inverse of a metric.

– 

Raise and lower indices of a tensor using a metric.

– 

Generate spaces of symmetric tensors.

 

Rearrange the indices of a tensor

 

The Tensor command RearrangeIndices is used to rearrange the indices (or arguments) of a tensor.

>

with(DifferentialGeometry): with(Tensor):

DGsetup([x, y, z], E2):

E2 > 

T := evalDG(dx &t D_y &t dz);

TdxD_ydz

(2.1)

 

Flip the 2nd and 3rd indices of T using the permutation notation ([1, 3, 2] means 1 -> 1, 2 -> 3, 3 -> 2 -- see the help page for details).

E2 > 

RearrangeIndices(T, [1, 3, 2]);

dxdzD_y

(2.2)

 

Flip the 2nd and 3rd indices of T using the disjoint cycle notation ([[3, 2]], means 3 -> 2 and 2 -> 3 and all other indices remain in the same place).

E2 > 

RearrangeIndices(T, [[3,2]]);

dxdzD_y

(2.3)

 

Permute the indices of T (send 1 -> 2, 2 -> 3, and 3 -> 1).

E2 > 

RearrangeIndices(T, [[1, 2, 3]]);

dzdxD_y

(2.4)

 

Symmetrize and skew-symmetrize a list of indices

 

The Tensor command SymmetrizeIndices is used to symmetrize or skew-symmetrize a given list of indices.  The SymmetrizeIndices command acts as a projection operator -- the effect of two applications of this command yields the same result as a single application.

E2 > 

with(DifferentialGeometry): with(Tensor):

E2 > 

DGsetup([x, y, z], E2):

 

Define a tensor T.

E2 > 

T := evalDG(D_x &t D_y &t D_z);

TD_xD_yD_z

(3.1)

 

Symmetrize T over its first two indices.

E2 > 

W := SymmetrizeIndices(T, [1, 2], "Symmetric");

WD_xD_yD_z2+D_yD_xD_z2

(3.2)

 

Symmetrize W over its first two indices.  The tensor W is returned.

E2 > 

newW := SymmetrizeIndices(W, [1, 2], "Symmetric");

newWD_xD_yD_z2+D_yD_xD_z2

(3.3)
E2 > 

newW &minus W;

0D_xD_xD_x

(3.4)

 

Symmetrize T over all its indices.

E2 > 

U := SymmetrizeIndices(T, [1, 2, 3], "Symmetric");

UD_xD_yD_z6+D_xD_zD_y6+D_yD_xD_z6+D_yD_zD_x6+D_zD_xD_y6+D_zD_yD_x6

(3.5)

 

Skew-symmetrize U over its 2nd and 3rd indices.

E2 > 

SymmetrizeIndices(U, [2, 3], "SkewSymmetric");

0D_xD_xD_x

(3.6)

 

Contract the indices of a tensor or contract the indices between two tensors

 

The Tensor command ContractIndices can be used in two ways.

E2 > 

with(DifferentialGeometry): with(Tensor):

E2 > 

DGsetup([x, y, z], E3):

 

The first use is to contract a list of pairs of indices of a given tensor.

E3 > 

T:= evalDG(D_x &t dy &t D_z &t dz - 2*D_x &t dx &t D_x &t dx);

T2D_xdxD_xdx+D_xdyD_zdz

(4.1)

 

Contract the 2nd and 3rd indices of T.

E3 > 

ContractIndices(T, [[2, 3]]);

2D_xdx

(4.2)

 

Simultaneously contract the 2nd and 3rd indices and the 1st and 4th indices of T.

E3 > 

ContractIndices(T, [[2,3], [1,4]]);

2

(4.3)
E3 > 

S := convert(D_y, DGtensor);

SD_y

(4.4)

 

The second use is contract indices of one tensor against those of a second tensor.  Contract the 2nd index of T against the 1st index of S.

E3 > 

ContractIndices(T, S, [[2, 1]]);

D_xD_zdz

(4.5)

 

Find the inverse of a metric tensor

 

In the DifferentialGeometry package, a metric tensor is defined to be a rank 2 covariant tensor which is symmetric and non-degenerate.  Use the command InverseMetric to find the inverse of a metric tensor.

E3 > 

with(DifferentialGeometry): with(Tensor):

E3 > 

DGsetup([x, y], E2):

E2 > 

g := evalDG(2*dx &t dx + dx &t dy + dy &t dx);

g2dxdx+dxdy+dydx

(5.1)
E2 > 

h := InverseMetric(g);

hD_xD_y+D_yD_x2D_yD_y

(5.2)

 

Let's check that the symmetric matrix for g and the symmetric matrix for h are inverses.

E2 > 

A := convert(g, DGArray);

E2 > 

B := convert(h, DGArray);

E2 > 

convert(A,Matrix).convert(B,Matrix);

 

Raise and lower indices

 

In the DifferentialGeometry Tensor package, the command RaiseLowerIndices is used to perform the operation of lowering indices (contravariant -> covariant) with a metric tensor g and raising indices (covariant -> contravariant) with the inverse of g.

E2 > 

with(DifferentialGeometry): with(Tensor):

E2 > 

DGsetup([x, y], E2):

 

Define a metric tensor g and calculate its inverse.

E2 > 

g := evalDG(dx &t dy + dy &t dx);

gdxdy+dydx

(6.1)
E2 > 

h := InverseMetric(g);

hD_xD_y+D_yD_x

(6.2)

 

Define a tensor T.

E2 > 

T := evalDG(dx &t D_y &t D_x);

TdxD_yD_x

(6.3)

 

Lower the 2nd index of T using the metric g.

E2 > 

S := RaiseLowerIndices(g, T, [2]);

SdxdxD_x

(6.4)

 

Lower the 2nd and 3rd indices of T using the metric g.

E2 > 

RaiseLowerIndices(g, T, [2, 3]);

dxdxdy

(6.5)

 

Raise the 1st index of the tensor T using the inverse h.

E2 > 

RaiseLowerIndices(h, T, [1]);

D_yD_yD_x

(6.6)

 

Generating lists of tensors

 

The Tensor commands GenerateTensors and GenerateSymmetricTensors can be used to generate bases for various tensor spaces.

E2 > 

with(DifferentialGeometry): with(Tensor):

E2 > 

DGsetup([x, y], E2):

 

First, use the command Tools:-DGinfo to generate the basis for the tangent and cotangent spaces.

E2 > 

Fr := Tools:-DGinfo(E2, "FrameBaseVectors");

FrD_x,D_y

(7.1)
E2 > 

Omega := Tools:-DGinfo(E2, "FrameBaseForms");

Ωdx,dy

(7.2)

 

Generate all contravariant rank 2 tensors.

E2 > 

GenerateTensors([Fr, Fr]);

D_xD_x,D_xD_y,D_yD_x,D_yD_y

(7.3)

 

Generate all type (1, 1) tensors.

E2 > 

GenerateTensors([Fr, Omega]);

D_xdx,D_xdy,D_ydx,D_ydy

(7.4)

 

Generate all contravariant rank 3 symmetric tensors.

E2 > 

GenerateSymmetricTensors(Fr, 3);

D_xD_xD_x,D_xD_xD_y3+D_xD_yD_x3+D_yD_xD_x3,D_xD_yD_y3+D_yD_xD_y3+D_yD_yD_x3,D_yD_yD_y

(7.5)

 

Tensor algebra on vector bundles

 

The DifferentialGeometry package supports tensor algebra and tensor analysis computations on vector bundles E -> M other than the tangent bundle.  To begin, simply create the vector bundle by passing to DGsetup two lists of coordinates, the first giving the base coordinates on M and the second giving the fiber coordinates on the vector bundle E.

E2 > 

with(DifferentialGeometry): with(Tensor):

 

For example, we can define a rank 2 vector bundle over a 3 dimensional base space as follows:

E2 > 

DGsetup([x, y, z], [u, v], E);

frame name: E

(8.1)

 

We have 4 types of tensors defined on E.

E > 

T := map(convert, [D_x, dx, D_u, du] ,DGtensor);

TD_x,dx,D_u,du

(8.2)

 

Here are the index types for these 4 types of tensors.

E > 

map(Tools:-DGinfo, T, "TensorIndexType");

con_bas,cov_bas,con_vrt,cov_vrt

(8.3)

 

All the commands in the Tensor package work for tensors on the vector bundle E.

E > 

T := evalDG(du &t D_u &t dv);

TduD_udv

(8.4)
E > 

RearrangeIndices(T, [[1, 3]]);

dvD_udu

(8.5)
E > 

ContractIndices(T, [[1, 2]]);

dv

(8.6)

 

PushPullTensor

 

The command PushPullTensor is used to transform tensors from one coordinate system to another and, more generally, to map a tensor on one manifold to a tensor on another manifold.  In these latter applications, the transformation need not be invertible.

E > 

with(DifferentialGeometry): with(Tensor):

 

Example 1.  Transforming tensors from Cartesian to polar coordinates.

E > 

DGsetup([x, y], E2):

E2 > 

DGsetup([r, theta], P):

 

Define the change of variables from polar to Cartesian coordinates and calculate the inverse transformation.

P > 

Phi := Transformation(P, E2,[x = r*cos(theta), y = r*sin(theta)]);

Φx=rcosθ,y=rsinθ

(9.1)
P > 

_EnvExplicit := true:

P > 

InvPhi := InverseTransformation(Phi);

InvPhir=y2+x2,θ=arctanyy2+x2,xy2+x2

(9.2)

 

Define tensors T1, T2, and T3 in Cartesian coordinates.

E2 > 

T1 := evalDG(D_x &t D_x + D_y &t D_y);

T1D_xD_x+D_yD_y

(9.3)
E2 > 

T2 := evalDG(D_x &t dy - D_y &t dx);

T2D_xdyD_ydx

(9.4)
E2 > 

T3 := evalDG(dx &t dx + dy &t dy);

T3dxdx+dydy

(9.5)

 

To transform these tensors from Cartesian coordinates to polar coordinates we use, as the first map in the PushPullTensor command, the map whose domain is E2 and whose range is P.

E2 > 

PushPullTensor(InvPhi, Phi, T1);

D_rD_r+D_thetaD_thetar2

(9.6)
P > 

simplify(PushPullTensor(InvPhi, Phi, T2)) assuming r>0;

rD_rdthetaD_thetadrr

(9.7)
P > 

PushPullTensor(Phi,T3);

drdr+r2dthetadtheta

(9.8)

Note that for a covariant tensor such as T3, we use only one transformation.

 

Example 2.  In this example, we compute the induced metric of a torus in R^3.

P > 

DGsetup([u, v],E2): DGsetup([x, y, z], E3):

 

We use the standard parameterization of the torus.  See, for example, Bishop and Goldberg, page 29.

E3 > 

Phi := Transformation(E2, E3, [x = (a + b*sin(v))*cos(u), y = (a + b*sin(v))*sin(u), z = b*cos(v)]);

Φx=a+bsinvcosu,y=a+bsinvsinu,z=bcosv

(9.9)

 

Define the standard metric g on E3 and then pull it back to the torus using the parameterization Phi.

E2 > 

g := evalDG(dx &t dx + dy &t dy + dz &t dz);

gdxdx+dydy+dzdz

(9.10)
E3 > 

gTorus := PushPullTensor(Phi, g);

gTorus2absinv+a2+b2b2cosv2dudu+b2dvdv

(9.11)

In the next lesson, we shall calculate the Gaussian curvature of this metric.

 

Example 3.  In this example, we  consider a metric on E3 and project it to a metric on E2.

E2 > 

DGsetup([x, y], E2): DGsetup([x, y, z], E3):

E3 > 

gE3 := evalDG(y^2*dx &t dy + dx &s dz + x* dy &s dz);

gE3y2dxdy+dxdz+xdydz+dzdx+xdzdy

(9.12)

 

We note that this metric is invariant under translations in the z-direction.

E3 > 

T := Transformation(E3, E3, [x = x, y = y, z = z + epsilon]);

Tx=x,y=y,z=z+ε

(9.13)
E3 > 

PushPullTensor(T, gE3) &minus gE3;

0dxdx

(9.14)

 

Because of this invariance, we can project g to a metric in the xy-plane.  First, we define the projection pi from E3 to E2.

E3 > 

pi := Transformation(E3, E2, [x = x, y = y]);

πx=x,y=y

(9.15)

 

The map pi does not have an inverse but it does have a left inverse and this is the map that we shall use in the PushPullTensor command.

E3 > 

sigma := Transformation(E2, E3, [x = x ,y = y, z = 0]);

σx=x,y=y,z=0

(9.16)
E2 > 

ComposeTransformations(pi, sigma);

x=x,y=y

(9.17)
E2 > 

gE2 := PushPullTensor(pi, sigma, gE3);

gE2y2dxdy

(9.18)

 

Exercises

Exercise 1

 

Symmetrize the tensor T on its first 2 indices and then skew-symmetrize the result on the 2nd and 3rd indices to obtain a tensor S.  Show that the cyclic permutation of the indices of S vanishes.

 

E2 > 

with(DifferentialGeometry): with(Tensor):

E2 > 

DGsetup([x, y, z], E3):

E3 > 

T := evalDG(dx &t dy &t dy + 2*dz &t dx &t dy - 4*dx &t dz &t dx);

Tdxdydy4dxdzdx+2dzdxdy

(10.1.1)

 

Solution

 

E3 > 

T1 := SymmetrizeIndices(T, [1, 2], "Symmetric");

T1dxdydy22dxdzdx+dxdzdy+dydxdy22dzdxdx+dzdxdy

(10.1.1.1)
E3 > 

S := SymmetrizeIndices(T1, [2, 3], "SkewSymmetric");

Sdxdxdzdxdydz2dxdzdx+dxdzdy2+dydxdy4dydydx4+dzdxdy2dzdydx2

(10.1.1.2)
E3 > 

S1 := RearrangeIndices(S, [[1, 2, 3]]);

S1dzdxdxdzdxdy2dxdxdz+dydxdz2+dydydx4dxdydy4+dydzdx2dxdzdy2

(10.1.1.3)
E3 > 

S2 := RearrangeIndices(S1, [[1, 2, 3]]);

S2dxdzdxdydzdx2dzdxdx+dzdydx2+dxdydy4dydxdy4+dxdydz2dydxdz2

(10.1.1.4)
E3 > 

S &plus S1 &plus S2;

0dxdxdx

(10.1.1.5)

Exercise 2

 

Calculate the trace-free part of the rank 3 tensor T with respect to the metric g.

 

E3 > 

with(DifferentialGeometry): with(Tensor):

E3 > 

DGsetup([x, y, z], E3):

E3 > 

T := 3 &mult SymmetrizeIndices(dx &t dy &t dy + 2*dz &t dx &t dy - 4*(dx &t dz &t dx), [1, 2, 3], "Symmetric");

T4dxdxdz+dxdydy+dxdydz4dxdzdx+dxdzdy+dydxdy+dydxdz+dydydx+dydzdx4dzdxdx+dzdxdy+dzdydx

(10.2.1)
E3 > 

g := evalDG(dx &s dy + dz &t dz);

gdxdy+dydx+dzdz

(10.2.2)

 

Solution

 

We find the tensor U such that T - g &t S is trace-free.

E3 > 

h := InverseMetric(g);

hD_xD_y+D_yD_x+D_zD_z

(10.2.1.1)

 

Define S to be a rank 1 tensor with unknown coefficients.  We shall determine {a, b, c} so that T - g &t S is trace-free.

E3 > 

S := evalDG(a*dx + b*dy + c*dz);

Sadx+bdy+cdz

(10.2.1.2)
E3 > 

U := T &minus (SymmetrizeIndices(g &t S, [1, 2, 3], "Symmetric"));

U2adxdxdy34dxdxdz2adxdydx3+2b3+1dxdydy+c3+1dxdydz4dxdzdx+c3+1dxdzdyadxdzdz32adydxdx3+2b3+1dydxdy+c3+1dydxdz+2b3+1dydydx+c3+1dydzdxbdydzdz34dzdxdx+c3+1dzdxdyadzdxdz3+c3+1dzdydxbdzdydz3adzdzdx3bdzdzdy3cdzdzdz

(10.2.1.3)

 

Calculate the trace of U and find the values of {a, b, c} such that this trace vanishes.

E3 > 

V := ContractIndices(h, U, [[1, 1], [2, 2]]);

V5adx3+5b3+2dy+5c3+2dz

(10.2.1.4)
E3 > 

Eq := Tools:-DGinfo(V, "CoefficientSet");

Eq5a3,5b3+2,5c3+2

(10.2.1.5)
E3 > 

Soln := solve(Eq, {a, b, c});

Solna=0,b=65,c=65

(10.2.1.6)
E3 > 

U := Tools:-DGsimplify(eval(U, Soln));

U4dxdxdz+dxdydy5+3dxdydz54dxdzdx+3dxdzdy5+dydxdy5+3dydxdz5+dydydx5+3dydzdx52dydzdz54dzdxdx+3dzdxdy5+3dzdydx52dzdydz52dzdzdy56dzdzdz5

(10.2.1.7)

 

We check this answer by checking that U is symmetric and trace-free.

E3 > 

SymmetrizeIndices(U, [1, 2], "SkewSymmetric");

0dxdxdx

(10.2.1.8)
E3 > 

SymmetrizeIndices(U, [2, 3], "SkewSymmetric");

0dxdxdx

(10.2.1.9)
E3 > 

ContractIndices(h, U, [[1, 1], [2, 2]]);

0dx

(10.2.1.10)
E3 > 

ContractIndices(h, U, [[1, 1], [2, 3]]);

0dx

(10.2.1.11)

Exercise 3

 

Use the programs GenerateSymmetricTensors, GeneratorTensors, RearrangeIndices, DGzip, and Connection to create the general symmetry connection on the 2-dimensional space E2.

 

E3 > 

with(DifferentialGeometry): with(Tensor):

E3 > 

DGsetup([x, y], E2):

 

Solution

E2 > 

Fr := [D_x, D_y];

FrD_x,D_y

(10.3.1.1)
E2 > 

Omega:= [dx, dy];

Ωdx,dy

(10.3.1.2)

 

Step 1.  Generate all rank 2 covariant symmetric tensors.

E2 > 

T1 := GenerateSymmetricTensors(Omega, 2);

T1dxdx,dxdy2+dydx2,dydy

(10.3.1.3)

 

Step 2.  Form all tensor products of T1 with Fr.

E2 > 

T2 := GenerateTensors([Fr, T1]);

T2D_xdxdx,D_xdxdy2+D_xdydx2,D_xdydy,D_ydxdx,D_ydxdy2+D_ydydx2,D_ydydy

(10.3.1.4)

 

Step 3.  Rearrange the indices to obtain a list of tensors with index type ["cov_bas", "con_bas", "cov_bas"].

E2 > 

T3 := map(RearrangeIndices, T2, [[1, 2]]);

T3dxD_xdx,dxD_xdy2+dyD_xdx2,dyD_xdy,dxD_ydx,dxD_ydy2+dyD_ydx2,dyD_ydy

(10.3.1.5)

 

Step 4.  Generate a list of coefficients and zip against the list of tensors T3.

E2 > 

vars := [seq(a||i, i = 1 .. 6)](x, y);

varsa1x,y,a2x,y,a3x,y,a4x,y,a5x,y,a6x,y

(10.3.1.6)
E2 > 

T4 := DGzip(vars, T3, "plus");

T4a1x,ydxD_xdx+12a2x,ydxD_xdy+a4x,ydxD_ydx+12a5x,ydxD_ydy+12a2x,ydyD_xdx+a3x,ydyD_xdy+12a5x,ydyD_ydx+a6x,ydyD_ydy

(10.3.1.7)

 

Step 5.  Use T4 as input to the Connection procedure.

E2 > 

C := Connection(T4);

Ca1x,ydxD_xdx+12a2x,ydxD_xdy+a4x,ydxD_ydx+12a5x,ydxD_ydy+12a2x,ydyD_xdx+a3x,ydyD_xdy+12a5x,ydyD_ydx+a6x,ydyD_ydy

(10.3.1.8)

Exercise 4

 

Express the metric g in null coordinates.

 

E2 > 

with(DifferentialGeometry): with(Tensor):

E2 > 

DGsetup([x, u, y, v], M);

frame name: M

(10.4.1)
M > 

g := CanonicalTensors("Metric", "bas", 2, 2);

gdxdx+dududydydvdv

(10.4.2)

 

Solution

M > 

DGsetup([x1, x2, y1, y2], N);

frame name: N

(10.4.1.1)
N > 

Phi := Transformation(M, N,[x1 = (x + y)/sqrt(2), x2 = (x - y)/sqrt(2), y1 = (u + v)/sqrt(2), y2 = (u - v)/sqrt(2)]);

Φx1=x+y22,x2=xy22,y1=u+v22,y2=uv22

(10.4.1.2)
M > 

InvPhi := InverseTransformation(Phi);

InvPhix=2x1+x22,u=2y1+y22,y=2x2+x12,v=2y2+y12

(10.4.1.3)
N > 

PushPullTensor(InvPhi, g);

dx1dx2+dx2dx1+dy1dy2+dy2dy1

(10.4.1.4)
N >