A comprehensive TypeScript implementation of decompression calculation algorithms for scuba diving, featuring the industry-standard Bühlmann ZH-L16C algorithm with gradient factors.
- 16 tissue compartments with nitrogen and helium tracking
- Gradient Factors (GF) for conservative decompression profiles
- No Decompression Limit (NDL) calculations with multiple algorithms
- Ceiling depth calculations with real-time monitoring
- Decompression schedules with optimized stops and timing
- Time to Surface (TTS) calculations
- Mixed gas support: Air, Nitrox, Trimix with full validation
- Partial pressure calculations at depth with safety limits
- Maximum Operating Depth (MOD) calculations
- Equivalent Narcotic Depth (END) for trimix diving
- Multi-gas decompression with automatic gas switching
- Supersaturation monitoring (GF99, GFSurf)
- Individual compartment analysis with detailed pressure tracking
- Mixed gas coefficients for helium/nitrogen calculations
- Real-time gradient factor tracking
- CNS (Central Nervous System) oxygen toxicity monitoring
- OTU (Oxygen Tolerance Units) pulmonary toxicity calculations
- Real-time exposure tracking with safety thresholds
- Integrated safety warnings and limits
# Install dependencies
npm install
# Build the library
npm run build
# Run tests
npm test
# Format code
npm run format
npm install dive-deco
import { BuhlmannModel, Gas, Depth, Time } from 'dive-deco';
// Create model with default settings (GF 100/100)
const model = BuhlmannModel.default();
const air = Gas.air();
// Simulate dive to 30m for 25 minutes
model.recordTravel(Depth.fromMeters(30), Time.fromMinutes(3), air);
model.record(Depth.fromMeters(30), Time.fromMinutes(25), air);
// Check decompression status
console.log(`NDL remaining: ${model.ndl().asMinutes()}min`);
console.log(`Ceiling: ${model.ceiling().asMeters()}m`);
console.log(`In deco: ${model.inDeco()}`);
import {
BuhlmannConfig,
BuhlmannConfigBuilder,
CeilingType,
NDLType,
} from 'dive-deco';
// Method 1: Builder pattern (recommended) with full configuration
const config2 = new BuhlmannConfigBuilder()
.gradientFactors(20, 75) // Conservative GF
.surfacePressure(1013) // Sea level pressure
.decoAscentRate(9) // Slow ascent rate
.ceilingType(CeilingType.Adaptive)
.roundCeiling(false) // Precise ceiling depths
.ndlType(NDLType.Actual) // Account for off-gassing
.build();
// Method 2: Direct configuration with all options
const config = new BuhlmannConfig(
[30, 85], // GF Low/High 30/85
1013, // Surface pressure (mbar)
9, // Ascent rate (m/min)
CeilingType.Adaptive, // Ceiling calculation type
true, // Round ceiling to nearest meter
NDLType.ByCeiling // NDL calculation strategy
);
// Method 3: Default configuration
const defaultConfig = BuhlmannConfig.default(); // GF 100/100, standard settings
// Validation
const validationError = config.validate();
if (validationError) {
console.error(
`Configuration error in ${validationError.field}: ${validationError.reason}`
);
}
const model = new BuhlmannModel(config);
import { Gas } from 'dive-deco';
// Standard gas mixes
const air = Gas.air(); // 21% O2, 0% He
const nitrox32 = new Gas(0.32, 0); // EAN32: 32% O2, 0% He
const trimix2135 = new Gas(0.21, 0.35); // TMX 21/35: 21% O2, 35% He
// Safety calculations
const mod = nitrox32.maxOperatingDepth(1.4); // MOD at 1.4 ATA ppO2
const end = trimix2135.equivalentNarcoticDepth(Depth.fromMeters(45));
console.log(`EAN32 MOD: ${mod.asMeters()}m`);
console.log(`Trimix END: ${end.asMeters()}m`);
// Validate gas mix
console.log(`Valid mix: ${trimix2135.isValid()}`);
// Multi-gas decompression with gas switching
const decoGases = [air, nitrox32, new Gas(1.0, 0)]; // Air, EAN32, O2
const decoRuntime = model.deco(decoGases);
console.log(`Total Time to Surface: ${decoRuntime.tts.asMinutes()}min`);
// Detailed decompression schedule
decoRuntime.decoStages.forEach((stage, index) => {
console.log(`Stage ${index + 1}: ${stage.stageType}`);
console.log(
` ${stage.startDepth.asMeters()}m → ${stage.endDepth.asMeters()}m`
);
console.log(
` Duration: ${stage.duration.asMinutes()}min on ${stage.gas.toString()}`
);
});
// NDL calculations with different strategies
const adaptiveNDL = model.ndl(); // Adaptive algorithm
const conservativeNDL = model.ndl(NDLType.Conservative);
import { OxTox } from 'dive-deco';
// Create OxTox tracker
const oxTox = OxTox.default(); // Start with zero exposure
// Manual exposure tracking
const ppO2 = 1.4; // 1.4 ATA partial pressure
const exposureTime = Time.fromMinutes(30); // 30 minutes exposure
oxTox.addExposure(ppO2, exposureTime);
console.log(`CNS: ${oxTox.cns.toFixed(1)}%`);
console.log(`OTU: ${oxTox.otu.toFixed(1)}`);
// Integrated with BuhlmannModel (automatic tracking)
const cns = model.cns(); // Current CNS from all dive segments
const otu = model.otu(); // Current OTU from all dive segments
// Safety thresholds
if (cns > 80) {
console.warn('CNS approaching dangerous levels (>80%)');
}
if (otu > 300) {
console.warn('OTU exposure high (>300 units)');
}
// Clone for scenario planning
const futureOxTox = oxTox.clone();
futureOxTox.addExposure(1.6, Time.fromMinutes(20)); // Test future exposure
// Get detailed tissue information
const tissueData = model.tissurePressures();
const supersaturation = model.supersaturation();
tissueData.forEach((tissue, i) => {
const ss = supersaturation[i];
console.log(`Compartment ${i + 1}:`);
console.log(` N2: ${tissue.n2.toFixed(3)} bar`);
console.log(` GF99: ${ss.gf99.toFixed(1)}%`);
});
Main decompression model implementation with ZH-L16C algorithm.
Key Methods:
record(depth, time, gas)
- Record dive segmentrecordTravel(depth, time, gas)
- Record ascent/descent with travel timendl(type?)
- Calculate No Decompression Limitceiling(type?)
- Current ceiling depthdeco(gases)
- Full decompression schedule with gas switchinginDeco()
- Check if decompression is requiredcns()
- Current CNS oxygen toxicity percentageotu()
- Current OTU oxygen toxicity unitstissurePressures()
- Individual compartment pressuressupersaturation()
- GF99/GFSurf for all compartments
Model configuration with validation and builder pattern support.
Constructor Options:
gradientFactors: GradientFactors
- GF Low/High values [1-100, 1-100] (default: [100, 100])surfacePressure: MbarPressure
- Surface pressure in mbar [500-1200] (default: 1013)decoAscentRate: AscentRatePerMinute
- Ascent rate in m/min [0-30] (default: 10)ceilingType: CeilingType
- Ceiling calculation type (default: CeilingType.Actual)roundCeiling: boolean
- Round ceiling to nearest meter (default: false)ndlType: NDLType
- NDL calculation strategy (default: NDLType.Actual)
Configuration Enums:
enum CeilingType {
Actual = 'Actual', // Standard ceiling calculation
Adaptive = 'Adaptive', // Adaptive ceiling algorithm
}
enum NDLType {
Actual = 'Actual', // Consider off-gassing during ascent
ByCeiling = 'ByCeiling', // NDL when ceiling > 0
}
Builder Methods:
gradientFactors(low, high)
- Set gradient factorssurfacePressure(pressure)
- Set surface pressure (mbar)decoAscentRate(rate)
- Set ascent rate (m/min)ceilingType(type)
- Set ceiling calculation typeroundCeiling(round)
- Enable/disable ceiling roundingndlType(type)
- Set NDL calculation strategybuild()
- Create validated configurationvalidate()
- Validate current configuration
Static Methods:
BuhlmannConfig.default()
- Default configurationBuhlmannConfig.builder()
- Create new builder instance
Gas mix handling with safety calculations.
Methods:
Gas.air()
- Standard air (21% O2)maxOperatingDepth(ppO2)
- MOD calculationequivalentNarcoticDepth(depth)
- END calculation
Unit handling with conversion utilities.
Features:
- Metric/Imperial conversions
- Arithmetic operations
- Type-safe depth/time calculations
Oxygen toxicity tracking for CNS and OTU calculations using NOAA standards.
Properties:
cns: Cns
- Current CNS oxygen toxicity percentageotu: Otu
- Current OTU (Oxygen Tolerance Units)
Methods:
addExposure(ppO2, time)
- Add oxygen exposure for given partial pressure and timeclone()
- Create a copy of the current OxTox state
Static Methods:
OxTox.default()
- Create new instance with zero exposure
CNS Calculation:
Uses NOAA CNS coefficient table for accurate CNS tracking:
- PO2 0.5-0.6 ATA: Linear rate calculation
- PO2 0.6-1.65 ATA: Progressively increasing rates
- PO2 > 1.65 ATA: Maximum rate (dangerous levels)
OTU Calculation:
Formula: OTU = (ppO2 - 0.5 / 0.5)^0.83 * time_minutes
- Only accumulates when ppO2 > 0.5 ATA
- Tracks pulmonary oxygen toxicity over time
This library implements the Bühlmann ZH-L16C decompression algorithm with the following specifications:
- 16 tissue compartments with distinct nitrogen and helium half-times
- Gradient factors (GF) for adjustable conservatism (20-100% range)
- Mixed gas calculations supporting Air, Nitrox, and Trimix
- Haldane equation for accurate gas loading and off-loading
- M-value calculations with gradient factor adjustments
- Real-time ceiling and TTS computation assuming off-gassing on ascent with configurable ascent rates
npm test
- Algorithm follows established ZH-L16C parameters
- Test suite validates against known decompression scenarios
- Calculations verified for typical recreational and technical diving profiles
We welcome contributions! Areas where help is needed:
- Additional test cases and validation scenarios
- Performance optimizations
- Extended algorithm implementations
- Documentation improvements
- Real-world dive profile testing
This software is for educational, research, and development purposes only.
- DO NOT use for actual dive planning without proper validation and certification
- Always use certified dive computers and follow established decompression procedures
- Consult qualified diving professionals for dive planning and safety
- Verify all calculations against established decompression tables
- Understand diving risks and maintain proper certification and training
The developers assume no responsibility for diving safety or accuracy of calculations when used for actual diving activities.
This implementation provides decompression calculation algorithms adapted for TypeScript/JavaScript environments.