mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
Improve OTU calculations
Implement the protocol in Erik Baker's document "Oxygen Toxicity Calculations". This code uses a third-order polynomial approximation of Baker's equation 2. Provision is made for PSCR and CCR dive logs and dive plans. In the case of dive logs, the values of o2 sensors are used if there are data from such sensors. For CCR only the data from the first O2 sensor is used even if there are more than one sensor. This is a potential weakness, but this function is probably NOT the place to calculate mean o2 values accross all sensors and to emulate voting logic to reject info from aberrant sensors. Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za> Signed-off-by: Robert C. Helling <helling@atdotde.de>
This commit is contained in:
parent
da866583fd
commit
fba6ec5ad5
2 changed files with 36 additions and 9 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
- Dive: Perform more accurate OTU calculations, and include
|
||||||
|
OTU calculations for rebreather dives [#1851 & #1865].
|
||||||
- Mobile: add initial copy-paste support
|
- Mobile: add initial copy-paste support
|
||||||
- Desktop: translate trip date
|
- Desktop: translate trip date
|
||||||
---
|
---
|
||||||
|
|
|
@ -159,27 +159,52 @@ static int active_o2(const struct dive *dive, const struct divecomputer *dc, dur
|
||||||
return get_o2(gas);
|
return get_o2(gas);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate OTU for a dive - this only takes the first divecomputer into account */
|
/* Calculate OTU for a dive - this only takes the first divecomputer into account.
|
||||||
|
Implement the protocol in Erik Baker's document "Oxygen Toxicity Calculations". This code
|
||||||
|
implements a third-order continuous approximation of Baker's Eq. 2 and enables OTU
|
||||||
|
calculation for rebreathers. Baker obtained his information from:
|
||||||
|
Comroe Jr. JH et al. (1945) Oxygen toxicity. J. Am. Med. Assoc. 128,710-717
|
||||||
|
Clark JM & CJ Lambertsen (1970) Pulmonary oxygen tolerance in man and derivation of pulmonary
|
||||||
|
oxygen tolerance curves. Inst. env. Med. Report 1-70, University of Pennsylvania, Philadelphia, USA. */
|
||||||
static int calculate_otu(const struct dive *dive)
|
static int calculate_otu(const struct dive *dive)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double otu = 0.0;
|
double otu = 0.0;
|
||||||
const struct divecomputer *dc = &dive->dc;
|
const struct divecomputer *dc = &dive->dc;
|
||||||
|
|
||||||
for (i = 1; i < dc->samples; i++) {
|
for (i = 1; i < dc->samples; i++) {
|
||||||
int t;
|
int t;
|
||||||
int po2;
|
int po2i, po2f;
|
||||||
|
double pm;
|
||||||
struct sample *sample = dc->sample + i;
|
struct sample *sample = dc->sample + i;
|
||||||
struct sample *psample = sample - 1;
|
struct sample *psample = sample - 1;
|
||||||
t = sample->time.seconds - psample->time.seconds;
|
t = sample->time.seconds - psample->time.seconds;
|
||||||
if (sample->setpoint.mbar) {
|
if (sample->o2sensor[0].mbar) { // if dive computer has o2 sensor(s) (CCR & PSCR) ..
|
||||||
po2 = sample->setpoint.mbar;
|
po2i = psample->o2sensor[0].mbar;
|
||||||
|
po2f = sample->o2sensor[0].mbar; // ... use data from the first o2 sensor
|
||||||
} else {
|
} else {
|
||||||
int o2 = active_o2(dive, dc, psample->time);
|
if (dc->divemode == CCR) {
|
||||||
po2 = lrint(o2 * depth_to_atm(sample->depth.mm, dive));
|
po2i = psample->setpoint.mbar; // if CCR has no o2 sensors then use setpoint
|
||||||
|
po2f = sample->setpoint.mbar;
|
||||||
|
} else { // For OC and rebreather without o2 sensor/setpoint
|
||||||
|
int o2 = active_o2(dive, dc, psample->time); // ... calculate po2 from depth and FiO2.
|
||||||
|
po2i = lrint(o2 * depth_to_atm(psample->depth.mm, dive)); // (initial) po2 at start of segment
|
||||||
|
po2f = lrint(o2 * depth_to_atm(sample->depth.mm, dive)); // (final) po2 at end of segment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((po2i > 500) || (po2f > 500)) { // If PO2 in segment is above 500 mbar then calculate otu
|
||||||
|
if (po2i <= 500) { // For descent segment with po2i <= 500 mbar ..
|
||||||
|
t = t * (po2f - 500) / (po2f - po2i); // .. only consider part with PO2 > 500 mbar
|
||||||
|
po2i = 501; // Mostly important for the dive planner with long segments
|
||||||
|
} else {
|
||||||
|
if (po2f <= 500){
|
||||||
|
t = t * (po2i - 500) / (po2i - po2f); // For ascent segment with po2f <= 500 mbar ..
|
||||||
|
po2f = 501; // .. only consider part with PO2 > 500 mbar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pm = (po2f + po2i)/1000.0 - 1.0;
|
||||||
|
// This is a 3rd order continuous approximation of Baker's eq. 2, therefore Baker's eq. 1 is not used:
|
||||||
|
otu += t / 60.0 * pow(pm, 5.0/6.0) * (1.0 - 5.0 * (po2f - po2i) * (po2f - po2i) / 216000000.0 / (pm * pm));
|
||||||
}
|
}
|
||||||
if (po2 >= 500)
|
|
||||||
otu += pow((po2 - 500) / 1000.0, 0.83) * t / 30.0;
|
|
||||||
}
|
}
|
||||||
return lrint(otu);
|
return lrint(otu);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue