differential_geometry.dense_ops.dense_vector_divergence_contravariant#
- differential_geometry.dense_ops.dense_vector_divergence_contravariant(vector_field: ndarray, Dterm_field: ndarray, *varargs, derivative_field: ndarray | None = None, field_axes: Sequence[int] | None = None, derivative_axes: Sequence[int] | None = None, edge_order: Literal[1, 2] = 2, out: ndarray | None = None, **_) ndarray [source]#
Compute the divergence of a contravariant vector field in a general coordinate system using the D-terms and raw partial derivatives.
This implements the formula:
\[\nabla_i V^i = D_i V^i + \partial_i V^i\]where \(D_i = (\partial_i \rho) / \rho\) is the logarithmic derivative of the coordinate density.
- Parameters:
vector_field (
numpy.ndarray
) – Contravariant vector field with shape(F_1, ..., F_M, ndim)
, where the final axis corresponds to coordinate directions. The firstm
axes are spatial grid axes. Must be broadcast-compatible with Dterm_field.Dterm_field (
numpy.ndarray
) – D-term array of shape(..., ndim)
, where the last axis matches the number of coordinate directions. Must broadcast with the spatial axes of vector_field.*varargs –
Grid spacing for each axis. Follows the same format as
numpy.gradient()
, and can be:A single scalar (applied to all spatial axes),
A list of scalars (one per axis),
A list of coordinate arrays (one per axis),
A mix of scalars and arrays (broadcast-compatible).
If derivative_axes is provided, then varargs must match its shape. Otherwise, there must be
m
elements in varargs.derivative_field (
numpy.ndarray
, optional) – Optional array of precomputed partial derivatives of selected vector components. Must have shape broadcast-compatible with the spatial shape of vector_field, and a final axis indexing the selected derivative components (same length as derivative_axes).field_axes (
list
ofint
, optional) – Maps each grid axis (0 tom-1
) to a corresponding component index in the vector field. Defaults to identity mapping[0, 1, ..., m-1]
.derivative_axes (
list
ofint
, optional) – Grid axes along which to compute partial derivatives. If not specified, all spatial axes listed in field_axes are used.edge_order (
{1, 2}
, default2
) – Accuracy order of finite differences used in derivative computation.out (
numpy.ndarray
, optional) – Optional output buffer for storing the result. Must have shape equal to the broadcast of the grid (non-component) dimensions of vector_field and Dterm_field.
- Returns:
A scalar field representing the divergence, with shape equal to the broadcasted grid shape of vector_field and Dterm_field (excluding the final component axis).
- Return type:
- Raises:
ValueError – If axes length does not match the spatial rank of the input.
Examples
In the most basic case, we only need to supply the D-field and the vector field.
>>> import numpy as np >>> >>> # Build a field. >>> x,y = np.linspace(-1,1,5),np.linspace(-1,1,5) >>> X,Y = np.meshgrid(x,y,indexing='ij') >>> V = np.stack([np.ones_like(X),Y],axis=-1) >>> >>> # Create cartesian Dfield. >>> D = np.zeros_like(V) >>> >>> # Compute the divergence. >>> DivV = dense_vector_divergence_contravariant(V,D,x,y) >>> np.all(DivV == 1.0) True
In some cases, the D term and the vector field might only be broadcastable. This is perfectly fine, but the fields must be broadcastable already! For example, this will fail:
>>> import numpy as np >>> >>> # Build a field. >>> x,y = np.linspace(-1,1,6),np.linspace(-1,1,5) >>> X,Y = np.meshgrid(x,y,indexing='ij') >>> V = np.stack([np.ones_like(y),y],axis=-1) >>> V.shape (5, 2) >>> >>> # Create cartesian Dfield. >>> D = np.zeros(x.shape + (2,)) >>> >>> # Compute the divergence. >>> DivV = dense_vector_divergence_contravariant(V,D,x,y) ValueError: shape mismatch: objects cannot be broadcast to a single shape. Mismatch is between arg 0 with shape (5,) and arg 1 with shape (6,).
This will succeed:
>>> import numpy as np >>> >>> # Build a field. >>> x,y = np.linspace(-1,1,6),np.linspace(-1,1,5) >>> X,Y = np.meshgrid(x,y,indexing='ij') >>> V = np.stack([np.ones_like(y),y],axis=-1)[None,:,:] >>> V.shape (1, 5, 2) >>> >>> # Create cartesian Dfield. >>> D = np.zeros(x.shape + (2,))[:,None,:] >>> D.shape (6, 1, 2) >>> >>> # Compute the divergence. >>> DivV = dense_vector_divergence_contravariant(V,D,y,derivative_axes=[1]) >>> np.all(DivV == 1.0) True
The
derivative_axes=[1]
tellsdense_vector_divergence_contravariant()
not to compute a derivative over the x axis (its singleton).