geopulse.solver.lpm

Lehtinen-Pirjola matrix method for DC/quasi-DC GIC in earthed networks.

Solves the nodal ground-potential problem:

Y_n · V = J_e

where

  • Y_n is the total nodal admittance matrix (network conductances plus grounding conductances on the diagonal),

  • J_e is the injected-current vector — for every branch (i, j) with conductance g_ij = 1/R_ij and Thévenin voltage V_th,ij, add +g_ij · V_th,ij at node j and -g_ij · V_th,ij at node i,

  • V is the ground-potential rise at every node.

The GIC to ground at node i is then I_gnd,i = g_gnd,i · V_i, and the branch current is I_ij = g_ij · (V_i V_j + V_th,ij) following the sign convention used above.

This is mathematically equivalent to the I = (1 + Y_n · Z_e)^{-1} J_e form quoted in the handoff spec: both formulations produce identical per-branch currents; the Y·V = J form is preferred here because it handles ungrounded (g_gnd = 0) delta-winding nodes gracefully by excluding them from the linear solve.

References

Functions

solve_lpm(network_admittance, ...)

Functional core of the LPM solve.

Classes

LPMSolver()

Lehtinen-Pirjola matrix solver.

class geopulse.solver.lpm.LPMSolver[source]

Bases: Solver

Lehtinen-Pirjola matrix solver.

Examples

>>> import numpy as np
>>> from geopulse.network.powergrid import PowerGridNetwork
>>> net = PowerGridNetwork.from_file("benchmarks/horton2012/epri21.m")
>>> Y = net.assemble_network_admittance()
>>> Z = net.assemble_earthing_impedance()
>>> Vth = net.compute_thevenin_voltages(1e-3, 0.0)  # 1 mV/m eastward
>>> result = LPMSolver().solve(net, Y, Z, Vth)
solve(network, network_admittance, earthing_impedance, thevenin_voltages)[source]

Solve for GIC given a ConductorNetwork and its matrices.

Parameters:
  • network (ConductorNetwork) – The network object; used to pull node ids, branch ids, and the branch endpoint / conductance metadata that the raw matrices do not carry.

  • network_admittance (ndarray) – Y_n matrix, Siemens.

  • earthing_impedance (ndarray) – Z_e diagonal matrix, Ohms.

  • thevenin_voltages (ndarray) – V_th per branch, Volts. Length must equal len(network.get_branches()).

Return type:

SolverResult

Returns:

SolverResult – Node voltages and branch currents in canonical network order.

geopulse.solver.lpm.solve_lpm(network_admittance, earthing_impedance, thevenin_voltages, branch_endpoints, branch_conductances)[source]

Functional core of the LPM solve.

Parameters:
  • network_admittance (ndarray) – Y_n matrix (line conductances only, no grounding). Shape (n_nodes, n_nodes). Symmetric, Siemens.

  • earthing_impedance (ndarray) – Z_e diagonal (Ohms). Shape (n_nodes, n_nodes). Ungrounded nodes carry 0; those are excluded from the solve automatically.

  • thevenin_voltages (ndarray) – V_th per branch, Volts. Shape (n_branches,).

  • branch_endpoints (ndarray) – (n_branches, 2) array of (from_index, to_index) matrix rows.

  • branch_conductances (ndarray) – g_ij = 1/R_ij per branch, Siemens. Shape (n_branches,).

Return type:

tuple[ndarray, ndarray]

Returns:

  • node_voltages_V (numpy.ndarray) – Ground-potential rise at every node, Volts. Shape (n_nodes,).

  • branch_currents_A (numpy.ndarray) – Current in every branch, Amperes. Shape (n_branches,).

Raises:

ConvergenceError – If the reduced linear system is singular even after removing ungrounded nodes.