pycsamt.forward.grid2d#
2-D resistivity grid for MT forward modelling.
The Grid2D dataclass is the central data object shared by the 2-D
MT forward solver and any downstream processing that needs the subsurface
resistivity structure. It stores the model as a regular (but non-uniform)
finite-difference grid together with station positions and padding metadata.
Coordinate convention#
x — horizontal distance along the profile [m], increasing to the right.
z — depth below surface [m], increasing downward.
Cell (i, j) has its top-left corner at
(x_nodes[j], z_nodes[i])where i is the row index (depth) and j is the column index (x).resistivity[i, j]is the resistivity of cell (i, j) [Ω·m].
Grid layout (nx = 4, nz = 3, no padding shown):
x_nodes: 0 dx[0] dx[0]+dx[1] …
┌────┬────┬────┬────┐
z_nodes[0] │(0,0)│(0,1)│(0,2)│(0,3)│ ← row 0 (shallowest)
├────┼────┼────┼────┤
z_nodes[1] │(1,0)│(1,1)│(1,2)│(1,3)│
├────┼────┼────┼────┤
z_nodes[2] │(2,0)│(2,1)│(2,2)│(2,3)│ ← row nz-1 (deepest)
└────┴────┴────┴────┘
Padding#
The FD solver requires padding cells on both horizontal sides and at the bottom to push the Dirichlet boundaries far enough from the model region that edge effects are negligible. Padding cells are constructed with exponentially growing widths/depths. The resistivity in padding cells is copied from the nearest edge column (horizontal) or deepest row (vertical).
The n_pad attribute records how many padding cells were added on
each side so that station positions and visualisation can clip to the
core region (core_slice).
References
Wannamaker, P.E., Stodt, J.A., Rijo, L. (1987). A stable finite element solution for two-dimensional magnetotelluric modelling. Geophys. J. Int., 88(1), 277-296.
de Groot-Hedlin, C., Constable, S. (1990). Occam’s inversion to generate smooth, two-dimensional models from magnetotelluric data. Geophysics, 55(12), 1613-1624.
Functions
|
Return cell widths for one padding strip. |
Classes
|
Non-uniform 2-D finite-difference grid for MT forward modelling. |
- class pycsamt.forward.grid2d.Grid2D(dx, dz, resistivity, x_stations, n_pad=0, name='')[source]#
Bases:
objectNon-uniform 2-D finite-difference grid for MT forward modelling.
- Parameters:
dx (array-like, shape (nx,)) – Cell widths in the horizontal (x) direction [m].
dz (array-like, shape (nz,)) – Cell heights in the vertical (z, depth) direction [m].
resistivity (array-like, shape (nz, nx)) – Cell resistivities [Ω·m], top-to-bottom, left-to-right.
x_stations (array-like, shape (n_stations,)) – Horizontal positions of MT stations [m]. Must lie within
[x_nodes[0], x_nodes[-1]].n_pad (int) – Number of padding cells on each side (left, right) and at the bottom that were added during construction. Used internally to identify the core model region. Set to 0 if no padding is present.
name (str) – Optional label for the model.
- Variables:
nx (int) – Total number of cells in x (includes padding).
nz (int) – Total number of cells in z (includes padding).
x_nodes (ndarray, shape (nx+1,)) – x-coordinates of vertical node lines [m].
z_nodes (ndarray, shape (nz+1,)) – z-coordinates of horizontal node lines (depth) [m].
x_centers (ndarray, shape (nx,)) – x-coordinates of cell centres [m].
z_centers (ndarray, shape (nz,)) – z-coordinates (depth) of cell centres [m].
core_x_slice (slice) – Slice that selects core (non-padding) columns from any
[:, j]array.core_z_slice (slice) – Slice that selects core (non-padding) rows from any
[i, :]array.
Examples
Uniform halfspace:
>>> g = Grid2D.halfspace(rho=100.0, nx=30, nz=20, ... x_max=5_000.0, z_max=3_000.0, ... n_stations=10, station_x_max=4_000.0) >>> g.resistivity.shape (20, 30)
One conductive anomaly:
>>> g = Grid2D.with_anomaly( ... bg_rho=500.0, ... anomaly_rho=5.0, ... anomaly_bounds=(1_000.0, 3_000.0, 200.0, 800.0), ... nx=40, nz=25, ... x_max=6_000.0, z_max=4_000.0, ... n_stations=12, ... )
1-D layered model extended horizontally:
>>> from pycsamt.forward.synthetic import LayeredModel >>> m = LayeredModel([100, 10, 500], [300, 800]) >>> g = Grid2D.from_1d_layers(m, nx=40, x_max=6_000.0, n_stations=12)
- property core_resistivity: ndarray[source]#
Resistivity array clipped to the core (non-padding) region.
- column_profile(col)[source]#
Return the 1-D resistivity/thickness profile of column col.
Used by the FD solver to compute Dirichlet boundary conditions at the left and right edges from the 1-D MT response of the edge columns.
- station_cell_indices()[source]#
Return the column index of the cell that contains each station.
- Returns:
indices
- Return type:
ndarray of int, shape (n_stations,)
- station_node_indices()[source]#
Return the index of the nearest surface node for each station.
Surface nodes are at
z = 0and numbered0, 1, …, nx.- Returns:
indices
- Return type:
ndarray of int, shape (n_stations,)
- harmonic_mean_x()[source]#
Harmonic-mean conductivity at x-directed cell interfaces.
Used by the TM-mode FD assembler.
- plot(ax=None, *, log_scale=True, cmap='jet_r', clip_core=True, show_stations=True, figsize=(10, 5), vmin=None, vmax=None)[source]#
Plot the 2-D resistivity model.
- Parameters:
ax (Axes or None) – Target axes. Created when not given.
log_scale (bool) – Plot log₁₀(ρ) rather than ρ.
cmap (str) – Matplotlib colormap name.
clip_core (bool) – Clip to the non-padding core region.
show_stations (bool) – Mark station positions on the surface.
figsize ((float, float)) – Figure size when ax is not provided.
vmin (float or None) – Colormap limits in log₁₀(Ω·m) space when log_scale is True.
vmax (float or None) – Colormap limits in log₁₀(Ω·m) space when log_scale is True.
- Returns:
ax
- Return type:
Axes
- classmethod halfspace(rho=100.0, *, nx=40, nz=30, x_max=10000.0, z_max=5000.0, n_pad=8, pad_factor=1.3, n_stations=10, station_x_max=None, name='halfspace')[source]#
Create a uniform resistivity halfspace grid.
- Parameters:
rho (float) – Background resistivity [Ω·m].
nx (int) – Number of core cells in x (padding added on both sides).
nz (int) – Number of core cells in z (padding added at the bottom).
x_max (float) – Total horizontal extent of the core region [m].
z_max (float) – Total depth of the core region [m].
n_pad (int) – Number of padding cells on each side (left, right, bottom).
pad_factor (float) – Exponential growth factor for padding cell sizes.
n_stations (int) – Number of equally spaced stations across the core region.
station_x_max (float or None) – Right-most station position [m]. Defaults to
x_max.name (str) – Label for the model.
- Return type:
- classmethod from_1d_layers(model, *, nx=40, x_max=10000.0, n_pad=8, pad_factor=1.3, n_stations=10, station_x_max=None, dz_min=10.0, name='')[source]#
Build a 2-D grid by extending a 1-D
LayeredModel.Every column has the same 1-D layer stack. This is useful as a background model for synthetic anomaly tests and inversion starting models.
- Parameters:
model (LayeredModel) – Source 1-D model.
model.thicknessdefines the cell thicknesses; the deepest cell becomes the halfspace.nx (int) – Number of core cells in x.
x_max (float) – Horizontal extent of the core region [m].
n_pad (int) – Padding cells on each side.
pad_factor (float) – Padding growth factor.
n_stations (int) – Number of equally spaced surface stations.
station_x_max (float or None) – Right-most station x [m].
dz_min (float) – Minimum cell height [m]; avoids excessively thin cells at depth.
name (str) – Model label.
- Return type:
- classmethod with_anomaly(bg_rho=100.0, anomaly_rho=5.0, anomaly_bounds=(2000.0, 4000.0, 200.0, 800.0), *, nx=50, nz=35, x_max=8000.0, z_max=4000.0, n_pad=8, pad_factor=1.3, n_stations=12, station_x_max=None, name='')[source]#
Create a background halfspace with one rectangular anomaly.
- Parameters:
bg_rho (float) – Background resistivity [Ω·m].
anomaly_rho (float) – Anomaly resistivity [Ω·m].
anomaly_bounds ((x_lo, x_hi, z_lo, z_hi)) – Anomaly extent in core coordinates [m]: horizontal from x_lo to x_hi, depth from z_lo to z_hi.
nx (int) – Core cell counts.
nz (int) – Core cell counts.
x_max (float) – Core region extents [m].
z_max (float) – Core region extents [m].
n_pad (int) – Padding cells per side.
pad_factor (float) – Padding growth factor.
n_stations (int) – Number of equally spaced surface stations.
station_x_max (float or None) – Right-most station x [m].
name (str) – Model label.
- Return type:
Examples
Resistive body at mid-depth:
>>> g = Grid2D.with_anomaly( ... bg_rho=50.0, anomaly_rho=2000.0, ... anomaly_bounds=(2000.0, 4000.0, 500.0, 1500.0), ... )
- classmethod random(*, nx=40, nz=30, x_max=8000.0, z_max=4000.0, n_pad=8, pad_factor=1.3, n_stations=10, rho_min=1.0, rho_max=10000.0, n_layers=4, lateral_variation=True, seed=None, name='random')[source]#
Generate a random layered model with optional lateral variation.
Resistivities for
n_layershorizontal layers are drawn from a log-uniform prior. When lateral_variation isTrue, each column’s resistivity is perturbed by ±30 % in log₁₀ space.- Parameters:
nx (int) – Core cell counts.
nz (int) – Core cell counts.
x_max (float) – Core extents [m].
z_max (float) – Core extents [m].
n_pad (int) – Padding cells per side.
rho_min (float) – Resistivity bounds [Ω·m].
rho_max (float) – Resistivity bounds [Ω·m].
n_layers (int) – Number of horizontal layers.
lateral_variation (bool) – Add column-wise log-normal perturbation.
seed (int or Generator or None)
name (str)
pad_factor (float)
n_stations (int)
- Return type:
- pycsamt.forward.grid2d.make_padding(core_spacing, n_pad, factor=1.3)[source]#
Return cell widths for one padding strip.
The first padding cell has width
core_spacing * factorand each subsequent cell isfactortimes wider.- Parameters:
- Returns:
Cell widths ordered from the core edge outward.
- Return type:
numpy.ndarray, shape (n_pad,)