grids.mixins.mathops.DenseMathOpsMixin.dense_vector_divergence_covariant#

DenseMathOpsMixin.dense_vector_divergence_covariant(vector_field: _Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str], field_axes: Sequence[str], /, out: _Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str] | None = None, Dterm_field: _Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str] | None = None, inverse_metric_field: _Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str] | None = None, *, in_chunks: bool = False, edge_order: Literal[1, 2] = 2, output_axes: Sequence[str] | None = None, pbar: bool = True, pbar_kwargs: dict | None = None, **kwargs)[source]#

Compute the divergence of a covariant vector field on a grid.

For a covariant vector field \(V_\mu\), the divergence is:

\[\nabla \cdot V = \frac{1}{\rho} \partial_\mu(\rho g^{\mu\nu} V_\nu)\]

Expanded for numerical stability:

\[\nabla \cdot V = g^{\mu\nu} V_\nu \frac{\partial_\mu \rho}{\rho} + \partial_\mu(g^{\mu\nu} V_\nu)\]

This form is used internally, with precomputed or on-the-fly inverse metrics.

Parameters:
  • vector_field (array-like) – The vector field on which to compute the divergence. This should be an array-like object with a compliant shape (see Notes below).

  • field_axes (list of str) – The coordinate axes over which the field spans. This should be a sequence of strings referring to the various coordinates of the underlying coordinate_system of the grid. For each element in field_axes, field’s i-th index should match the shape of the grid for that coordinate. (See Notes for more details).

  • out (array-like, optional) – An optional buffer in which to store the result. This can be used to reduce memory usage when performing computations. The shape of out must be compliant with broadcasting rules (see Notes). out may be a buffer or any other array-like object.

  • Dterm_field (array-like, optional) – The D-term field for the specific coordinate system. This can be specified to improve computation speed; however, it can also be derived directly from the grid’s coordinate system. If it is provided, it should be compliant with the shaping / broadcasting rules (see Notes).

  • inverse_metric_field (array-like, optional) –

    A buffer containing the inverse metric field \(g^{\mu\nu}\). inverse_metric_field can be provided to improve computation speed (by avoiding computing it in stride); however, it is not required.

    The inverse metric can be derived from the coordinate system when this argument is not provided. See Notes below for details on the shape of inverse_metric_field.

  • output_axes (list of str, optional) –

    The axes of the coordinate system over which the result should span. By default, output_axes is the same as field_axes and the output field matches the span of the input field.

    This argument may be specified to expand the number of axes onto which the output field is computed. output_axes must be a superset of the field_axes.

  • in_chunks (bool, optional) – Whether to perform the computation in chunks. This can help reduce memory usage during the operation but will increase runtime due to increased computational load. If input buffers are all fully-loaded into memory, chunked performance will only marginally improve; however, if buffers are lazy loaded, then chunked operations will significantly improve efficiency. Defaults to False.

  • edge_order ({1, 2}, optional) – Order of the finite difference scheme to use when computing derivatives. See numpy.gradient() for more details on this argument. Defaults to 2.

  • pbar (bool, optional) – Whether to display a progress bar when in_chunks=True.

  • pbar_kwargs (dict, optional) – Additional keyword arguments passed to the progress bar utility. These can be any valid arguments to tqdm.tqdm().

  • **kwargs – Additional keyword arguments passed to dense_vector_divergence_contravariant().

Returns:

Scalar divergence on the grid. The shape equals the broadcasted grid shape over output_axes (ghost zones included when the grid carries them).

Return type:

array‑like

Notes

Broadcasting & shapes

If the full grid (including ghosts) has shape grid_shape = (G1, …, G_ndim), then

  • vector_field[..., k] must match grid_shape[field_axes[k]].

  • out must match grid_shape[output_axes].

  • Dterm_field and inverse_metric_field (when supplied) must be broadcast‑compatible with the same grid shape.

Chunking semantics

When in_chunks=True the routine iterates over the grid’s stored chunks, fetching or generating the necessary D‑terms and inverse metric on each sub‑domain. A one‑cell halo is automatically included to maintain gradient accuracy, and progress is reported through tqdm.

Inverse Metric:

In most cases, the inverse metric is computed by the coordinate system behind the scenes; however, it may be provided directly in cases where doing so is convenient. If this is done, the provided field must have a spatial portion corresponding to the grid’s shape (including ghost zones) over the output axes. Depending on the coordinate system, the provided metric may either be a rank-2 array (non-orthogonal coordinate systems) or a rank-1 array (orthogonal coordinate systems) in which each element corresponds to the diagonal element. The correct low-level callable is determined based on the coordinate system’s type.

Examples

Divergence of a covariant field in 2‑D cylindrical coordinates ((r, z)):

>>> from pymetric.grids.core import UniformGrid
>>> from pymetric.coordinates import CylindricalCoordinateSystem
>>> import numpy as np
>>>
>>> # Coordinate system & grid
>>> cs = CylindricalCoordinateSystem()       # (r, φ, z) – φ suppressed
>>> grid = UniformGrid(cs,
...     [[0,0,0],[1,2*np.pi,1]],
...     [400, 10, 200],ghost_zones=1,center='cell')
>>>
>>> # Covariant vector: V_r = r, V_z = z
>>> R, Z = grid.compute_domain_mesh(origin='global', axes=['rho', 'z'])
>>> Vcov = np.stack([R,np.zeros_like(R), Z], axis=-1)
>>>
>>> # Divergence (automatic metric & D‑term)
>>> div = grid.dense_vector_divergence_covariant(
...     Vcov, ['rho', 'z'])
>>> div.shape
(402, 202)
>>> bool(np.isclose(div.mean(),3.0))   # → analytical result for this field is constant 3
True