geopulse.earth
Earth conductivity models and the surface-impedance abstraction.
Every EarthModel produces an
Impedance object. The
efield module calls impedance.apply(Bx_f, By_f) and never
branches on model dimensionality — polymorphism is the whole point.
- class geopulse.earth.CoastalCorrection2D(land_model, ocean_model, distance_from_coast_m, tm_decay_ratio=0.7)[source]
Bases:
EarthModelSemi-analytic coast-effect 2-D Earth model.
Interpolates between two 1-D reference models (land and ocean) via a tanh-shaped coupling function of distance from the coast, producing a
TensorImpedanceat each frequency.- Parameters:
land_model (
Layered1D) – Layered 1-D model for the land side (well inland). Provides the far-fieldd → +∞asymptote.ocean_model (
Layered1D) – Layered 1-D model for the ocean side (well offshore). Typically a thin high-conductivity seawater layer over the same deep conductivity structure. Provides thed → −∞asymptote.distance_from_coast_m (
float) – Distance of the observation site from the coastline, in metres. Positive inland, negative seaward.0sits exactly at the coast.tm_decay_ratio (
float) – Ratio of TM to TE decay lengthL_TM / L_TE. Smaller → TM transitions more sharply than TE. Default 0.7 matches the Boteler-Pirjola (1998) observation that TM is more perturbed than TE near the interface.
Notes
tier == 2. Coordinate frame: coast alongy(east);x(north) points inland. The tensor is anti-diagonal.Examples
>>> import numpy as np >>> from geopulse.earth.base import ConductivityLayer >>> from geopulse.earth.layered_1d import Layered1D >>> land = Layered1D([ConductivityLayer(np.inf, 0.001)]) >>> ocean = Layered1D([ ... ConductivityLayer(1_000.0, 3.3), ... ConductivityLayer(np.inf, 0.001), ... ]) >>> coast = CoastalCorrection2D(land, ocean, distance_from_coast_m=0.0) >>> imp = coast.compute_impedance(np.array([1e-3, 1e-2, 1e-1])) >>> imp.rank 2
- class geopulse.earth.ConductivityLayer(thickness_m, conductivity_Sm)[source]
Bases:
objectA single layer in a 1-D conductivity model.
- thickness_m
Layer thickness in meters. Use
numpy.inffor the terminating half-space (bottom layer).- Type:
Notes
Resistivity
ρ = 1/σis NOT stored — compute it when needed to avoid redundancy and potential inconsistency.- Raises:
ValueError – If
conductivity_Smis non-positive, orthickness_mis non-positive and not infinite.- Parameters:
- class geopulse.earth.EarthModel[source]
Bases:
ABCAbstract base class for Earth conductivity models.
Subclasses represent different spatial complexity:
Layered1D— horizontally layered half-space (Wait recursion).Structured2D— 2-D cross-section (finite-difference).Unstructured3D— full volumetric (ModEM / SimPEG wrapper).
All produce an
Impedanceobject viacompute_impedance().- abstractmethod compute_impedance(freqs_Hz)[source]
Compute the surface impedance at the given frequencies.
- classmethod from_library(name)[source]
Load a named model from the built-in library.
- Parameters:
name (
str) – Model name. Seegeopulse.earth.library.list_models()for the registry.- Return type:
- Returns:
EarthModel – The requested model.
- Raises:
KeyError – If
nameis not registered.
- class geopulse.earth.Impedance(freqs_Hz)[source]
Bases:
ABCAbstract base class for surface impedance.
- Parameters:
freqs_Hz (
ndarray) – Frequency array in Hz. Cast internally tofloat64. Shape:(n_freqs,).
- freqs_Hz
The stored frequency array.
- Type:
- abstractmethod apply(Bx_f, By_f)[source]
Apply the impedance to frequency-domain B-field, returning E-field.
- Parameters:
- Return type:
- Returns:
Ex_f (numpy.ndarray) – FFT of
Exin V/m. Shape matches subclass semantics.Ey_f (numpy.ndarray) – FFT of
Eyin V/m. Shape matches subclass semantics.
- abstract property rank: int
0 for scalar (1-D), 2 for tensor (2-D), 4 for kernel (3-D).
- Type:
Rank marker
- class geopulse.earth.ScalarImpedance(freqs_Hz, Z_values)[source]
Bases:
Impedance1-D scalar impedance
Z(ω).For a horizontally layered Earth under plane-wave excitation, the surface impedance is a single complex number per frequency. This is the standard magnetotelluric relation for the 1-D case.
- Parameters:
- Raises:
ShapeMismatchError – If
Z_values.shapedoes not equalfreqs_Hz.shape.
Notes
The applied relation is [1]_:
E_x(ω) = (Z(ω) / μ₀) · B_y(ω) E_y(ω) = -(Z(ω) / μ₀) · B_x(ω)
Examples
>>> import numpy as np >>> freqs = np.array([1e-3, 1e-2, 1e-1]) >>> Z = np.array([1+1j, 3+3j, 10+10j]) >>> imp = ScalarImpedance(freqs, Z) >>> Ex, Ey = imp.apply(np.ones(3), np.ones(3)) >>> Ex.shape (3,)
- apply(Bx_f, By_f)[source]
Apply the 1-D plane-wave MT relation
E = (Z/μ₀) · B_perp.- Parameters:
- Return type:
- Returns:
Ex_f, Ey_f (numpy.ndarray) – FFT of the horizontal E-field components in V/m. Shape:
(n_freqs,).- Raises:
ShapeMismatchError – If
Bx_forBy_fdo not have the same length asfreqs_Hz.
- to_hdf5(group)[source]
Serialise to an HDF5 group with a schema-version attribute.
Layout:
group/ attrs: impedance_type = "scalar_1d" schema_version = 1 freqs_Hz dataset Z_values dataset (complex128)
- Return type:
- Parameters:
group (Group)
- classmethod from_hdf5(group)[source]
Read a
ScalarImpedancefrom an HDF5 group.- Return type:
- Parameters:
group (Group)
- class geopulse.earth.TensorImpedance(freqs_Hz, Z_tensor)[source]
Bases:
Impedance2-D magnetotelluric impedance tensor
Z̃(ω)— 2×2 per frequency.Applied relation (per frequency
ω_i):Ex(ω_i) = (Z[i,0,0] · Bx(ω_i) + Z[i,0,1] · By(ω_i)) / μ₀ Ey(ω_i) = (Z[i,1,0] · Bx(ω_i) + Z[i,1,1] · By(ω_i)) / μ₀
Shape convention:
Z_tensor[i, :, :]is the 2×2 tensor atfreqs_Hz[i]. A 1-D isotropic Earth is the special caseZ_tensor[i] = [[0, Z], [-Z, 0]].- Parameters:
- Raises:
ShapeMismatchError – If
Z_tensor.shapedoes not equal(n_freqs, 2, 2).
- apply(Bx_f, By_f)[source]
Apply the 2×2 tensor relation
E(ω) = Z̃(ω) · B(ω) / μ₀.- Parameters:
- Return type:
- Returns:
Ex_f, Ey_f (numpy.ndarray) – FFT of horizontal E-field components in V/m. Shape
(n_freqs,).- Raises:
ShapeMismatchError – If either input does not match
freqs_Hzin shape.
- to_hdf5(group)[source]
Serialise to an HDF5 group with a schema-version attribute.
Layout:
group/ attrs: impedance_type = "tensor_2d" schema_version = 1 freqs_Hz dataset Z_tensor dataset (complex128, shape (n_freq, 2, 2))
- Return type:
- Parameters:
group (Group)
- classmethod from_hdf5(group)[source]
Read a
TensorImpedancefrom an HDF5 group.- Return type:
- Parameters:
group (Group)
- class geopulse.earth.KernelImpedance(freqs_Hz, Z_kernel)[source]
Bases:
Impedance3-D volumetric-response kernel
Z̃(r, r', ω)— STUB (WP3).Shape convention:
(n_freqs, n_r, n_r, 2, 2). In practice the kernel will be sparse or block-structured and use chunked HDF5 storage.- Parameters:
freqs_Hz (np.ndarray)
Z_kernel (np.ndarray)
Modules
Abstract base class for Earth conductivity models. |
|
Surface-impedance abstraction — the polymorphism spine of GeoPulse. |
|
1-D layered-Earth surface impedance via Wait (1954) recursion. |
|
Built-in 1-D Earth-model registry. |
|
2-D structured Earth models. |
|
3-D unstructured Earth model (ModEM / SimPEG wrapper) — STUB (WP3). |