mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Use PSCR gas when computing O2 toxicity
Both the calculations for CNS and OTU did not take into account the pO2 drop when using a PSCR. Furthermore, there was some unit confusion due to not using internal units. Reported-by: arosl Signed-off-by: Robert C. Helling <helling@atdotde.de>
This commit is contained in:
parent
41fc822d56
commit
7c62f7541c
4 changed files with 33 additions and 9 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
- core: Take into account PSCR pO2 drop when computing CNS and OTU
|
||||||
- planner: allow automatic setpoint changes at specified depths in CCR mode
|
- planner: allow automatic setpoint changes at specified depths in CCR mode
|
||||||
- core: fix OTU und CNS calculations for CCR dives at shallow depths
|
- core: fix OTU und CNS calculations for CCR dives at shallow depths
|
||||||
- desktop: make selection of multiple dives reasonable fast
|
- desktop: make selection of multiple dives reasonable fast
|
||||||
|
|
|
@ -114,9 +114,16 @@ static int calculate_otu(const struct dive *dive)
|
||||||
po2f = MIN((int) sample->setpoint.mbar,
|
po2f = MIN((int) sample->setpoint.mbar,
|
||||||
depth_to_mbar(sample->depth.mm, dive));
|
depth_to_mbar(sample->depth.mm, dive));
|
||||||
} else { // For OC and rebreather without o2 sensor/setpoint
|
} else { // For OC and rebreather without o2 sensor/setpoint
|
||||||
int o2 = active_o2(dive, dc, psample->time); // ... calculate po2 from depth and FiO2.
|
double amb_presure = depth_to_bar(sample->depth.mm, dive);
|
||||||
po2i = lrint(o2 * depth_to_bar(psample->depth.mm, dive)); // (initial) po2 at start of segment
|
double pamb_pressure = depth_to_bar(psample->depth.mm , dive);
|
||||||
po2f = lrint(o2 * depth_to_bar(sample->depth.mm, dive)); // (final) po2 at end of segment
|
if (dc->divemode == PSCR) {
|
||||||
|
po2i = pscr_o2(pamb_pressure, get_gasmix_at_time(dive, dc, psample->time));
|
||||||
|
po2f = pscr_o2(amb_presure, get_gasmix_at_time(dive, dc, sample->time));
|
||||||
|
} else {
|
||||||
|
int o2 = active_o2(dive, dc, psample->time); // ... calculate po2 from depth and FiO2.
|
||||||
|
po2i = lrint(o2 * pamb_pressure); // (initial) po2 at start of segment
|
||||||
|
po2f = lrint(o2 * amb_presure); // (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) || (po2f > 500)) { // If PO2 in segment is above 500 mbar then calculate otu
|
||||||
|
@ -173,9 +180,16 @@ static double calculate_cns_dive(const struct dive *dive)
|
||||||
trueo2 = true;
|
trueo2 = true;
|
||||||
}
|
}
|
||||||
if (!trueo2) {
|
if (!trueo2) {
|
||||||
int o2 = active_o2(dive, dc, psample->time); // For OC and rebreather without o2 sensor:
|
double amb_presure = depth_to_bar(sample->depth.mm, dive);
|
||||||
po2i = lrint(o2 * depth_to_bar(psample->depth.mm, dive)); // (initial) po2 at start of segment
|
double pamb_pressure = depth_to_bar(psample->depth.mm , dive);
|
||||||
po2f = lrint(o2 * depth_to_bar(sample->depth.mm, dive)); // (final) po2 at end of segment
|
if (dc->divemode == PSCR) {
|
||||||
|
po2i = pscr_o2(pamb_pressure, get_gasmix_at_time(dive, dc, psample->time));
|
||||||
|
po2f = pscr_o2(amb_presure, get_gasmix_at_time(dive, dc, sample->time));
|
||||||
|
} else {
|
||||||
|
int o2 = active_o2(dive, dc, psample->time); // ... calculate po2 from depth and FiO2.
|
||||||
|
po2i = lrint(o2 * pamb_pressure); // (initial) po2 at start of segment
|
||||||
|
po2f = lrint(o2 * amb_presure); // (final) po2 at end of segment
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int po2avg = (po2i + po2f) / 2; // po2i now holds the mean po2 of initial and final po2 values of segment.
|
int po2avg = (po2i + po2f) / 2; // po2i now holds the mean po2 of initial and final po2 values of segment.
|
||||||
/* Don't increase CNS when po2 below 500 matm */
|
/* Don't increase CNS when po2 below 500 matm */
|
||||||
|
|
13
core/gas.c
13
core/gas.c
|
@ -96,6 +96,15 @@ fraction_t get_gas_component_fraction(struct gasmix mix, enum gas_component comp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// O2 pressure in mbar according to the steady state model for the PSCR
|
||||||
|
// NB: Ambient pressure comes in bar!
|
||||||
|
int pscr_o2(const double amb_pressure, struct gasmix mix) {
|
||||||
|
int o2 = get_o2(mix) * amb_pressure - (int)((1.0 - get_o2(mix) / 1000.0) * prefs.o2consumption / (prefs.bottomsac * prefs.pscr_ratio) * 1000000);
|
||||||
|
if (o2 < 0.0) // He's dead, Jim.
|
||||||
|
o2 = 0.0;
|
||||||
|
return o2;
|
||||||
|
}
|
||||||
|
|
||||||
/* fill_pressures(): Compute partial gas pressures in bar from gasmix and ambient pressures, possibly for OC or CCR, to be
|
/* fill_pressures(): Compute partial gas pressures in bar from gasmix and ambient pressures, possibly for OC or CCR, to be
|
||||||
* extended to PSCT. This function does the calculations of gas pressures applicable to a single point on the dive profile.
|
* extended to PSCT. This function does the calculations of gas pressures applicable to a single point on the dive profile.
|
||||||
* The structure "pressures" is used to return calculated gas pressures to the calling software.
|
* The structure "pressures" is used to return calculated gas pressures to the calling software.
|
||||||
|
@ -123,9 +132,7 @@ void fill_pressures(struct gas_pressures *pressures, const double amb_pressure,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (divemode == PSCR) { /* The steady state approximation should be good enough */
|
if (divemode == PSCR) { /* The steady state approximation should be good enough */
|
||||||
pressures->o2 = get_o2(mix) / 1000.0 * amb_pressure - (1.0 - get_o2(mix) / 1000.0) * prefs.o2consumption / (prefs.bottomsac * prefs.pscr_ratio / 1000.0);
|
pressures->o2 = pscr_o2(amb_pressure, mix) / 1000.0;
|
||||||
if (pressures->o2 < 0) // He's dead, Jim.
|
|
||||||
pressures->o2 = 0;
|
|
||||||
if (get_o2(mix) != 1000) {
|
if (get_o2(mix) != 1000) {
|
||||||
pressures->he = (amb_pressure - pressures->o2) * get_he(mix) / (1000.0 - get_o2(mix));
|
pressures->he = (amb_pressure - pressures->o2) * get_he(mix) / (1000.0 - get_o2(mix));
|
||||||
pressures->n2 = (amb_pressure - pressures->o2) * get_n2(mix) / (1000.0 - get_o2(mix));
|
pressures->n2 = (amb_pressure - pressures->o2) * get_n2(mix) / (1000.0 - get_o2(mix));
|
||||||
|
|
|
@ -59,6 +59,8 @@ static inline int get_n2(struct gasmix mix)
|
||||||
return 1000 - get_o2(mix) - get_he(mix);
|
return 1000 - get_o2(mix) - get_he(mix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pscr_o2(const double amb_pressure, struct gasmix mix);
|
||||||
|
|
||||||
struct gas_pressures {
|
struct gas_pressures {
|
||||||
double o2, n2, he;
|
double o2, n2, he;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue