A 120 VDC microgrid with the reactor a kilometre out. The simulation runs in this page — scrub the clock or change the outpost and the diagram answers.
buildTopology(), not by hand — the feeder lengths,
voltages and conductor areas shown are the ones the model used.
Where the watts came from, hour by hour. Night is shaded.
The two-tier split. The shaded strip is the hysteresis dead band.
There is no state-of-charge sensor. The dashed line is the truth the simulation knows; the solid line is what an EKF infers from terminal voltage and a current sensor biased by 2 A.
Near zero the filter has stopped listening and is coasting on its own arithmetic. The gain follows the OCV slope, so it collapses wherever the curve flattens — chemistry, not tuning.
The signal this project added. Below zero, the bus cannot meet demand.
A bar marks every hour a load was disconnected. ECLSS never sheds.
An hour-by-hour simulation of the power system for an autonomous lunar outpost — a photovoltaic array, a fission reactor, a battery, a regenerative fuel cell, four loads, and a controller that decides what to switch off when the reserves run low. It runs 60 days, just over two full lunar cycles, and the whole thing is executing in this page.
A conventional microgrid controller watches one signal: state of charge. Run a reactor outage through this model in deep lunar night and that signal reports everything is fine while the outpost is already browning out.
Every hour of unserved power happened at a fleet reserve of 0.62 — comfortably above the 0.30 shed threshold, and rising. The mechanism is the two-tier storage: the battery is fast but shallow and empties about 36 hours into a 354-hour night; the fuel cell is deep but slow, holding 2090 kWh behind a 12 kW stack. The fleet can be full of energy and still unable to deliver it fast enough. Hence two signals rather than one — a capacity-weighted energy reserve and a measured power headroom, with the controller acting on whichever fires first.
Switch the conductors and converters off and on to see this. Modelling them turns a run that met its load perfectly into one that does not:
| 60-day run | Unserved | Loss |
|---|---|---|
| Power balance only | 0.0 kWh | — |
| Conductors | 10.3 kWh | 8.56 % |
| Converters | 142.1 kWh | 9.79 % |
| Both | 155.5 kWh | 18.10 % |
The silicon costs more than the copper — fourteen times the unserved energy. Copper gets drawn on diagrams and attracts the attention; the power electronics are a box on a wall. Two further findings fall out of the same model: a conductor on the regolith runs near 400 K in sunlight and 100 K at night, so it is worst exactly when the array is pushing hardest; and running the reactor link at user-bus voltage instead of 1000 V would need 736 mm² of aluminium and 3975 kg — a busbar, not a cable.
This page runs a JavaScript port of a Python model. A port that fails
loudly is not the risk; one that diverges quietly is — a
<= where a < belongs leaves two
simulators and no way to say which is right. So the port is held to the
Python original tick for tick:
198,720 comparisons. That 5e-10 is the reference file's storage format,
not the model: at full precision one scenario is bit-identical and the
others agree to 1.85e-16, under one ULP of a double. The diagram above is
generated from the same buildTopology() the simulation uses,
and the model inside this page is injected from the very bundle that
passes those checks — so nothing here can drift from what was verified.
On the Python side: 300 tests, plus a mutation check
that reintroduces nine bugs the project actually shipped and confirms the
suite catches eight, the ninth being a provably equivalent mutant.
Stated so absence is not mistaken for oversight: dust accumulation is a fixed derate rather than a mechanism that worsens over mission life; source impedance is not modelled, so fault currents are upper bounds; every fault is bolted, and a real arcing fault draws less current and is harder to detect; the linear temperature coefficient is optimistic near 100 K; and the controller has never actually run on a microcontroller, though it was written numpy-free so it could.
Source, tests and full write-up: github.com/troyfrancoceldran-ctrl/Autonomous-lunar-power-grid-simulation