Deco models¶
Model contract¶
Decompression model base classes.
Each deco model defines its own DecoState subclass — the typed,
copyable snapshot of everything the model knows at an instant (tissue
tensions, ceiling, …). Models are generic over their state type, so
ZHL16C.integrate_segment(...) returns a ZHL16State, not a bare dict.
State snapshots are what the result/report layer stores at checkpoints and
what counterfactual queries (TTS at time t) resume from.
- class diveplan.models.base.BaseDecoModel(*args, **kwargs)[source]¶
-
Base class for all decompression models.
Generic over the model’s
DecoStatesubclass: each model type processes and returns its own state type.- property name: str¶
Display name of this model instance, conservatism included.
Defaults to the registry
NAME. Models with a conservatism setting (gradient factors, VPM conservatism level) append it, so the name alone says how a schedule was computed — e.g."zhl16c GF 30/70"or"vpmb +3".
- integrate_segment(segment)[source]¶
Integrate a dive segment into the model and return the state after it.
Numerical scheme: rectangle rule — each sample step is integrated at the pressure of its end point over the actual elapsed dt (the final step may be shorter than the sample rate). Models with an analytic solution for linear pressure change (Schreiner) should override this.
- Parameters:
segment (
DiveSegment)- Return type:
- integrate(pressure, gas, dt)[source]¶
Advance the model by a single step at the given pressure and gas.
Public stepwise entry point for consumers that drive their own sample loop (result layer, planner);
integrate_segmentremains the segment-level API.
- abstractmethod get_ceiling()[source]¶
Return the current (conservative) ceiling.
Anything the ceiling depends on beyond tissue state — gradient factors, conservatism level — is instance configuration, baked in at construction. Overrides keep this exact signature.
- Return type:
- get_ascent_ceiling(target, first_stop=None)[source]¶
Ceiling for testing an ascent to target during staged deco.
The ascent planner calls this — never a model-specific API — so models whose tolerance evolves over the ascent can express that here: Bühlmann interpolates its gradient factor toward target, and VPM-B’s Boyle/CVA compensation will land here too. first_stop is the first (deepest) stop of the ascent being planned, or None while it is not yet known.
Default: the plain
get_ceiling(), which is correct for any model whose tolerance does not depend on ascent context.
Bühlmann engine and helpers¶
Generic Bühlmann decompression engine.
All Bühlmann-family models share the same algorithm — parallel Haldane compartments integrated toward alveolar inert-gas pressures, with a ceiling from the a/b M-value line (optionally scaled by Baker gradient factors). Variants differ only in their coefficient tables: number of compartments, half-times, and a/b values.
BuhlmannModel implements the whole algorithm; a concrete model
(e.g. ZHL16C) supplies only NAME
and the six class-level tables. Table consistency is validated at class
definition time. Running without gradient factors is the default
(Gradient(1.0, 1.0) — raw Bühlmann); pass a Gradient for GF.
- class diveplan.models.buhlmann.model.BuhlmannModel(gradient=None)[source]¶
Bases:
BaseDecoModel[BuhlmannState]Bühlmann algorithm over a subclass-supplied coefficient table.
Subclasses define
NAMEand the six tables (half-times in minutes,ain bar,bdimensionless), all of equal length:class ZHL16C(BuhlmannModel): NAME = "zhl16c" N2_HALF_TIMES = (5.0, 8.0, ...) ...
Fresh instances start at surface equilibrium on air. The sample rate is read from
DiveConfig.current().planning.sample_rate_sat construction.- Parameters:
gradient (
Gradient|str|None) – GF pair — aGradientor the usual string notation ("30/70", percentages). Defaults to raw Bühlmann (GF 100/100).
- get_ceiling()[source]¶
Ceiling at the instance’s GF-low — the conservative bound.
A ceiling above surface pressure means decompression stops are required. The gradient pair is instance configuration; ceilings under a different GF come from an instance built with it, not a parameter. Ascent-context interpolation is
get_ascent_ceiling().- Return type:
- get_ascent_ceiling(target, first_stop=None)[source]¶
Ceiling with the gradient factor interpolated at target.
GF-low anchors at first_stop (the deepest stop of the ascent being planned), GF-high at the surface. Until the first stop is known the conservative GF-low applies.
- set_state(state)[source]¶
Restore tissue tensions from a snapshot (exact, lossless).
- Raises:
ValueError – If the snapshot’s compartment count does not match this model’s table.
- Parameters:
state (
BuhlmannState)- Return type:
- class diveplan.models.buhlmann.model.BuhlmannState(tissues)[source]¶
Bases:
DecoStateFrozen snapshot of (ppn2, pphe) tissue tensions in float mbar.
Shared by all Bühlmann-family models; the tuple length equals the model’s compartment count.
Shared Bühlmann machinery: gradient factors and Haldane tissue compartments.
Unit conventions¶
Bühlmann
acoefficients are published in bar; they are converted to mbar internally.bcoefficients are dimensionless.Tissue tensions are tracked as float mbar internally, not integer-mbar
Pressure: at fine sample rates (1 s) a slow compartment’s per-step change is far below 1 mbar, and integer quantization would silently freeze it.Pressureremains the boundary type for all inputs and outputs.Alveolar (inspired) inert-gas pressure subtracts water vapor at body temperature:
(P_amb − 62.7 mbar) · fraction(Bühlmann’s 0.0627 bar).
Gradient factors follow Erik Baker’s convention: GF-low applies at the first
(deepest) stop, GF-high at the surface, interpolated linearly in ambient
pressure between the two. Factors are fractions (Gradient(0.3, 0.85) is
GF 30/85); Gradient(1.0, 1.0) is raw Bühlmann.
- class diveplan.models.buhlmann.common.Gradient(gf_low, gf_high)[source]¶
Bases:
objectA gradient-factor pair (Baker GF low/high), as fractions.
GF-low is the allowed fraction of the Bühlmann M-value gradient at the first (deepest) stop; GF-high applies at the surface.
factor()interpolates linearly in ambient pressure between the two.- classmethod from_str(s)[source]¶
Parse the usual GF notation:
"30/70","GF 30/70","85/85".Numbers are percentages (the way divers write them);
"100/100"is raw Bühlmann.- Raises:
ValueError – If the string is not two /-separated numbers.
- Parameters:
s (
str)- Return type:
- class diveplan.models.buhlmann.common.Compartment(*, ht_n2, ht_he, a_n2, a_he, b_n2, b_he, ppn2=None, pphe=None)[source]¶
Bases:
objectOne Haldane tissue compartment with Bühlmann a/b coefficients.
Holds the compartment constants (N2/He half-times in minutes,
ain bar,bdimensionless) and the current inert-gas tensions. Fresh compartments default to surface equilibrium on air: N2 at(P_surface − P_H2O) · 0.79, He at zero.- Parameters:
- property tensions_mbar: tuple[float, float]¶
Exact (ppn2, pphe) tensions in float mbar — for state snapshots.
- integrate(pressure, gas, duration)[source]¶
Haldane exponential update toward the alveolar inert pressures.
P(t+Δt) = P(t) + (P_alv − P(t)) · (1 − 2^(−Δt/ht))per inert gas, withP_alv = (P_amb − P_H2O) · fraction.
- tolerated_ambient_pressure(gradient_factor=1.0)[source]¶
Minimum ambient pressure this compartment tolerates (Baker formula).
P_amb_tol = (P_t − a·GF) / (GF/b + 1 − GF)with tension-weighted a/b for the N2/He mix. At GF = 1 this reduces to Bühlmann’s(P_t − a) · b. Clamped at zero (a fully desaturated compartment tolerates any ambient pressure).
ZHL-16 variants¶
Bühlmann ZHL-16 variants — coefficient tables over the shared engine.
The whole algorithm lives in BuhlmannModel;
a variant is nothing but NAME plus its published tables (half-times in
minutes, a in bar, b dimensionless). ZHL-16A/16B can be added the
same way once their tables are transcribed and verified.
- class diveplan.models.buhlmann.zhl16.ZHL16C(gradient=None)[source]¶
Bases:
BuhlmannModelBühlmann ZHL-16C, 16 compartments (1b first-compartment variant).
Sources: Bühlmann, Tauchmedizin; identical values are used by Subsurface/OSTC.
VPM-B (bubble model)¶
VPM-B decompression model (Varying Permeability Model, revision B).
A dual-phase (bubble) model: gas loading uses the same Haldane compartments and ZHL-16 half-times as Bühlmann, but the ceiling comes from bubble-nuclei mechanics instead of M-values — the allowable supersaturation gradient of a compartment is set by the size of its gas nuclei, which are crushed smaller by descent (raising the allowed gradient) and regenerate over weeks.
Scope¶
This class implements the VPM-B core: tissue loading, crushing-pressure
tracking (permeable and impermeable regimes), nuclear regeneration, and the
ceiling from initial allowable gradients (Baker’s vpmb_start_gradient
stage). The Critical Volume Algorithm and Boyle-law stop compensation operate
on a full ascent schedule and therefore live in the ascent planner, not here;
until the planner applies them, ceilings from this model are the conservative
pre-CVA values. CRIT_VOLUME_LAMBDA_BAR_MIN is exported for that later
stage.
Constants and formulas follow the Subsurface implementation of Erik Baker’s
VPM-B (core/deco.cpp), which uses bar/µm units: gamma quantities are the
Yount surface-tension values pre-scaled so that 2·γ/r with r in µm
yields bar.
- class diveplan.models.vpm.model.VpmB(conservatism=0)[source]¶
Bases:
BaseDecoModel[VpmState]VPM-B core model (pre-CVA ceilings; see module docstring for scope).
Gas loading runs on the ZHL-16 half-times (the standard VPM-B choice), reusing the Bühlmann
Compartment— its a/b coefficients are inert here; the ceiling comes from bubble mechanics.- Parameters:
conservatism (
int) – 0 (nominal) … 4 — scales the initial critical radii by(1.0, 1.05, 1.12, 1.22, 1.35).
- get_ceiling()[source]¶
Minimum tolerated ambient pressure across compartments (pre-CVA).
Per compartment: total inert tension (+ fixed other-gases pressure) minus the tension-weighted (N2, He) allowable gradient.
- Return type:
- class diveplan.models.vpm.model.VpmState(compartments, runtime_min)[source]¶
Bases:
DecoStateFrozen VPM-B snapshot.
Per compartment:
(ppn2, pphe, max_crush_n2, max_crush_he, onset_tension)— tensions in float mbar, crushing pressures and onset tension in bar (the bubble-mechanics unit).runtime_mindrives nuclear regeneration.