Planning¶
Ascent planner¶
Ascent planner: compute the decompression schedule from a model state.
plan_ascent is a pure function of (model state, position, gases,
config) → list of DiveSegments. It clones the model and never mutates the
caller’s — the property that makes TTS/counterfactual queries safe.
Algorithm (standard staged-decompression loop):
From the current depth, find the shallowest reachable target — the surface, or the deepest required stop on the configured stop grid (
stop_increment_m, cut off atlast_stop_m).Ascend there at
ascent_rate(integrating the ascent into the model).At a stop: switch to the best deco gas (richest ppO2-safe mix from the gas plan), then wait in
min_stop_time_sincrements until the next shallower target clears.Repeat until surfaced.
The planner is model-agnostic: the ceiling test delegates to
BaseDecoModel.get_ascent_ceiling(target, first_stop), so any
ascent-context behavior (Bühlmann’s gradient-factor interpolation, VPM-B’s
future Boyle/CVA compensation) lives in the model, never here. VPM-B
currently uses the default plain ceiling — its schedules use the
conservative pre-CVA gradients.
- diveplan.planning.ascent_plan.plan_ascent(model, start_pressure, gas, gas_plan=None, clock_offset=datetime.timedelta(0))[source]¶
Plan the decompression ascent from the given position and model state.
- Parameters:
model (
BaseDecoModel[Any]) – Deco model holding the tissue state at start_pressure. Cloned internally — the caller’s instance is not touched.start_pressure (
Pressure|str|float) – Current position — a Pressure, a “40 m”-style string, or bare metres.gas (
Gas|str) – Gas currently being breathed — a Gas or a name like “ean50”.gas_plan (
GasPlan|None) – Gases available for switches during the ascent. Defaults to just the current gas.clock_offset (
timedelta|float) – Dive runtime at which this ascent starts (minutes or timedelta). Stop departures are extended to whole multiples ofmin_stop_time_son this clock — the dive-table convention (a stop ends at e.g. runtime 31:00, not 30:26), which keeps schedules comparable with planners like Subsurface. Pass the bottom runtime when planning a real dive; the default plans on an ascent-relative clock.
- Returns:
deco ascents, stops, and gas switches. Empty if already at the surface.
- Return type:
- Raises:
AscentNotConvergingError – If stops fail to clear within the iteration cap (pathological state or misconfiguration).
- exception diveplan.planning.ascent_plan.AscentNotConvergingError[source]¶
Bases:
RuntimeErrorThe stop loop failed to clear the next target within the iteration cap.
Gas plan, consumption, reserves, and oxygen exposure¶
Gas plan: carried gases, selection, consumption, and reserve planning.
Selection delegates breathability to Gas.is_breathable() (the
configured deco ppO2 window — the planner switches gases during ascent,
where the deco limit applies). Among breathable carried gases the richest
(highest fO2) wins: it off-gasses inert load fastest.
Everything about breathing gas over a dive lives here: GasPlan
(selection), gas_consumption() (surface litres per gas),
rock_bottom() (emergency reserve), and the oxygen-exposure trackers
cns_percent() / otu(). The accounting functions all take any
sequence of segments — a profile’s or an ascent plan’s. They are module
functions, not GasPlan methods, deliberately: toxicity and consumption
depend on what was breathed (the profile), not on what was carried.
- class diveplan.planning.gas_plan.GasPlan(gases)[source]¶
Bases:
objectAn ordered collection of carried gases with depth-based selection.
Gases may be given as
Gasobjects or names —GasPlan(["air", "ean50"])— parsed viaGas.from_name().
- diveplan.planning.gas_plan.gas_consumption(segments)[source]¶
Surface litres of each gas consumed over segments.
Per segment:
SAC × mean ambient pressure (atm) × minutes— exact, since the mean pressure of a linear traverse is its midpoint. Deco phases (deco ascents, stops, gas switches) are billed atgas.sac_deco, everything else atgas.sac_bottom. Works on a profile’s segments or on a plan fromplan_ascent().- Parameters:
segments (
Iterable[DiveSegment])- Return type:
- diveplan.planning.gas_plan.rock_bottom(depth, *, divers=2)[source]¶
Minimum gas reserve (surface litres) at depth for an emergency.
Models the classic worst case: divers divers (out-of-gas buddy plus donor) breathe from one supply at a stressed rate (
sac_bottom × sac_factor) while solving the problem at depth forproblem_solving_minutes, then ascend directly to the surface at the configured ascent rate. Decompression stops are not included — this is a direct-ascent reserve; divide by cylinder size × working pressure to express it in bar.
- diveplan.planning.gas_plan.cns_percent(segments, *, step=datetime.timedelta(seconds=10))[source]¶
CNS oxygen-toxicity clock over segments, in percent (100 = NOAA limit).
- Parameters:
segments (
Iterable[DiveSegment])step (
timedelta)
- Return type: