Skip to content

davidsanz21/hashheat-dispatch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hashheat-dispatch

Hourly dispatch simulator for PV + battery + a hydro-cooled bitcoin miner used as a thermal-cascade heat source.

Why this exists

I'm renovating a family house and wanted the heating to run on a bitcoin miner fed exclusively by solar surplus. Every installer I asked had an opinion about whether that works. None of them had numbers. So I built the hour-by-hour model that settles the argument, used it to size my own system, and stripped out the personal data so the engine itself could be published.

What it does

  • Parses real PVGIS hourly CSVs (seriescalc format) or generates a synthetic, seeded test year in the same layout — no real location required to try it.
  • Simulates 8,760 hours of dispatch under a strict priority chain: loads → thermal buffers → heat pump → battery → grid, with the miner allowed to run only on pure surplus after the battery is nearly full.
  • Models the thermal side in electric terms: DHW buffer, space-heating inertia tank, a covered pool as overflow heat sink with a temperature cap.
  • Writes a markdown KPI report (generation, import, export, miner energy split, self-consumption, self-sufficiency, monthly import) plus two charts.
  • Runs marginal-payback sweeps across battery sizes.
  • Ships 10 unit tests covering energy-balance closure, SOC bounds, and the miner's never-causes-import invariant.

Architecture

A single-pass hourly engine (hashheat/dispatch.py) over parsed weather rows, configured entirely from a JSON file (hashheat/config.py). One hour of dispatch:

flowchart TD
    SUN(["hourly irradiance + T2m"]) --> GEN["PV generation"]
    HEAT(["heat demand<br>space + DHW"]) --> BUF["thermal buffers<br>serve first"]
    BUF -- "unmet heat" --> HP["heat pump<br>heat &#247; COP"]
    HP -- "electric load" --> LOADS["electric loads<br>house + EV + standby + heat pump"]
    GEN --> LOADS
    LOADS -- "deficit" --> DIS["battery discharge<br>to reserve floor"]
    DIS -- "still short" --> IMP["grid import"]
    LOADS -- "surplus" --> CHG["battery charge<br>to 100%"]
    CHG -- "SOC &ge; threshold" --> MIN["miner at COP 1<br>shared hourly budget"]
    MIN --> MBUF["buffers"]
    MIN --> POOL["pool, up to T max"]
    CHG -- "remainder" --> EXP["export"]
    CHG -. "miner gated: heat pump<br>may top up buffers" .-> BUF
    classDef impc fill:#b04a4a,stroke:#b04a4a,color:#ffffff
    classDef expc fill:#8aa86b,stroke:#8aa86b,color:#ffffff
    classDef minc fill:#caa3d6,stroke:#caa3d6,color:#1f1f1f
    class IMP impc
    class EXP expc
    class MIN,MBUF,POOL minc
Loading

The deliberate decisions: the battery charges to full before the miner may run, so the miner can never trigger an import — that ordering is the difference between "heating with surplus" and "mining with grid power". The miner is modelled as a COP-1 heat source and nothing else; mining economics are out of scope on purpose. Thermal buffers decouple midday surplus from morning demand. The pool closes the balance: it absorbs overflow heat under a temperature cap, and in practice it is what keeps the miner running once the buffers fill. All accounting stays in one unit, electric kWh — heat-pump heat enters divided by COP. The reasoning behind each rule is in docs/METHODOLOGY.md.

Stack

Python 3.10+, standard library only for the engine and tests. matplotlib for the optional charts. No other dependencies.

Setup & run

Built for my own design study and published as a working reference, not as a polished installable package.

git clone <this repo> && cd hashheat-dispatch
pip install -r requirements.txt   # matplotlib, charts only

# synthetic demo year (or download a real hourly series from PVGIS)
python -m hashheat make-weather --out examples/synthetic_year.csv --seed 7

python -m hashheat simulate --weather examples/synthetic_year.csv \
    --config examples/config_miner_cascade.json --out examples/outputs --charts

python -m hashheat sweep-battery --weather examples/synthetic_year.csv \
    --config examples/config_miner_cascade.json --caps 8,12,16,20,24

python -m unittest discover tests

To model a real site, request the hourly series for your coordinates from PVGIS and point --weather at the download. Replace the load shapes in the config with your metered curve if you have one.

Example

Everything below comes from the committed synthetic year (seed 7, generic 37° N placeholder climate) and examples/config_miner_cascade.json — an 18 kWp array, 16 kWh battery, 5 kW hydro miner, heat pump at COP 3.5, buffers and a covered pool. Fictional house, real engine.

Annual figure kWh
Generation 23,978
Grid import 1,719
Grid export 7,363 (31% of generation)
Miner → buffers / pool 3,821 / 1,690

Switch the miner off in the same house and export rises to 45% of generation while import barely moves. That asymmetry — the miner eats export, not import — held in my real design study too, and it is the single most useful thing the model taught me.

Monthly balance

The winter week below shows why import survives: the battery is empty before sunrise on short days, and a midday heat source can't help with that. The miner (violet) only fires when a bright day fills the battery first.

Winter week dispatch

Full generated reports are in examples/outputs/.

Status & roadmap

Working prototype: it sized one real system and its figures survived an architect's review. Next, in order:

  • Multi-year TMY runs with percentile bands instead of a single weather year.
  • Forecast-aware battery dispatch (current logic is greedy, which makes import slightly pessimistic).
  • Occupancy layering — separate electric and DHW profiles for guests or rental use.

Notes

The code was written with Claude under my direction; I specified the model rules, reviewed the maths, and operate and maintain it. The weather file format follows PVGIS (© European Union) for compatibility — no PVGIS data is bundled, you download your own. The miner-as-boiler concept owes a debt to the bitcoin mining heat-reuse literature, in particular Braiins' Bitcoin Mining Heat Reuse book. All examples are synthetic; no real location, consumption data, or hardware inventory appears in this repository. This is a design-exploration tool — it does not replace the licensed engineer who signs your installation project, and the payback sweep is not financial advice.


Built by David Sanz Cañal.

About

Hourly dispatch simulator for PV + battery + a hydro-cooled bitcoin miner as thermal-cascade heat source. Sized a real system.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages