Interventions API¶
The src.interventions module models super-greenhouse gas (GHG) injection and its radiative effects on the Martian climate. Radiative forcing efficiencies are calibrated to Mars conditions (Marinova et al. 2005) — they differ from Earth IPCC values because Mars lacks water-vapour overlap bands and has a much thinner CO₂ column.
Radiative Forcing Model¶
The net greenhouse amplification from injected GHGs:
where \(\eta_i\) is the Mars-specific radiative forcing efficiency (W m⁻² ppb⁻¹) and \(C_i\) is the concentration in ppb.
The updated greenhouse factor fed into the temperature ODE:
Supported Compounds¶
| Compound | Lifetime (yr) | Notes |
|---|---|---|
| CF4 | >50,000 | Extremely long-lived |
| SF6 | 3,200 | High GWP |
| C2F6 | 10,000 | — |
| NF3 | 500 | — |
| C3F8, CHF3, CH2F2, CH3F | varies | HFC/PFC family |
| CH4 | 12 | Short-lived, synergistic |
| N2O | 114 | — |
| C3H8, CH3Cl | varies | — |
See list_compounds() for current values loaded at runtime.
GHG Compounds Registry¶
src.interventions.compounds
¶
GHG compound registry for Mars terraforming interventions.
Radiative forcing efficiencies are from Marinova et al. (2005), "Radiative-convective model of warming Mars with artificial greenhouse gases", Journal of Geophysical Research, Table 2. Mars-specific values differ from Earth (IPCC AR6) because Mars lacks water-vapour overlap bands and has a thinner CO₂ column.
Atmospheric lifetimes are from IPCC AR5/AR6 and Ravishankara et al. (1993).
CompoundProperties
dataclass
¶
Physical and radiative properties of a super-greenhouse gas.
Attributes¶
molecular_weight_g_mol : float Molecular weight in g/mol. atmospheric_lifetime_yr : float First-order e-folding decay lifetime (years). On Mars, photolysis and chemistry are slower than on Earth, so lifetimes are longer. rf_efficiency_W_m2_ppb : float Radiative forcing efficiency in W m⁻² per ppb (mixing ratio). Marinova 2005 Mars-specific values. gwp100 : float Global Warming Potential relative to CO₂ over 100 years (Earth-based reference, provided for familiarity). description : str Human-readable name.
Source code in package/src/interventions/compounds.py
get_compound(name)
¶
Return properties for a compound by name.
Raises¶
KeyError
If the compound is not in the registry. Available names are
listed by :func:list_compounds.
Source code in package/src/interventions/compounds.py
Radiative Forcing¶
src.interventions.forcing
¶
Radiative forcing from super-greenhouse gases — Mars.
Converts atmospheric GHG masses to concentration (ppb), computes total radiative forcing ΔF (W/m²), and updates the planet's greenhouse factor.
All tensor operations stay on the planet's device. Python-float constants are broadcast safely by PyTorch without allocating CPU intermediates.
References¶
Marinova et al. (2005), "Radiative-convective model of warming Mars with artificial greenhouse gases", J. Geophys. Res., 110, E03002.
compute_concentration_ppb(ghg_state, total_atm_mass_kg)
¶
Convert atmospheric masses to molar mixing ratios (ppb).
Uses the molar-fraction definition:
ppb_i = (M_i / MW_i) / (M_atm / MW_atm) × 1e9
where M_i is the atmospheric mass of compound i (kg), MW_i is its molecular weight (g/mol), M_atm is the total atmospheric mass (kg), and MW_atm is the mean molecular weight of the Mars atmosphere (g/mol).
Parameters¶
ghg_state : GHGState Current atmospheric GHG mass state. total_atm_mass_kg : torch.Tensor Total Mars atmospheric mass in kg (from mars.atmosphere.atmospheric_mass).
Returns¶
dict[str, torch.Tensor] Per-compound concentration in ppb, on the same device as ghg_state.
Source code in package/src/interventions/forcing.py
delta_F_total(ghg_state, total_atm_mass_kg)
¶
Compute total radiative forcing from all tracked GHGs (W/m²).
ΔF = Σ_i η_i [W m⁻² ppb⁻¹] × C_i [ppb]
This is the linear (optically thin) approximation appropriate for trace gases at concentrations < ~1000 ppb, which covers realistic injection rates over 50–100 year horizons.
Parameters¶
ghg_state : GHGState Current atmospheric GHG mass state. total_atm_mass_kg : torch.Tensor Total Mars atmospheric mass in kg.
Returns¶
torch.Tensor Scalar total forcing (W/m²) on the GHGState's device.
Source code in package/src/interventions/forcing.py
delta_F_from_composition(composition, total_pressure)
¶
Compute total GHG radiative forcing from atmosphere composition (W/m²).
Uses partial pressures (Pa) to derive mole-fraction concentrations (ppb), then applies compound-specific RF efficiencies:
ppb_i = P_i / P_total × 10⁹
ΔF = Σ_i η_i × ppb_i
Only species present in the COMPOUNDS registry contribute — background gases (CO₂, N₂, Ar) are silently skipped.
Parameters¶
composition : dict[str, torch.Tensor]
Species → partial pressure (Pa), as stored in mars.atmosphere.composition.
total_pressure : torch.Tensor
Total atmospheric surface pressure (Pa).
Source code in package/src/interventions/forcing.py
update_greenhouse_factor(mars, delta_F, baseline_ghf=None, baseline_olr=None)
¶
Apply cumulative GHG radiative forcing via the energy-balance GHF formula.
Derivation¶
At the original (CO₂-only) equilibrium::
F_in = OLR_baseline = ε σ (T_eq / GHF_base)⁴ (1)
Injected GHGs trap ΔF extra W/m². At the new radiative equilibrium the atmosphere must emit more to compensate — T rises until::
F_in + ΔF = ε σ (T_eq_new / GHF_base)⁴ (2)
Combining (1) and (2) gives the new effective greenhouse factor::
GHF_new = GHF_base × (1 + ΔF / F_in_base)^(1/4) (3)
where F_in_base = ε σ (T₀ / GHF_base)⁴ is the baseline OLR (≈ mean absorbed solar flux for the initial conditions).
This formula: * Is independent of instantaneous surface temperature — no singularity when Mars is in a cold polar winter (T ≈ 149 K). * Grows monotonically with cumulative ΔF — no year-to-year oscillation. * Is stable for any physically reachable ΔF over 50–200 year horizons.
Parameters¶
mars : Mars The Mars instance whose greenhouse_factor will be updated. delta_F : torch.Tensor Cumulative total forcing from all GHGs (W/m²), on mars._device. baseline_ghf : torch.Tensor, optional Initial CO₂-only GHF. Callers must pass the value saved at t=0 so that ΔF is applied relative to the fixed baseline (not compounded). Defaults to the current mars.thermal.greenhouse_factor (first call only). baseline_olr : torch.Tensor, optional Pre-computed F_in_base = ε σ (T₀/GHF_base)⁴ in W/m². Callers should cache this at initialisation to avoid recomputing it at every annual update. Computed on-the-fly if not provided.
Source code in package/src/interventions/forcing.py
Intervention Controller¶
src.interventions.controller
¶
InterventionController — annual GHG injection scheduler for Mars.
The controller drives terraforming experiments by injecting super-greenhouse
gases on a yearly schedule. All atmospheric state lives in
mars.atmosphere.composition — injected GHGs are just additional entries
in the same dict alongside CO₂, N₂, Ar. There is no separate GHGState object.
Architecture¶
mars.atmosphere.composition = {
"CO2": 580 Pa, # pre-existing
"N2": 15 Pa, # pre-existing
"CF4": X Pa, # added by inject()
"SF6": Y Pa, # added by inject()
...
}
mars.inject(schedule) converts kg → Pa and adds directly to composition.
mars.decay_ghg(dt_years) decays all COMPOUNDS-registered species in place.
mars.thermal.greenhouse_factor and mars.delta_F are always current.
The controller adds only one piece of state not derivable from physics: cumulative_injected_kg — how much total mass has ever been injected per species. This is a reporting quantity, not physics state.
InterventionSnapshot
dataclass
¶
Climate state at the end of one Mars year of intervention.
All tensor fields live on the planet's device.
Source code in package/src/interventions/controller.py
time
property
¶
Alias for time_s — keeps compatibility with Snapshot consumers.
InterventionController
¶
Annual GHG injection scheduler + climate simulation driver.
Injected gases become part of mars.atmosphere.composition — the same
dict that holds CO₂, N₂, and Ar. No separate atmospheric bookkeeper exists.
Parameters¶
mars : Mars
Configured Mars instance.
injection_schedule_kg_yr : dict[str, float]
{compound_name: kg_per_Mars_year} for each injected species.
All compound names must be present in the COMPOUNDS registry.
dt : float
Sub-annual integration timestep in seconds. Default 3600 s (1 hour).
accuracy : Accuracy
Integration accuracy passed to the underlying TimeController.
compile : bool
If True, wrap physics methods with torch.compile.
Examples¶
from src.celestials import Mars from src.interventions import InterventionController mars = Mars() ic = InterventionController(mars, {"CF4": 1e9, "SF6": 5e8}, dt=21600) history = ic.run(n_years=50)
mars.atmosphere.composition now contains CF4 and SF6 partial pressures¶
print(mars.atmosphere.composition.keys()) print(f"ΔF = {mars.delta_F.item():.3f} W/m²")
Source code in package/src/interventions/controller.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | |
run(n_years, callback=None)
¶
Run the intervention simulation for n_years Mars years.
Per year
- mars.inject(schedule) → partial pressures updated in composition
- TimeController.run(1 year) → ODE integrates with updated GHF
- mars.decay_ghg(1.0) → COMPOUNDS species decay in composition
- InterventionSnapshot → read from mars state
Returns¶
list[InterventionSnapshot] One snapshot per year (length = n_years).