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
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.
The Tensor command RearrangeIndices is used to rearrange the indices (or arguments) of a tensor.
with(DifferentialGeometry): with(Tensor):
DGsetup([x, y, z], E2):
T := evalDG(dx &t D_y &t dz);
T ≔ dx⁢D_y⁢dz
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).
RearrangeIndices(T, [1, 3, 2]);
dx⁢dz⁢D_y
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).
RearrangeIndices(T, [[3,2]]);
Permute the indices of T (send 1 -> 2, 2 -> 3, and 3 -> 1).
RearrangeIndices(T, [[1, 2, 3]]);
dz⁢dx⁢D_y
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.
Define a tensor T.
T := evalDG(D_x &t D_y &t D_z);
T ≔ D_x⁢D_y⁢D_z
Symmetrize T over its first two indices.
W := SymmetrizeIndices(T, [1, 2], "Symmetric");
W ≔ D_x⁢D_y⁢D_z2+D_y⁢D_x⁢D_z2
Symmetrize W over its first two indices. The tensor W is returned.
newW := SymmetrizeIndices(W, [1, 2], "Symmetric");
newW ≔ D_x⁢D_y⁢D_z2+D_y⁢D_x⁢D_z2
newW &minus W;
0⁢D_x⁢D_x⁢D_x
Symmetrize T over all its indices.
U := SymmetrizeIndices(T, [1, 2, 3], "Symmetric");
U ≔ D_x⁢D_y⁢D_z6+D_x⁢D_z⁢D_y6+D_y⁢D_x⁢D_z6+D_y⁢D_z⁢D_x6+D_z⁢D_x⁢D_y6+D_z⁢D_y⁢D_x6
Skew-symmetrize U over its 2nd and 3rd indices.
SymmetrizeIndices(U, [2, 3], "SkewSymmetric");
The Tensor command ContractIndices can be used in two ways.
DGsetup([x, y, z], E3):
The first use is to contract a list of pairs of indices of a given tensor.
T:= evalDG(D_x &t dy &t D_z &t dz - 2*D_x &t dx &t D_x &t dx);
T ≔ −2⁢D_x⁢dx⁢D_x⁢dx+D_x⁢dy⁢D_z⁢dz
Contract the 2nd and 3rd indices of T.
ContractIndices(T, [[2, 3]]);
−2⁢D_x⁢dx
Simultaneously contract the 2nd and 3rd indices and the 1st and 4th indices of T.
ContractIndices(T, [[2,3], [1,4]]);
−2
S := convert(D_y, DGtensor);
S ≔ D_y
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.
ContractIndices(T, S, [[2, 1]]);
D_x⁢D_z⁢dz
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.
DGsetup([x, y], E2):
g := evalDG(2*dx &t dx + dx &t dy + dy &t dx);
g ≔ 2⁢dx⁢dx+dx⁢dy+dy⁢dx
h := InverseMetric(g);
h ≔ D_x⁢D_y+D_y⁢D_x−2⁢D_y⁢D_y
Let's check that the symmetric matrix for g and the symmetric matrix for h are inverses.
A := convert(g, DGArray);
B := convert(h, DGArray);
convert(A,Matrix).convert(B,Matrix);
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.
Define a metric tensor g and calculate its inverse.
g := evalDG(dx &t dy + dy &t dx);
g ≔ dx⁢dy+dy⁢dx
h ≔ D_x⁢D_y+D_y⁢D_x
T := evalDG(dx &t D_y &t D_x);
T ≔ dx⁢D_y⁢D_x
Lower the 2nd index of T using the metric g.
S := RaiseLowerIndices(g, T, [2]);
S ≔ dx⁢dx⁢D_x
Lower the 2nd and 3rd indices of T using the metric g.
RaiseLowerIndices(g, T, [2, 3]);
dx⁢dx⁢dy
Raise the 1st index of the tensor T using the inverse h.
RaiseLowerIndices(h, T, [1]);
D_y⁢D_y⁢D_x
The Tensor commands GenerateTensors and GenerateSymmetricTensors can be used to generate bases for various tensor spaces.
First, use the command Tools:-DGinfo to generate the basis for the tangent and cotangent spaces.
Fr := Tools:-DGinfo(E2, "FrameBaseVectors");
Fr ≔ D_x,D_y
Omega := Tools:-DGinfo(E2, "FrameBaseForms");
Ω ≔ dx,dy
Generate all contravariant rank 2 tensors.
GenerateTensors([Fr, Fr]);
D_x⁢D_x,D_x⁢D_y,D_y⁢D_x,D_y⁢D_y
Generate all type (1, 1) tensors.
GenerateTensors([Fr, Omega]);
D_x⁢dx,D_x⁢dy,D_y⁢dx,D_y⁢dy
Generate all contravariant rank 3 symmetric tensors.
GenerateSymmetricTensors(Fr, 3);
D_x⁢D_x⁢D_x,D_x⁢D_x⁢D_y3+D_x⁢D_y⁢D_x3+D_y⁢D_x⁢D_x3,D_x⁢D_y⁢D_y3+D_y⁢D_x⁢D_y3+D_y⁢D_y⁢D_x3,D_y⁢D_y⁢D_y
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.
For example, we can define a rank 2 vector bundle over a 3 dimensional base space as follows:
DGsetup([x, y, z], [u, v], E);
frame name: E
We have 4 types of tensors defined on E.
T := map(convert, [D_x, dx, D_u, du] ,DGtensor);
T ≔ D_x,dx,D_u,du
Here are the index types for these 4 types of tensors.
map(Tools:-DGinfo, T, "TensorIndexType");
con_bas,cov_bas,con_vrt,cov_vrt
All the commands in the Tensor package work for tensors on the vector bundle E.
T := evalDG(du &t D_u &t dv);
T ≔ du⁢D_u⁢dv
RearrangeIndices(T, [[1, 3]]);
dv⁢D_u⁢du
ContractIndices(T, [[1, 2]]);
dv
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.
Example 1. Transforming tensors from Cartesian to polar coordinates.
DGsetup([r, theta], P):
Define the change of variables from polar to Cartesian coordinates and calculate the inverse transformation.
Phi := Transformation(P, E2,[x = r*cos(theta), y = r*sin(theta)]);
Φ ≔ x=r⁢cos⁡θ,y=r⁢sin⁡θ
_EnvExplicit := true:
InvPhi := InverseTransformation(Phi);
InvPhi ≔ r=y2+x2,θ=arctan⁡yy2+x2,xy2+x2
Define tensors T1, T2, and T3 in Cartesian coordinates.
T1 := evalDG(D_x &t D_x + D_y &t D_y);
T1 ≔ D_x⁢D_x+D_y⁢D_y
T2 := evalDG(D_x &t dy - D_y &t dx);
T2 ≔ D_x⁢dy−D_y⁢dx
T3 := evalDG(dx &t dx + dy &t dy);
T3 ≔ dx⁢dx+dy⁢dy
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.
PushPullTensor(InvPhi, Phi, T1);
D_r⁢D_r+D_theta⁢D_thetar2
simplify(PushPullTensor(InvPhi, Phi, T2)) assuming r>0;
r⁢D_r⁢dtheta−D_theta⁢drr
PushPullTensor(Phi,T3);
dr⁢dr+r2⁢dtheta⁢dtheta
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.
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.
Phi := Transformation(E2, E3, [x = (a + b*sin(v))*cos(u), y = (a + b*sin(v))*sin(u), z = b*cos(v)]);
Φ ≔ x=a+b⁢sin⁡v⁢cos⁡u,y=a+b⁢sin⁡v⁢sin⁡u,z=b⁢cos⁡v
Define the standard metric g on E3 and then pull it back to the torus using the parameterization Phi.
g := evalDG(dx &t dx + dy &t dy + dz &t dz);
g ≔ dx⁢dx+dy⁢dy+dz⁢dz
gTorus := PushPullTensor(Phi, g);
gTorus ≔ 2⁢a⁢b⁢sin⁡v+a2+b2−b2⁢cos⁡v2⁢du⁢du+b2⁢dv⁢dv
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.
DGsetup([x, y], E2): DGsetup([x, y, z], E3):
gE3 := evalDG(y^2*dx &t dy + dx &s dz + x* dy &s dz);
gE3 ≔ y2⁢dx⁢dy+dx⁢dz+x⁢dy⁢dz+dz⁢dx+x⁢dz⁢dy
We note that this metric is invariant under translations in the z-direction.
T := Transformation(E3, E3, [x = x, y = y, z = z + epsilon]);
T ≔ x=x,y=y,z=z+ε
PushPullTensor(T, gE3) &minus gE3;
0⁢dx⁢dx
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.
pi := Transformation(E3, E2, [x = x, y = y]);
π ≔ x=x,y=y
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.
sigma := Transformation(E2, E3, [x = x ,y = y, z = 0]);
σ ≔ x=x,y=y,z=0
ComposeTransformations(pi, sigma);
x=x,y=y
gE2 := PushPullTensor(pi, sigma, gE3);
gE2 ≔ y2⁢dx⁢dy
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.
T := evalDG(dx &t dy &t dy + 2*dz &t dx &t dy - 4*dx &t dz &t dx);
T ≔ dx⁢dy⁢dy−4⁢dx⁢dz⁢dx+2⁢dz⁢dx⁢dy
Solution
T1 := SymmetrizeIndices(T, [1, 2], "Symmetric");
T1 ≔ dx⁢dy⁢dy2−2⁢dx⁢dz⁢dx+dx⁢dz⁢dy+dy⁢dx⁢dy2−2⁢dz⁢dx⁢dx+dz⁢dx⁢dy
S := SymmetrizeIndices(T1, [2, 3], "SkewSymmetric");
S ≔ dx⁢dx⁢dz−dx⁢dy⁢dz2−dx⁢dz⁢dx+dx⁢dz⁢dy2+dy⁢dx⁢dy4−dy⁢dy⁢dx4+dz⁢dx⁢dy2−dz⁢dy⁢dx2
S1 := RearrangeIndices(S, [[1, 2, 3]]);
S1 ≔ dz⁢dx⁢dx−dz⁢dx⁢dy2−dx⁢dx⁢dz+dy⁢dx⁢dz2+dy⁢dy⁢dx4−dx⁢dy⁢dy4+dy⁢dz⁢dx2−dx⁢dz⁢dy2
S2 := RearrangeIndices(S1, [[1, 2, 3]]);
S2 ≔ dx⁢dz⁢dx−dy⁢dz⁢dx2−dz⁢dx⁢dx+dz⁢dy⁢dx2+dx⁢dy⁢dy4−dy⁢dx⁢dy4+dx⁢dy⁢dz2−dy⁢dx⁢dz2
S &plus S1 &plus S2;
0⁢dx⁢dx⁢dx
Exercise 2
Calculate the trace-free part of the rank 3 tensor T with respect to the metric g.
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");
T ≔ −4⁢dx⁢dx⁢dz+dx⁢dy⁢dy+dx⁢dy⁢dz−4⁢dx⁢dz⁢dx+dx⁢dz⁢dy+dy⁢dx⁢dy+dy⁢dx⁢dz+dy⁢dy⁢dx+dy⁢dz⁢dx−4⁢dz⁢dx⁢dx+dz⁢dx⁢dy+dz⁢dy⁢dx
g := evalDG(dx &s dy + dz &t dz);
g ≔ dx⁢dy+dy⁢dx+dz⁢dz
We find the tensor U such that T - g &t S is trace-free.
h ≔ D_x⁢D_y+D_y⁢D_x+D_z⁢D_z
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.
S := evalDG(a*dx + b*dy + c*dz);
S ≔ a⁢dx+b⁢dy+c⁢dz
U := T &minus (SymmetrizeIndices(g &t S, [1, 2, 3], "Symmetric"));
U ≔ −2⁢a⁢dx⁢dx⁢dy3−4⁢dx⁢dx⁢dz−2⁢a⁢dx⁢dy⁢dx3+−2⁢b3+1⁢dx⁢dy⁢dy+−c3+1⁢dx⁢dy⁢dz−4⁢dx⁢dz⁢dx+−c3+1⁢dx⁢dz⁢dy−a⁢dx⁢dz⁢dz3−2⁢a⁢dy⁢dx⁢dx3+−2⁢b3+1⁢dy⁢dx⁢dy+−c3+1⁢dy⁢dx⁢dz+−2⁢b3+1⁢dy⁢dy⁢dx+−c3+1⁢dy⁢dz⁢dx−b⁢dy⁢dz⁢dz3−4⁢dz⁢dx⁢dx+−c3+1⁢dz⁢dx⁢dy−a⁢dz⁢dx⁢dz3+−c3+1⁢dz⁢dy⁢dx−b⁢dz⁢dy⁢dz3−a⁢dz⁢dz⁢dx3−b⁢dz⁢dz⁢dy3−c⁢dz⁢dz⁢dz
Calculate the trace of U and find the values of {a, b, c} such that this trace vanishes.
V := ContractIndices(h, U, [[1, 1], [2, 2]]);
V ≔ −5⁢a⁢dx3+−5⁢b3+2⁢dy+−5⁢c3+2⁢dz
Eq := Tools:-DGinfo(V, "CoefficientSet");
Eq ≔ −5⁢a3,−5⁢b3+2,−5⁢c3+2
Soln := solve(Eq, {a, b, c});
Soln ≔ a=0,b=65,c=65
U := Tools:-DGsimplify(eval(U, Soln));
U ≔ −4⁢dx⁢dx⁢dz+dx⁢dy⁢dy5+3⁢dx⁢dy⁢dz5−4⁢dx⁢dz⁢dx+3⁢dx⁢dz⁢dy5+dy⁢dx⁢dy5+3⁢dy⁢dx⁢dz5+dy⁢dy⁢dx5+3⁢dy⁢dz⁢dx5−2⁢dy⁢dz⁢dz5−4⁢dz⁢dx⁢dx+3⁢dz⁢dx⁢dy5+3⁢dz⁢dy⁢dx5−2⁢dz⁢dy⁢dz5−2⁢dz⁢dz⁢dy5−6⁢dz⁢dz⁢dz5
We check this answer by checking that U is symmetric and trace-free.
SymmetrizeIndices(U, [1, 2], "SkewSymmetric");
ContractIndices(h, U, [[1, 1], [2, 2]]);
0⁢dx
ContractIndices(h, U, [[1, 1], [2, 3]]);
Exercise 3
Use the programs GenerateSymmetricTensors, GeneratorTensors, RearrangeIndices, DGzip, and Connection to create the general symmetry connection on the 2-dimensional space E2.
Fr := [D_x, D_y];
Omega:= [dx, dy];
Step 1. Generate all rank 2 covariant symmetric tensors.
T1 := GenerateSymmetricTensors(Omega, 2);
T1 ≔ dx⁢dx,dx⁢dy2+dy⁢dx2,dy⁢dy
Step 2. Form all tensor products of T1 with Fr.
T2 := GenerateTensors([Fr, T1]);
T2 ≔ D_x⁢dx⁢dx,D_x⁢dx⁢dy2+D_x⁢dy⁢dx2,D_x⁢dy⁢dy,D_y⁢dx⁢dx,D_y⁢dx⁢dy2+D_y⁢dy⁢dx2,D_y⁢dy⁢dy
Step 3. Rearrange the indices to obtain a list of tensors with index type ["cov_bas", "con_bas", "cov_bas"].
T3 := map(RearrangeIndices, T2, [[1, 2]]);
T3 ≔ dx⁢D_x⁢dx,dx⁢D_x⁢dy2+dy⁢D_x⁢dx2,dy⁢D_x⁢dy,dx⁢D_y⁢dx,dx⁢D_y⁢dy2+dy⁢D_y⁢dx2,dy⁢D_y⁢dy
Step 4. Generate a list of coefficients and zip against the list of tensors T3.
vars := [seq(a||i, i = 1 .. 6)](x, y);
vars ≔ a1⁡x,y,a2⁡x,y,a3⁡x,y,a4⁡x,y,a5⁡x,y,a6⁡x,y
T4 := DGzip(vars, T3, "plus");
T4 ≔ a1⁡x,y⁢dx⁢D_x⁢dx+12⁢a2⁡x,y⁢dx⁢D_x⁢dy+a4⁡x,y⁢dx⁢D_y⁢dx+12⁢a5⁡x,y⁢dx⁢D_y⁢dy+12⁢a2⁡x,y⁢dy⁢D_x⁢dx+a3⁡x,y⁢dy⁢D_x⁢dy+12⁢a5⁡x,y⁢dy⁢D_y⁢dx+a6⁡x,y⁢dy⁢D_y⁢dy
Step 5. Use T4 as input to the Connection procedure.
C := Connection(T4);
C ≔ a1⁡x,y⁢dx⁢D_x⁢dx+12⁢a2⁡x,y⁢dx⁢D_x⁢dy+a4⁡x,y⁢dx⁢D_y⁢dx+12⁢a5⁡x,y⁢dx⁢D_y⁢dy+12⁢a2⁡x,y⁢dy⁢D_x⁢dx+a3⁡x,y⁢dy⁢D_x⁢dy+12⁢a5⁡x,y⁢dy⁢D_y⁢dx+a6⁡x,y⁢dy⁢D_y⁢dy
Exercise 4
Express the metric g in null coordinates.
DGsetup([x, u, y, v], M);
frame name: M
g := CanonicalTensors("Metric", "bas", 2, 2);
g ≔ dx⁢dx+du⁢du−dy⁢dy−dv⁢dv
DGsetup([x1, x2, y1, y2], N);
frame name: 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+y⁢22,x2=x−y⁢22,y1=u+v⁢22,y2=u−v⁢22
InvPhi ≔ x=2⁢x1+x22,u=2⁢y1+y22,y=2⁢−x2+x12,v=2⁢−y2+y12
PushPullTensor(InvPhi, g);
dx1⁢dx2+dx2⁢dx1+dy1⁢dy2+dy2⁢dy1
Download Help Document