Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
a12a2f6
Use exact SI constants and add proton mass, Planck constant, and Jupi…
maraattia Aug 20, 2026
cf146b8
Measure the tidal factor from the radius the scaling selects and name…
maraattia Aug 20, 2026
2caecb1
Add element masses, formula parsing, and composition atomization
maraattia Aug 20, 2026
cb4709a
Add the atmosphere profile container and the escape working levels
maraattia Aug 20, 2026
b1a3d27
Add the collision cross-section ladder and the sonic-point Knudsen sw…
maraattia Aug 20, 2026
c6e6b01
Add the binary diffusion coefficient library with provenance classes
maraattia Aug 20, 2026
01092cd
Add bolometrically driven boil-off escape with Bondi and luminosity caps
maraattia Aug 20, 2026
493104c
Add radiative cooling data and the wind temperature thermostat
maraattia Aug 20, 2026
5d51e5d
Add the energy limited and radiation recombination limited hydrodynam…
maraattia Aug 20, 2026
3c08135
Add hydrostatic escape with the extended upper structure and supply cap
maraattia Aug 20, 2026
c3f7abc
Add the simultaneous N-species fractionation closure with its verific…
maraattia Aug 20, 2026
6abee82
Add the regime diagnostics reported beside every dispatch verdict
maraattia Aug 20, 2026
a2ee93c
Assemble the escape regime dispatcher and export it from the package
maraattia Aug 20, 2026
ed92abc
Track the new escape sources in the test quality gates and agent guide
maraattia Aug 20, 2026
5255cab
Document the escape regime dispatcher across the docs site
maraattia Aug 20, 2026
7f7c621
Sharpen pinned-value tests at non-degenerate geometry and close weak …
maraattia Aug 20, 2026
7297ace
Host EL_escape in hydrodynamic.py behind a compatibility re-export
maraattia Aug 21, 2026
b070eda
Restructure the docs around the two-channel, five-regime model
maraattia Aug 21, 2026
cb1f2f3
Report the wind base pressure as a level value
maraattia Aug 21, 2026
080c7a1
Add a worked example for the regime dispatcher
maraattia Aug 21, 2026
6a52f28
Document the dispatcher end to end for users
maraattia Aug 21, 2026
74e8005
Pin the example output the docs quote
maraattia Aug 21, 2026
9731510
State the diagnostics group count per branch
maraattia Aug 21, 2026
1b34dc6
Keep the dominant species out of the flags
maraattia Aug 21, 2026
b989dc3
Render the mermaid diagrams on the docs site
maraattia Aug 21, 2026
ba08214
Name the closure multiplier after the shared scale height
maraattia Aug 21, 2026
c088b23
Rename the verdict guide to troubleshooting
maraattia Aug 21, 2026
d6ebd7a
Show the code behind every output in the tutorial
maraattia Aug 21, 2026
60056ec
Read the wind-versus-thermosphere screen from its source
maraattia Aug 22, 2026
48abaf9
Anchor the evaluation order with its own flowchart
maraattia Aug 22, 2026
67121bf
Make the tutorial's first step runnable as printed
maraattia Aug 22, 2026
dd80ef1
Say what the RR mechanism diagnostic separates
maraattia Aug 22, 2026
186aa8c
Retire the base Jeans parameter mechanism split
maraattia Aug 22, 2026
a3c66f8
Divide the luminosity cap by the tidal barrier
maraattia Aug 22, 2026
5dfb7b6
Keep the branch rate under the overflow label
maraattia Aug 22, 2026
3618fd2
Report the rate floor beside every verdict
maraattia Aug 22, 2026
bb2589e
Say what the overflow label does and does not mean
maraattia Aug 22, 2026
90bacde
Set the figure annotations in the mono family
maraattia Aug 22, 2026
f559a4f
Cover every species a coupled run can supply
maraattia Aug 23, 2026
3529574
Keep trace species in the exobase anchor
maraattia Aug 23, 2026
ef0bbd4
Split a dry reservoir by its base composition
maraattia Aug 23, 2026
7670e84
Pin small quantities against a zero absolute tolerance
maraattia Aug 23, 2026
c4b100d
Check that the validation inventory names real tests
maraattia Aug 23, 2026
6df48e1
State the near-Roche trigger the way the code tests it
maraattia Aug 23, 2026
a1f40de
Read the nitrogen recombination fit from its table
maraattia Aug 23, 2026
8d98778
Correct four bibliographic records
maraattia Aug 23, 2026
2fa1a1a
Bound every numeric dispatch setting
maraattia Aug 23, 2026
4d0d9a3
Report what the tidal factor is doing to the rate
maraattia Aug 23, 2026
8d961e4
Declare the wind mean-mass convention and what it recovers
maraattia Aug 23, 2026
a723c6e
Scope every flag to the branch that produced the rate
maraattia Aug 23, 2026
393321c
Define the rate floor once
maraattia Aug 23, 2026
0c5a8a9
Catch a malformed profile where it enters
maraattia Aug 23, 2026
546acb1
Stop the profile top at the last bound level
maraattia Aug 23, 2026
eaf45b5
Requote the boil-off flags the dispatch now returns
maraattia Aug 23, 2026
23e90e7
Build one upper structure per dispatch
maraattia Aug 23, 2026
0530c85
Take both front constants from one front
maraattia Aug 23, 2026
164aad1
Refine the supply quadrature to a stated target
maraattia Aug 23, 2026
9baf726
Floor the exobase temperature at the profile top
maraattia Aug 23, 2026
68dbae9
Sweep the exobase temperature above the profile top
maraattia Aug 23, 2026
69251c8
Report the optical depth of the boil-off launch level
maraattia Aug 23, 2026
9f503ff
Say what the collisionality ladder assumes
maraattia Aug 28, 2026
fcbb47d
Order the diffusion ladder by provenance class
maraattia Aug 28, 2026
6b52d3e
Read the band quantum in kelvin and cap its escape probability
maraattia Aug 28, 2026
7f29ff5
Say what a clamped wind temperature is
maraattia Aug 28, 2026
1837184
Pin the split by identity, every flag, and the printed bands
maraattia Aug 28, 2026
a8bf9b9
Pin the absolute scale of six closed forms
maraattia Aug 28, 2026
a0a7c1c
Hold the tutorial's numbers to what the code prints
maraattia Aug 28, 2026
933f825
Let the module marker set the tutorial test's tier
maraattia Aug 28, 2026
13fe11f
Put the repository root on the path for the tutorial test
maraattia Aug 28, 2026
e8665d6
Run the tutorial's stellar track in the tier that has its data
maraattia Aug 28, 2026
3f1b8a9
Merge branch 'main' into ma/escape-regime-dispatcher
maraattia Aug 28, 2026
131cfac
Say what the pages actually describe
maraattia Aug 28, 2026
060a667
Correct five citation details
maraattia Aug 28, 2026
9022f49
Write what the fallback order does instead of naming it a ladder
maraattia Aug 28, 2026
d788998
Put the mono family behind its own dependency guard
maraattia Aug 28, 2026
ee06bb4
Add the Roche lobe overflow nozzle rate module
maraattia Aug 31, 2026
676c248
Dispatch the L1 nozzle transfer as a rate candidate
maraattia Aug 31, 2026
d123611
Document the overflow label's two readings
maraattia Aug 31, 2026
e01b76d
Correct the diagnostic group and case counts
maraattia Aug 31, 2026
3717e4d
Average the L1 transfer over the orbit
maraattia Aug 31, 2026
ad2ef44
Read the overflow subflag against the Roche lobe
maraattia Aug 31, 2026
0d75b03
Launch the wind-mode transfer from the wind's own column
maraattia Aug 31, 2026
aba0cd7
Merge only the winning candidate's warnings
maraattia Sep 2, 2026
244c2e9
Name the dispatched transfer with its own label
maraattia Sep 2, 2026
1b38d32
Reject unphysical arguments on the nozzle surface
maraattia Sep 2, 2026
76a6765
Measure the launch level as a width off an isothermal column
maraattia Sep 2, 2026
61d1385
State what the Table 2 anchor covers
maraattia Sep 2, 2026
b946ed0
Correct what the overflow pages claim about the primary
maraattia Sep 2, 2026
e16416c
Date the overflow validation comparison correctly
maraattia Sep 2, 2026
e8d4ba6
Make the post-gate bolometric residual opt-in
maraattia Sep 3, 2026
1494d8c
Document the opt-in bolometric residual
maraattia Sep 3, 2026
9e7b128
State the Bondi cap's temperature convention
maraattia Sep 3, 2026
65e543f
Let the boil-off candidate own its diagnostics
maraattia Sep 28, 2026
c8a5f06
Quote the default dispatch from a tutorial snippet
maraattia Sep 28, 2026
7677070
Anchor the boil-off branch on its launch level
maraattia Sep 28, 2026
ebf347b
Admit the residual in the example's overflow case
maraattia Sep 28, 2026
3bc9684
Say what the RR separator is instead of its history
maraattia Sep 28, 2026
79bcca1
Cap inline comments in the physics data modules
maraattia Sep 28, 2026
a9d662d
Cap inline comments in the escape branches
maraattia Sep 28, 2026
5144a15
Cap inline comments in the tests at three lines
maraattia Sep 28, 2026
77afc4f
Quote the residual gap at its retargeted state
maraattia Sep 28, 2026
c28a5d2
Format the modules and tests the branch adds
maraattia Sep 28, 2026
7e349cc
Merge remote-tracking branch 'origin/main' into ma/escape-regime-disp…
maraattia Sep 28, 2026
9864520
Cap the XUV wind at the photon count
maraattia Sep 28, 2026
af9d78f
Check boil-off termination on the uncapped wind
maraattia Sep 28, 2026
ad40af0
State which van der Waals radii Bondi omits
maraattia Sep 28, 2026
3e8a10c
Add a switch for the recombination-limited candidate
maraattia Sep 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions .github/.claude/rules/zephyrus-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,34 @@ The guard lines are mandatory whenever the test's primary assertion is a `pytest

### When required

Every unit test on a **physics source** must assert at least one of the four invariants below. The physics source is:
Every unit test on a **physics source** must assert at least one of the four invariants below. The physics sources are:

```
src/zephyrus/escape.py
src/zephyrus/atomic_data.py
src/zephyrus/boiloff.py
src/zephyrus/collision.py
src/zephyrus/diagnostics.py
src/zephyrus/diffusion.py
src/zephyrus/dispatcher.py
src/zephyrus/fractionation.py
src/zephyrus/hydrodynamic.py
src/zephyrus/hydrostatic.py
src/zephyrus/knudsen.py
src/zephyrus/profiles.py
src/zephyrus/thermostat.py
```

Per-source-file granularity: `escape.py` needs at least one `@pytest.mark.physics_invariant` test and at least one `@pytest.mark.reference_pinned` test in `tests/test_escape.py`. Granularity is per source file, not per directory.
Per-source-file granularity: every physics source needs at least one `@pytest.mark.physics_invariant` test and at least one `@pytest.mark.reference_pinned` test in its companion `tests/test_<source>.py`. Granularity is per source file, not per directory.

Utility sources are exempt from the physics-invariant requirement but still subject to all anti-happy-path rules:

```
src/zephyrus/__init__.py (version string)
src/zephyrus/__init__.py (version string, package exports)
src/zephyrus/composition.py (element masses, formula parsing)
src/zephyrus/escape.py (compatibility re-export of EL_escape,
which lives in hydrodynamic.py; its
companion test file guards the released
import path and the EL physics through it)
src/zephyrus/constants.py (pure physical constants, no derivation)
src/zephyrus/planets_parameters.py (tabulated star-planet parameters)
```
Expand Down Expand Up @@ -291,6 +307,7 @@ Write the OUTCOME (what the test verifies; what the PR achieves) never the PROCE
- Test file names mirror source 1:1: `src/zephyrus/<file>.py` -> `tests/test_<file>.py`. Documented exceptions to the 1:1 rule:
- **Cross-cutting coupling tests** (`test_mors_coupling.py`, `test_earth.py`): regressions that span the MORS flux hand-off and the escape formula rather than a single source file. `test_mors_coupling.py` mocks the stellar-luminosity lookup so the coupling recipe runs in the fast `unit` tier without a download; `test_earth.py` performs a real MORS lookup end to end and carries the `integration` tier.
- **Property-based companion** (`test_escape_properties.py`): the Hypothesis-driven sweeps for `escape.py`. They sit in their own module so the `pytest.importorskip('hypothesis')` gate covers only the property tests, leaving the closed-form pins and error-contract guards in `test_escape.py` running when the develop-extra dependency is absent.
- **Shipped examples** (`test_examples.py`): the scripts under `examples/` and the documentation pages that quote their output. The tests import an example module by path and exercise its own entry points, so a physics change that moves a documented result fails CI instead of leaving a stale number on a docs page. They carry the `smoke` tier because they run the real dispatch path, and they mock the stellar lookup, because the PR job does not have the MORS tracks. When adding an example, extend this file rather than creating a per-example test module.

