Skip to content

ohagen-geo/pushit-summer-school-sim

Repository files navigation

BTES example — Borehole Thermal Energy Storage with OpenGeoSys

A small, self-contained OpenGeoSys (HEAT_TRANSPORT_BHE) example for the summer school: a Borehole Thermal Energy Storage field of 37 borehole heat exchangers in a two-layer ground model, meshed with the ogstools BHE mesher and driven with the ogstools Project (ogs6py) API.

Setup

Create a virtual environment and install the pinned dependencies (so everyone runs the exact versions this example was built and tested with):

python -m venv .venv
# Windows:        .venv\Scripts\activate
# macOS / Linux:  source .venv/bin/activate
pip install -r requirements.txt

The ogs package ships the OpenGeoSys solver itself (no separate install); the ogs executable lands inside the environment, where 02_create_run_prj.py finds it automatically. Quick check that everything imports and the solver is present:

python -c "import ogstools, gmsh, pyvista; print(ogstools.__version__)"
ogs --version

Model

BHE field 37 boreholes, hexagonal grid (3 rings), 5 m spacing
Domain 120 × 120 m, 500 m deep
BHEs 400 m long, coaxial (CXA)
Geology weathered basalt 0…−200 m (MaterialID 0), granodiorite −200…−500 m (MaterialID 1)
Initial state geothermal gradient (10 °C at surface → 25 °C at −500 m)
Boundaries fixed temperature on top & bottom, insulated sides
Operation 5 yearly cycles: inject 90 °C for half a year, then extract 30 °C, at 4 L/s per BHE

Scripts

Run them in order with the project's Python environment (.venv):

python 01_create_mesh.py        # ogstools BHE mesher -> model/{domain,top,bottom}.vtu
python 02_create_run_prj.py     # ogstools -> model/btes_model.prj, then runs OGS
python 03_visualize_results.py  # reads model/results/btes.pvd -> figures
  1. 01_create_mesh.py — builds the mesh with gen_bhe_mesh. The bulk domain.vtu holds both the soil prisms (MaterialIDs 0, 1) and the 37 BHE line elements (MaterialIDs 2…38); top.vtu / bottom.vtu are the boundary meshes for the surface and base temperature BCs. The sides are insulated (the natural zero-flux BC), so no sides mesh is needed. Also writes model/mesh_overview.png, a rendered preview of the mesh (MaterialIDs on a vertical clip + the BHE lines) for a quick visual check.

  2. 02_create_run_prj.py — assembles the project file with the ot.Project (ogs6py) API and runs OGS. The coaxial (CXA) BHEs are driven by inlet temperature (InflowTemperature) on a seasonal curve repeated for 5 years. The adaptive (iteration-number-based) time stepper has a 5-day cap and is forced — via fixed_output_times — to land exactly on every inject↔extract switch. Output is written every time step to model/results/.

  3. 03_visualize_results.py — reads the btes.pvd time series and produces six figures: vertical & horizontal temperature sections (colour scale capped at the 90 °C injection temperature), soil temperature vs. time at several radii, BHE inlet vs. outlet temperature, the storage heat rate, and the cumulative energy injected / extracted. The BHE outlet temperature is read as component 1 of temperature_BHE{i} at each borehole's top node.

All outputs go to the model/ sub-folder (created on first run).

Things you will likely want to change

  • Mesh (top of 01_create_mesh.py): bhe_spacing, n_rings, field_center, domain width/length/depth, bhe_length, bhe_radius, and the layer thicknesses. Set SHOW_MESH = True to inspect the mesh.
  • Physics & run (top of 02_create_run_prj.py): soil thermal properties (WEATHERED_BASALT, GRANODIORITE), coaxial pipe geometry, grout, refrigerant, BHE_FLOW_RATE, the inject/extract temperatures, the geothermal gradient, N_YEARS, and the time-stepping bounds (MAX_DT, …). The material/operational values shipped here are placeholders for the demo — replace them with your own data.
  • Visualization (top of 03_visualize_results.py): RADII, the colour scale T_SCALE_MIN/T_SCALE_MAX. The model constants near the top (BHE_LENGTH, N_BHE, BHE_FLOW_RATE, refrigerant properties) must match 02_create_run_prj.py — they are used for the heat-rate/energy evaluation.

Notes

  • The BHE length is set in the project file (<borehole><length>) and must equal the meshed BHE length (BHE_LENGTH == bhe_length = 400 m).
  • 02 writes the current OGS 6.5.x form of the BHE blocks (inlet-temperature control type = InflowTemperature with the inflow as a time-curve parameter; coaxial <pipes> with <outer>/<inner>, no distance_between_pipes). The high-level ogstools BHE helper targets an older schema, so the BHE blocks are written with the generic add_element / add_block methods instead.
  • Runtime. The full 5-year run takes ~2.5 h (401 time steps, output every step → ~400 VTUs, ~1–2 GB) on a typical laptop. This is too long to run live in a workshop — use the pre-computed results in model/results/ and run only 03_visualize_results.py. For a quick hands-on run, lower N_YEARS (e.g. 1) or coarsen the mesh in 01 (larger inner_mesh_size/outer_mesh_size, fewer n_rings); the script structure is unchanged.

About

Python scripts and reference results for the PUSH-IT UTES Summer School 2026 Simulation Workshop

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages