How to create a vector as a tensor object for different euclidean bases?

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.

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

Clear["Global*", "ns*"]
SeedRandom[1];
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:

nsvecs = <||>;
nsbas = <|global -> IdentityMatrix[3]|>;


To store a new basis, we define:

storeBas[name_, mat_] := AssociateTo[nsbas, 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 = nsUnique[]}, (AssociateTo[nsvecs, name -> coord];
Function[{basname}, nsbas[basname] . nsvecs[name]])
]


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

storeBas[bas1,m1];
storeBas[bas2,m2];


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":

myten[global]

{1, 2, 3}

myten[bas1]

{10.8218, 0.0276542, -10.0992}

myten[bas2]

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.}


makeTen[coord_] := Function[{basname}, ns$$$$bas[basname] . coord]

• 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]]])] Nov 10, 2023 at 9:22