groundfield 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. groundfield-0.4.0/LICENSE +21 -0
  2. groundfield-0.4.0/PKG-INFO +230 -0
  3. groundfield-0.4.0/README.md +202 -0
  4. groundfield-0.4.0/pyproject.toml +66 -0
  5. groundfield-0.4.0/scripts/__init__.py +6 -0
  6. groundfield-0.4.0/scripts/benchmarks/__init__.py +0 -0
  7. groundfield-0.4.0/scripts/benchmarks/pen_1km_carson.py +304 -0
  8. groundfield-0.4.0/scripts/generate_graphify_report.py +340 -0
  9. groundfield-0.4.0/scripts/generate_third_party_licenses.py +288 -0
  10. groundfield-0.4.0/scripts/release.py +738 -0
  11. groundfield-0.4.0/src/groundfield/__init__.py +331 -0
  12. groundfield-0.4.0/src/groundfield/api.py +408 -0
  13. groundfield-0.4.0/src/groundfield/boundary.py +83 -0
  14. groundfield-0.4.0/src/groundfield/conductors/__init__.py +33 -0
  15. groundfield-0.4.0/src/groundfield/conductors/conductor.py +256 -0
  16. groundfield-0.4.0/src/groundfield/coupling/__init__.py +141 -0
  17. groundfield-0.4.0/src/groundfield/coupling/carson.py +531 -0
  18. groundfield-0.4.0/src/groundfield/coupling/inductance.py +824 -0
  19. groundfield-0.4.0/src/groundfield/coupling/layered_green.py +486 -0
  20. groundfield-0.4.0/src/groundfield/coupling/sommerfeld_inductance.py +730 -0
  21. groundfield-0.4.0/src/groundfield/diagnostics.py +490 -0
  22. groundfield-0.4.0/src/groundfield/generators/__init__.py +150 -0
  23. groundfield-0.4.0/src/groundfield/generators/base.py +285 -0
  24. groundfield-0.4.0/src/groundfield/generators/building.py +179 -0
  25. groundfield-0.4.0/src/groundfield/generators/distributions.py +335 -0
  26. groundfield-0.4.0/src/groundfield/generators/electrode_specs.py +287 -0
  27. groundfield-0.4.0/src/groundfield/generators/grounding.py +220 -0
  28. groundfield-0.4.0/src/groundfield/generators/measurement.py +363 -0
  29. groundfield-0.4.0/src/groundfield/generators/placement.py +158 -0
  30. groundfield-0.4.0/src/groundfield/generators/soil_specs.py +192 -0
  31. groundfield-0.4.0/src/groundfield/generators/tn_network.py +693 -0
  32. groundfield-0.4.0/src/groundfield/generators/tn_ortsnetz.py +43 -0
  33. groundfield-0.4.0/src/groundfield/geometry/__init__.py +41 -0
  34. groundfield-0.4.0/src/groundfield/geometry/electrodes.py +243 -0
  35. groundfield-0.4.0/src/groundfield/geometry/primitives.py +11 -0
  36. groundfield-0.4.0/src/groundfield/io/__init__.py +67 -0
  37. groundfield-0.4.0/src/groundfield/io/csv.py +236 -0
  38. groundfield-0.4.0/src/groundfield/io/groundinsight.py +687 -0
  39. groundfield-0.4.0/src/groundfield/io/vtk.py +310 -0
  40. groundfield-0.4.0/src/groundfield/postprocess/__init__.py +100 -0
  41. groundfield-0.4.0/src/groundfield/postprocess/convergence.py +210 -0
  42. groundfield-0.4.0/src/groundfield/postprocess/current_balance.py +538 -0
  43. groundfield-0.4.0/src/groundfield/postprocess/geometry_plot.py +579 -0
  44. groundfield-0.4.0/src/groundfield/postprocess/plotting.py +616 -0
  45. groundfield-0.4.0/src/groundfield/postprocess/rho_f_standard.py +276 -0
  46. groundfield-0.4.0/src/groundfield/postprocess/safety.py +431 -0
  47. groundfield-0.4.0/src/groundfield/postprocess/sweep.py +359 -0
  48. groundfield-0.4.0/src/groundfield/postprocess/vector_fitting.py +538 -0
  49. groundfield-0.4.0/src/groundfield/references/__init__.py +39 -0
  50. groundfield-0.4.0/src/groundfield/references/carson.py +222 -0
  51. groundfield-0.4.0/src/groundfield/references/dwight1936.py +381 -0
  52. groundfield-0.4.0/src/groundfield/references/oeding.py +179 -0
  53. groundfield-0.4.0/src/groundfield/soil/__init__.py +47 -0
  54. groundfield-0.4.0/src/groundfield/soil/models.py +135 -0
  55. groundfield-0.4.0/src/groundfield/solver/__init__.py +49 -0
  56. groundfield-0.4.0/src/groundfield/solver/_layered.py +377 -0
  57. groundfield-0.4.0/src/groundfield/solver/bem.py +422 -0
  58. groundfield-0.4.0/src/groundfield/solver/cim.py +683 -0
  59. groundfield-0.4.0/src/groundfield/solver/engine.py +244 -0
  60. groundfield-0.4.0/src/groundfield/solver/fem.py +705 -0
  61. groundfield-0.4.0/src/groundfield/solver/field_study.py +26 -0
  62. groundfield-0.4.0/src/groundfield/solver/image.py +1539 -0
  63. groundfield-0.4.0/src/groundfield/solver/image_2layer.py +739 -0
  64. groundfield-0.4.0/src/groundfield/solver/image_nlayer.py +196 -0
  65. groundfield-0.4.0/src/groundfield/solver/mom.py +664 -0
  66. groundfield-0.4.0/src/groundfield/solver/mom_sommerfeld.py +585 -0
  67. groundfield-0.4.0/src/groundfield/solver/result.py +414 -0
  68. groundfield-0.4.0/src/groundfield/sources.py +76 -0
  69. groundfield-0.4.0/src/groundfield/utils/__init__.py +13 -0
  70. groundfield-0.4.0/src/groundfield/utils/logging.py +43 -0
  71. groundfield-0.4.0/src/groundfield/validation.py +238 -0
  72. groundfield-0.4.0/src/groundfield/world.py +200 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Christian Ehlert
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,230 @@
1
+ Metadata-Version: 2.4
2
+ Name: groundfield
3
+ Version: 0.4.0
4
+ Summary: Numerical field computation for grounding systems (PDE / field model, coupling to groundinsight)
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Author: Christian Ehlert
8
+ Author-email: christian.ehlert@mailbox.org
9
+ Requires-Python: >=3.12,<4.0
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Provides-Extra: groundinsight
16
+ Requires-Dist: groundinsight (>=0.3) ; extra == "groundinsight"
17
+ Requires-Dist: matplotlib (>=3.9.2,<4.0.0)
18
+ Requires-Dist: numpy (>=2.1.0,<3.0.0)
19
+ Requires-Dist: pandas (>=3.0.2,<4.0.0)
20
+ Requires-Dist: polars (>=1.5.0,<2.0.0)
21
+ Requires-Dist: pydantic (>=2.8.2,<3.0.0)
22
+ Requires-Dist: scipy (>=1.14.1,<2.0.0)
23
+ Requires-Dist: sympy (>=1.13.2,<2.0.0)
24
+ Project-URL: Documentation, https://ce1ectric.github.io/groundfield/
25
+ Project-URL: Repository, https://github.com/Ce1ectric/groundfield
26
+ Description-Content-Type: text/markdown
27
+
28
+ # groundfield
29
+
30
+ **Numerical field computation for grounding systems.**
31
+
32
+ [![Python versions](https://img.shields.io/badge/python-3.12%20%7C%203.13-blue)](https://www.python.org/)
33
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
34
+
35
+ `groundfield` is an open-source Python package for the physical
36
+ reference modelling of networked grounding systems. Within the
37
+ `groundmeas` / `groundinsight` / `groundfield` software family,
38
+ `groundfield` covers the field-theoretical side: soil models,
39
+ electrode geometries, conductors and their couplings are formulated as
40
+ a 3-D problem in the soil and solved numerically. The results are
41
+ field profiles, potential curves, current distributions, and — most
42
+ importantly — reduced equivalent models (`rho-f` model) that, via
43
+ vector fitting and a SymPy-compatible export, can be handed over
44
+ directly to `groundinsight` as a `BusType`. A world-generator
45
+ framework (`groundfield.generators`, ADR-0009) parameterises the
46
+ AP1 TN-Ortsnetz study (5–200 single-family houses, two-layer soil,
47
+ stochastic electrode mixes) and produces fully-wired `World`
48
+ instances ready for any of the eight integral / FEM backends.
49
+
50
+ - **Documentation**: <https://ce1ectric.github.io/groundfield/>
51
+ - **Source code**: <https://github.com/Ce1ectric/groundfield>
52
+ - **Issue tracker**: <https://github.com/Ce1ectric/groundfield/issues>
53
+
54
+ ## Position within the software family
55
+
56
+ ```
57
+ groundmeas ──▶ groundinsight ◀── groundfield
58
+ (measurement) (reduced network (field model,
59
+ model) PDE reference)
60
+ ```
61
+
62
+ `groundfield` provides the physically grounded reference model from
63
+ which reduced impedance and multi-port representations are derived.
64
+ These travel into `groundinsight` as `BusType` / `BranchType`
65
+ formulas where they can be reconciled with measurement data from
66
+ `groundmeas`.
67
+
68
+ ## Goals
69
+
70
+ `groundfield` is being developed as a tool for **work package 1** of
71
+ the dissertation on networked grounding systems. The investigations
72
+ include:
73
+
74
+ - layered soil (two-layer and multi-layer models),
75
+ - arbitrary electrode geometries (ring, strip, rod, foundation, mesh),
76
+ - conductors, cable shields, and PEN with mutual coupling,
77
+ - inductive coupling between distributed conductors (Neumann
78
+ partial-inductance assembly, ADR-0004),
79
+ - finite-conductivity earth-return correction (Carson 1926, ADR-0005)
80
+ as a fast asymptotic option, plus the rigorous geometric Sommerfeld
81
+ Green's function (ADR-0006) with native layered-earth support — the
82
+ combination directly answers the AP1 question on diffusion-field
83
+ effects, layered-earth coupling, and short-wire end effects below
84
+ 1 kHz,
85
+ - driven rods (Tiefenerder), foundation electrodes and conductors
86
+ that cross soil-layer interfaces (ADR-0007) — `image_2layer`
87
+ automatically dispatches to a rigorous Sommerfeld kernel for
88
+ cross-layer pairs and keeps the fast Tagg/Sunde image series for
89
+ pure-upper-layer worlds,
90
+ - current and potential distribution in the soil,
91
+ - influence of the current injection and measurement geometry on the
92
+ grounding-measurement result,
93
+ - derivation of reduced `rho-f` models for `groundinsight`.
94
+
95
+ ## Installation
96
+
97
+ `groundfield` requires **Python 3.12 or newer**.
98
+
99
+ ```bash
100
+ git clone https://github.com/Ce1ectric/groundfield.git
101
+ cd groundfield
102
+ poetry install
103
+ ```
104
+
105
+ The documentation extras live in an optional Poetry group:
106
+
107
+ ```bash
108
+ poetry install --with docs
109
+ ```
110
+
111
+ ## Quickstart
112
+
113
+ ```python
114
+ import groundfield as gf
115
+
116
+ # 1. Soil model (e.g. two-layer model from the AP1 parameter space)
117
+ soil = gf.TwoLayerSoil(rho_1=100.0, rho_2=500.0, h_1=2.0)
118
+
119
+ # 2. Build a world and add a ring electrode
120
+ world = gf.create_world(soil=soil)
121
+ gf.create_electrode(
122
+ world, "ring", name="g1",
123
+ center=(0.0, 0.0, 0.8), radius=5.0, wire_radius=0.005,
124
+ )
125
+ gf.create_source(world, attached_to="g1", magnitude=1.0)
126
+
127
+ # 3. Configure the engine and solve.
128
+ # Backends (auto-dispatched on the soil model):
129
+ # "image" — homogeneous, image charges
130
+ # "image_2layer" — Tagg/Sunde series for 2-layer soils
131
+ # "image_nlayer" — n-layer image dispatcher
132
+ # "cim" — Complex Image Method
133
+ # "mom" — Galerkin Method-of-Moments
134
+ # "mom_sommerfeld" — Galerkin MoM with direct Sommerfeld quadrature
135
+ # "bem" — boundary-element collocation
136
+ # "fem" — axisymmetric volume FEM (optional)
137
+ engine = gf.create_engine(backend="image",
138
+ frequencies=[50.0, 150.0, 250.0])
139
+ result = world.solve(engine)
140
+
141
+ # 4. Inspect
142
+ print(result.cluster_impedance("g1"))
143
+ gf.plot_potential_radial(result, around="g1", world=world,
144
+ depths=[0.0, 0.5, 1.0])
145
+ ```
146
+
147
+ ### Reduced-model export to groundinsight
148
+
149
+ Turn a field-grade ``Z(s)`` into a `BusType` consumable by
150
+ `groundinsight`:
151
+
152
+ ```python
153
+ from groundfield.postprocess.vector_fitting import rho_f_from_field_result
154
+ from groundfield.io.groundinsight import save_bustype_json, to_bustype
155
+
156
+ fit = rho_f_from_field_result(result, electrode_name="g1", n_poles=3)
157
+
158
+ # JSON path (no groundinsight installed required):
159
+ save_bustype_json(fit, "bus_type_substation.json",
160
+ name="SubstationBus", system_type="Substation",
161
+ voltage_level=20)
162
+
163
+ # Python API path (pip install groundfield[groundinsight]):
164
+ bus_type = to_bustype(fit, name="SubstationBus",
165
+ system_type="Substation", voltage_level=20)
166
+ ```
167
+
168
+ ### TN-Ortsnetz generator (AP1)
169
+
170
+ Build a fully-wired AP1 reference world from a high-level config:
171
+
172
+ ```python
173
+ cfg = gf.TnNetworkConfig(
174
+ soil=gf.TwoLayerSoilSpec(rho_1=100.0, rho_2=500.0, h_1=2.0),
175
+ building_counts={"residential": 30},
176
+ source_magnitude_A=1.0,
177
+ )
178
+ world = gf.TnNetworkGenerator().build(cfg)
179
+ ```
180
+
181
+ Numerical / categorical fields accept either fixed values or any
182
+ of `Constant`, `Uniform`, `Normal`, `LogNormal`, `Weibull`,
183
+ `Discrete`, `Categorical` for parameter sweeps and Monte Carlo runs.
184
+
185
+ ## Guiding principles
186
+
187
+ - **The PDE / field model is a reference, not the end product.** The
188
+ solver must be instrumented so that every solution can be reduced
189
+ to an identification-friendly form.
190
+ - **Measurability before accuracy.** The relevant frequency range is
191
+ < 1 kHz; this allows simplified soil models and fast solvers.
192
+ - **Grey-box, not black-box.** Geometric and material inputs stay
193
+ visible; only the parts that are not physically prescribed are
194
+ identified.
195
+
196
+ ## Development
197
+
198
+ ```bash
199
+ # Tests with coverage
200
+ poetry run pytest --cov=groundfield
201
+
202
+ # Formatting
203
+ poetry run black src tests scripts
204
+
205
+ # Local documentation
206
+ poetry install --with docs
207
+ poetry run mkdocs serve
208
+ ```
209
+
210
+ Releases are triggered through the Poetry script. It updates the
211
+ version in `pyproject.toml`, `src/groundfield/__init__.py`, and
212
+ `CITATION.cff`, moves the `[Unreleased]` block of `CHANGELOG.md` into
213
+ a new section, and creates an annotated tag.
214
+
215
+ ```bash
216
+ poetry run release patch
217
+ poetry run release minor
218
+ poetry run release major
219
+ poetry run release set 1.2.3
220
+ ```
221
+
222
+ ## Citing
223
+
224
+ If you use `groundfield` in academic work, please cite according to
225
+ the metadata in `CITATION.cff`.
226
+
227
+ ## License
228
+
229
+ `groundfield` is released under the [MIT license](LICENSE).
230
+
@@ -0,0 +1,202 @@
1
+ # groundfield
2
+
3
+ **Numerical field computation for grounding systems.**
4
+
5
+ [![Python versions](https://img.shields.io/badge/python-3.12%20%7C%203.13-blue)](https://www.python.org/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ `groundfield` is an open-source Python package for the physical
9
+ reference modelling of networked grounding systems. Within the
10
+ `groundmeas` / `groundinsight` / `groundfield` software family,
11
+ `groundfield` covers the field-theoretical side: soil models,
12
+ electrode geometries, conductors and their couplings are formulated as
13
+ a 3-D problem in the soil and solved numerically. The results are
14
+ field profiles, potential curves, current distributions, and — most
15
+ importantly — reduced equivalent models (`rho-f` model) that, via
16
+ vector fitting and a SymPy-compatible export, can be handed over
17
+ directly to `groundinsight` as a `BusType`. A world-generator
18
+ framework (`groundfield.generators`, ADR-0009) parameterises the
19
+ AP1 TN-Ortsnetz study (5–200 single-family houses, two-layer soil,
20
+ stochastic electrode mixes) and produces fully-wired `World`
21
+ instances ready for any of the eight integral / FEM backends.
22
+
23
+ - **Documentation**: <https://ce1ectric.github.io/groundfield/>
24
+ - **Source code**: <https://github.com/Ce1ectric/groundfield>
25
+ - **Issue tracker**: <https://github.com/Ce1ectric/groundfield/issues>
26
+
27
+ ## Position within the software family
28
+
29
+ ```
30
+ groundmeas ──▶ groundinsight ◀── groundfield
31
+ (measurement) (reduced network (field model,
32
+ model) PDE reference)
33
+ ```
34
+
35
+ `groundfield` provides the physically grounded reference model from
36
+ which reduced impedance and multi-port representations are derived.
37
+ These travel into `groundinsight` as `BusType` / `BranchType`
38
+ formulas where they can be reconciled with measurement data from
39
+ `groundmeas`.
40
+
41
+ ## Goals
42
+
43
+ `groundfield` is being developed as a tool for **work package 1** of
44
+ the dissertation on networked grounding systems. The investigations
45
+ include:
46
+
47
+ - layered soil (two-layer and multi-layer models),
48
+ - arbitrary electrode geometries (ring, strip, rod, foundation, mesh),
49
+ - conductors, cable shields, and PEN with mutual coupling,
50
+ - inductive coupling between distributed conductors (Neumann
51
+ partial-inductance assembly, ADR-0004),
52
+ - finite-conductivity earth-return correction (Carson 1926, ADR-0005)
53
+ as a fast asymptotic option, plus the rigorous geometric Sommerfeld
54
+ Green's function (ADR-0006) with native layered-earth support — the
55
+ combination directly answers the AP1 question on diffusion-field
56
+ effects, layered-earth coupling, and short-wire end effects below
57
+ 1 kHz,
58
+ - driven rods (Tiefenerder), foundation electrodes and conductors
59
+ that cross soil-layer interfaces (ADR-0007) — `image_2layer`
60
+ automatically dispatches to a rigorous Sommerfeld kernel for
61
+ cross-layer pairs and keeps the fast Tagg/Sunde image series for
62
+ pure-upper-layer worlds,
63
+ - current and potential distribution in the soil,
64
+ - influence of the current injection and measurement geometry on the
65
+ grounding-measurement result,
66
+ - derivation of reduced `rho-f` models for `groundinsight`.
67
+
68
+ ## Installation
69
+
70
+ `groundfield` requires **Python 3.12 or newer**.
71
+
72
+ ```bash
73
+ git clone https://github.com/Ce1ectric/groundfield.git
74
+ cd groundfield
75
+ poetry install
76
+ ```
77
+
78
+ The documentation extras live in an optional Poetry group:
79
+
80
+ ```bash
81
+ poetry install --with docs
82
+ ```
83
+
84
+ ## Quickstart
85
+
86
+ ```python
87
+ import groundfield as gf
88
+
89
+ # 1. Soil model (e.g. two-layer model from the AP1 parameter space)
90
+ soil = gf.TwoLayerSoil(rho_1=100.0, rho_2=500.0, h_1=2.0)
91
+
92
+ # 2. Build a world and add a ring electrode
93
+ world = gf.create_world(soil=soil)
94
+ gf.create_electrode(
95
+ world, "ring", name="g1",
96
+ center=(0.0, 0.0, 0.8), radius=5.0, wire_radius=0.005,
97
+ )
98
+ gf.create_source(world, attached_to="g1", magnitude=1.0)
99
+
100
+ # 3. Configure the engine and solve.
101
+ # Backends (auto-dispatched on the soil model):
102
+ # "image" — homogeneous, image charges
103
+ # "image_2layer" — Tagg/Sunde series for 2-layer soils
104
+ # "image_nlayer" — n-layer image dispatcher
105
+ # "cim" — Complex Image Method
106
+ # "mom" — Galerkin Method-of-Moments
107
+ # "mom_sommerfeld" — Galerkin MoM with direct Sommerfeld quadrature
108
+ # "bem" — boundary-element collocation
109
+ # "fem" — axisymmetric volume FEM (optional)
110
+ engine = gf.create_engine(backend="image",
111
+ frequencies=[50.0, 150.0, 250.0])
112
+ result = world.solve(engine)
113
+
114
+ # 4. Inspect
115
+ print(result.cluster_impedance("g1"))
116
+ gf.plot_potential_radial(result, around="g1", world=world,
117
+ depths=[0.0, 0.5, 1.0])
118
+ ```
119
+
120
+ ### Reduced-model export to groundinsight
121
+
122
+ Turn a field-grade ``Z(s)`` into a `BusType` consumable by
123
+ `groundinsight`:
124
+
125
+ ```python
126
+ from groundfield.postprocess.vector_fitting import rho_f_from_field_result
127
+ from groundfield.io.groundinsight import save_bustype_json, to_bustype
128
+
129
+ fit = rho_f_from_field_result(result, electrode_name="g1", n_poles=3)
130
+
131
+ # JSON path (no groundinsight installed required):
132
+ save_bustype_json(fit, "bus_type_substation.json",
133
+ name="SubstationBus", system_type="Substation",
134
+ voltage_level=20)
135
+
136
+ # Python API path (pip install groundfield[groundinsight]):
137
+ bus_type = to_bustype(fit, name="SubstationBus",
138
+ system_type="Substation", voltage_level=20)
139
+ ```
140
+
141
+ ### TN-Ortsnetz generator (AP1)
142
+
143
+ Build a fully-wired AP1 reference world from a high-level config:
144
+
145
+ ```python
146
+ cfg = gf.TnNetworkConfig(
147
+ soil=gf.TwoLayerSoilSpec(rho_1=100.0, rho_2=500.0, h_1=2.0),
148
+ building_counts={"residential": 30},
149
+ source_magnitude_A=1.0,
150
+ )
151
+ world = gf.TnNetworkGenerator().build(cfg)
152
+ ```
153
+
154
+ Numerical / categorical fields accept either fixed values or any
155
+ of `Constant`, `Uniform`, `Normal`, `LogNormal`, `Weibull`,
156
+ `Discrete`, `Categorical` for parameter sweeps and Monte Carlo runs.
157
+
158
+ ## Guiding principles
159
+
160
+ - **The PDE / field model is a reference, not the end product.** The
161
+ solver must be instrumented so that every solution can be reduced
162
+ to an identification-friendly form.
163
+ - **Measurability before accuracy.** The relevant frequency range is
164
+ < 1 kHz; this allows simplified soil models and fast solvers.
165
+ - **Grey-box, not black-box.** Geometric and material inputs stay
166
+ visible; only the parts that are not physically prescribed are
167
+ identified.
168
+
169
+ ## Development
170
+
171
+ ```bash
172
+ # Tests with coverage
173
+ poetry run pytest --cov=groundfield
174
+
175
+ # Formatting
176
+ poetry run black src tests scripts
177
+
178
+ # Local documentation
179
+ poetry install --with docs
180
+ poetry run mkdocs serve
181
+ ```
182
+
183
+ Releases are triggered through the Poetry script. It updates the
184
+ version in `pyproject.toml`, `src/groundfield/__init__.py`, and
185
+ `CITATION.cff`, moves the `[Unreleased]` block of `CHANGELOG.md` into
186
+ a new section, and creates an annotated tag.
187
+
188
+ ```bash
189
+ poetry run release patch
190
+ poetry run release minor
191
+ poetry run release major
192
+ poetry run release set 1.2.3
193
+ ```
194
+
195
+ ## Citing
196
+
197
+ If you use `groundfield` in academic work, please cite according to
198
+ the metadata in `CITATION.cff`.
199
+
200
+ ## License
201
+
202
+ `groundfield` is released under the [MIT license](LICENSE).
@@ -0,0 +1,66 @@
1
+ [tool.poetry]
2
+ name = "groundfield"
3
+ version = "0.4.0"
4
+ description = "Numerical field computation for grounding systems (PDE / field model, coupling to groundinsight)"
5
+ authors = ["Christian Ehlert <christian.ehlert@mailbox.org>"]
6
+ license = "MIT"
7
+ repository = "https://github.com/Ce1ectric/groundfield"
8
+ documentation = "https://ce1ectric.github.io/groundfield/"
9
+ readme = "README.md"
10
+ packages = [
11
+ { include = "groundfield", from = "src" },
12
+ { include = "scripts" },
13
+ ]
14
+
15
+ [tool.poetry.dependencies]
16
+ python = "^3.12"
17
+ pydantic = "^2.8.2"
18
+ numpy = "^2.1.0"
19
+ scipy = "^1.14.1"
20
+ matplotlib = "^3.9.2"
21
+ polars = "^1.5.0"
22
+ sympy = "^1.13.2"
23
+ pandas = "^3.0.2"
24
+ # Optional: bridge to the sister project ``groundinsight``. When this
25
+ # extra is installed, ``groundfield.io.groundinsight.to_bustype`` /
26
+ # ``save_bustype_to_db`` can return a live ``BusType`` instance and
27
+ # write into the ``groundinsight`` SQLite store. The JSON export path
28
+ # (``save_bustype_json`` / ``load_bustype_json``) does not require
29
+ # this extra. See ADR-0008.
30
+ groundinsight = { version = ">=0.3", optional = true }
31
+
32
+ [tool.poetry.extras]
33
+ groundinsight = ["groundinsight"]
34
+
35
+ [tool.poetry.group.dev.dependencies]
36
+ ipykernel = "^6.29.5"
37
+ pytest = "^8.3.2"
38
+ pytest-cov = "^5.0.0"
39
+ black = "^24.8.0"
40
+ # ``groundinsight`` is pulled into the dev group so the bridge tests
41
+ # in ``tests/test_io_groundinsight.py`` can run end-to-end against
42
+ # the consumer's real Pydantic + SymPy parser. Keeps the runtime
43
+ # dependency optional (see ``[tool.poetry.extras]``).
44
+ groundinsight = ">=0.3"
45
+
46
+ [tool.poetry.group.docs]
47
+ optional = true
48
+
49
+ [tool.poetry.group.docs.dependencies]
50
+ mkdocs = "^1.6.1"
51
+ mkdocs-material = "^9.5.34"
52
+ mkdocstrings = { extras = ["python"], version = "^0.26.1" }
53
+ pymdown-extensions = "^10.9"
54
+ mkdocs-jupyter = "^0.25.0"
55
+
56
+ [tool.poetry.scripts]
57
+ release = "scripts.release:main"
58
+ generate-third-party-licenses = "scripts.generate_third_party_licenses:main"
59
+
60
+ [tool.pytest.ini_options]
61
+ testpaths = ["tests"]
62
+ addopts = "-ra"
63
+
64
+ [build-system]
65
+ requires = ["poetry-core"]
66
+ build-backend = "poetry.core.masonry.api"
@@ -0,0 +1,6 @@
1
+ """Automation and release scripts for ``groundfield``.
2
+
3
+ These scripts are not part of the runtime API. They are invoked via
4
+ ``poetry run`` and support release, license-report, and similar dev
5
+ tasks.
6
+ """
File without changes