# Isidis Propellant Refinery 01 (`isidis-01`)

**ISRU Sabatier reactor.** An automated Martian propellant refinery that runs like a real one, day and night.

In Isidis Planitia on Mars, this refinery makes methane from what the planet offers: carbon dioxide from the atmosphere and hydrogen from the electrolysis of mined ice. In its Sabatier reactor, CO2 + 4 H2 → CH4 + 2 H2O on a ruthenium catalyst between 340 and 435 °C; the reaction releases heat, which a coolant loop removes. The water is then condensed against radiators and adsorbed in a dryer. The refinery makes three grades: propellant for starships, surface fuel for landers and rovers, and feedstock for the chemical works of Isidis City. It runs on solar power, so its rate follows the Martian day and the dust storms. A rover collects a sample every 3 hours for the Isidis City Central Lab, which reports methane purity and dew point 2 hours later. The catalyst is replaced about every 25 days, and the dryer bed is regenerated about every nine days.

Status at 2026-10-31T17:34:07Z: last row 2026-10-31T17:30:00Z; making Feedstock. Lab results are released for samples taken before 2026-10-23T17:00:00Z; the next release is 2026-11-06T17:00:00Z.

This card: https://homeostat.kausalflow.com/live/isidis-01.md. The live page: https://homeostat.kausalflow.com/live/?plant=isidis-01.

## Background

This refinery belongs to the InterImm universe, the setting of a book in which the Interplanetary Immigration Agency begins to terraform Mars in 2219. The open facilities of the Mars colonies (propellant, power, air, iron, water and food) publish their instruments for anyone to watch. This refinery is not one of them: it is privately operated, and it is not monitored on the open facilities site.

Its operators share what they choose to. The sensors stream every ten minutes and the Central Lab's results follow a week late, while the catalyst's condition, the ice batches and the faults stay with the operators. The challenge on this page is that gap: predict what the lab will find from what the sensors show.

Homeostat Live runs on Earth time, on the real UTC clock. InterImm's own story clock is set 193 years ahead.

- [Mars Open Facilities](https://interimm.org/mars-open-facilities/): the colonies' open facilities, live, among them Procyon Propellant Works, also in Isidis Planitia
- [The InterImm book](https://book.interimm.org/history/mars_immigration/): the story of Mars immigration

## Process

```mermaid
flowchart TD
  SUN[Solar array JT-001] -->|power| EL[Electrolysers: ice to H2]
  EL -->|H2, FT-101| FIC101((FIC-101))
  ATM[Atmospheric CO2 acquisition] -->|CO2, FT-102| FIC102((FIC-102))
  FIC101 -->|H2| R[Sabatier reactor TIC-201, TT-201]
  FIC102 -->|CO2| R
  FFC102[/FFC-102: CO2 = ratio x FT-101/] -.->|setpoint| FIC102
  FIC101 -.->|FT-101| FFC102
  TT200[Feed gas TT-200] --- R
  CW[Coolant loop, valve TIC-201.out] --- R
  R -->|CH4, H2O, residual H2 and CO2| REC[Receiver]
  REC --> C[Condenser, TT-301, radiators]
  C -->|water out| W[Water to electrolysis]
  C --> D[Adsorbent dryer]
  C -.->|bypass by grade| P
  D --> P[Product methane]
  P -->|rover sample every 3 h| LAB[Isidis City Central Lab: AT-201 purity, AT-202 dew point]
```

### Design basis

| Item | Value |
|---|---|
| Reaction | CO2 + 4 H2 → CH4 + 2 H2O, exothermic (about −165 kJ/mol), on a ruthenium catalyst |
| Stoichiometry | CO2 : H2 = 1 : 4, the ratio FFC-102 at 0.25; the dry product holds 5 (1 − X) / (X + 5 (1 − X)) of residual H2 and CO2 at conversion X |
| Gas held up | about 20 Nm3 in the reactor loop and receiver: residence = 20 / total feed (Nm3/h) hours, so about 4 h for propellant, 1.8 h for surface fuel and 1.1 h for feedstock at full power |
| Line to the sampling point | about 3 Nm3 in plug flow (10-40 min) |
| Reactor temperature | 340-435 degC by grade: cooler converts more completely (the equilibrium) but more slowly (the kinetics); above about 420 degC the reverse water-gas shift makes CO |
| Cooling | a coolant loop removes the reaction heat: TIC-201 opens the coolant valve when the temperature rises (direct acting) |
| Condenser | cooled by radiators, so warmer by day and under dust; the water left in the gas is set by its outlet temperature TT-301 (saturation at about 30 bar) |
| Dryer | adsorbent bed, regenerated about every 9 days (in the plan); water breaks through as the bed nears its capacity; part of the gas bypasses it, by grade |
| Power | solar: the hydrogen rate is the grade's rate times the available power JT-001, which follows the Martian day (a sol, 24 h 39 min 35 s; about 75 % at night) and falls in dust storms |
| Catalyst | replaced about every 25 days (in the plan); poisoned by chlorine and sulfur from the ice, and sinters faster when hot |
| Lab | a rover collects a sample of the product every 3 hours; the Central Lab reports purity (dry basis, ±0.05 %, resolution 0.1 %) and dew point (±1 degC, resolution 0.5 degC) 2 hours later |
| Data | one row every 10 minutes: an instantaneous snapshot of every tag, not an average; times in UTC |

### Control loops

| Loop | Controls | By | Setpoint |
|---|---|---|---|
| FIC-101 | hydrogen feed FT-101 | hydrogen valve FIC-101.out | cascade: the grade's rate H2.rate times the available power |
| FIC-102 | CO2 feed FT-102 | CO2 valve FIC-102.out | cascade: FFC-102, the ratio times the measured hydrogen FT-101 |
| TIC-201 | reactor temperature TT-201 | coolant valve TIC-201.out | the grade's temperature TIC-201.sp; more reaction heat, more coolant |

A controller holds its measurement at the setpoint, so a disturbance often shows on the controller's output (a valve) rather than on the controlled measurement. A biased or drifting measurement moves the true process while the recorded value looks normal.

### Known and hidden

- Known to operators, and in the data: grade recipes and their changes; the planned maintenance (catalyst replacement; dryer regenerations; calibrations; valve replacements); the available power.
- Hidden, never published: the contaminants of each ice batch; the catalyst's activity; the dryer bed's condition; instrument drift and faults; the weather on the radiators.

## Grades

| Grade | Use | Methane purity (AT-201): target (range) | Dew point (AT-202): target (range) | Recipe: H2.rate | Recipe: FFC-102.ratio | Recipe: TIC-201.sp | Recipe: DRY.bypass |
|---|---|---|---|---|---|---|---|
| Propellant (`propellant`) | Liquefied for starships. Residual gases lower engine performance, and water would freeze in the cryogenic tanks. | 99.7 % (99.5 to 99.9) | -76 °C (-80 to -72) | 4 | 0.25 | 340 | 0 |
| Surface fuel (`surface_fuel`) | For landers, rovers and generators, which tolerate some hydrogen and CO₂. | 97 % (96 to 98) | -55 °C (-62 to -48) | 9 | 0.25 | 395 | 0.03 |
| Feedstock (`feedstock`) | For the methanol and plastics works of Isidis City, which consume the leftover hydrogen and CO₂ and make water themselves. | 86 % (81 to 92) | -27 °C (-34 to -20) | 14 | 0.25 | 435 | 0.9 |

A result below the range is off-spec; above it is giveaway (the plant worked harder than needed). The grade changes are in the plan, and the recipe values are in the data.

## Data

- The sunlight follows the Martian day, 24 h 39 min 35 s, while every time is UTC on the Earth calendar: night comes about 40 minutes later each day.
- Purity is on a dry basis; the dew point is measured at 1 bar on the same sample.

### Sensor tags

One row every 10 minutes since 2026-09-04T17:00:00Z: an instantaneous snapshot of every tag, not an average. Times are UTC. An empty value means no reading (a sensor removed or failed).

| Tag | Name | Unit | Kind | Group | Instrument | Description |
|---|---|---|---|---|---|---|
| `JT-001` | Available solar power | % | measurement | solar power | power meter on the electrolysers' supply; noise 0.2 % of 0-100 %, resolution 0.1 % | Power for the electrolysers, in % of the array's peak: day and night, and dust storms |
| `FT-101` | Hydrogen feed | Nm³/h | measurement | hydrogen feed | gas flow transmitter, 0-20 Nm3/h; noise 0.5 % of span (0.1 Nm3/h), resolution 0.01 Nm3/h, lag about 1 s | Hydrogen from the electrolysis of mined ice |
| `H2.rate` | Hydrogen rate at full power | Nm³/h | setting | hydrogen feed |  | Set by the grade's recipe |
| `FIC-101.rsp` | Hydrogen feed setpoint | Nm³/h | setpoint | hydrogen feed |  | The recipe's rate times the available power |
| `FIC-101.out` | Hydrogen feed valve | % | output | hydrogen feed |  | Opening of the hydrogen control valve |
| `FIC-101.mode` | Hydrogen controller mode |  | mode | hydrogen feed |  | 2 cascade: the setpoint follows the recipe and the power |
| `FFC-102.ratio` | CO₂ to hydrogen ratio | mol/mol | setting | CO₂ feed |  | 0.25 is the Sabatier stoichiometry, CO2 + 4 H2 |
| `FFC-102.out` | CO₂ feed setpoint | Nm³/h | setpoint | CO₂ feed |  | The ratio times the measured hydrogen feed |
| `FT-102` | CO₂ feed | Nm³/h | measurement | CO₂ feed | gas flow transmitter, 0-5 Nm3/h; noise 0.5 % of span (0.025 Nm3/h), resolution 0.0025 Nm3/h, lag about 1 s | Carbon dioxide from the atmospheric acquisition plant |
| `FIC-102.out` | CO₂ feed valve | % | output | CO₂ feed |  | Opening of the CO2 control valve |
| `FIC-102.mode` | CO₂ controller mode |  | mode | CO₂ feed |  | 2 cascade: the setpoint follows the hydrogen feed |
| `TT-201` | Reactor core temperature | °C | measurement | Sabatier reactor | thermocouple in a thermowell, 0-600 degC; noise 0.05 % of span (0.3 degC), resolution 0.06 degC, lag about 20 s; drifts between calibrations | Thermocouple in the catalyst bed |
| `TIC-201.sp` | Reactor temperature setpoint | °C | setpoint | Sabatier reactor |  | Set by the grade: cooler converts more completely but more slowly |
| `TIC-201.out` | Coolant flow valve | % | output | Sabatier reactor |  | Opens to remove the heat of the exothermic reaction |
| `TIC-201.mode` | Temperature controller mode |  | mode | Sabatier reactor |  | 0 manual, 1 automatic, 2 cascade |
| `TT-200` | Feed gas temperature | °C | measurement | feed gas | thermocouple, 0-400 degC; noise 0.2 degC, resolution 0.04 degC, lag about 20 s | The combined feed entering the reactor |
| `TT-301` | Condenser outlet temperature | °C | measurement | condenser and dryer | resistance thermometer, -20-60 degC; noise 0.08 degC, resolution 0.02 degC, lag about 20 s | The gas leaving the condenser, cooled by radiators: it sets how much water reaches the dryer |
| `DRY.bypass` | Dryer bypass |  | setting | condenser and dryer |  | Fraction of the gas that bypasses the dryer; set by the grade's recipe |

Kinds: `measurement` (an instrument's reading), `setpoint` (what a controller aims for), `setting` (a recipe value set by the operators), `output` (a controller's output, the valve opening in %), `mode` (0 manual, 1 automatic, 2 cascade).

### Lab results

| Tag | Name | Unit | Sampling | Description |
|---|---|---|---|---|
| `AT-201` | Methane purity | % | a sample every 3 h, reported 2 h later | Mass spec assay at the Isidis City Central Lab, dry basis: a rover collects a sample every 3 hours, reported 2 hours later |
| `AT-202` | Dew point | °C | a sample every 3 h, reported 2 h later | Water dew point at 1 bar of the same sample, from the same lab |

Each result has the time the sample was taken (`sampled_at`) and the time it was reported (`reported_at`). It describes the product at the sampling point at `sampled_at`.

### Plan

Grade changes and maintenance as the operators know them, a week ahead. The full past plan is in `GET /api/plants/{plant}` (`plan`).

- 2026-10-17T20:57:28Z: switch to Feedstock over 3 h
- 2026-10-20T18:57:02Z: calibrate: Sabatier reactor
- 2026-10-25T17:48:50Z: switch to Propellant over 3 h
- 2026-10-26T15:35:03Z: regenerate dryer bed: condenser and dryer
- 2026-10-29T23:48:34Z: switch to Feedstock over 3 h
- 2026-11-02T19:47:35Z: replace catalyst: Sabatier reactor (upcoming)
- 2026-11-03T04:55:56Z: regenerate dryer bed: condenser and dryer (upcoming)
- 2026-11-04T09:11:29Z: switch to Propellant over 3 h (upcoming)

## Access

Read-only, no key needed. Times in queries are ISO 8601 or unix seconds.

| Request | Answer |
|---|---|
| GET https://homeostat.kausalflow.com/api/plants/isidis-01 | metadata, status and plan (JSON) |
| GET https://homeostat.kausalflow.com/api/plants/isidis-01/live?since&until&tags&every | sensor rows (JSON): at most 1,100 rows and 35 days a request; `every` (seconds, a multiple of 600) thins them to snapshots every so often |
| GET https://homeostat.kausalflow.com/api/plants/isidis-01/lab?since&until | released lab results (JSON), at most 12 weeks a request |
| GET https://homeostat.kausalflow.com/api/plants/isidis-01/live.csv | the same sensor rows as CSV |
| GET https://homeostat.kausalflow.com/api/plants/isidis-01/lab.csv | the same lab results as CSV |
| GET https://homeostat.kausalflow.com/api/plants/isidis-01/tags.csv | the data dictionary as CSV |

```python
import pandas as pd

base = "https://homeostat.kausalflow.com/api/plants/isidis-01"
week = "since=2026-09-18T17:00:00Z&until=2026-09-25T17:00:00Z"
sensors = pd.read_csv(f"{base}/live.csv?{week}", parse_dates=["time"], index_col="time")
lab = pd.read_csv(f"{base}/lab.csv?{week}", parse_dates=["sampled_at", "reported_at"])
tags = pd.read_csv(f"{base}/tags.csv")
```

## Benchmark

- A benchmark opens every Friday at 17:00 UTC with the week that has just closed, and is named by that date. It asks for the lab results of every sample taken in the week, and freezes a week later, when they are released and every submission is scored. A user's last submission before the freeze counts.
- Causal rule: a prediction for a sample may use only data up to that sample's `sampled_at`: sensor data up to then, and lab results of earlier, released weeks.
- Releases: every Friday at 17:00 UTC, the lab results of the week that ended a week earlier join the released data.
- The first benchmark of this plant is 2026-10-09; `GET https://homeostat.kausalflow.com/api/benchmarks` lists them all.

Taking part, from the command line (Python 3.10 or later):

```bash
pip install homeostat-live
homeostat_live register <your-id>
homeostat_live benchmark --plant isidis-01
homeostat_live submit <date> isidis-01 homeostat-live-data/isidis-01/benchmarks/<date>/predictions.csv --note "v1"
```

Building a model, with an AI coding agent or without: `homeostat_live init` starts a project with a guide for coding agents (AGENTS.md), the plant's data and a working model to improve, the reference model `ref-linear`; the harness behind `backtest` and `predict` keeps the causal rule. Instructions for AI agents: https://homeostat.kausalflow.com/live/agents.md.

```bash
pip install 'homeostat-live[models]'
homeostat_live init my-model --plant isidis-01
cd my-model
homeostat_live backtest model.py      # score it on the released weeks, next to the reference models
homeostat_live predict model.py       # predictions for the open benchmark, checked
homeostat_live predictions --out p.csv  # what the reference models and the best participants predicted, next to the lab results (CSV, for pandas)
```

Scoring: every submission is scored when its benchmark freezes, with the code in the package's `homeostat_live.metrics`; `homeostat_live score predictions.csv --week <date> --plant <plant>` runs the same code on any released week (a backtest). The normalised error of a prediction is |prediction − lab| divided by half the width of the range of the grade being made when the sample was taken, each sample's counting at most 5; **the ranking is its mean over every target of the week** (lower is better). Also scored: MAE, RMSE, bias, median, 90th-percentile and worst error per analysis; within ¼ and ½ of the tolerance; inside grade-change windows (from the start of a change's ramp to 12 h after its end) the normalised error, its ratio to steady state, the error in the time to reach the new grade's range, and the worst error; off-spec detection (precision, recall, F1, balanced accuracy); direction accuracy and the correlation of changes; skill against the reference models `ref-last-lab` (the last released result of the same grade) and `ref-linear` (a ridge regression on the sensor values at the sample time, around each grade's level), which run every week like any user; and the errors per grade.

| Request | Answer |
|---|---|
| GET https://homeostat.kausalflow.com/api/leaderboard?plant=isidis-01 | the ranking of the last frozen week, the last four weeks and all weeks |
| GET https://homeostat.kausalflow.com/api/compare?plant=isidis-01&users=ref-linear,alice | up to 6 models' predictions next to the lab results of released weeks (a participant's once their benchmark is scored) |
| GET https://homeostat.kausalflow.com/api/benchmarks/{date}/isidis-01/scores | every metric of every ranked user, once the benchmark has frozen |
| POST https://homeostat.kausalflow.com/api/users with {"user": "<id>"} | a token, shown once; send it as `Authorization: Bearer <token>` |
| GET https://homeostat.kausalflow.com/api/benchmarks/{date}/isidis-01 | a benchmark: its week, status, data links and targets (tags and sample times) |
| GET https://homeostat.kausalflow.com/api/benchmarks/{date}/isidis-01/targets.csv | the targets as CSV: fill in `value` |
| POST https://homeostat.kausalflow.com/api/benchmarks/{date}/isidis-01/predictions | submit the filled-in CSV (`text/csv`) or JSON; a receipt |
| GET https://homeostat.kausalflow.com/api/users/{user}/history | a user's submissions and scores |

Every Friday at 17:00 UTC, the lab results from the Isidis City Central Lab are released for the week before. The true, continuous purity and moisture and the hidden conditions (ice batches and their contaminants, ruthenium catalyst degradation, the dryer bed's capacity, subsystem anomalies) never are.
