Changing Coordinate Systems

Changing coordinate systems can involve two very different operations. One is recomputing coordinate values that correspond to the same point. The other is re-expressing a field in terms of new variables. The Wolfram Language provides functions to perform both these operations.

Converting Points

Two coordinate systems are related by a mapping that takes coordinate values in the old system and returns coordinate values in the new system.

Converting points between two coordinate systems.

The function (RefLink[CoordinateTransformData, paclet:ref/CoordinateTransformData]) returns information about mappings between the coordinate systems in (RefLink[CoordinateChartData, paclet:ref/CoordinateChartData]).

This converts the point {r,θ} in polar coordinates to the corresponding {x,y} Cartesian coordinates:

CoordinateTransformData["Polar"->"Cartesian", "Mapping", {r,θ}]

This converts the point {1,1,0} in Cartesian coordinates to the corresponding {r,θ,φ} values in spherical coordinates:

CoordinateTransformData["Cartesian"->"Spherical", "Mapping", {1,1,0}]

The mapping function can be requested from (RefLink[CoordinateTransformData, paclet:ref/CoordinateTransformData]) and stored for later use:

mapping=CoordinateTransformData[{"Cartesian"->"Hyperspherical",3} ,"Mapping"]

The mapping naturally takes a single point:

mapping[{1,1,0}]

Using (RefLink[Map, paclet:ref/Map]), it can be applied to several points at once:

mapping /@ {{0,1,0},{0,0,1}, {0,1,1}, {1,1,1}}

The function (RefLink[CoordinateTransform, paclet:ref/CoordinateTransform]) provides a convenient mechanism for converting one or several points.

This converts the point {1,(π/3),(π/4)} in spherical coordinates to the corresponding cylindrical coordinates:

CoordinateTransform["Spherical"->"Cylindrical",{1,π/3,π/4}]

The previous answer can be verified by converting both coordinate values to Cartesian coordinates:

CoordinateTransform["Spherical"->"Cartesian",{1,π/3,π/4}]===CoordinateTransform["Cylindrical"->"Cartesian",{Sqrt[3]/2,π/4,1/2}]

Parameters can be specified in (RefLink[CoordinateTransform, paclet:ref/CoordinateTransform]) in the same way as in (RefLink[CoordinateTransformData, paclet:ref/CoordinateTransformData]). This converts a generic point {η,θ,ψ} from prolate spheroidal coordinates with parameter a to hyperspherical coordinates:

CoordinateTransform[{{"ProlateSpheroidal", a}->"Hyperspherical",3},{η,θ,ψ}]//Simplify

Several points can be transformed at once:

CoordinateTransform["Cartesian"->"Polar",{{1,1},{1,-1}, {0,-2}}]

Transforming Fields

When transforming fields between two coordinate systems, a field given in terms of variables in the old system is re-expressed in terms of variables in the new system. In addition to the mapping between the systems, several additional steps are needed: solving for the old variables in terms of the new, substituting in these expressions, and, in the case of vector and tensor fields, accounting for differences in basis vectors between the two coordinate systems. All of these steps are performed by the command (RefLink[TransformedField, paclet:ref/TransformedField]).

Transforming a field between two coordinate systems.

The simpler scalar case is considered first.

This converts the scalar field (x^2)+(y^2)+(z^2) from Cartesian {x,y,z} to cylindrical {r,θ,ζ} coordinates:

TransformedField["Cartesian"->"Cylindrical",x^2+y^2+z^2, {x,y,z}->{r,θ,ζ}]//Simplify

The previous example can be done "by hand". Unlike for (RefLink[CoordinateTransform, paclet:ref/CoordinateTransform]), for these steps to make sense, {x,y,z} and {r,θ,ζ} must be coordinate names and not coordinate values such as numbers:

CoordinateTransform["Cartesian"->"Cylindrical",{x,y,z}]

Solve[Thread[%=={r,θ,ζ}],{x,y,z}]//Simplify

x^2 + y^2 + z^2 /. First[%]//Simplify

Parameters can be specified in (RefLink[TransformedField, paclet:ref/TransformedField]) in the same way as in (RefLink[CoordinateTransformData, paclet:ref/CoordinateTransformData]). This is a transformation from cylindrical {r,θ,z} to prolate spheroidal {η,Θ,ψ} coordinates with parameter a:

TransformedField[{"Cylindrical"->{"ProlateSpheroidal", a},3},Sinh[r]Sin[θ] Cos[z] ,{r,θ,z}->{η,Θ,ψ}]//FullSimplify

The vector and tensor case is more complicated because of the need to account for the change of basis vectors. As a result, the transformation of a vector is not merely the transformation of its components. For arrays, which are interpreted as components in an orthonormal basis, the rotation matrix that relates the two bases is given by the (RefLink[CoordinateTransformData, paclet:ref/CoordinateTransformData]) property "OrthonormalBasisRotation".

This converts the vector field x(OverHat[x])+y(OverHat[y])+z(OverHat[z]) from Cartesian {x,y,z} coordinates to spherical {r,θ,φ} coordinates, producing the manifestly radial result r (OverHat[r]):

TransformedField["Cartesian"->"Spherical",{x,y,z}, {x,y,z}->{r,θ,φ}]//Simplify

Two pieces of information are needed to reproduce the previous example: the variable replacement rules, as in the scalar case, and the basis rotation matrix. Since the rotation matrix specifies the rotation between bases, its transpose is the matrix that acts on components:

CoordinateTransform["Cartesian"->"Spherical",{x,y,z}]

replacements = First@Solve[Thread[%=={r,θ,φ}],{x,y,z}]//Simplify

rotation=Transpose@CoordinateTransformData["Cartesian"->"Spherical","OrthonormalBasisRotation",{x,y,z}]

To transform a vector between coordinate systems, first the vector is multiplied by the rotation matrix to change components in the {(OverHat[x,])(OverHat[y,])(OverHat[z])} basis to components in the {(OverHat[r,])(OverHat[θ,])(OverHat[φ])} basis (equivalently, the projection of the vector onto the local basis vectors). Subsequently, the replacement rules are applied:

Simplify[rotation. {x,y,z} /.replacements, CoordinateChartData["Spherical", "CoordinateRangeAssumptions", {r,θ,φ}]]

Using (RefLink[Map, paclet:ref/Map]), lists of scalar fields can be transformed between coordinates. The result is quite different from transforming a vector field with the same components:

TransformedField["Cartesian"->"Spherical",#, {x,y,z}->{r,θ,φ}]& /@ {x,y,z}

TransformedField["Cartesian"->"Spherical",{x,y,z}, {x,y,z}->{r,θ,φ}]//Simplify

This transforms the vector field r sin(θ)(OverHat[φ]) from spherical {r,θ,φ} to Cartesian {x,y,z} coordinates:

TransformedField["Spherical"->"Cartesian",{0,0,r Sin[θ]},{r,θ,φ}->{x,y,z}]

The vector field in hyperspherical coordinates with the same local components is in fact a rotational vector field about the x axis:

TransformedField["Hyperspherical"->"Cartesian",{0,0,r Sin[θ]},{r,θ,φ}->{x,y,z}]//Simplify

Parameters for coordinate systems can be specified in (RefLink[TransformedField, paclet:ref/TransformedField]). This converts the vector field (OverHat[x]) from Cartesian {x,y,z} coordinates to prolate spheroidal {η,Θ,ψ} coordinates with parameter a:

TransformedField[{"Cartesian"->{"ProlateSpheroidal",a},3},{1,0,0} ,{x,y,z}->{η,Θ,ψ}]

This transforms a rank-2 tensor from Cartesian to polar coordinates:

matrix = {{x ^2 + y^2,0}, {0,x^2y^2}}

TransformedField["Cartesian"->"Polar",matrix, {x,y}->{r,θ}]//Simplify

Using (RefLink[Map, paclet:ref/Map]), it is possible to transform the matrix as a list of two vectors or as a matrix of four scalar fields. The results are quite different in each case:

Map[TransformedField[ "Cartesian"->"Polar",#, {x,y}->{r,θ}]&,matrix]//Expand

Map[TransformedField[ "Cartesian"->"Polar",#, {x,y}->{r,θ}]&,matrix,{2}]//Simplify

Relating Orthonormal Bases

The basis rotation matrix used above combines information about both the Jacobian matrix of the mapping and the orthonormal basis in each chart. For orthogonal coordinate systems, it is constructed from the Jacobian and the two sets of scale factors.

Computing properties of charts and transformations.

The matrix rot rotates the basis vectors {(OverHat[x,])(OverHat[y,])(OverHat[z])} into the basis vectors {(OverHat[r,])(OverHat[θ,])(OverHat[φ])}:

rot =CoordinateTransformData["Cartesian"->"Spherical","OrthonormalBasisRotation",{x,y,z}]

The rotated vector rot . (OverHat[x]) is (OverHat[r]) in the {(OverHat[x,])(OverHat[y,])(OverHat[z])} basis, and rot . (OverHat[z]) is (OverHat[φ]) in that same basis:

rot. {1,0,0}

rot. {0,0,1}

To compute the rotation matrix, the scale factors, which define the orthonormal bases in orthogonal systems, are needed. Notice that (RefLink[CoordinateTransform, paclet:ref/CoordinateTransform]) is used to ensure both sets of scale factors are evaluated at the same point:

cartScales = CoordinateChartData["Cartesian", "ScaleFactors",{x,y,z}]

sphereScales = CoordinateChartData["Spherical", "ScaleFactors",CoordinateTransform["Cartesian"->"Spherical",{x,y,z}]]

The rotation matrix is constructed from the transposed Jacobian matrix by conjugating it with diagonal matrices containing the scale factors:

jac=Transpose @ CoordinateTransformData["Cartesian"->"Spherical","MappingJacobian",{x,y,z}]

Inverse@DiagonalMatrix[cartScales].jac.DiagonalMatrix[sphereScales]==rot

This is the matrix that rotates the cylindrical basis vectors {(OverHat[r,])(OverHat[θ,])(OverHat[z])} into the spherical basis vectors {(Subscript[(OverHat[r]), s]),(Subscript[(OverHat[θ]), s]),(OverHat[φ])}:

rotC = CoordinateTransformData["Cylindrical"->"Spherical","OrthonormalBasisRotation",{r,θ,z}]//Simplify

The matrix rotates (OverHat[r]) into (r (OverHat[r])+z (OverHat[z]))/(Sqrt[(r^2)+(z^2)]), which is (Subscript[(OverHat[r]), s]), and it rotates (OverHat[z]) into (OverHat[θ]), which is the same as (OverHat[φ]):

rotC . {1,0,0}

rotC . {0,0,1}

This rotation matrix can be constructed using the scale factors and the Jacobian matrix in the same manner as before:

cylScales = CoordinateChartData["Cylindrical", "ScaleFactors",{r,θ,z}]

cylSphereScales =CoordinateChartData["Spherical", "ScaleFactors",CoordinateTransform["Cylindrical"->"Spherical",{r,θ,z}]]

jacC = Transpose[CoordinateTransformData["Cylindrical"->"Spherical","MappingJacobian",{r,θ,z}]]

Inverse@DiagonalMatrix[cylScales].jacC.DiagonalMatrix[cylSphereScales] === rotC