pycsamt.inversion.mesh#

Mesh descriptions and builders for EM inversion workflows.

Functions

build_1d_tensor_mesh(start, options, ...)

Build a 1-D TensorMesh-like object and positive-downward centres.

build_3d_tensor_mesh(station_x, station_y, ...)

Build a 3-D TensorMesh-like object around station coordinates.

build_fd2d_grid(start, station_x, options, ...)

Build the finite-difference 2-D grid used by built-in inversion.

core_rho_from_start(start, nz, nx)

Expand a layered starting model into a 2-D core resistivity grid.

depth_widths(depth_max, n_cells[, options])

Return geometrically growing positive depth cell widths.

Classes

InversionMesh([dimension, x_centers, ...])

Lightweight mesh/grid descriptor.

class pycsamt.inversion.mesh.InversionMesh(dimension='1d', x_centers=None, z_centers=None, native=None, metadata=<factory>)[source]#

Bases: PyCSAMTObject, MetadataMixin

Lightweight mesh/grid descriptor.

InversionMesh is the common mesh metadata object carried by pycsamt.inversion.results.InversionResult. Numerical engines may keep their real discretization object in native while exposing common profile/depth centers through x_centers and z_centers.

Parameters:
  • dimension ({"1d", "2d", "3d"}, default "1d") – Mesh dimensionality represented by this descriptor.

  • x_centers (array-like of float, optional) – Horizontal/profile cell centers in metres. For 1-D meshes this is usually [0.0].

  • z_centers (array-like of float, optional) – Depth cell centers in metres, positive downward.

  • native (object, optional) – Backend-native mesh/grid object, for example a SimPEG TensorMesh or built-in forward Grid2D.

  • metadata (dict, optional) – Free-form mesh provenance such as builder name, backend engine, padding, or core-cell shape.

Examples

>>> from pycsamt.inversion.mesh import InversionMesh
>>> mesh = InversionMesh.for_1d([25.0, 125.0, 275.0])
>>> mesh.dimension
'1d'
>>> mesh.z_centers.tolist()
[25.0, 125.0, 275.0]

References

dimension: str = '1d'#
x_centers: Any = None#
z_centers: Any = None#
native: Any = None#
metadata: dict[str, Any]#
classmethod for_1d(depths)[source]#

Build a 1-D mesh descriptor from depth centres.

Parameters:

depths (array-like of float) – Positive-downward depth cell centers in metres.

Returns:

Descriptor with dimension="1d", x_centers=[0.0], and the supplied depth centers.

Return type:

InversionMesh

Examples

>>> from pycsamt.inversion.mesh import InversionMesh
>>> InversionMesh.for_1d([10.0, 30.0]).z_centers.tolist()
[10.0, 30.0]
validate()[source]#

Validate object state.

Subclasses can override this hook. The base implementation intentionally accepts all states.

Return type:

None

pycsamt.inversion.mesh.build_1d_tensor_mesh(start, options, tensor_mesh_cls)[source]#

Build a 1-D TensorMesh-like object and positive-downward centres.

This helper centralizes the depth discretization used by optional engines such as SimPEG. The caller supplies the actual TensorMesh class so this module stays free of optional dependencies.

Parameters:
  • start (object) – Starting model exposing n_layers, resistivities, and thicknesses.

  • options (dict, optional) – Mesh controls. Recognized keys include n_cells, depth_max, origin, min_cell_size, and growth_factor.

  • tensor_mesh_cls (type) – TensorMesh-like constructor accepting ([widths], origin=...).

Returns:

  • mesh (object) – Backend-native 1-D tensor mesh.

  • z_centers (ndarray) – Positive-downward depth cell centers in metres.

Return type:

tuple[Any, ndarray]

Examples

>>> import numpy as np
>>> from pycsamt.inversion.mesh import build_1d_tensor_mesh
>>> from pycsamt.inversion.model import StartingModel
>>> class TensorMesh:
...     def __init__(self, widths, origin="0"):
...         self.widths = widths
...         self.origin = origin
>>> start = StartingModel([100.0, 300.0], [500.0])
>>> mesh, z = build_1d_tensor_mesh(
...     start, {"n_cells": 2, "depth_max": 100.0, "growth_factor": 1.0}, TensorMesh
... )
>>> np.round(z, 1).tolist()
[25.0, 75.0]
pycsamt.inversion.mesh.build_3d_tensor_mesh(station_x, station_y, options, tensor_mesh_cls)[source]#

Build a 3-D TensorMesh-like object around station coordinates.

The helper constructs uniform horizontal cells around the station footprint and geometrically growing depth cells. It is used by optional 3-D physics paths while keeping the native mesh class injectable.