---

Expand Down
29 changes: 21 additions & 8 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Sister modules in the ecosystem: AGNI (atmospheric radiative transfer), SOCRATES

**Languages**: Python 3.12+.

**Size**: 3 source files in `src/zephyrus/`.
**Size**: 17 source files in `src/zephyrus/`.

**Target Runtime**: Python 3.12+ on Linux / macOS.

Expand Down Expand Up @@ -134,13 +134,26 @@ pre-commit install -f

### Key Directories

- `src/zephyrus/` - Main Python source code (flat layout, 3 files)
- `__init__.py` - Package version (utility)
- `src/zephyrus/` - Main Python source code (flat layout)
- `__init__.py` - Package version and top-level exports (utility)
- `constants.py` - Physical constants and unit conversions (utility)
- `planets_parameters.py` - Star-planet system parameters (utility)
- `escape.py` - Energy-limited (EL) atmospheric escape, tidal correction (physics)

- `tests/` - Test suite. Each physics source has a 1:1 test file at `tests/test_<file>.py`. Cross-cutting or coupling regression tests (e.g. `test_earth.py`) are the exception.
- `composition.py` - Element masses, formula parsing, atomization (utility)
- `escape.py` - Compatibility re-export of `EL_escape` (utility; the physics lives in `hydrodynamic.py`)
- `collision.py` - Giant-impact atmospheric erosion scaling law (physics)
- `profiles.py` - Atmosphere-profile container and escape working levels (physics)
- `knudsen.py` - Collision cross sections and the sonic-point Knudsen switch (physics)
- `diffusion.py` - Binary diffusion coefficient library with provenance (physics)
- `atomic_data.py` - Cooling data tables and closed-form rate coefficients (physics)
- `thermostat.py` - Wind-temperature thermostat (heating against cooling) (physics)
- `boiloff.py` - Bolometrically driven boil-off escape (physics)
- `hydrodynamic.py` - `EL_escape` plus the EL and radiation-recombination-limited dispatch limbs (physics)
- `hydrostatic.py` - Jeans escape with the diffusion-limited supply cap (physics)
- `fractionation.py` - Simultaneous N-species fractionation closure (physics)
- `diagnostics.py` - Regime diagnostics reported beside every verdict (physics)
- `dispatcher.py` - The escape-regime dispatcher assembling the branches (physics)

- `tests/` - Test suite. Each physics source has a 1:1 test file at `tests/test_<file>.py`. Cross-cutting or coupling regression tests (e.g. `test_earth.py`) and the shipped-example tests (`test_examples.py`) are the exception.

- `tools/` - Build / utility scripts
- `check_test_quality.py` - AST linter (blocking on PRs)
Expand Down Expand Up @@ -168,7 +181,7 @@ pre-commit install -f

### Entry Points

- **Python API**: `from zephyrus.escape import EL_escape`.
- **Python API**: `from zephyrus.escape import EL_escape` (energy-limited rate); `from zephyrus import dispatch, EscapeInputs, DispatchSettings` (the regime dispatcher); `from zephyrus.collision import mass_loss` (giant-impact erosion).
- **No CLI**: ZEPHYRUS is library-only; PROTEUS provides the simulator CLI that calls ZEPHYRUS.

## Testing Standards
Expand All @@ -177,7 +190,7 @@ ZEPHYRUS is scientific simulation code, so the test suite is held to physics-gra

### Structure

- Tests mirror source 1:1: `src/zephyrus/<file>.py` -> `tests/test_<file>.py`. Cross-cutting or coupling regression tests (e.g. `test_earth.py`) are the exception, not the rule.
- Tests mirror source 1:1: `src/zephyrus/<file>.py` -> `tests/test_<file>.py`. Cross-cutting or coupling regression tests (e.g. `test_earth.py`) and the shipped-example tests (`test_examples.py`, which pin the numbers the docs quote) are the exception, not the rule.
- Framework: `pytest` exclusively in the `tests/` directory.

