geopulse.network.pipeline

Pipeline network via Distributed-Source Transmission-Line (DSTL) theory.

A buried pipeline of length L is modelled as a transmission line with:

  • longitudinal series impedance z (Ω/m) — the pipeline steel + coating return path,

  • transverse shunt admittance y (S/m) — leakage to soil through the coating,

  • a distributed source term equal to the longitudinal geoelectric field E (V/m) acting along the pipe.

Following Boteler & Cookson (1986) and Boteler (1997), the pipeline is discretised into segments of length Δl and each segment is replaced by its equivalent-π two-port:

        Z_ser
i o---/\/\/\----o j
  |            |
  Y_sh        Y_sh
  |            |
 gnd          gnd

with

\[\begin{split}Z_\mathrm{ser}(\Delta\ell) &= Z_0 \sinh(\gamma \Delta\ell), \\ Y_\mathrm{sh}(\Delta\ell) &= \tanh(\gamma \Delta\ell / 2) / Z_0, \\ \gamma &= \sqrt{z y}, \\ Z_0 &= \sqrt{z / y}.\end{split}\]

In the small-segment limit γ·Δℓ 0 this collapses to the distributed-parameter model (Z_ser zΔℓ, Y_sh yΔℓ/2). Each segment is emitted as a single Branch with resistance Real(Z_ser) between end nodes, and shunt admittances are summed onto earthing_impedance_Ohm. LPMSolver then solves the whole thing as a standard LP network.

Insulated (open-circuit) ends are the default: the pipeline endpoints carry only their half-segment shunt admittance, so ends are grounded through the coating alone.

Closed-form validation

For a straight pipeline of length L, uniform longitudinal field E, and insulated ends, the pipe-to-soil voltage is

\[V(x) = \frac{E}{\gamma}\,\frac{\sinh(\gamma(x - L/2))}{\cosh(\gamma L / 2)}, \qquad x \in [0, L].\]

Peak \(|V|\) sits at the ends and equals \((E/\gamma)\tanh(\gamma L / 2)\). pipe_to_soil_voltage_analytic() returns this profile; PipelineNetwork solved via LPMSolver reproduces it to better than 1 % once n_segments is a few tens.

References

Functions

pipe_to_soil_voltage_analytic(E_Vm, ...)

Closed-form pipe-to-soil voltage for a uniform longitudinal E-field.

Classes

PipelineNetwork(params)

Straight buried pipeline modelled by equivalent-π DSTL segments.

PipelineParameters(length_m, ...[, n_segments])

Physical DSTL parameters of a straight buried pipeline.

class geopulse.network.pipeline.PipelineParameters(length_m, series_impedance_Ohm_per_m, shunt_admittance_S_per_m, start_lat_deg, start_lon_deg, end_lat_deg, end_lon_deg, n_segments=40)[source]

Bases: object

Physical DSTL parameters of a straight buried pipeline.

Parameters:
length_m

Total pipeline length in metres.

Type:

float

series_impedance_Ohm_per_m

Longitudinal series impedance z in Ω/m. For DC/quasi-DC GIC problems this is real (the pipe steel resistance per metre).

Type:

float

shunt_admittance_S_per_m

Transverse shunt admittance y in S/m through the coating to soil. Real for DC.

Type:

float

start_lat_deg, start_lon_deg

Coordinates of the x = 0 end.

Type:

float

end_lat_deg, end_lon_deg

Coordinates of the x = L end.

Type:

float

n_segments

Number of equivalent-π segments used to discretise the pipeline. The resulting network has n_segments + 1 nodes.

Type:

int

Notes

Discretisation guideline: keep γ · Δℓ = γ · L / n_segments well below unity — the equivalent-π reduces to the true distributed model only in the small-segment limit. For typical steel pipelines (z ~ 3 × 10⁻⁴ Ω/m, y ~ 10⁻⁶ S/m), γ 1.7 × 10⁻⁵ /m; a 100-km pipeline needs n_segments 30 to get sub-percent agreement with the closed form.

length_m: float
series_impedance_Ohm_per_m: float
shunt_admittance_S_per_m: float
start_lat_deg: float
start_lon_deg: float
end_lat_deg: float
end_lon_deg: float
n_segments: int = 40
class geopulse.network.pipeline.PipelineNetwork(params)[source]

Bases: ConductorNetwork

Straight buried pipeline modelled by equivalent-π DSTL segments.

Parameters:

params (PipelineParameters) – Pipeline physical + discretisation parameters.

params
Type:

PipelineParameters

node_positions_m

Along-pipe coordinate x for every node, in metres. Shape (n_segments + 1,).

Type:

numpy.ndarray

Notes

Node ids are "pipe_x0", "pipe_x1", …, in order from x = 0 to x = L. Branch ids are "seg_0", "seg_1", ….

Examples

>>> params = PipelineParameters(
...     length_m=100_000.0,
...     series_impedance_Ohm_per_m=3e-4,
...     shunt_admittance_S_per_m=1e-6,
...     start_lat_deg=45.0, start_lon_deg=-75.0,
...     end_lat_deg=45.0, end_lon_deg=-73.72,   # ~100 km east
...     n_segments=40,
... )
>>> net = PipelineNetwork(params)
>>> len(list(net.get_nodes()))
41
>>> len(list(net.get_branches()))
40
get_nodes()[source]

Return one Node per discretisation point.

Interior nodes carry the shunt from two adjacent π-sections (2 · Y_sh); endpoint nodes carry a single half-section (Y_sh). earthing_impedance_Ohm is the reciprocal.

Return type:

Sequence[Node]

get_branches()[source]

Return one Branch per equivalent-π segment.

Return type:

Sequence[Branch]

assemble_network_admittance()[source]

Assemble Y_n from the series conductance of each π-section.

Return type:

ndarray

assemble_earthing_impedance()[source]

Diagonal Z_e from the shunt admittances of each π-section.

Return type:

ndarray

compute_thevenin_voltages(ex_Vm, ey_Vm, lat_deg=None, lon_deg=None)[source]

Per-segment Thévenin voltage from the geoelectric field.

V_th = E_x · Δx + E_y · Δy where Δx, Δy are the eastward and northward offsets of the segment endpoints in the local equirectangular projection.

Return type:

ndarray

Parameters:
classmethod from_file(path)[source]

Load pipeline parameters from a YAML file (WP4).

Return type:

PipelineNetwork

Parameters:

path (str)

geopulse.network.pipeline.pipe_to_soil_voltage_analytic(E_Vm, length_m, series_impedance_Ohm_per_m, shunt_admittance_S_per_m, x_m)[source]

Closed-form pipe-to-soil voltage for a uniform longitudinal E-field.

Insulated-end boundary condition (no ground path except through the coating shunt). Follows the standard DSTL result [1]_:

V(x) = (E / γ) · sinh(γ · (x − L/2)) / cosh(γ · L / 2)
Parameters:
  • E_Vm (float | ndarray) – Uniform longitudinal E-field along the pipe, in V/m.

  • length_m (float) – Pipeline length L in metres.

  • series_impedance_Ohm_per_m (float) – DSTL parameters z and y.

  • shunt_admittance_S_per_m (float) – DSTL parameters z and y.

  • x_m (ndarray) – Positions along the pipe at which to evaluate V, in metres.

Return type:

ndarray

Returns:

numpy.ndarray – Pipe-to-soil voltage in Volts. Same shape as x_m.

References

Examples

>>> import numpy as np
>>> V = pipe_to_soil_voltage_analytic(1e-3, 100_000.0, 3e-4, 1e-6,
...                                    np.array([0, 50_000, 100_000]))
>>> V.shape
(3,)