Geothermal Suitability Screening — Po Plain (Piemonte)
A reproducible workflow that screens legacy hydrocarbon wells for geothermal reuse using bottom-hole-temperature archives, Horner/hybrid corrections, and cross-validated spatial interpolation — turning decades-old exploration data into a transparent, validated geothermal screening.
Overview
This project turns a sparse set of decades-old exploration-well bottom-hole-temperature (BHT) readings into a transparent, validated geothermal screening for the Piemonte sector of the Po Plain, Italy. It classifies each legacy well into a geothermal reuse category, builds an interactive map, and interpolates a spatial geothermal-gradient surface whose prediction error is quantified and openly reported. It is a regional screening aid, not a site-specific feasibility study — every threshold is externalised and documented, and the interpolated surface always carries its cross-validation error.
Headline Results
Methodology
- 1Governing reading
The deepest BHT measurement per well is taken as most representative of the recoverable thermal resource.
- 2Correction
Temperatures use the Horner-corrected value where multiple readings allow, otherwise the hybrid correction.
- 3Gradient
An apparent geothermal gradient is computed as (T_corrected − T_surface) / depth, normalising temperature against depth.
- 4Classification
Each well is assigned the highest-grade class whose temperature AND depth gates it satisfies (all thresholds externalised in YAML).
- 5Spatial field
The geothermal gradient (not raw temperature) is interpolated by inverse-distance weighting, with the power exponent selected by minimising leave-one-out cross-validation (LOOCV) RMSE.
Honest by design
Interpolating temperature directly is physically unsound — temperature is dominated by depth, and these wells span 834–5245 m. The correct quantity to interpolate is the depth-normalised geothermal gradient. Leave-one-out cross-validation gives a gradient RMSE of ≈ 3.5 °C/km — comparable to the gradient's own spatial spread, which honestly reflects how little structure a sparse, irregular well network can resolve. The interpolated surface is therefore presented as a screening visualisation, never a predictive model; on the map, cells far from any well are progressively faded so the figure never implies confidence where there is no data. Per-well classifications rest entirely on measured data.
Suitability Classification
| Class | Temperature | Depth | Wells |
|---|---|---|---|
| 🔴 Power Generation | ≥ 120 °C | ≥ 1000 m | 2 |
| 🟠 Direct Use | 60–120 °C | ≥ 1000 m | 17 |
| 🟡 Ground-Source Heat Pump | 40–60 °C | any | 9 |
| 🔵 Below Threshold | < 40 °C | — | 3 |
Tech Stack
| Layer | Technologies |
|---|---|
| Core | Python 3.12+, Pydantic v2, NumPy, Pandas, PyYAML |
| Interpolation | Inverse-distance weighting, LOOCV power tuning (haversine distances) |
| Visualisation | Folium (interactive map), Plotly (charts), Matplotlib (overlay raster) |
| Dashboard | Streamlit |
| Quality | pytest (18 tests), ruff, mypy --strict, GitHub Actions CI |
| License | MIT |
Key Features
Folium map with wells color-coded by suitability and a faded predicted-temperature overlay at a chosen reference depth.
IDW power selected by minimising leave-one-out RMSE; every surface ships with its error.
All classification gates live in thresholds.yaml, tunable without code changes.
Adjustable reference depth and grid resolution, live map, ranking chart, and validation report.
Deterministic pipeline; CLI (gsp screen / map / validate) and dashboard share one code path.
18 tests, mypy --strict, ruff, CI on Python 3.12 & 3.13.
Quick Start
pip install -e ".[all]"
gsp screen # ranked table + class summary
gsp map --out map.html # interactive map
gsp validate # interpolation LOOCV report
streamlit run dashboard/app.py # interactive dashboardCompanion project: well-integrity screening is addressed by LWRA — Legacy Well Risk Assessment Tool.
View source code, data, and documentation on GitHub
Data: BHT archives from ViDEPI / GEOTHOPICA public records. CITATION.cff in the repository.