### Markers and the module-level marker rule
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ src/zephyrus/_version.py
# Verification and diagnostic artifacts (plots, raw data, plot scripts)
output_files/

# Figures the shipped examples write, which the tutorials ask readers to
# create in the repository root
output/

# Local editor and session state (personal, not shared)
/.claude/
.mcp.json
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Named after Zephyrus, the Greek god of the west wind and a messenger of spring.

## Escape model

Energy-limited (EL) escape: the deposited XUV power divided by the gravitational binding energy of the escaping gas, with an optional tidal enhancement `K_tide`. The XUV cross section scales as `Rp * Rxuv**2` (default) or `Rxuv**3`, and the tidal factor applies only outside the Roche lobe (`R_Hill / R_XUV > 1`).
Energy-limited (EL) escape: the deposited XUV power divided by the gravitational binding energy of the escaping gas, with an optional tidal enhancement `K_tide`. The XUV cross section scales as `Rp * Rxuv**2` (default) or `Rxuv**3`, and the tidal factor applies only outside the Roche lobe, measured from whichever radius the scaling selects: `R_Hill / Rp > 1` for the default `Rp * Rxuv**2` form and `R_Hill / Rxuv > 1` for `Rxuv**3`.

## Documentation

Expand Down
72 changes: 72 additions & 0 deletions docs/Explanations/energy_limited.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Energy-limited escape

Energy-limited (EL) escape is the default rate prescription of ZEPHYRUS: the one PROTEUS consumes at each coupled time step, through the released entry point `zephyrus.escape.EL_escape`. Within the [escape-regime framework](regimes.md) it is one of the two hydrodynamic limits, valid when the atmosphere sustains a collisional, XUV-driven fluid wind; this page defines the prescription itself, its radius scaling, and its tidal correction.

The physical idea is an energy budget. The stellar X-ray and extreme-ultraviolet (XUV) flux absorbed high in the atmosphere heats the gas; if a fixed fraction of that power goes into lifting gas out of the planet's gravitational well, the mass-loss rate follows from dividing the absorbed power by the escape energy per unit mass [^watson][^lammer2003]. The rate is computed as

$$\dot{M}_\mathrm{EL} = \frac{\epsilon\,\pi\,R^3\,F_\mathrm{XUV}}{G\,M_\mathrm{p}\,K_\mathrm{tide}} \tag{1}$$

where $\epsilon$ is the escape efficiency (the fraction of intercepted XUV power converted into work against gravity), $R^3$ is the radius term selected below, $F_\mathrm{XUV}$ is the XUV flux received at the planet's orbit (supplied by [MORS](https://proteus-framework.org/MORS) in coupled runs), $G$ is the gravitational constant, $M_\mathrm{p}$ is the planetary mass, and $K_\mathrm{tide}$ is the tidal correction of Eq. (2). Canonical efficiencies for rocky planets lie between 0.1 and 0.3, and ZEPHYRUS accepts any $\epsilon \in (0, 1]$; hydrodynamic simulations find that for strongly bound planets the effective efficiency collapses far below the canonical band, reaching of order $10^{-2}$ above a threshold gravitational potential near $\log_{10}(G M_\mathrm{p} / R_\mathrm{p}) \approx 12.9$ to $13.2$ in cgs units [^caldiroli]. The threshold is on the untidal specific binding energy, which is the convention the screen in the diagnostics uses and the one Salz et al. (2016) share; the tidal factor enters the rate, not the potential the threshold is quoted against. The regime framework offers that fitted efficiency as an option; the entry point itself treats $\epsilon$ as an input.

Two radii enter the problem, and keeping them apart matters. $R_\mathrm{p}$ is the planetary (interior) radius. $R_\mathrm{XUV}$ is the radius at which the atmosphere becomes optically thick to XUV photons; in PROTEUS it is recomputed at each time step from the atmospheric structure at a configured reference pressure, by default 20 mbar following the photosphere-type level of Baumeister et al. (2023) [^baumeister]. That level is a bookkeeping radius for the intercepting area: the XUV heating is actually deposited, and the wind launched, at the far lower pressure (of order a nanobar) where the gas first reaches unit optical depth to ionizing photons [^lopez2017]; the [escape-regime framework](regimes.md) locates that launching level on the profile when it needs it.

## Radius scaling

