Skip to content

Commit

Permalink
Merge pull request #21 from KG32/feat/tmx-equivalent-narcotic-depth
Browse files Browse the repository at this point in the history
Feat/tmx equivalent narcotic depth
  • Loading branch information
KG32 authored Jul 12, 2024
2 parents c562c74 + a7d8d3b commit 2a33938
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dive-deco"
version = "2.0.0"
version = "2.1.0"
edition = "2021"
license = "MIT"
description = "A dive decompression models library (Buehlmann ZH-L 16C)"
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ The Bühlmann decompression set of parameters is an Haldanian mathematical model

### Planned features

- extended deco model config [metric/imprial units, water density and more] (currently metric and density assumed to be 1.03kg/l as salt water)
- extended deco model config [metric/imperial units, water density and more] (currently metric and density assumed to be 1.03kg/l as salt water)
- travel steps optimization (linear ascent / descent steps using Schreiner equation instead of iterative Haldane equation)
- BuehlmannModel Default trait implementation
- other deco algorithms (VPM-B)
Expand Down Expand Up @@ -253,6 +253,8 @@ Breathing gas used in the model.
- he - helium partial pressure
- `partial_pressures(depth)` - compounded gas's components partial pressures at certain depth
- `inspired_partial_pressures(depth)` - inspired gas partial pressures in alveoli taking into account alveolar water vapor pressure
- `maximum_operating_depth(pp_o2_limit)` - maximum operating depth considering o2 partial, with maximum o2 partial pressure as parameter
- `equivalent_narcotic_depth(depth)` - equivalent depth at which given gas has the same narcotic potential as air. Assumes o2 - n2 1:1 narcotic ratio.

```rust
let mix = Gas::new(0.21, 0.);
Expand Down
7 changes: 4 additions & 3 deletions src/common/deco.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::{DecoModel, Depth, Gas, Minutes};

use super::{AscentRatePerMinute, DecoModelConfig, DiveState, MbarPressure};

const DEFAULT_ASCENT_RATE: AscentRatePerMinute = 9.;
// @todo move to model config
const DEFAULT_ASCENT_RATE: AscentRatePerMinute = 9.;
const DEFAULT_CEILING_WINDOW: Depth = 3.;
const DEFAULT_MAX_END_DEPTH: Depth = 30.;

#[derive(Copy, Clone, Debug, PartialEq)]
enum DecoAction {
Expand Down Expand Up @@ -166,7 +166,8 @@ impl Deco {
if let Some(switch_gas) = next_switch_gas {
//switch gas without ascent if within mod of next deco gas
let gas_mod = switch_gas.max_operating_depth(1.6);
if (switch_gas != current_gas) && (current_depth <= gas_mod) {
let gas_end = switch_gas.equivalent_narcotic_depth(current_depth);
if (switch_gas != current_gas) && (current_depth <= gas_mod) && (gas_end <= DEFAULT_MAX_END_DEPTH) {
return (Some(DecoAction::SwitchGas), Some(switch_gas));
}
}
Expand Down
45 changes: 39 additions & 6 deletions src/common/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,17 @@ impl Gas {
}

/// MOD
pub fn max_operating_depth(&self, pp_o2: Pressure) -> Depth {
10. * ((pp_o2 / self.o2_pp) - 1.)
pub fn max_operating_depth(&self, pp_o2_limit: Pressure) -> Depth {
10. * ((pp_o2_limit / self.o2_pp) - 1.)
}

/// END
pub fn equivalent_narcotic_depth(&self, depth: Depth) -> Depth {
let mut end = (depth + 10.) * (1. - self.he_pp) - 10.;
if end < 0. {
end = 0.;
}
end
}

// TODO standard nitrox (bottom and deco) and trimix gasses
Expand All @@ -76,6 +85,8 @@ impl Gas {

#[cfg(test)]
mod tests {
use std::f64::INFINITY;

use super::*;

#[test]
Expand Down Expand Up @@ -136,10 +147,32 @@ mod tests {

#[test]
fn test_mod() {
let air = Gas::new(0.21, 0.);
let ean_50 = Gas::new(0.50, 0.);
assert_eq!(air.max_operating_depth(1.4), 56.66666666666666);
assert_eq!(ean_50.max_operating_depth(1.6), 22.);
// o2, he, max_ppo2, MOD
let test_cases = [
(0.21, 0., 1.4, 56.66666666666666),
(0.50, 0., 1.6, 22.),
(0.21, 0.35, 1.4, 56.66666666666666),
(0., 0., 1.4, INFINITY),
];
for (pp_o2, pe_he, max_pp_o2, expected_mod) in test_cases {
let gas = Gas::new(pp_o2, pe_he);
let calculated_mod = gas.max_operating_depth(max_pp_o2);
assert_eq!(calculated_mod, expected_mod);
}
}

#[test]
fn test_end() {
// depth, o2, he, END
let test_cases = [
(60., 0.21, 0.40, 32.),
(0., 0.21, 0.40, 0.),
(40., 0.21, 0., 40.),
];
for (depth, o2_pp, he_pp, expected_end) in test_cases {
let tmx = Gas::new(o2_pp, he_pp);
let calculated_end = tmx.equivalent_narcotic_depth(depth);
assert_eq!(calculated_end, expected_end);
}
}
}

0 comments on commit 2a33938

Please sign in to comment.