Dive

Dive: a deco model run over a profile, queryable and extendable.

The profile stays pure input geometry; everything a model computes lands here. A Dive may be complete or in progress (just the bottom phase) — it stores model-state checkpoints at segment boundaries only (O(segments) memory for batch runs) and answers time-addressed queries by re-integrating at most one segment from the nearest checkpoint (exact, since Haldane integration composes).

Queries and operations:

  • state_at(t) / ceiling_at(t) — model state and ceiling at any runtime

  • cns_at(t) / otu_at(t) — oxygen exposure accumulated by t

  • tissue_series(dt) — (time, state) samples for visualization

  • tts(t) — time-to-surface: a counterfactual ascent planned from t

  • plan_ascent() — the deco schedule from the dive’s current end

  • with_ascent() / extend() — a new Dive continuing this one

One profile can be run under any number of models/settings and the dives compared — nothing here mutates the profile or the caller’s model.

class diveplan.dive.dive.Dive(profile, model, checkpoints)[source]

Bases: Generic

A deco model’s run over a profile — complete or still in progress.

Build via run(). The dive owns an independent model copy and a copy of the profile’s segment list; neither input is mutated. Extend an in-progress dive with with_ascent() (plan and append the deco schedule) or extend() (append arbitrary segments).

Parameters:
classmethod run(profile, model)[source]

Integrate model over profile and capture boundary checkpoints.

The caller’s model is copied, not mutated — run the same profile under several models/settings and compare. The profile is integrated as-is; validate/repair it first if it may be discontinuous.

Parameters:
Return type:

Dive[TypeVar(StateT, bound= DecoState)]

property profile: DiveProfile

The dive profile this dive was computed from (own copy).

property checkpoints: tuple[StateT, ...]

Model states at segment boundaries; [0] is the pre-dive state, [i] the state after segment i-1.

property final_state: StateT

Model state at the end of the profile.

model_at(t)[source]

Independent model instance positioned at runtime t.

Restores the checkpoint before t’s segment and re-integrates the partial segment — exact, since Haldane integration composes. The returned model is yours: integrating it further does not touch the result.

Parameters:

t (timedelta | float)

Return type:

BaseDecoModel[TypeVar(StateT, bound= DecoState)]

state_at(t)[source]

Model state at runtime t (minutes or timedelta).

Parameters:

t (timedelta | float)

Return type:

TypeVar(StateT, bound= DecoState)

ceiling_at(t)[source]

Deco ceiling at runtime t.

Parameters:

t (timedelta | float)

Return type:

Pressure

cns_at(t)[source]

CNS oxygen-toxicity clock accumulated by runtime t, in percent.

cns_at(profile.runtime) is the whole dive so far — the figure a DiveReport carries as cns.

Parameters:

t (timedelta | float)

Return type:

float

otu_at(t)[source]

Pulmonary oxygen-toxicity units (REPEX) accumulated by runtime t.

Parameters:

t (timedelta | float)

Return type:

float

tissue_series(interval)[source]

Yield (time, state) at each sample step — for tissue plots.

Starts with the pre-dive state at t=0, then one snapshot per profile sample (see DiveProfile.iter_samples()).

Parameters:

interval (timedelta | float)

Return type:

Iterator[tuple[timedelta, TypeVar(StateT, bound= DecoState)]]

tts(t, gas_plan=None)[source]

Time-to-surface at runtime t: the duration of an ascent planned from the model state, depth, and gas at that moment.

Parameters:
  • t (timedelta | float) – Runtime to ask “if I ascended now, how long?” at.

  • gas_plan (GasPlan | None) – Deco gases available for the hypothetical ascent. Defaults to all gases appearing in the profile.

Return type:

timedelta

plan_ascent(gas_plan=None)[source]

Deco schedule from the dive’s current end to the surface.

Plans from the end-of-profile model state, depth, and gas, with stop departures aligned to the dive clock. The dive itself is untouched — use with_ascent() to get a new Dive that includes the ascent.

Parameters:

gas_plan (GasPlan | None) – Gases available for the ascent. Defaults to all gases appearing in the profile so far.

Return type:

list[DiveSegment]

extend(segments)[source]

New Dive with segments appended and integrated.

Cheap: the existing checkpoints are reused and only the new segments are integrated. The profile’s builder policy applies to the new seams; this dive is not modified.

Parameters:

segments (list[DiveSegment])

Return type:

Dive[TypeVar(StateT, bound= DecoState)]

with_ascent(gas_plan=None)[source]

New Dive completed with its planned deco ascent — dive.extend(dive.plan_ascent(gas_plan)).

Parameters:

gas_plan (GasPlan | None)

Return type:

Dive[TypeVar(StateT, bound= DecoState)]

tts_variations(gas_plan=None)[source]

Extra time-to-surface per +1 m on the final segment and per +1 min of extra time at the current depth (both re-planned, not estimated).

Meaningful when the profile ends in the bottom phase (the normal planning situation): “+1 m” re-runs the model over the profile with its final segment shifted one metre deeper (a transition is inserted automatically), “+1 min” extends the dive by a minute at the final depth. Deltas are clamped at zero — clock-aligned stop rounding can otherwise produce a spurious −few-seconds.

Parameters:

gas_plan (GasPlan | None)

Return type:

TtsVariations

property model_name: str

Name of the model this result was computed with, conservatism included — e.g. "zhl16c GF 30/70" or "vpmb +3".

class diveplan.dive.dive.TtsVariations(per_meter, per_minute)[source]

Bases: NamedTuple

Sensitivity of the time-to-surface to small plan changes — the “+x /m +y /min” figures planners print next to a runtime.

Parameters:
per_meter: timedelta

Alias for field number 0

per_minute: timedelta

Alias for field number 1