|
DifferentialGeometry Lessons
Lesson 9: Tensor Algebra
|
|
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);
|
|
| (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]);
|
|
| (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]]);
|
|
| (2.3) |
Permute the indices of T (send 1 -> 2, 2 -> 3, and 3 -> 1).
|
E2 >
|
RearrangeIndices(T, [[1, 2, 3]]);
|
|
| (2.4) |
|
|
|
Symmetrize and skew-symetrize 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);
|
|
| (3.1) |
Symmetrize T over its first two indices.
|
E2 >
|
W := SymmetrizeIndices(T, [1, 2], "Symmetric");
|
|
| (3.2) |
Symmetrize W over its first two indices. The tensor W is returned.
|
E2 >
|
newW := SymmetrizeIndices(W, [1, 2], "Symmetric");
|
|
| (3.3) |
|
| (3.4) |
Symmetrize T over all its indices.
|
E2 >
|
U := SymmetrizeIndices(T, [1, 2, 3], "Symmetric");
|
|
| (3.5) |
Skew-symmetrize U over its 2nd and 3rd indices.
|
E2 >
|
SymmetrizeIndices(U, [2, 3], "SkewSymmetric");
|
|
| (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);
|
|
| (4.1) |
Contract the 2nd and 3rd indices of T.
|
E3 >
|
ContractIndices(T, [[2, 3]]);
|
|
| (4.2) |
Simultaneously contract the 2nd and 3rd indices and the 1st and 4th indices of T.
|
E3 >
|
ContractIndices(T, [[2,3], [1,4]]);
|
|
| (4.3) |
|
E3 >
|
S := convert(D_y, DGtensor);
|
|
| (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]]);
|
|
| (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);
|
|
| (5.1) |
|
E2 >
|
h := InverseMetric(g);
|
|
| (5.2) |
Let's check that the symmetric matrix for g and the symmetric matrix for h are inverses.
|
E2 >
|
A := convert(g, DGArray);
|
|
| (5.3) |
|
E2 >
|
B := convert(h, DGArray);
|
|
| (5.4) |
|
E2 >
|
convert(A,Matrix).convert(B,Matrix);
|
|
| (5.5) |
|
|
|
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);
|
|
| (6.1) |
|
E2 >
|
h := InverseMetric(g);
|
|
| (6.2) |
Define a tensor T.
|
E2 >
|
T := evalDG(dx &t D_y &t D_x);
|
|
| (6.3) |
Lower the 2nd index of T using the metric g.
|
E2 >
|
S := RaiseLowerIndices(g, T, [2]);
|
|
| (6.4) |
Lower the 2nd and 3rd indices of T using the metric g.
|
E2 >
|
RaiseLowerIndices(g, T, [2, 3]);
|
|
| (6.5) |
Raise the 1st index of the tensor T using the inverse h.
|
E2 >
|
RaiseLowerIndices(h, T, [1]);
|
|
| (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");
|
|
| (7.1) |
|
E2 >
|
Omega := Tools:-DGinfo(E2, "FrameBaseForms");
|
|
| (7.2) |
Generate all contravariant rank 2 tensors.
|
E2 >
|
GenerateTensors([Fr, Fr]);
|
|
| (7.3) |
Generate all type (1, 1) tensors.
|
E2 >
|
GenerateTensors([Fr, Omega]);
|
|
| (7.4) |
Generate all contravariant rank 3 symmetric tensors.
|
E2 >
|
GenerateSymmetricTensors(Fr, 3);
|
|
![[D_x*D_x*D_x, D_x*D_x*D_y/3+D_x*D_y*D_x/3+D_y*D_x*D_x/3, D_x*D_y*D_y/3+D_y*D_x*D_y/3+D_y*D_y*D_x/3, D_y*D_y*D_y]](/support/helpjp/helpview.aspx?si=6678/file07619/math556.png)
| (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);
|
|
| (8.1) |
We have 4 types of tensors defined on E.
|
E >
|
T := map(convert, [D_x, dx, D_u, du] ,DGtensor);
|
|
| (8.2) |
Here are the index types for these 4 types of tensors.
|
E >
|
map(Tools:-DGinfo, T, "TensorIndexType");
|
|
| (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);
|
|
| (8.4) |
|
E >
|
RearrangeIndices(T, [[1, 3]]);
|
|
| (8.5) |
|
E >
|
ContractIndices(T, [[1, 2]]);
|
|
| (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.
|
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)]);
|
|
| (9.1) |
|
P >
|
_EnvExplicit := true:
|
|
P >
|
InvPhi := InverseTransformation(Phi);
|
|
| (9.2) |
Define tensors T1, T2, and T3 in Cartesian coordinates.
|
E2 >
|
T1 := evalDG(D_x &t D_x + D_y &t D_y);
|
|
| (9.3) |
|
E2 >
|
T2 := evalDG(D_x &t dy - D_y &t dx);
|
|
| (9.4) |
|
E2 >
|
T3 := evalDG(dx &t dx + dy &t dy);
|
|
| (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);
|
|
| (9.6) |
|
P >
|
simplify(PushPullTensor(InvPhi, Phi, T2)) assuming r>0;
|
|
| (9.7) |
|
P >
|
PushPullTensor(Phi,T3);
|
|
| (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)]);
|
|
| (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);
|
|
| (9.10) |
|
E3 >
|
gTorus := PushPullTensor(Phi, g);
|
|
| (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);
|
|
| (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]);
|
|
| (9.13) |
|
E3 >
|
PushPullTensor(T, gE3) &minus gE3;
|
|
| (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]);
|
|
| (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]);
|
|
| (9.16) |
|
E2 >
|
ComposeTransformations(pi, sigma);
|
|
| (9.17) |
|
E2 >
|
gE2 := PushPullTensor(pi, sigma, gE3);
|
|
| (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);
|
|
| (10.1.1) |
|
|
Solution
|
|
|
E3 >
|
T1 := SymmetrizeIndices(T, [1, 2], "Symmetric");
|
|
| (10.1.1.1) |
|
E3 >
|
S := SymmetrizeIndices(T1, [2, 3], "SkewSymmetric");
|
|