Parameters:
  • station_x (array-like of float) – Station coordinates in metres.

  • station_y (array-like of float) – Station coordinates in metres.

  • options (dict, optional) – Mesh controls. Recognized keys include x_pad, y_pad, depth_max, nx, ny, nz, min_cell_size, and growth_factor.

  • tensor_mesh_cls (type) – TensorMesh-like constructor accepting ([hx, hy, hz], origin=...).

Returns:

  • mesh (object) – Backend-native 3-D tensor mesh.

  • centers (dict of ndarray) – Cell-center arrays with keys "x", "y", "z", and "z_depth". z follows the native mesh coordinate with depth negative; z_depth is positive downward.

Return type:

tuple[Any, dict[str, ndarray]]

Examples

>>> from pycsamt.inversion.mesh import build_3d_tensor_mesh
>>> class TensorMesh:
...     def __init__(self, widths, origin=None):
...         self.widths = widths
...         self.origin = origin
>>> mesh, centers = build_3d_tensor_mesh(
...     [0.0, 100.0], [0.0, 50.0],
...     {"nx": 2, "ny": 2, "nz": 2, "depth_max": 100.0}, TensorMesh
... )
>>> sorted(centers)
['x', 'y', 'z', 'z_depth']
pycsamt.inversion.mesh.build_fd2d_grid(start, station_x, options, grid_cls, *, make_padding_func=None)[source]#

Build the finite-difference 2-D grid used by built-in inversion.

This builder creates the starting Grid2D-like object for the built-in finite-difference MT/AMT/CSAMT profile inversion. It shifts station coordinates into the grid coordinate system, adds optional lateral/depth padding, and expands the layered starting model into a 2-D resistivity array.

Parameters:
  • start (object) – Starting model exposing resistivities and thicknesses.

  • station_x (array-like of float) – Station positions along profile in metres. At least two distinct stations are required.

  • options (dict, optional) – Grid controls. Recognized keys include nx/fd2d_nx, n_pad/fd2d_n_pad, pad_factor, x_margin, x_max, and halfspace_thickness.

  • grid_cls (type) – Grid2D-like constructor accepting dx, dz, resistivity, x_stations, n_pad, and name.

  • make_padding_func (callable, optional) – Padding-width function. If omitted, pycsamt.forward.make_padding() is imported lazily.

Returns:

  • grid (object) – Built finite-difference grid.

  • core_shape (tuple of int) – (nz_core, nx_core) shape of the unpadded inversion core.

Return type:

tuple[Any, tuple[int, int]]

Examples

>>> from pycsamt.inversion.mesh import build_fd2d_grid
>>> from pycsamt.inversion.model import StartingModel
>>> class Grid:
...     def __init__(self, dx, dz, resistivity, x_stations, n_pad, name):
...         self.dx = dx
...         self.dz = dz
...         self.resistivity = resistivity
...         self.x_stations = x_stations
>>> start = StartingModel([100.0, 300.0], [500.0])
>>> grid, core_shape = build_fd2d_grid(
...     start, [0.0, 1000.0], {"nx": 2, "n_pad": 0}, Grid
... )
>>> core_shape
(2, 2)
pycsamt.inversion.mesh.core_rho_from_start(start, nz, nx)[source]#

Expand a layered starting model into a 2-D core resistivity grid.

Parameters:
  • start (object) – Starting model exposing resistivities.

  • nz (int) – Number of vertical and horizontal core cells.

  • nx (int) – Number of vertical and horizontal core cells.

Returns:

Resistivity grid with shape (nz, nx). If nz is larger than the number of supplied layers, the final layer resistivity is repeated.

Return type:

ndarray

Examples

>>> from pycsamt.inversion.mesh import core_rho_from_start
>>> from pycsamt.inversion.model import StartingModel
>>> start = StartingModel([100.0, 300.0], [500.0])
>>> core_rho_from_start(start, 3, 2).tolist()
[[100.0, 100.0], [300.0, 300.0], [300.0, 300.0]]
pycsamt.inversion.mesh.depth_widths(depth_max, n_cells, options=None)[source]#

Return geometrically growing positive depth cell widths.

Parameters:
  • depth_max (float) – Total target depth in metres. The returned widths sum to this value.

  • n_cells (int) – Number of depth cells.

  • options (dict, optional) – Mesh options. Recognized keys are min_cell_size and growth_factor. Defaults are chosen conservatively from depth_max and n_cells.

Returns:

Positive cell widths in metres.

Return type:

ndarray

Raises:

ValueError – If depth_max, n_cells, min_cell_size, or growth_factor are not positive.

Examples

>>> from pycsamt.inversion.mesh import depth_widths
>>> depth_widths(100.0, 4, {"growth_factor": 1.0}).round(2).tolist()
[25.0, 25.0, 25.0, 25.0]

References