Geometry¶
The geometry subpackage describes the physical shape of every
buried metallic object — rods, rings, strips, polylines, stars, mesh
and grid-mesh electrodes — together with the wire-segment
representation that the field solver consumes.
Physical background¶
A grounding electrode is a finite metal body buried in conducting soil. For frequencies below 1 kHz it can be treated as a thin-wire boundary along which the potential is enforced and the current distribution is unknown (or, in the cheaper image backends, prescribed as uniform). All standard geometries are reduced to a collection of straight cylindrical segments
each carrying a wire radius \(a_i\) and a material tag. The
discretisation length \(\Delta s\) is set by
:attr:groundfield.solver.engine.Engine.segment_length. The
geometry layer is intentionally decoupled from the solver, so the
same electrodes can be fed into the closed-form image backend, MoM,
or FEM without modification.
For mesh and grid electrodes the segment count per wire is aligned to a
whole multiple of the mesh-span count, so the grid crossings fall on
segment endpoints rather than on the midpoint point sources. This
avoids a discretisation trap in which a longitudinal and a transverse
segment midpoint would coincide on a crossing — collapsing to the
singularity clamp and inflating the grid resistance by ~2× for the
uniform-current image backend. The effective \(\Delta s\) is therefore
never coarser than requested and the grid resistance is stable for any
segment_length (see notebooks/44_grid_discretization_robustness.ipynb).
Example¶
import groundfield as gf
world = gf.create_world(soil=gf.HomogeneousSoil(resistivity=100.0))
# Vertical driven rod
rod = gf.create_electrode(
world, "rod", name="g1",
position=(0.0, 0.0, 0.0), length=1.5, wire_radius=0.005,
)
# Buried ring earth at house-foundation depth
ring = gf.create_electrode(
world, "ring", name="g2",
center=(10.0, 0.0, 0.8), radius=2.0, wire_radius=0.005,
)
# Rectangular mesh (e.g. substation grid)
mesh = gf.create_electrode(
world, "grid_mesh", name="g3",
corner=(-10.0, -10.0, 0.5), size=(20.0, 20.0),
n_x=11, n_y=11, wire_radius=0.005,
)
# Pre-solve resolution / segment-budget check
for warning in gf.check_segment_resolution(
world, gf.create_engine(backend="image", segment_length=0.1)
):
print("WARN:", warning)
For programmatic generation of large typical worlds (5 – 200 single-family houses, stochastic electrode mixes) see Generators.
Strip electrode concrete shell (new in 0.6.0)¶
:class:StripElectrode carries an optional
concrete_shell_coefficient_ohm_m field (default 0.0 —
historic behaviour). When set, the per-meter Sunde coefficient
\(C = \rho_c/(2\pi)\,\ln(r_b/r_a)\) in Ω·m enters the
image / image_2layer self-action: every segment of length
\(\Delta s\) in this strip has its MoM diagonal augmented by
\(C/\Delta s\), the radial voltage drop through the concrete shell.
This is the V2 distributed path of
ADR-0012. The
field is populated automatically by
:meth:~groundfield.generators.grounding.GroundingSystemSpec.build_at
when a :class:~groundfield.generators.electrode_specs.FoundationElectrodeSpec
with concrete_model="distributed" is materialised; it is not
intended to be set by hand on isolated strip electrodes outside
the generator pipeline (but does work there, see the closed-form
verification in tests/test_concrete_encasement.py).
Star electrode (Sternerder)¶
:class:StarElectrode is the classic \(n\)-point star: n_arms equal
horizontal wires of length \(L\) radiate from a common centre node at one
depth, uniformly spaced by \(360^\circ / n\). All arms share the centre,
so the star is a single galvanic cluster. Its closed-form grounding
resistance follows Dwight (1936, Eqs. 23–26),
with per-\(n\) coefficients \(c_k\) tabulated for \(n \in \{3, 4, 6, 8\}\) in
:func:groundfield.references.dwight1936.n_point_star (\(a\) = wire
radius, \(t\) = burial depth, \(s = 2t\) the image distance). The image
backend reproduces this to ~1 % (see
tests/test_dwight_references.py).
star = gf.create_electrode(
world, "star", name="g4",
center=(0.0, 0.0, 0.5), n_arms=4, arm_length=5.0,
orientation_deg=0.0, wire_radius=0.005,
)
API reference¶
geometry ¶
Geometries of electrodes and grounding systems.
This subpackage provides the 3-D geometry of the grounding system. An
electrode is built from a set of wire segments (:class:Segment) with
start and end points, wire radius, material, and a mapping to one or
more electric nodes. The subpackage builds a mesh for the field solver
and exposes the standard parametric geometries.
Contents
RodElectrode, RingElectrode, StripElectrode, MeshElectrode, GridMeshElectrode Parametric standard electrode geometries. Electrode Discriminated union over all electrode types.
Notes
The geometry layer is deliberately decoupled from the solver, so the same geometry can be fed into the image-charge backend, MoM, or FEM.
GridMeshElectrode ¶
Bases: _ElectrodeBase
Rectangular meshed earth electrode with explicit n × m divisions.
Defines an axis-aligned rectangle of size (dx, dy) at depth
corner[2], divided into n_x × n_y internal meshes.
The geometry consists of n_x + 1 longitudinal wires (running
along the local \(x\) axis from corner to corner + (dx, 0))
and n_y + 1 transverse wires (running along the local \(y\)
axis). All wires share the same depth.
Attributes:
| Name | Type | Description |
|---|---|---|
corner |
Point3D
|
Corner point |
size |
tuple[float, float]
|
Extent |
n_x |
int
|
Number of meshes along \(x\) (must be ≥ 1). The number of
longitudinal wires is |
n_y |
int
|
Number of meshes along \(y\) (must be ≥ 1). The number of
transverse wires is |
Notes
Naming convention: n_x × n_y is the count of meshes
(cells), not of wires.
A grid with n_x = n_y = 1 is therefore a single closed
rectangle (the perimeter wires only).
MeshElectrode ¶
Bases: _ElectrodeBase
Rectangular mesh earth electrode (uniform spacing).
Backwards-compatible primitive that sets the inner mesh density
via a single spacing parameter. For finer control over the
column / row count, prefer :class:GridMeshElectrode.
Attributes:
| Name | Type | Description |
|---|---|---|
corner |
Point3D
|
Corner point |
size |
tuple[float, float]
|
Extent |
spacing |
float
|
Spacing between adjacent longitudinal / transverse wires in m. |
PolylineElectrode ¶
Bases: _ElectrodeBase
Buried wire following an arbitrary horizontal polyline.
Generalises :class:StripElectrode from a single straight wire to
a chain of straight wires through vertices. With
closed = True the last vertex is wired back to the first,
which makes this the Ringerder along an arbitrary building
outline — the DIN-18014 Streifenfundament that follows the real
building perimeter instead of its bounding rectangle.
All vertices must lie at the same depth (the wire is horizontal),
consistent with :class:StripElectrode.
Attributes:
| Name | Type | Description |
|---|---|---|
vertices |
list[Point3D]
|
Ordered polyline vertices |
closed |
bool
|
Whether the polyline is closed into a ring (default
|
Notes
Motivation (AP1): approximating a building footprint by its oriented bounding rectangle (OMBR) overestimates the electrode perimeter for L- and U-shaped buildings and — worse — lets the rectangles of neighbouring buildings coincide or overlap, which drives distinct segments into the solver's 1 mm singularity clamp. Following the real polygon removes both artefacts by construction.
RingElectrode ¶
Bases: _ElectrodeBase
Horizontal ring electrode (foundation / ring earth electrode).
Attributes:
| Name | Type | Description |
|---|---|---|
center |
Point3D
|
Ring centre |
radius |
float
|
Ring radius in metres. |
RodElectrode ¶
Bases: _ElectrodeBase
Vertical driven rod (Tiefenerder).
Attributes:
| Name | Type | Description |
|---|---|---|
position |
Point3D
|
Position of the head (top end) as |
length |
float
|
Rod length in metres (downwards along \(+z\)). |
StarElectrode ¶
Bases: _ElectrodeBase
Buried horizontal star electrode (Sternerder).
n_arms equal-length wires radiate from a common centre node at a
single depth, spaced uniformly by \(360^\circ / n\). This is the
classic \(n\)-point star of Dwight (1936, Eqs. 23–26); the closed-form
grounding resistance is available as
:func:groundfield.references.dwight1936.n_point_star for
validation (Dwight covers 3, 4, 6 and 8 arms).
Attributes:
| Name | Type | Description |
|---|---|---|
center |
Point3D
|
Hub |
n_arms |
int
|
Number of radial arms (\(\ge 2\)). |
arm_length |
float
|
Length \(L\) of a single arm in metres. |
orientation_deg |
float
|
Azimuth of the first arm measured from the world |
concrete_shell_coefficient_ohm_m |
float
|
Optional per-segment radial concrete-shell coefficient, same
semantics as on :class: |
Notes
Discretisation and the reaction-matrix assembly treat the star as
n_arms straight wires sharing the centre node, so it forms a
single galvanic cluster — exactly the physical Sternerder.
StripElectrode ¶
Bases: _ElectrodeBase
Horizontal straight strip earth electrode (Banderder).
A buried straight wire from start to end. Both end points
must lie at the same depth (\(z_\text{start} = z_\text{end}\));
the in-plane direction is arbitrary, not restricted to the \(x\)
or \(y\) axis. The strip's length is the Euclidean distance between
the end points.
Attributes:
| Name | Type | Description |
|---|---|---|
start |
Point3D
|
Strip start |
end |
Point3D
|
Strip end |
Notes
The strip is the canonical Banderder. For the image /
mom family the discretisation produces one chain of wire
segments (no doubled-wire approximation). Plausibility tests
compare against
:func:groundfield.references.dwight1936.horizontal_wire.