Tensorial Analysis

Renan Cabrera 
With the support of "Academia Nacional de Ciencias de Bolivia"

renanbo@hotmail.com
rencabla@ceibo.entelnet.bo
La Paz Bolivia -2000

Abstract
"Tensorial Analysis" is a tensor calculus package made for general purpose, easy to use with good looking formula display. In this document firstly is defined a Euclidean Metric space in spherical coordinates as a particular case and then the package performance is shown step by step from basic elements such as the index expansion to more advanced tensor treatment involving several types of derivatives and dummy variables.

Electronicaly published at 
http://www.mathsource.com/Content/Applications/Physics/0211-419

This notebook was tested with "Tensorial Analysis 1.3"

\(Needs["tensorial`", 
	"F:\Renan\Fiscom\Book\tensorial.m"]
      \)

First of all we define the Coordinate label, the Tensor Metric label and its specific value. (Obligatory)

x[p_]  =  Tensor[x, {Void}, {p}];
\(GM\  = {
            \ {\ \ 1\ \ \ \ , \ \ \ 0\ \ \ \ \ \ \ \ \ \ \ \ \ \ , 
              \ \ \ \ \ \ \ \ \ \ 0}, 

            		\ \ \ \ \ \ \ \ \ {\ \ 0\ \ \ \ , \ \ x[1]^2\ \ \ , 
              \ \ \ \ \ \ \ \ \ 0\ }, 

            \ \ 		\ \ \ \ \ \ \ {\ \ 0\ \ \ \ , \ \ \ 0
              \ \ \ \ \ \ \ \ \ \ \ \ \ \ , \ \((x[1]\ Sin[x[2]])\)^2}\ }\);

SetSystem[x , g,  GM ]

Tensor Definition

A tensor is an object that can be denoted by the Head Tensor and two lists keeping the conventional covariant and contravariant indexes.

TB1  = Tensor[B, {i, Void}, {Void, j}]

We can expand a certain tensor with ExpandIndex[ Tensor, index].  
Important: index must be always list !!

a ( TB1 +  Tensor[F, {i, Void}, {Void, j}])ExpandIndex[%,  {i, j}]

To expand tensors with double indexes we have to use explicitely the command ExpandDoubleIndex[ Tensor , double index ] . In this case double indexes are treated as dummy variales.

\(TB\  = \ 
\ 
      Tensor[B, {Void\ , i}, {j}]\ Tensor[A, {Void, j}\ , \ {i}]\)

ExpandDoubleIndex[  TB,  {j} ]

ExpandDoubleIndex[TB,  {i, j} ]

\(\((Tensor[A, {i, j}, {Void, Void}] + \ Tensor[A, {i, k}, {Void, Void}])
        \) Tensor[B, {Void}, {i}]
\)ExpandDoubleIndex[ % , {i} ]

ExpandDoubleIndex[ Tensor[Q, {Void}, {m}]  +  TB,  {j} ]

Dummy Variables

One of the most important and also more difficult procedures to implement in a Tensor package is the handling of the dummy variables.

\(c\ \ Tensor[A, {Void}, {i}]\ \ Tensor[B, {i}, {Void}]\  + \ 
      a\ Tensor[A, {Void}, {j}]\ \ Tensor[B, {j}, {Void}] + 
		
      b\ Tensor[A, {Void}, {m}]\ \ Tensor[B, {m}, {Void}]
\)\(DummyVariableSimplify[%]
\)

\(r\ Tensor[A, {Void, Void}, {i, j}]\ \ Tensor[B, {i}, {Void}]\ 
        Tensor[C, {j}, {Void}]\  + 

      s\ Tensor[A, {Void, Void}, {k, m}]\ \ Tensor[B, {k}, {Void}]\ 
        Tensor[C, {m}, {Void}]
\)\(DummyVariableSimplify[%]
\)

\(c\ \ Tensor[A, {Void}, {i}]\ \ Tensor[B, {i}, {Void}]\  + \ 
      a\ Tensor[A, {Void}, {j}]\ \ Tensor[B, {j}, {Void}] + 
		
      b\ Tensor[A, {Void}, {m}]\ \ Tensor[B, {m}, {Void}] + \ 
      r\ Tensor[A, {Void, Void}, {i, j}]\ \ Tensor[B, {i}, {Void}]\ 
        Tensor[C, {j}, {Void}]\  + \ 
      Tensor[A, {Void, Void}, {k, m}]\ \ Tensor[B, {k}, {Void}]\ 
        Tensor[C, {m}, {Void}]\ 
\)DummyVariableSimplify[%]

\(a\ Tensor[A, {i, j}, {Void, Void}] Tensor[G, {Void, Void}, {i}]\  + 

      b\ Tensor[A, {k, m}, {Void, Void}] Tensor[G, {Void, Void}, {k}]\ 
\)DummyVariableSimplify[ % ]

\(a*Tensor[U, {Void}, {i}] Tensor[A, {i, j}, {Void, Void}] 
        Tensor[G, {Void, Void}, {j, k}]\ Tensor[B, {k}, {Void}] + 

      b*Tensor[U, {Void}, {k}] Tensor[A, {k, m}, {Void, Void}] 
        Tensor[G, {Void, Void}, {m, p}]\ Tensor[B, {p}, {Void}]
\)\(DummyVariableSimplify[%]
\)

\(a\ Tensor[F, {Void, Void, i}, {i, j, Void}] + \ 
      b\ Tensor[F, {Void, Void, k}, {k, j, Void}] + 
      c\ Tensor[F, {Void, Void, m}, {m, j, Void}]
	\)DummyVariableSimplify[ %]

\(a\ Tensor[F, {Void, Void, i, j}, {i, j, Void, Void}] + \ 
      b\ Tensor[F, {Void, Void, j, p}, {j, p, Void, Void}] + 
      c\ Tensor[F, {Void, Void, m, r}, {m, r, Void, Void}]	
\)DummyVariableSimplify[ % ]

\(c\ \ Tensor[A, {Void}, {i}]\ \ Tensor[B, {i}, {Void}]\ \ 
        Tensor[F, {Void}, {j}]\ \ Tensor[G, {j}, {Void}] + \ 
      a\ Tensor[A, {Void}, {j}]\ \ Tensor[B, {j}, {Void}] + 
		
      b\ Tensor[A, {Void}, {m}]\ \ Tensor[B, {m}, {Void}]
\)DummyVariableSimplify[ % ]

\(a\ Tensor[F, {Void, Void, i, j}, {i, j, Void, Void}] + \ 

      b\ Tensor[F, {Void, Void, j, p}, {j, p, Void, Void}] + 
      c\ Tensor[F, {Void, Void, m, r}, {m, r, Void, Void}]\ *\ 

        Tensor[A, {Void}, {i}] Tensor[B, {i}, {Void}]	
\)DummyVariableSimplify[%]

\(a\ Tensor[B, {r}, {Void}] 
        Tensor[F, {Void, Void, Void, i, j}, {i, j, r, Void, Void}] + \ 

      b\ Tensor[B, {k}, {Void}] 
        Tensor[F, {Void, Void, Void, i, j}, {i, j, k, Void, Void}] + 

      c\ Tensor[B, {m}, {Void}] 
        Tensor[F, {Void, Void, Void, k, j}, {k, j, m, Void, Void}]	
\)DummyVariableSimplify[ % ]

Assigning Values

In order to assign particular values we have two ways to do it. Defining a rule for each value or assign explicit values.

\(ValueRuleA\  = \ 
      SetTensorRule[\ \ 
	
        ExpandIndex[\ Tensor[A, {Void}, {i}], {i}]\ \ , {X, Y, Z}\ 	]\)

\(ExpandIndex[
	Tensor[A, {Void}, {i}], {i}

        \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ] /. \ ValueRuleA\)

Assigning explicit values.

\(VA\  = \ {a, b, c}; 


    Do[
	\(Tensor[A, {Void}, {i}]\  = \ VA[\([i]\)]; \)
	, {i, 1, 3}]\)

ExpandIndex[ Tensor[A, {Void}, {i}] ,  {i}]

Special Tensors

Metric Tensor

The Metric Tensor was already defined in the begining

TM  = Tensor[g, {i, j}, {Void, Void}]

ExpandIndex[TM, {i, j}]

We can simplify some tensors

\(\ \((b\ Tensor[A, {Void}, {j}] + Tensor[M, {Void}, {j}])\) 
      Tensor[g, {i, j}, {Void, Void}]
\)TensorSimplify[%]

(b Tensor[A, {j}, {Void}] + Tensor[M, {j}, {Void}] ) 
      Tensor[g, {Void, Void}, {i, j}]TensorSimplify[%]

Kronecker's  Delta

Special Tensors are predefined such as the Kronecker Delta.

Kronecker[i, j]Kronecker[i, 1]Kronecker[1, 1]Kronecker[1, 3]Kronecker[i, i + 1]

The function TensorSimplify can also be used to simplify expresions with Kronecker's Delta.

Kronecker[j, i] 
      ( Tensor[A, {i}, {Void, m}] +  Tensor[B, {i}, {Void, m}])TensorSimplify[%]

Levi-Civita symbol

Other important tensors are the the Levi-Civita symbol  and the Generalized Kronecker's Delta

\(Tensor[ϵ, {i, j, k}, {Void, Void, Void}]\ 
\)\(Tensor[ϵ, {Void, Void, Void}, {i, j, k}]\ 
\)\(Tensor[ϵ, {1, 2, 3}, {Void, Void, Void}]

\)

\(\(ExpandIndex[
      Tensor[ϵ, {i, j, k}, {Void, Void, Void}]\ , {i, j, k}\ \ ]


    \)\)

\(Kronecker[{i, j, k}, {m, n, p}]\ 
\)Kronecker[{1, 2, 3}, {1, 3, 2}]

Christoffel's Symbols

Very important in Tensor Analysis are the Christoffel's Symbols, which are introduced below.

\(\(Christoffel1[g, x]\)[{i, j}, {k}]
\)\(\(Christoffel2[g, x]\)[{i, j}, {k}]
\)

Christoffel's symbols by default are not evaluated in their derivatives. We have to use EvaluateIndexDerivative as below

Christoffel1[g, x][{3, 3}, {1}] 
EvaluateIndexDerivative[%]

Christoffel2[g, x][{2, 1}, {2}] 
EvaluateIndexDerivative[%]

\(ExpandIndex[
	\(Christoffel1[g, x]\)[{i, j}, {k}]
, {i, j, k}]\)//EvaluateIndexDerivative

\(ExpandIndex[
	\(Christoffel2[g, x]\)[{i, j}, {k}]
, {i, j, k}]\)%//EvaluateIndexDerivative

Note.- [g] stands for the particular Tensor Metric which is defined

Derivatives

Partial Derivative

Taking Derivatives is very important, so we defined a differential operator called IndexDerivative, which behaves in many ways like the normal Derivative "D", but with important especific Characteristics as we'll see below.

In order to have a more short way to express  the coordinates
 Tensor[x,{Void},{i}] we define a short cut.

x[i_]  =  Tensor[x, {Void}, {i}]

As an example of IndexDerivative we define a Tensor A with
particular values.

\(
TA\  = \ Tensor[A, {Void}, {j}]
\)\(ValuesTA\  = \ {a\ x[1], b\ x[2], c\ x[3]}; 


    Do[
	
	\(Tensor[A, {Void}, {i}]\  = \ ValuesTA[\([i]\)]; \)
	

      	, {i, 1, 3}]\)

ExpandIndex[TA, {j}]

Now we take a IndexDerivative

\(DTA\  = IndexDerivative[\ TA\ \ \ , \ x[i]]
\)\(ExpandIndex[DTA, {j, i}]\ 
\)% //  EvaluateIndexDerivative

Lets see other example

\(DTA\  = IndexDerivative[\ TA\ \ \ , \ x[j]]
\)\(ExpandDoubleIndex[DTA, {j}]\ 
\)ExpandDoubleIndex[DTA, {j}]  // EvaluateIndexDerivative

Lets Try Derivatives on functions over the coordinates themselves

IndexDerivative[ x[i], x[j]] % // EvaluateIndexDerivative

IndexDerivative[h[x[k]] a^f[x[i]], x[j]] EvaluateIndexDerivative[%]ExpandIndex[%, {i, j, k}]

You have to be very careful when indexes are expanded. Above {i,k,k }are all free indexes, even though they certainly repeat.  In these cases dont! use Tensor Simplify.
Lets see other example:

\(TX = \ \ Sin[Tensor[x, {Void}, {i}]	]^2\)

\(IndexDerivative[\ TX	\ \ \ , \ \ \ 
	Tensor[x, {Void}, {j}]]\ \)EvaluateIndexDerivative[%]\(ExpandIndex[%, {i, j}]
\)

Lets try  more complicated derivatives

\(DUM\  = 
      IndexDerivative[\ 	\(Christoffel2[g, x]\)[{i, j}, {k}]
, 
        Tensor[x, {Void}, {k}]	]
\)\(ExpandIndex[	
ExpandDoubleIndex[DUM, {k}]\ \ , {i, j}]\  // 
      EvaluateIndexDerivative\)

\(\(ExpandIndex[
\ 
        IndexDerivative[
\(Christoffel2[g, x]\)[{i, j}, {k}]
\ \ , \ x[m]]
          
, {i, j, k}] // EvaluateIndexDerivative
	\)\)

Now we have to be aware of some problems when partial derivative is used.  
EvaluateIndexDerivative must be used over expanded tensors in most of the cases to avoid  problems!!!!!!!!!!

IndexDerivative[ Christoffel2[g, x][{i, j}, {k}] ,  x[m] ]EvaluateIndexDerivative[%]

Now lets see partial derivatives of higher order.

IndexDerivative[ IndexDerivative[F, x[i]], x[j] ]

IndexDerivative[ IndexDerivative[IndexDerivative[F, x[k]], x[i]], 
      x[j] ]

IndexDerivative[F,  x[i], x[j]]

\(TX = \ \ Sin[Tensor[x, {Void}, {k}]	]^2
\)\(TX2\  = IndexDerivative[TX, \ x[i]] // EvaluateIndexDerivative
\)IndexDerivative[TX2,  x[j]] // EvaluateIndexDerivative

IndexDerivative[TX,  x[i], x[j]]  // EvaluateIndexDerivative

Warning: k is not dummy variable

Covariant Derivative

The Covariant Derivative is ready to be used.

\(CovariantDerivative[
\ 	\ 
      Tensor[A, {Void, m}, {k, Void}] + Tensor[B, {Void, m}, {k, Void}], 
	
      x, j, g	]\)

It obeys the differentiation Rules

\(CovariantDerivative[
	\ 
      Tensor[A, {Void, m}, {k, Void}] Tensor[B, {Void, k}, {m, Void}], 
	x, 
      j, g	]\)

CovariantDerivative has the attribute Hold First. It means that it holds unevaluated the first argument. To evaluate it must be used Evaluate.

\(DTA\  = \ 
      CovariantDerivative[
	\ Tensor[A, {Void, i}, {j, Void}], 
	x, k, g]
        
\)CovariantDerivative[ Evaluate[DTA] , x, m ,  g]

\(CovariantDerivative[

      CovariantDerivative[
\ \ \ \ \ \ 	\ 
          Tensor[A, {Void, m}, {k, Void}] Tensor[B, {Void, k}, {m, Void}]
, 
          x, j, g	] // Evaluate
, x, p, g	]\)

\(CovariantDerivative[
	\ 
      Tensor[A, {Void, m}, {k, Void}] Tensor[B, {Void, k}, {m, Void}], 
	
      x, {j, p, q}, g	]\)

The Covariant Derivative is fully evaluated only at particular indexes values.

 Lets try some well know identities.

\(ExpandIndex[
	
	
      CovariantDerivative[
	\ Tensor[g, {k, m}, {Void, Void}]
	, x, j, g]
        \ 
	
	, {k, m, j}\ ]\)

\(CovariantDerivative[Kronecker[i, j], 	x, k, g]\)

Another  calculation for particular values of the indexes

\(CovariantDerivative[
	\ Tensor[P, {Void, 1}, {1, Void}], 
	x, 3\ , 
      g]\)% // EvaluateIndexDerivative

Divergence

Lets work with a particular tensor

Tensor[ B, {Void}, {m}]

With particular values.

\(\({\ Tensor[\ B, {Void}, {1}]\ , \ 
\ 	Tensor[\ B, {Void}, {2}], \ 

        	\ Tensor[\ B, {Void}, {3}]\ \ }\  = \ 
      
{\ \ B1[x[1], x[2], x[3]]\ , 
	\ \ B2[x[1], x[2], x[3]], 
		
        B3[x[1], x[2], x[3]]}; \)\)

\(DivA\  = \ 
      CovariantDerivative[
\ 	\ Tensor[\ B, {Void}, {m}]

        	\ \ \ \ \ \ \ \ \ \ \ , x, m, g	]
\)ExpandDoubleIndex[DivA, {m}] // EvaluateIndexDerivative

Gradient

To denote a Escalar function we have to put over it the Head tensor

\(\(Tensor[GradF, {i_?IntegerQ}, {Void}]\  := \ 

      CovariantDerivative[\ 		Tensor[\ F[x[1], x[2], x[3]]\ ]\ 	, x, i, g]
        
\)\)

\(Tensor[GradF, {i}, {Void}]
\)ExpandIndex[Tensor[GradF, {j}, {Void}], {j}]

\(ExpandIndex[
	\ \ \ \ Tensor[GradF, {i}, {Void}]
\ \ \ , {i}] // \ 
      EvaluateIndexDerivative\)

Laplacian

\(\(DivF\  = 
	\ \ \ 
      CovariantDerivative[\ 		
		
        Tensor[g, {Void, Void}, {i, j}]\ \ Tensor[\ GradF, {j}, {Void}]\ 		
        
		, x, i, g]\ 

    	\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \)\)

ExpandDoubleIndex[ DivF , {i, j}] //  EvaluateIndexDerivative 
       // Expand

Absolute Derivative

\(AbsoluteDerivative[\ x[i]*x[i] + x[i]\ , t]
\)AbsoluteDerivative[  x[i] Exp[t^2] , t]

\(Attributes[Bx]\  = \ {Constant}; 


    AbsoluteDerivative[\ x[i]*\ a*\ Bx\ , t]\)

AbsoluteDerivative[  x[i] Exp[ x[j] ] , t]

Intrinsec Derivative

IntrinsecDerivative[ Tensor[F] , t, {x, g}]

\(IntrinsecDerivative[\ Tensor[F, {Void}, {k}]\ , t, {x, g}]
\)ExpandIndex[%, {k}]

The Velocity Tensor is the Absolute Derivative of position

Tensor[V, {Void}, {i_?IntegerQ}]  =  
      AbsoluteDerivative[ x[i] ,  t ]

Tensor[V, {Void}, {i}]

But the acceleration is the Intrinsec derivative of the velocity

\(ac\  = 
      ExpandIndex[

          IntrinsecDerivative[\ 
	Tensor[V, {Void}, {i}]\ , t, {x, g}]

          \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ , {i}]\  // 
        EvaluateIndexDerivative\)

Finding its physical components is easy

\(\(\(ac*{1, \ Sqrt[Tensor[g, {2, 2}, {Void, Void}]\ ]\ \ \ , \ \ 
            Sqrt[Tensor[g, {3, 3}, {Void, Void}]]\ \ \ \ }\ \  // Expand\) // 
      PowerExpand
		\)\)

Example. Riemann Christoffel Tensor

Now we can define important Tensors like the RiemannChristoffel Tensor

-((∂((Subscript[Γ, ij]^a)"["g"]"))/(∂(Subscript[x, "  "]^k)))+((∂((Subscript[Γ, ik]^a)"["g"]"))/(∂(Subscript[x, "  "]^j)))+((Subscript[Γ, ik]^β)"["g"]") ((Subscript[Γ, βj]^a)"["g"]")-((Subscript[Γ, ij]^β)"["g"]") ((Subscript[Γ, βk]^a)"["g"]")

\(\(RC[{i_, j_, k_}, {a_}]\  = \ 
	
      ExpandDoubleIndex[

        IndexDerivative[\ \(Christoffel2[g, x]\)[{i, k}, {a}]\ , \ 
            Tensor[x, {Void}, {j}]\ ] - 

          IndexDerivative[\ \(Christoffel2[g, x]\)[{i, j}, {a}]\ , \ 
            Tensor[x, {Void}, {k}]\ ] + 

          \(Christoffel2[g, x]\)[{i, k}, {β}]\ 
            \(Christoffel2[g, x]\)[{β, j}, {a}]\  - 

          \(Christoffel2[g, x]\)[{i, j}, {β}]\ 
            \(Christoffel2[g, x]\)[{β, k}, {a}]

        	\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ , {β}]\ 	\)\)

Lets see its elements in our Euclidian space

\(\(\(ExpandIndex[
RC[{i, j, k}, {l}]

          \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ , {i, j, k, l}]\  // 
        EvaluateIndexDerivative\) // Simplify

\)\)

As we know it measures the curvature, and the Euclidean space is plane then all their elements must be  0