coordinates.coordinate_systems.ProlateSpheroidalCoordinateSystem.lower_index_dense#

ProlateSpheroidalCoordinateSystem.lower_index_dense(tensor_field: ndarray, index: int, rank: int, *coordinates: ndarray, metric_field: ndarray | None = None, fixed_axes: Dict[str, float] | None = None, out: ndarray | None = None, **kwargs) ndarray#

Lower a single tensor index using \(g_{ab}\).

\[T_{\mu\dots} = g_{\mu\nu}\,T^{\nu}{}_{\dots}\]
Parameters:
  • tensor_field (numpy.ndarray) – Tensor field of shape (F₁, ..., F_m, N, ...), where the last rank axes are the tensor index dimensions.

  • index – Which tensor slot (0, ..., rank-1) to raise.

  • rank (int) – Number of trailing axes that represent tensor indices (i.e., tensor rank). The rank determines the number of identified coordinate axes and therefore determines the shape of the returned array.

  • *coordinates – ND coordinate grids in canonical axis order. Only needed when inverse_metric_field is None.

  • metric_field (numpy.ndarray) – Metric tensor with shape (F₁, ..., F_n, N, ) or (F₁, ..., F_n, N, N), where N == n. Must be broadcast-compatible with the field shape of tensor_field.

  • fixed_axes – Constant axis values to use when computing the metric.

  • out – Optional output buffer.

  • **kwargs – Forwarded verbatim to dense_raise_index().

Returns:

Tensor identical to tensor_field except the chosen slot is now contravariant.

Return type:

numpy.ndarray

Examples

In spherical coordinates, the vector \(V^\mu = (r^2,r^{-2},0)\) becomes

\[v_\mu = g_{\mu\mu} V^\mu = (r^2, 1, 0).\]

To perform the operation computationally,

>>> from pymetric.coordinates import SphericalCoordinateSystem
>>> from pymetric.utilities.logging import pg_log
>>> pg_log.level = 50
>>>
>>> # Build the coordinate system.
>>> u = SphericalCoordinateSystem()
>>>
>>> # Create the R,THETA grid.
>>> r = np.linspace(1e-3,1,10)
>>> theta = np.linspace(1e-3,np.pi-1e-3,10)
>>> R, THETA = np.meshgrid(r,theta)
>>>
>>> # Create the vector field.
>>> V_contra = np.stack([R**2,R**-2,np.zeros_like(R)],axis=-1)
>>>
>>> # Raise the index.
>>> V_co = u.lower_index_dense(V_contra,0,1,R, THETA, fixed_axes={'phi':0})
>>> V_co.shape
(10, 10, 3)
>>> np.allclose(V_co[...,0],R**2)
True
>>> np.allclose(V_co[...,1],np.ones_like(R))
True

It is also possible to provide the inverse metric immediately to avoid needing to compute it on the fly. This also allows us to get away without the coordinates.

>>> from pymetric.coordinates import SphericalCoordinateSystem
>>>
>>> # Build the coordinate system.
>>> u = SphericalCoordinateSystem()
>>>
>>> # Create the R,THETA grid.
>>> r = np.linspace(1e-3,1,10)
>>> theta = np.linspace(1e-3,np.pi-1e-3,10)
>>> R, THETA = np.meshgrid(r,theta)
>>>
>>> # Create the vector field.
>>> V_contra = np.stack([R**2,R**-2,np.zeros_like(R)],axis=-1)
>>>
>>> # Create the inverse metric tensor
>>> mt = np.stack([np.ones_like(R),R**2,R**2 * np.sin(THETA)],axis=-1)
>>>
>>> # Raise the index.
>>> V_co = u.raise_index_dense(V_contra,0,1, inverse_metric_field=mt, fixed_axes={'phi':0})
>>> V_co.shape
(10, 10, 3)
>>> np.allclose(V_co[...,0],R**2)
True
>>> np.allclose(V_co[...,1],np.ones_like(R))
True