The cubic radius term in Eq. (1) is selected at runtime by the `scaling` argument of `EL_escape`:

| `scaling` | $R^3$ | Description |
|---|---|---|
| `2` | $R_\mathrm{p}\,R^2_\mathrm{XUV}$ | Default; the XUV-absorbing cross section paired with the potential measured at the surface radius, the form of Erkaev et al. (2007) [^erkaev] |
| `3` | $R^3_\mathrm{XUV}$ | All three powers taken at the XUV radius, the single-radius form of Lopez, Fortney & Miller (2012) [^lfm2012] and Lehmer & Catling (2017) [^lehmer] |

Both forms reduce to $R_\mathrm{p}^3$ when $R_\mathrm{XUV} = R_\mathrm{p}$, the conservative lower bound adopted by Luger & Barnes (2015) [^luger] and Moore et al. (2023) [^moore]. Allowing $R_\mathrm{XUV} > R_\mathrm{p}$ increases the effective XUV-absorbing area and therefore the escape rate.

## Tidal correction

When the `tidal_contribution` flag is `True`, the effective potential barrier is reduced by the host star's tidal field, following Erkaev et al. (2007), their Eq. 17 [^erkaev]:

$$K_\mathrm{tide} = 1 - \frac{3}{2\xi} + \frac{1}{2\xi^3}, \qquad \xi = \frac{R_\mathrm{Hill}}{R} \tag{2}$$

with the periapsis Hill radius

$$R_\mathrm{Hill} = a\,(1-e)\,\left(\frac{M_\mathrm{p}}{3\,M_\star}\right)^{1/3} \tag{3}$$

where $a$ is the semi-major axis, $e$ the orbital eccentricity, and $M_\star$ the stellar mass. The radius $R$ in $\xi$ is the one that appears linearly in the $R^3$ term of Eq. (1): $R_\mathrm{p}$ for `scaling=2` (the convention of Erkaev et al. 2007, whose own $\xi$ is the Roche-lobe distance over the planetary radius) and $R_\mathrm{XUV}$ for `scaling=3`, where the XUV radius is the only radius in the problem.

Factoring the numerator gives $K_\mathrm{tide} = (\xi - 1)^2\,(2\xi + 1) / (2\xi^3)$, non-negative for every $\xi > 0$ with a double root at $\xi = 1$. In the physical regime $\xi > 1$ it lies in $(0, 1)$, rising toward 1 for $\xi \gg 1$ (the escape level deep inside the Hill sphere) and falling toward 0 as the atmosphere expands toward the Roche lobe at $\xi = 1$. Because the rate divides by $K_\mathrm{tide}$, the tidal correction enhances escape and diverges at the Roche lobe, so the tidally corrected rate is defined only for $\xi > 1$: `EL_escape` raises a `ValueError` for $\xi \le 1$, where the atmosphere reaches the Roche lobe and the energy-limited approximation no longer applies. When `tidal_contribution` is `False`, $K_\mathrm{tide} = 1$. The [regime framework](regimes.md) handles the $\xi \le 1$ geometry itself, as the `roche_overflow` label.

## When the prescription applies

The EL form is appropriate in the high-irradiation, collisional-wind regime that dominates the loss during roughly the first $10^6$ to $10^8$ years of a close-in planet's evolution [^watson][^lammer2003]. Outside it, at lower XUV flux or for a less extended atmosphere, particle-by-particle (nonthermal and Jeans) escape becomes comparable or dominant and the bulk EL prescription no longer applies. The [regime framework](regimes.md) classifies each state before choosing a rate; when using `EL_escape` alone, verify that the XUV-driven loss genuinely dominates (for scale, present-day nonthermal rates for an Earth-mass planet are of order $10^7$ to $10^8$ g s$^{-1}$; Kislyakova et al. 2014 [^kislyakova]).

Bulk removal is the second assumption. When the escaping particle flux drops below the critical value needed to drag a heavy species along, the outflow fractionates: hydrogen escapes preferentially and the residual atmosphere is enriched in heavy species [^wordsworth2018][^cherubim2024]. For scale, the critical flux for water in a hydrogen background is about $1.9 \times 10^{8}$ g s$^{-1}$ (Yoshida et al. 2022 [^yoshida]). `EL_escape` removes everything in bulk; the [fractionation](fractionation.md) page describes the closure that resolves the partition when the regime framework confirms a wind.

---

[^watson]: Watson, A. J., Donahue, T. M., & Walker, J. C. G. (1981). The dynamics of a rapidly escaping atmosphere: applications to the evolution of Earth and Venus. *Icarus, 48*(2), 150–166. https://doi.org/10.1016/0019-1035(81)90101-9

[^lammer2003]: Lammer, H., Selsis, F., Ribas, I., et al. (2003). Atmospheric loss of exoplanets resulting from stellar X-ray and extreme-ultraviolet heating. *The Astrophysical Journal, 598*(2), L121–L124. https://doi.org/10.1086/380815

[^erkaev]: Erkaev, N. V., Kulikov, Y. N., Lammer, H., et al. (2007). Roche lobe effects on the atmospheric loss from "Hot Jupiters". *Astronomy & Astrophysics, 472*(1), 329–334. https://doi.org/10.1051/0004-6361:20066929

[^lfm2012]: Lopez, E. D., Fortney, J. J., & Miller, N. (2012). How thermal evolution and mass-loss sculpt populations of super-Earths and sub-Neptunes: application to the Kepler-11 system and beyond. *The Astrophysical Journal, 761*(1), 59.

[^lehmer]: Lehmer, O. R., & Catling, D. C. (2017). Rocky worlds limited to 1.8 Earth radii by atmospheric escape during a star's extreme UV saturation. *The Astrophysical Journal, 845*(2), 130.

[^lopez2017]: Lopez, E. D. (2017). Born dry in the photoevaporation desert: Kepler's ultra-short-period planets formed water-poor. *Monthly Notices of the Royal Astronomical Society, 472*(1), 245–253.

[^baumeister]: Baumeister, P., Tosi, N., Brachmann, C., Grenfell, J. L., & Noack, L. (2023). Redox state and interior structure control on the long-term habitability of stagnant-lid planets. *Astronomy & Astrophysics, 675*, A122. https://doi.org/10.1051/0004-6361/202245791

[^caldiroli]: Caldiroli, A., Haardt, F., Gallo, E., Spinelli, R., Malsky, I., & Rauscher, E. (2022). Irradiation-driven escape of primordial planetary atmospheres II. Evaporation efficiency of sub-Neptunes through hot Jupiters. *Astronomy & Astrophysics, 663*, A122. https://doi.org/10.1051/0004-6361/202142763

[^luger]: Luger, R., & Barnes, R. (2015). Extreme water loss and abiotic O$_2$ buildup on planets throughout the habitable zones of M dwarfs. *Astrobiology, 15*(2), 119–143. https://doi.org/10.1089/ast.2014.1231

[^moore]: Moore, K., Cowan, N. B., & Boukaré, C.-É. (2023). The role of magma oceans in maintaining surface water on rocky planets orbiting M-dwarfs. *Monthly Notices of the Royal Astronomical Society, 526*(4), 6235–6249. https://doi.org/10.1093/mnras/stad3138

[^kislyakova]: Kislyakova, K. G., Johnstone, C. P., Odert, P., et al. (2014). Stellar wind interaction and pick-up ion escape of the Kepler-11 "super-Earths". *Astronomy & Astrophysics, 562*, A116. https://doi.org/10.1051/0004-6361/201322933

[^wordsworth2018]: Wordsworth, R. D., Schaefer, L. K., & Fischer, R. A. (2018). Redox evolution via gravitational differentiation on low-mass planets: implications for abiotic oxygen, water loss, and habitability. *The Astronomical Journal, 155*(5), 195. https://doi.org/10.3847/1538-3881/aab608

[^cherubim2024]: Cherubim, C., Wordsworth, R., Hu, R., & Shkolnik, E. (2024). Strong Fractionation of Deuterium and Helium in Sub-Neptune Atmospheres along the Radius Valley. *The Astrophysical Journal, 967*(2), 139. https://doi.org/10.3847/1538-4357/ad3e77

[^yoshida]: Yoshida, T., Terada, N., Ikoma, M., & Kuramoto, K. (2022). Less Effective Hydrodynamic Escape of H$_2$-H$_2$O Atmospheres on Terrestrial Planets Orbiting Pre-main-sequence M Dwarfs. *The Astrophysical Journal, 934*(2), 137. https://doi.org/10.3847/1538-4357/ac7be7
Loading
Loading