mirror of
https://github.com/subsurface/subsurface.git
synced 2025-01-19 14:25:27 +00:00
Prepare for PSCR calculations
Calculations for passive semi-closed rebreathers are pretty much like OC except the pO2 is lower bey a certain (SAC dependent) factor. This patch introduces the corresponding calculations in case dctype == PSCR which is so far never set and there is currently no UI for these calculations. As pO2 is SAC dependent it takes a certain attempt at getting it and drops to defaults from the prefs otherwise. As there is no UI at this point and I also don't have any dives, this has not received much testing, yet, but it compiles. At least. Signed-off-by: Robert C. Helling <helling@atdotde.de> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
f31d34adfd
commit
06ddfc0122
8 changed files with 29 additions and 19 deletions
5
deco.c
5
deco.c
|
@ -18,6 +18,7 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "dive.h"
|
#include "dive.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
//! Option structure for Buehlmann decompression.
|
//! Option structure for Buehlmann decompression.
|
||||||
struct buehlmann_config {
|
struct buehlmann_config {
|
||||||
|
@ -184,12 +185,12 @@ double he_factor(int period_in_seconds, int ci)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add period_in_seconds at the given pressure and gas to the deco calculation */
|
/* add period_in_seconds at the given pressure and gas to the deco calculation */
|
||||||
double add_segment(double pressure, const struct gasmix *gasmix, int period_in_seconds, int ccpo2, const struct dive *dive)
|
double add_segment(double pressure, const struct gasmix *gasmix, int period_in_seconds, int ccpo2, const struct dive *dive, int sac)
|
||||||
{
|
{
|
||||||
int ci;
|
int ci;
|
||||||
struct gas_pressures pressures;
|
struct gas_pressures pressures;
|
||||||
|
|
||||||
fill_pressures(&pressures, pressure - WV_PRESSURE, gasmix, (double) ccpo2 / 1000.0);
|
fill_pressures(&pressures, pressure - WV_PRESSURE, gasmix, (double) ccpo2 / 1000.0, ccpo2 ? CCR : OC, sac);
|
||||||
|
|
||||||
if (buehlmann_config.gf_low_at_maxdepth && pressure > gf_low_pressure_this_dive)
|
if (buehlmann_config.gf_low_at_maxdepth && pressure > gf_low_pressure_this_dive)
|
||||||
gf_low_pressure_this_dive = pressure;
|
gf_low_pressure_this_dive = pressure;
|
||||||
|
|
7
dive.c
7
dive.c
|
@ -1549,8 +1549,13 @@ int gasmix_distance(const struct gasmix *a, const struct gasmix *b)
|
||||||
* *mix = structure containing cylinder gas mixture information.
|
* *mix = structure containing cylinder gas mixture information.
|
||||||
* This function called by: calculate_gas_information_new() in profile.c; add_segment() in deco.c.
|
* This function called by: calculate_gas_information_new() in profile.c; add_segment() in deco.c.
|
||||||
*/
|
*/
|
||||||
extern void fill_pressures(struct gas_pressures *pressures, const double amb_pressure, const struct gasmix *mix, double po2)
|
extern void fill_pressures(struct gas_pressures *pressures, const double amb_pressure, const struct gasmix *mix, double po2, enum dive_comp_type dctype, int sac)
|
||||||
{
|
{
|
||||||
|
if (!sac) {
|
||||||
|
/* The SAC has not yet been computer, so use the default *
|
||||||
|
* We might try harder... */
|
||||||
|
sac = prefs.bottomsac;
|
||||||
|
}
|
||||||
if (po2) { // This is probably a CCR dive where pressures->o2 is defined
|
if (po2) { // This is probably a CCR dive where pressures->o2 is defined
|
||||||
if (po2 >= amb_pressure) {
|
if (po2 >= amb_pressure) {
|
||||||
pressures->o2 = amb_pressure;
|
pressures->o2 = amb_pressure;
|
||||||
|
|
6
dive.h
6
dive.h
|
@ -47,7 +47,7 @@ extern "C" {
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum dive_comp_type {OC, CCR}; // Flags (Open-circuit and Closed-circuit-rebreather) for setting dive computer type
|
enum dive_comp_type {OC, CCR, PSCR}; // Flags (Open-circuit and Closed-circuit-rebreather) for setting dive computer type
|
||||||
enum cylinderuse {oxygen, diluent, bailout}; // The different uses for cylinders in CCR dives
|
enum cylinderuse {oxygen, diluent, bailout}; // The different uses for cylinders in CCR dives
|
||||||
|
|
||||||
struct gasmix {
|
struct gasmix {
|
||||||
|
@ -140,7 +140,7 @@ struct gas_pressures {
|
||||||
double o2, n2, he;
|
double o2, n2, he;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void fill_pressures(struct gas_pressures *pressures, const double amb_pressure, const struct gasmix *mix, double po2);
|
extern void fill_pressures(struct gas_pressures *pressures, const double amb_pressure, const struct gasmix *mix, double po2, enum dive_comp_type dctype, int sac);
|
||||||
|
|
||||||
extern void sanitize_gasmix(struct gasmix *mix);
|
extern void sanitize_gasmix(struct gasmix *mix);
|
||||||
extern int gasmix_distance(const struct gasmix *a, const struct gasmix *b);
|
extern int gasmix_distance(const struct gasmix *a, const struct gasmix *b);
|
||||||
|
@ -731,7 +731,7 @@ extern void subsurface_command_line_exit(int *, char ***);
|
||||||
|
|
||||||
#define FRACTION(n, x) ((unsigned)(n) / (x)), ((unsigned)(n) % (x))
|
#define FRACTION(n, x) ((unsigned)(n) / (x)), ((unsigned)(n) % (x))
|
||||||
|
|
||||||
extern double add_segment(double pressure, const struct gasmix *gasmix, int period_in_seconds, int setpoint, const struct dive *dive);
|
extern double add_segment(double pressure, const struct gasmix *gasmix, int period_in_seconds, int setpoint, const struct dive *dive, int sac);
|
||||||
extern void clear_deco(double surface_pressure);
|
extern void clear_deco(double surface_pressure);
|
||||||
extern void dump_tissues(void);
|
extern void dump_tissues(void);
|
||||||
extern unsigned int deco_allowed_depth(double tissues_tolerance, double surface_pressure, struct dive *dive, bool smooth);
|
extern unsigned int deco_allowed_depth(double tissues_tolerance, double surface_pressure, struct dive *dive, bool smooth);
|
||||||
|
|
|
@ -322,7 +322,7 @@ static void add_dive_to_deco(struct dive *dive)
|
||||||
for (j = t0; j < t1; j++) {
|
for (j = t0; j < t1; j++) {
|
||||||
int depth = interpolate(psample->depth.mm, sample->depth.mm, j - t0, t1 - t0);
|
int depth = interpolate(psample->depth.mm, sample->depth.mm, j - t0, t1 - t0);
|
||||||
(void)add_segment(depth_to_mbar(depth, dive) / 1000.0,
|
(void)add_segment(depth_to_mbar(depth, dive) / 1000.0,
|
||||||
&dive->cylinder[sample->sensor].gasmix, 1, sample->setpoint.mbar, dive);
|
&dive->cylinder[sample->sensor].gasmix, 1, sample->setpoint.mbar, dive, dive->sac);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -396,7 +396,7 @@ double init_decompression(struct dive *dive)
|
||||||
if (pdive->when > lasttime) {
|
if (pdive->when > lasttime) {
|
||||||
surface_time = pdive->when - lasttime;
|
surface_time = pdive->when - lasttime;
|
||||||
lasttime = pdive->when + pdive->duration.seconds;
|
lasttime = pdive->when + pdive->duration.seconds;
|
||||||
tissue_tolerance = add_segment(surface_pressure, &air, surface_time, 0, dive);
|
tissue_tolerance = add_segment(surface_pressure, &air, surface_time, 0, dive, prefs.decosac);
|
||||||
#if DECO_CALC_DEBUG & 2
|
#if DECO_CALC_DEBUG & 2
|
||||||
printf("after surface intervall of %d:%02u\n", FRACTION(surface_time, 60));
|
printf("after surface intervall of %d:%02u\n", FRACTION(surface_time, 60));
|
||||||
dump_tissues();
|
dump_tissues();
|
||||||
|
@ -407,7 +407,7 @@ double init_decompression(struct dive *dive)
|
||||||
if (lasttime && dive->when > lasttime) {
|
if (lasttime && dive->when > lasttime) {
|
||||||
surface_time = dive->when - lasttime;
|
surface_time = dive->when - lasttime;
|
||||||
surface_pressure = get_surface_pressure_in_mbar(dive, true) / 1000.0;
|
surface_pressure = get_surface_pressure_in_mbar(dive, true) / 1000.0;
|
||||||
tissue_tolerance = add_segment(surface_pressure, &air, surface_time, 0, dive);
|
tissue_tolerance = add_segment(surface_pressure, &air, surface_time, 0, dive, prefs.decosac);
|
||||||
#if DECO_CALC_DEBUG & 2
|
#if DECO_CALC_DEBUG & 2
|
||||||
printf("after surface intervall of %d:%02u\n", FRACTION(surface_time, 60));
|
printf("after surface intervall of %d:%02u\n", FRACTION(surface_time, 60));
|
||||||
dump_tissues();
|
dump_tissues();
|
||||||
|
|
|
@ -127,7 +127,7 @@ double interpolate_transition(struct dive *dive, duration_t t0, duration_t t1, d
|
||||||
|
|
||||||
for (j = t0.seconds; j < t1.seconds; j++) {
|
for (j = t0.seconds; j < t1.seconds; j++) {
|
||||||
int depth = interpolate(d0.mm, d1.mm, j - t0.seconds, t1.seconds - t0.seconds);
|
int depth = interpolate(d0.mm, d1.mm, j - t0.seconds, t1.seconds - t0.seconds);
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(depth, dive) / 1000.0, gasmix, 1, po2.mbar, dive);
|
tissue_tolerance = add_segment(depth_to_mbar(depth, dive) / 1000.0, gasmix, 1, po2.mbar, dive, prefs.bottomsac);
|
||||||
}
|
}
|
||||||
return tissue_tolerance;
|
return tissue_tolerance;
|
||||||
}
|
}
|
||||||
|
@ -831,7 +831,7 @@ int plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool s
|
||||||
|
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
||||||
&displayed_dive.cylinder[current_cylinder].gasmix,
|
&displayed_dive.cylinder[current_cylinder].gasmix,
|
||||||
TIMESTEP, po2, &displayed_dive);
|
TIMESTEP, po2, &displayed_dive, prefs.decosac);
|
||||||
clock += TIMESTEP;
|
clock += TIMESTEP;
|
||||||
depth -= deltad;
|
depth -= deltad;
|
||||||
} while (depth > stoplevels[stopidx]);
|
} while (depth > stoplevels[stopidx]);
|
||||||
|
@ -869,7 +869,7 @@ int plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool s
|
||||||
deltad = trial_depth;
|
deltad = trial_depth;
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(trial_depth, &displayed_dive) / 1000.0,
|
tissue_tolerance = add_segment(depth_to_mbar(trial_depth, &displayed_dive) / 1000.0,
|
||||||
&displayed_dive.cylinder[current_cylinder].gasmix,
|
&displayed_dive.cylinder[current_cylinder].gasmix,
|
||||||
TIMESTEP, po2, &displayed_dive);
|
TIMESTEP, po2, &displayed_dive, prefs.decosac);
|
||||||
if (deco_allowed_depth(tissue_tolerance, diveplan->surface_pressure / 1000.0, &displayed_dive, 1) > trial_depth - deltad) {
|
if (deco_allowed_depth(tissue_tolerance, diveplan->surface_pressure / 1000.0, &displayed_dive, 1) > trial_depth - deltad) {
|
||||||
/* We should have stopped */
|
/* We should have stopped */
|
||||||
clear_to_ascend = false;
|
clear_to_ascend = false;
|
||||||
|
@ -892,7 +892,7 @@ int plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool s
|
||||||
}
|
}
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
||||||
&displayed_dive.cylinder[current_cylinder].gasmix,
|
&displayed_dive.cylinder[current_cylinder].gasmix,
|
||||||
DECOTIMESTEP, po2, &displayed_dive);
|
DECOTIMESTEP, po2, &displayed_dive, prefs.decosac);
|
||||||
cache_deco_state(tissue_tolerance, &trial_cache);
|
cache_deco_state(tissue_tolerance, &trial_cache);
|
||||||
clock += DECOTIMESTEP;
|
clock += DECOTIMESTEP;
|
||||||
/* Finish infinite deco */
|
/* Finish infinite deco */
|
||||||
|
|
2
pref.h
2
pref.h
|
@ -67,6 +67,8 @@ struct preferences {
|
||||||
bool drop_stone_mode;
|
bool drop_stone_mode;
|
||||||
int bottomsac;
|
int bottomsac;
|
||||||
int decosac;
|
int decosac;
|
||||||
|
int o2consumption; // ml per min
|
||||||
|
int pscr_ratio; // dump ratio times 1000
|
||||||
bool show_pictures_in_profile;
|
bool show_pictures_in_profile;
|
||||||
bool use_default_file;
|
bool use_default_file;
|
||||||
};
|
};
|
||||||
|
|
12
profile.c
12
profile.c
|
@ -735,7 +735,7 @@ static void calculate_ndl_tts(double tissue_tolerance, struct plot_data *entry,
|
||||||
while (entry->ndl_calc < max_ndl && deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1) <= 0) {
|
while (entry->ndl_calc < max_ndl && deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1) <= 0) {
|
||||||
entry->ndl_calc += time_stepsize;
|
entry->ndl_calc += time_stepsize;
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(entry->depth, dive) / 1000.0,
|
tissue_tolerance = add_segment(depth_to_mbar(entry->depth, dive) / 1000.0,
|
||||||
&dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->pressures.o2 * 1000, dive);
|
&dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->pressures.o2 * 1000, dive, prefs.bottomsac);
|
||||||
}
|
}
|
||||||
/* we don't need to calculate anything else */
|
/* we don't need to calculate anything else */
|
||||||
return;
|
return;
|
||||||
|
@ -747,7 +747,7 @@ static void calculate_ndl_tts(double tissue_tolerance, struct plot_data *entry,
|
||||||
/* Add segments for movement to stopdepth */
|
/* Add segments for movement to stopdepth */
|
||||||
for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_step, entry->tts_calc += ascent_s_per_step) {
|
for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_step, entry->tts_calc += ascent_s_per_step) {
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(ascent_depth, dive) / 1000.0,
|
tissue_tolerance = add_segment(depth_to_mbar(ascent_depth, dive) / 1000.0,
|
||||||
&dive->cylinder[cylinderindex].gasmix, ascent_s_per_step, entry->pressures.o2 * 1000, dive);
|
&dive->cylinder[cylinderindex].gasmix, ascent_s_per_step, entry->pressures.o2 * 1000, dive, prefs.decosac);
|
||||||
next_stop = ROUND_UP(deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1), deco_stepsize);
|
next_stop = ROUND_UP(deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1), deco_stepsize);
|
||||||
}
|
}
|
||||||
ascent_depth = next_stop;
|
ascent_depth = next_stop;
|
||||||
|
@ -765,13 +765,13 @@ static void calculate_ndl_tts(double tissue_tolerance, struct plot_data *entry,
|
||||||
|
|
||||||
entry->tts_calc += time_stepsize;
|
entry->tts_calc += time_stepsize;
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(ascent_depth, dive) / 1000.0,
|
tissue_tolerance = add_segment(depth_to_mbar(ascent_depth, dive) / 1000.0,
|
||||||
&dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->pressures.o2 * 1000, dive);
|
&dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->pressures.o2 * 1000, dive, prefs.decosac);
|
||||||
|
|
||||||
if (deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1) <= next_stop) {
|
if (deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1) <= next_stop) {
|
||||||
/* move to the next stop and add the travel between stops */
|
/* move to the next stop and add the travel between stops */
|
||||||
for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_deco_step, entry->tts_calc += ascent_s_per_deco_step)
|
for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_deco_step, entry->tts_calc += ascent_s_per_deco_step)
|
||||||
add_segment(depth_to_mbar(ascent_depth, dive) / 1000.0,
|
add_segment(depth_to_mbar(ascent_depth, dive) / 1000.0,
|
||||||
&dive->cylinder[cylinderindex].gasmix, ascent_s_per_deco_step, entry->pressures.o2 * 1000, dive);
|
&dive->cylinder[cylinderindex].gasmix, ascent_s_per_deco_step, entry->pressures.o2 * 1000, dive, prefs.decosac);
|
||||||
ascent_depth = next_stop;
|
ascent_depth = next_stop;
|
||||||
next_stop -= deco_stepsize;
|
next_stop -= deco_stepsize;
|
||||||
}
|
}
|
||||||
|
@ -799,7 +799,7 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
|
||||||
for (j = t0 + time_stepsize; j <= t1; j += time_stepsize) {
|
for (j = t0 + time_stepsize; j <= t1; j += time_stepsize) {
|
||||||
int depth = interpolate(entry[-1].depth, entry[0].depth, j - t0, t1 - t0);
|
int depth = interpolate(entry[-1].depth, entry[0].depth, j - t0, t1 - t0);
|
||||||
double min_pressure = add_segment(depth_to_mbar(depth, dive) / 1000.0,
|
double min_pressure = add_segment(depth_to_mbar(depth, dive) / 1000.0,
|
||||||
&dive->cylinder[entry->cylinderindex].gasmix, time_stepsize, entry->pressures.o2 * 1000, dive);
|
&dive->cylinder[entry->cylinderindex].gasmix, time_stepsize, entry->pressures.o2 * 1000, dive, entry->sac);
|
||||||
tissue_tolerance = min_pressure;
|
tissue_tolerance = min_pressure;
|
||||||
if (j - t0 < time_stepsize)
|
if (j - t0 < time_stepsize)
|
||||||
time_stepsize = j - t0;
|
time_stepsize = j - t0;
|
||||||
|
@ -905,7 +905,7 @@ static void calculate_gas_information_new(struct dive *dive, struct plot_info *p
|
||||||
if ((dive->dc.dctype == CCR) && (cylinderindex == dive->oxygen_cylinder_index))
|
if ((dive->dc.dctype == CCR) && (cylinderindex == dive->oxygen_cylinder_index))
|
||||||
cylinderindex = dive->diluent_cylinder_index;
|
cylinderindex = dive->diluent_cylinder_index;
|
||||||
|
|
||||||
fill_pressures(&entry->pressures, amb_pressure, &dive->cylinder[cylinderindex].gasmix, entry->pressures.o2);
|
fill_pressures(&entry->pressures, amb_pressure, &dive->cylinder[cylinderindex].gasmix, entry->pressures.o2, dive->dc.dctype, entry->sac);
|
||||||
|
|
||||||
/* Calculate MOD, EAD, END and EADD based on partial pressures calculated before
|
/* Calculate MOD, EAD, END and EADD based on partial pressures calculated before
|
||||||
* so there is no difference in calculating between OC and CC
|
* so there is no difference in calculating between OC and CC
|
||||||
|
|
|
@ -45,6 +45,8 @@ struct preferences default_prefs = {
|
||||||
.drop_stone_mode = false,
|
.drop_stone_mode = false,
|
||||||
.bottomsac = 20000,
|
.bottomsac = 20000,
|
||||||
.decosac = 17000,
|
.decosac = 17000,
|
||||||
|
.o2consumption = 1000,
|
||||||
|
.pscr_ratio = 100,
|
||||||
.show_pictures_in_profile = true,
|
.show_pictures_in_profile = true,
|
||||||
.tankbar = false
|
.tankbar = false
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue