The components of a tensor are always displayed with respect to one or multiple basis vectors. For a tensor of rank 1, a vector, in 3D-euclidean space, we resort to three orthonormal basis vectors.

Now my question is, whether it is possible to define a vector v as a tensor, rather than just a list with fixed basis. The wished functionality is to easily access its components with respect to any previously defined basis.

As an example: Two basis systems are predefined with respect to a global basis: Basis eS with basis vectors eS1,eS2,eS3 and basis eB with basis vectors eB1,eB2,eB3. Then v is stored as a tensor object with respect to any known basis.

Now I would like to say "Give me the components of v with respect to Basis eS like v[BasiseS1eS2eS3] = {v_(eS1), v_(eS2), v_(eS3)} or with respect to eB v[BasiseB1eB2eB3] = {v_(eB1), v_(eB2), v_(eB3)}.

Is there a functionality in MMA already implemented?

Addendum: It would also be interesting to extend this concept to different coordinate system origins, like give me the components of the location vector v with respect to basis eS and origin O.

Addendum: I would like to avoid saving the same vector with different symbolic names for different basis systems, like v_eB v_eS.


1 Answer 1


We name "global" the built in basis. Assume then that 2 arbitrary basis are stored column wise in the following matrices:

Clear["Global`*", "ns`*"]
m1 = RandomReal[{-1, 1}, {3, 3}];
m2 = RandomReal[{-1, 1}, {3, 3}];

For safety, we create a separate names space "ns` to remember our bases and vectors. We define folowing associations:

ns`vecs = <||>;
ns`bas = <|global -> IdentityMatrix[3]|>;

To store a new basis, we define:

storeBas[name_, mat_] := AssociateTo[ns`bas, name -> Inverse[mat]];

Finally, to store a new tensor, we create a name that is not visible to the user and create a function, that returns a function. This returned function will remember the name of the tensor and returns the value of the tensor in the basis of choice:

makeTen[coord_] := 
 Module[{name = ns`Unique[]}, (AssociateTo[ns`vecs, name -> coord]; 
   Function[{basname}, ns`bas[basname] . ns`vecs[name]])

To make a test if everything works as intended, we first need to store our basis:


With the this we can now define some test tensor: {1,2,3} in the global basis by:

myten = makeTen[{1, 2, 3}];

and express it in the basis "global" and "bas1" and "basis2":


{1, 2, 3}


{10.8218, 0.0276542, -10.0992}


1.20725, 1.99029, 3.34407}

To check if this correct, note that "bas.coordinates" should give the vector in the global basis:

m1 . myten[bas1]

{1., 2., 3.}


To simplify, we may store the coordinates in the function itself, like:

makeTen[coord_] := Function[{basname}, ns`bas[basname] . coord]
  • $\begingroup$ Thank you very much for this elegant approach. which does exactly what I wish it to do! So nice to learn new ways to use MMA $\endgroup$
    – ango4
    Nov 9, 2023 at 17:10
  • 1
    $\begingroup$ I added a simplification, we can actually store the coordinates in the function itself. $\endgroup$ Nov 10, 2023 at 9:00
  • $\begingroup$ An extension for a symmetric tensor of second order, stored as a 3x3 array can be used as makeTen2[matrix3x3_] := Module[{name = nsUnique[]}, (AssociateTo[nsvecs, name -> matrix3x3]; Function[{basname}, nsbas[basname] . nsvecs[name] . Transpose[nsbas[basname]]])]` $\endgroup$
    – ango4
    Nov 10, 2023 at 9:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.