-
Notifications
You must be signed in to change notification settings - Fork 0
Algo 03 First Stop Ramped GF
The first decompression stop is where two things coincide: it is the deepest mandatory stop on the 3 m grid, and it is the anchor of the GF ramp. Same depth, two roles. The deco loop then ascends from there toward the surface.
DecoJS implements the standard Baker GF convention:
The first stop is the shallowest stop-grid depth at which the dive ceiling at
$GF_{low}$ — the maximum ceiling across all 16 compartments — is satisfied after a simulated ascent from current depth.
pAnchor is the ambient pressure at that depth. Below it the active GF is clamped at
// js/decoModel.js (signature)
export function findFirstStopAtGFLow(
tissuePressures, currentDepth, n2Fraction, gfLow,
stopIncrement = STOP_INCREMENT, ascentRate = ASCENT_SPEED, gasSwitchPoints = null
)Returns { anchorDepth, pAnchor, tissuesAtAnchor }.
Iterate the stop grid surface-up. For each candidate depth
- Simulate the ascent from
currentDepthto$d$ (Schreiner integration with gas switches if applicable). - Compute the dive ceiling at
$GF_{low}$ —getDiveCeiling(simTissues, gfLow). - If
ceilingDepth ≤ d, the diver can arrive at$d$ within$GF_{low}$ ; this is the first stop.
// js/decoModel.js findFirstStopAtGFLow
for (let candidate = 0; candidate <= currentDepth + 1e-9; candidate += stopIncrement) {
let simTissues;
if (safeGases) {
simTissues = _simulateAscentWithGasSwitches(
tissuePressures, currentDepth, candidate, n2Fraction, safeGases
);
} else {
const ascentTime = (currentDepth - candidate) / ascentRate;
simTissues = ascentTime > 0
? simulateDepthChange({ ...tissuePressures }, currentDepth, candidate, ascentTime, n2Fraction)
: { ...tissuePressures };
}
const { ceilingDepth } = getDiveCeiling(simTissues, gfLow);
if (ceilingDepth <= candidate + 1e-9) {
anchorDepth = candidate;
tissuesAtAnchor = simTissues;
break;
}
}stopIncrement is 3 m by default (matching dive-computer practice) and 0.1 m in continuous-deco mode (educational visualization).
getDiveCeiling takes the maximum across all 16 compartments. The compartment with the highest instantaneous GF is not always the same as the compartment with the deepest GF_low ceiling — the two can disagree, especially after a gas switch shifts which compartment is loading vs off-gassing. The convention takes the deepest of all per-compartment ceilings, so the diver isn't sent shallower than safe.
The simulated ascent within the search uses _simulateAscentWithGasSwitches when deco gases are provided. Switching to a richer mix at its MOD changes
// js/decoModel.js _simulateAscentWithGasSwitches
function _simulateAscentWithGasSwitches(tissuePressures, fromDepth, toDepth, startN2, gasSwitchPoints) {
let tissues = { ...tissuePressures };
let currentDepth = fromDepth;
let currentN2 = startN2;
const relevantSwitches = gasSwitchPoints
.filter(sp => sp.switchDepth < currentDepth && sp.switchDepth >= toDepth)
.sort((a, b) => b.switchDepth - a.switchDepth);
for (const sp of relevantSwitches) {
const segmentTime = (currentDepth - sp.switchDepth) / ASCENT_SPEED;
if (segmentTime > 0) {
tissues = simulateDepthChange(tissues, currentDepth, sp.switchDepth, segmentTime, currentN2);
}
currentDepth = sp.switchDepth;
currentN2 = sp.n2;
}
if (currentDepth > toDepth) {
const segmentTime = (currentDepth - toDepth) / ASCENT_SPEED;
tissues = simulateDepthChange(tissues, currentDepth, toDepth, segmentTime, currentN2);
}
return tissues;
}If candidate = 0 (surface) already satisfies the ceiling check, the diver is within NDL. findFirstStopAtGFLow returns anchorDepth = 0 and pAnchor = SURFACE_PRESSURE. The deco loop then takes the no-deco branch (js/decoModel.js no-deco path).
40 m on air, 25 min bottom time,
- After descent + 25 min at 40 m, the deepest GF_low ceiling lands somewhere around 12-13 m.
- Iterate the 3 m grid: candidates at 0, 3, 6, 9, 12 all fail (
ceilingDepth > candidateafter simulated ascent). - Candidate 15 passes: dive ceiling at
$GF_{low}$ on the post-ascent tissues is$\le 15$ m. - First stop = 15 m.
$pAnchor = 1.01325 + 1.5 = 2.51$ bar. - The deco loop then runs from 15 m, with
interpolateGFgiving GF rising from 0.30 at 15 m to 0.85 at the surface.
-
Model-05-Gradient-Factors — what
$pAnchor$ does once it's been found. -
Algo-04-Deco-Stop-Loop — consumes
firstStopDepthandtissuesAtAnchor. -
Algo-05-Multi-Gas-Switching — how
gasSwitchPointsis constructed before being passed in.