zephyrus.hydrostatic
hydrostatic
hydrostatic.py
Hydrostatic escape: extended upper structure, per-species Jeans escape,
and the diffusion-limited supply cap.
Authors: Ioana Balint, Viesturs Strelcs, Mara Attia
volkov_flat_factor(lam)
Kinetic enhancement C(lambda) on the Jeans flux, dimensionless.
Direct simulation Monte Carlo runs exceed the Jeans flux by a factor 1.7 near lambda = 6, falling to 1.4 by lambda = 15 (Volkov et al. 2011); linear between, held at the endpoint values outside, where the caller flags the extrapolation on either side. Below lambda = 6 the held value likely understates the flux, and trace light species on a heavy background reach that side.
Source code in src/zephyrus/hydrostatic.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | |
jeans_effusion_velocity(T, m, lam)
Jeans effusion velocity sqrt(kT/(2 pi m)) (1 + lambda) exp(-lambda), m/s.
Source code in src/zephyrus/hydrostatic.py
87 88 89 | |
bates_extension(profile, M_p, T_exo, gamma=0.75, zeta_max=40.0, n_levels=400)
Bates upper structure above the topmost profile level.
The hydrostatic relation on the Bates temperature profile in
zeta = ln(p_top / p), with composition and mean mass frozen at the
anchor, integrates in closed form: d(1/r)/dzeta = -kB T / (G M mu)
and the Bates profile integrates analytically, so the structure carries
no step error at any resolution. It ends, flagged unbound, where the
local Jeans parameter falls to 2: an isothermal-tail structure is
unbound beyond that point and the geometry belongs to the overflow and
boil-off machinery, not to a hydrostatic exosphere.
Returns a dict of arrays on n_levels points spanning the extension
(zeta, p [Pa], r [m], T [K], n [m^-3]), the end
point zeta_end, the frozen mu [kg], the normalized species
vmr, the anchor values p0 and r0, the Bates parameters
(T_exo, T_top, gamma, M_p), and unbound.
bates_state evaluates the same structure at any zeta.
Source code in src/zephyrus/hydrostatic.py
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 | |
bates_state(ext, zeta)
Radius [m], temperature [K], number density [m^-3], and 1/r at zeta.
T = T_exo - (T_exo - T_top) exp(-gamma zeta) integrates to
T_exo zeta - (T_exo - T_top)(1 - exp(-gamma zeta)) / gamma, which
gives 1/r exactly. Beyond the point where 1/r reaches zero the
radius is infinite, and bates_extension stops well before it.
Source code in src/zephyrus/hydrostatic.py
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | |
find_exobase(ext, M_p, n_scan=201)
Exobase on the extension, as (zeta_exo, flags).
The level where the Maxwell mean free path 1/(sqrt(2) sigma n) with
the mixture cross section equals the local scale height
kB T r^2 / (G M mu), located by a bracketing root find on the
closed-form structure rather than snapped to a grid level, so the
exobase state does not depend on any quadrature resolution. n_scan
points bracket the first crossing. When the extension never reaches
that point its end is used, flagged exobase_not_reached. An exobase
at the anchor itself returns zeta_exo = 0, flagged
exobase_at_anchor.
Source code in src/zephyrus/hydrostatic.py
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 223 224 225 226 227 228 229 230 231 232 233 | |
hydrostatic_rates(profile, M_p, T_exo, gamma_bates=0.75, kzz_default=300.0, n_levels=400)
Per-species hydrostatic escape mapped onto per-element rates [kg/s].
Builds the Bates extension at the prescribed exobase temperature, locates the exobase, and combines the kinetic-corrected Jeans flux with the diffusion-limited supply by the harmonic mean, species by species (the module notes give the construction and its provenance). The species are the ones the supplied profile carries at its top level (the profile chemistry decides how atomized the exobase gas is); their rates map onto elements stoichiometrically at output.
The eddy diffusion coefficient comes from the profile's top level when
a kzz column is present, else kzz_default [m^2/s]. Species
whose supply-free Jeans rate already falls below one proton mass per
year skip the supply integrals (pruned in the per-species detail)
and return that rate at their profile-top mole fraction. It is an
estimate, not a bound, since diffusive enrichment can raise a light
species' full rate above it (2 to 5 times on the trace hydrogen and
helium profiles tested), enough to carry a rate just under the floor
above it. The shortcut exists because the integrals dominate
the cost of the branch on many-species profiles.
n_levels sets the quadrature resolution of the supply integrals,
which are first-order accurate in the log-pressure step;
hydrostatic_rates_refined refines it to a target. The exobase does
not depend on it.
Returns (per_element, detail); the detail dict carries the exobase
state, both escape temperatures, the dominant species that supplies
itself without a diffusion cap, the per-species terms, coefficient
provenance, and flags (including hydrostatic_lower_limit, which is
always on: nonthermal loss channels are absent).
Source code in src/zephyrus/hydrostatic.py
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | |
hydrostatic_rates_refined(profile, M_p, T_exo, gamma_bates=0.75, kzz_default=300.0, n_levels_min=200, n_levels_max=3200, rtol=0.01)
Hydrostatic rates refined until the quadrature stops moving them.
The exobase is located once, on the closed-form structure, so only the
supply integrals depend on the grid. They are first-order accurate in
the log-pressure step, so the change between a grid and its refinement
estimates the remaining error. The resolution doubles from
n_levels_min until two successive relative changes fall below
rtol, in the bulk rate and in every element whose rate clears the
rate floor, or until n_levels_max is reached. Two changes, so a
single chance agreement does not end the refinement, and every element,
since a trace whose supply integral is still moving can sit under a bulk
the dominant species sets alone. Meeting the target needs
n_levels_max of at least four times n_levels_min.
The finest grid's rates are returned, never an extrapolation.
The detail dict gains a convergence entry recording the levels used,
the last relative change in the bulk rate and the worst one across the
elements that clear the rate floor, the grid history, and whether the target was met. A call that
exhausts n_levels_max without meeting it reports converged False
rather than raising: the rate is still the best available and the
caller can see how far from the target it is.
Source code in src/zephyrus/hydrostatic.py
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 | |
gate_unstable(T_exo, detail, gate, f_plus_exo)
Escape-temperature gate on the hydrostatic branch.
The hydrostatic equilibrium is unstable when the exobase temperature
exceeds half the gating escape temperature (the stability criterion of
Chatterjee & Pierrehumbert 2026, their Figure 10). gate selects the
neutral or the plasma escape temperature; both are always computed, and
the returned contested marks points where the two conventions
disagree, which is where the (unmodeled) ion physics decides the branch
assignment and both branch rates belong in the diagnostics.
f_plus_exo is carried for the caller's record and does not gate.
Source code in src/zephyrus/hydrostatic.py
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 | |