coordinates.mixins.mathops.CoordinateSystemMathMixin.lower_index_dense#
- CoordinateSystemMathMixin.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 [source]#
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)
, whereN == 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:
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