fields.mixins.dense_mathops.DenseTensorFieldDMOMixin.contract_with_metric#

DenseTensorFieldDMOMixin.contract_with_metric(index: int, mode: str = 'lower', out: _Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str] | None = None, metric_field: _Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str] | None = None, *, output_axes: Sequence[str] | None = None, as_array: bool = False, buffer_class: Type[BufferBase] | None = None, buffer_registry: BufferRegistry | None = None, buffer_args: Sequence[Any] | None = None, buffer_kwargs: Dict | None = None, **kwargs)[source]#

Contract this tensor field with the metric or inverse metric tensor.

This method raises or lowers a single index of the field by contracting it with either the metric \(g_{\mu\nu}\) or its inverse \(g^{\mu\nu}\), depending on the selected mode. The contraction modifies one of the field’s trailing tensor slots, changing its variance (covariant or contravariant).

Hint

This method wraps the grid-level dense_contract_with_metric(), which wraps the low-level dense_contract_with_metric().

Parameters:
  • index (int) –

    The tensor slot (i.e., axis in the field’s trailing element shape) to operate on.

    This refers to the position among the field’s value axes, not its spatial grid axes. For example, in a rank-2 tensor field with shape (Nx, Ny, 3, 3), index=0 contracts the first value index (e.g., the row), while index=1 contracts the second (e.g., the column).

  • mode ({'raise', 'lower'}, optional) –

    Whether to raise or lower the index being operated on. This determines which metric is used in the contraction and (therefore) which metric field is expected if manually supplied by metric_field.

    By default, mode='lower'.

  • 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.

  • metric_field (array-like, optional) –

    Override metric to use for the contraction:

    • For mode='raise' this must be the inverse metric \(g^{\mu\nu}\).

    • For mode='lower' this must be the metric \(g_{\mu\nu}\).

    The field can be rank-2 (full) or rank-1 (diagonal); if not supplied it is generated chunk-by-chunk (or once globally) from the coordinate system. See Notes for more details on the shape requirements.

  • output_axes (list of str, optional) –

    The axes of the coordinate system over which the result should span. By default, the dependence is calculated internally.

    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 axes of the calling field.

  • **kwargs – Additional keyword arguments passed to the low-level operation dense_contract_with_metric().

  • 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.

  • 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().

  • as_array (bool, optional) – If True, then no post-processing occurs and an array is returned.

  • buffer_class (type, optional) –

    Class to use when wrapping the result buffer, e.g., fields.buffers.core.ArrayBuffer or fields.buffers.core.UnytArrayBuffer.

    Defaults to buffer resolution to determine a fitting buffer for the resulting array result.

  • buffer_registry (BufferRegistry, optional) – Optional registry to use when resolving the buffer class. This is eventually passed on to fields.buffers.base.buffer_from_array().

  • buffer_args (optional) – arguments to pass to fields.buffers.base.buffer_from_array().

  • buffer_kwargs (optional) – arguments to pass to fields.buffers.base.buffer_from_array().

Returns:

The result of contracting one index of the tensor field with the metric or inverse metric.

  • If as_array=False (default), returns a new DenseField instance with the specified slot adjusted (lowered or raised).

  • If as_array=True, returns a raw NumPy array with shape:

    (grid_shape over output_axes, ..., element_shape)
    

where element_shape reflects the adjusted tensor signature after contraction.

Return type:

DenseTensorField or numpy.ndarray

Notes

Contraction Behavior

This operation modifies the variance of a single tensor index by contracting it with either the metric \(g_{\mu\nu}\) or its inverse \(g^{\mu\nu}\). The result has the same rank but with the specified slot changed from covariant to contravariant or vice versa.

Index Semantics

The index parameter refers to the position within the field’s element shape. For example, a rank-2 tensor field with shape (Nx, Ny, 3, 3) uses index=0 for the first component axis and index=1 for the second.

Metric Field Requirements

The shape of metric_field depends on the metric type:

  • Diagonal metric (orthogonal coordinates): (*spatial_shape, ndim)

  • Full metric (non-orthogonal): (*spatial_shape, ndim, ndim)

If not supplied, the appropriate metric is computed automatically from the coordinate system (either once globally or per chunk).

Chunking Behavior

If in_chunks=True, the operation is performed chunk-by-chunk across the grid. This is particularly helpful when working with large, memory-mapped, or HDF5-backed fields.

Each chunk is evaluated with a 1-cell halo to preserve accuracy during intermediate gradient computations.

Backend Buffer Customization

If as_array=False, the result is wrapped in a new DenseField. You may control the buffer backend (NumPy, Unyt, HDF5, etc.) using buffer_class, buffer_registry, buffer_args, and buffer_kwargs.

If as_array=True, these options are ignored and a raw NumPy array is returned.