| (10.1.1.2) |
|
E3 >
|
S1 := RearrangeIndices(S, [[1, 2, 3]]);
|
|

| (10.1.1.3) |
|
E3 >
|
S2 := RearrangeIndices(S1, [[1, 2, 3]]);
|
|

| (10.1.1.4) |
|
E3 >
|
S &plus S1 &plus S2;
|
|
| (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");
|
|

| (10.2.1) |
|
E3 >
|
g := evalDG(dx &s dy + dz &t dz);
|
|
| (10.2.2) |
|
|
Solution
|
|
We find the tensor U such that T - g &t S is trace-free.
|
E3 >
|
h := InverseMetric(g);
|
|
| (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);
|
|
| (10.2.1.2) |
|
E3 >
|
U := T &minus (SymmetrizeIndices(g &t S, [1, 2, 3], "Symmetric"));
|
|

| (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]]);
|
|
| (10.2.1.4) |
|
E3 >
|
Eq := Tools:-DGinfo(V, "CoefficientSet");
|
|
| (10.2.1.5) |
|
E3 >
|
Soln := solve(Eq, {a, b, c});
|
|
| (10.2.1.6) |
|
E3 >
|
U := Tools:-DGsimplify(eval(U, Soln));
|
|

| (10.2.1.7) |
We check this answer by checking that U is symmetric and trace-free.
|
E3 >
|
SymmetrizeIndices(U, [1, 2], "SkewSymmetric");
|
|
| (10.2.1.8) |
|
E3 >
|
SymmetrizeIndices(U, [2, 3], "SkewSymmetric");
|
|
| (10.2.1.9) |
|
E3 >
|
ContractIndices(h, U, [[1, 1], [2, 2]]);
|
|
| (10.2.1.10) |
|
E3 >
|
ContractIndices(h, U, [[1, 1], [2, 3]]);
|
|
| (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
|
|
|
| (10.3.1.1) |
|
| (10.3.1.2) |
Step 1. Generate all rank 2 covariant symmetric tensors.
|
E2 >
|
T1 := GenerateSymmetricTensors(Omega, 2);
|
|
| (10.3.1.3) |
Step 2. Form all tensor products of T1 with Fr.
|
E2 >
|
T2 := GenerateTensors([Fr, T1]);
|
|
![T2 := [D_x*dx*dx, D_x*dx*dy/2+D_x*dy*dx/2, D_x*dy*dy, D_y*dx*dx, D_y*dx*dy/2+D_y*dy*dx/2, D_y*dy*dy]](/support/helpjp/helpview.aspx?si=6678/file07619/math1220.png)
| (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]]);
|
|
![T3 := [dx*D_x*dx, dx*D_x*dy/2+dy*D_x*dx/2, dy*D_x*dy, dx*D_y*dx, dx*D_y*dy/2+dy*D_y*dx/2, dy*D_y*dy]](/support/helpjp/helpview.aspx?si=6678/file07619/math1234.png)
| (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);
|
|
| (10.3.1.6) |
|
E2 >
|
T4 := DGzip(vars, T3, "plus");
|
|

| (10.3.1.7) |
Step 5. Use T4 as input to the Connection procedure.
|
E2 >
|
C := Connection(T4);
|
|

| (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);
|
|
| (10.4.1) |
|
M >
|
g := CanonicalTensors("Metric", "bas", 2, 2);
|
|
| (10.4.2) |
|
|
Solution
|
|
|
M >
|
DGsetup([x1, x2, y1, y2], 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)]);
|
|
| (10.4.1.2) |
|
M >
|
InvPhi := InverseTransformation(Phi);
|
|
![InvPhi := [x = 2^(1/2)*(x1+x2)/2, u = 2^(1/2)*(y1+y2)/2, y = 2^(1/2)*(-x2+x1)/2, v = 2^(1/2)*(-y2+y1)/2]](/support/helpjp/helpview.aspx?si=6678/file07619/math1328.png)
| (10.4.1.3) |
|
N >
|
PushPullTensor(InvPhi, g);
|
|
| (10.4.1.4) |
|
|
|
�Ian M. Anderson 2006
|