mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-01 01:33:23 +00:00
Implement bailout outside of the dive planner
This is the second step for implementing bailout. The indirect calls to fill_pressures through add_segment() (in deco.c) are addressed. Bailout is now fully implemented in the dive log but not in the dive planner. 1) The parameters to add_segment() are changed to take a divemode as the second last parameter, and not a *dive. 2) Call to add_segment() in profile.c and in divelist.c are adapted. In divelist.c some calls to add_segment were left using dc-> divemode instead of possible bailout. This appears tp be the most appropriate route. 3) The functions get_divemode_from_time() and get_next_divemodechange() in dive.c have had some small changes. 4) The calls to get_segment(0 in planner.c were changed to reflect the new parameter list, but not updated to reflect bailout. This is the next step. Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
This commit is contained in:
parent
cf377beb2e
commit
27a0542220
6 changed files with 58 additions and 38 deletions
|
@ -478,14 +478,14 @@ void calc_crushing_pressure(struct deco_state *ds, double pressure)
|
|||
}
|
||||
|
||||
/* add period_in_seconds at the given pressure and gas to the deco calculation */
|
||||
void add_segment(struct deco_state *ds, double pressure, const struct gasmix *gasmix, int period_in_seconds, int ccpo2, const struct dive *dive, int sac)
|
||||
void add_segment(struct deco_state *ds, double pressure, const struct gasmix *gasmix, int period_in_seconds, int ccpo2, enum dive_comp_type divemode, int sac)
|
||||
{
|
||||
(void) sac;
|
||||
int ci;
|
||||
struct gas_pressures pressures;
|
||||
bool icd = false;
|
||||
fill_pressures(&pressures, pressure - ((in_planner() && (decoMode() == VPMB)) ? WV_PRESSURE_SCHREINER : WV_PRESSURE),
|
||||
gasmix, (double) ccpo2 / 1000.0, dive->dc.divemode);
|
||||
gasmix, (double) ccpo2 / 1000.0, divemode);
|
||||
|
||||
for (ci = 0; ci < 16; ci++) {
|
||||
double pn2_oversat = pressures.n2 - ds->tissue_n2_sat[ci];
|
||||
|
|
43
core/dive.c
43
core/dive.c
|
@ -244,7 +244,7 @@ void add_extra_data(struct divecomputer *dc, const char *key, const char *value)
|
|||
struct event *get_next_divemodechange(struct event **evd)
|
||||
{ /* Starting at the event pointed to by evd, find the next divemode change event and initialise its
|
||||
* type and divemode. Requires an external pointer (evd) to a divemode change event, usually
|
||||
* initialised to dc->events. This function is self-tracking and the value of evd needs no
|
||||
* a copy of dc->events. This function is self-tracking and the value of evd needs no
|
||||
* setting or manipulation outside of this function. */
|
||||
struct event *ev = *evd;
|
||||
while (ev) { // Step through the events.
|
||||
|
@ -277,27 +277,40 @@ struct event *peek_next_divemodechange(struct event *evd)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
enum dive_comp_type get_divemode_at_time(struct divecomputer *dc, int divetime, struct event **ev_dmc)
|
||||
{ // The dummy version of this function, call parameters compatible with self-tracking version.
|
||||
return dc->divemode;
|
||||
}
|
||||
|
||||
enum dive_comp_type get_divemode_at_time(struct divecomputer *dc, int divetime, struct event **ev_dmc)
|
||||
{ // The non-self-tracking version of this function, call parameters compatible with self-tracking version.
|
||||
struct event *ev, *ev_ndc = dc->events;
|
||||
enum dive_comp_type mode = dc->divemode;
|
||||
ev = get_next_divemodechange(&ev_ndc);
|
||||
while (ev && (divetime >= ev->time.seconds)) {
|
||||
mode = ev->divemode;
|
||||
ev = get_next_divemodechange(&ev_ndc);
|
||||
}
|
||||
return mode;
|
||||
} */
|
||||
|
||||
enum dive_comp_type get_divemode_at_time(struct divecomputer *dc, int dtime, struct event **ev_dmc)
|
||||
{ /* For a particular dive computer and its linked list of events, find the divemode dtime seconds
|
||||
* into the dive. Requires an external pointer (ev_dmc) to a divemode change event, usually
|
||||
* initialised by a call to get_next_divemodechange(dc->events). This function is self-tracking
|
||||
* and the value of ev_dmc needs no setting or manipulation outside of this function. */
|
||||
enum dive_comp_type mode;
|
||||
struct event *ev = *ev_dmc; // ev_dmc points to event initialised by get_next_divemodechange()
|
||||
if (!ev)
|
||||
mode = dc->divemode; // if there is no divemodechange event, default to dc->divemode
|
||||
else {
|
||||
mode = ev->divemode; // If there is a starting divemodechange event, use the divemode of that event.
|
||||
while (ev && (dtime >= ev->time.seconds)) { // If dtime is AFTER this event time, store divemode
|
||||
mode = ev->divemode;
|
||||
*ev_dmc = ev;
|
||||
ev = peek_next_divemodechange(ev->next); // peek at the time of the following divemode change event
|
||||
}
|
||||
* initialised by a call to get_next_divemodechange(©-of-dc->events). This function is self-tracking
|
||||
* and the value of ev_dmc needs no manipulation outside of this function. */
|
||||
enum dive_comp_type mode = dc->divemode;
|
||||
struct event *ev_last = *ev_dmc, *ev = *ev_dmc; // ev_dmc points to event initialised by get_next_divemodechange()
|
||||
while (ev && (dtime >= ev->time.seconds)) { // If dtime is AFTER this event time, store divemode
|
||||
mode = ev->divemode;
|
||||
ev_last = ev;
|
||||
ev = peek_next_divemodechange(ev->next); // peek at the time of the following divemode change event
|
||||
}
|
||||
*ev_dmc = ev_last;
|
||||
return (mode);
|
||||
}
|
||||
|
||||
|
||||
/* this returns a pointer to static variable - so use it right away after calling */
|
||||
struct gasmix *get_gasmix_from_event(struct dive *dive, struct event *ev)
|
||||
{
|
||||
|
|
|
@ -83,6 +83,7 @@ struct event {
|
|||
/* This is the annoying libdivecomputer format. */
|
||||
int flags, value;
|
||||
/* .. and this is our "extended" data for some event types */
|
||||
enum dive_comp_type divemode;
|
||||
union {
|
||||
/*
|
||||
* Currently only for gas switch events.
|
||||
|
@ -91,7 +92,6 @@ struct event {
|
|||
* case, the get_cylinder_index() function will give the best
|
||||
* match with the cylinders in the dive based on gasmix.
|
||||
*/
|
||||
enum dive_comp_type divemode;
|
||||
struct {
|
||||
int index;
|
||||
struct gasmix mix;
|
||||
|
@ -854,7 +854,7 @@ struct deco_state {
|
|||
bool icd_warning;
|
||||
};
|
||||
|
||||
extern void add_segment(struct deco_state *ds, double pressure, const struct gasmix *gasmix, int period_in_seconds, int setpoint, const struct dive *dive, int sac);
|
||||
extern void add_segment(struct deco_state *ds, double pressure, const struct gasmix *gasmix, int period_in_seconds, int setpoint, enum dive_comp_type divemode, int sac);
|
||||
extern void clear_deco(struct deco_state *ds, double surface_pressure);
|
||||
extern void dump_tissues(struct deco_state *ds);
|
||||
extern void set_gf(short gflow, short gfhigh);
|
||||
|
|
|
@ -415,6 +415,7 @@ static void add_dive_to_deco(struct deco_state *ds, struct dive *dive)
|
|||
struct divecomputer *dc = &dive->dc;
|
||||
struct gasmix *gasmix = NULL;
|
||||
struct event *ev = NULL;
|
||||
struct event *ev_dmc = dc->events, *ev_dmt = get_next_divemodechange(&ev_dmc);
|
||||
int i;
|
||||
|
||||
if (!dc)
|
||||
|
@ -430,7 +431,8 @@ static void add_dive_to_deco(struct deco_state *ds, struct dive *dive)
|
|||
for (j = t0; j < t1; j++) {
|
||||
int depth = interpolate(psample->depth.mm, sample->depth.mm, j - t0, t1 - t0);
|
||||
gasmix = get_gasmix(dive, dc, j, &ev, gasmix);
|
||||
add_segment(ds, depth_to_bar(depth, dive), gasmix, 1, sample->setpoint.mbar, dive, dive->sac);
|
||||
add_segment(ds, depth_to_bar(depth, dive), gasmix, 1, sample->setpoint.mbar,
|
||||
get_divemode_at_time(dc, j, &ev_dmt), dive->sac);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -584,7 +586,7 @@ int init_decompression(struct deco_state *ds, struct dive *dive)
|
|||
#endif
|
||||
return surface_time;
|
||||
}
|
||||
add_segment(ds, surface_pressure, &air, surface_time, 0, dive, prefs.decosac);
|
||||
add_segment(ds, surface_pressure, &air, surface_time, 0, dive->dc.divemode, prefs.decosac);
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Tissues after surface intervall of %d:%02u:\n", FRACTION(surface_time, 60));
|
||||
dump_tissues(ds);
|
||||
|
@ -622,7 +624,7 @@ int init_decompression(struct deco_state *ds, struct dive *dive)
|
|||
#endif
|
||||
return surface_time;
|
||||
}
|
||||
add_segment(ds, surface_pressure, &air, surface_time, 0, dive, prefs.decosac);
|
||||
add_segment(ds, surface_pressure, &air, surface_time, 0, dive->dc.divemode, prefs.decosac);
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Tissues after surface intervall of %d:%02u:\n", FRACTION(surface_time, 60));
|
||||
dump_tissues(ds);
|
||||
|
|
|
@ -121,7 +121,7 @@ void interpolate_transition(struct deco_state *ds, struct dive *dive, duration_t
|
|||
|
||||
for (j = t0.seconds; j < t1.seconds; j++) {
|
||||
int depth = interpolate(d0.mm, d1.mm, j - t0.seconds, t1.seconds - t0.seconds);
|
||||
add_segment(ds, depth_to_bar(depth, dive), gasmix, 1, po2.mbar, dive, prefs.bottomsac);
|
||||
add_segment(ds, depth_to_bar(depth, dive), gasmix, 1, po2.mbar, dive->dc.divemode, prefs.bottomsac);
|
||||
}
|
||||
if (d1.mm > d0.mm)
|
||||
calc_crushing_pressure(ds, depth_to_bar(d1.mm, &displayed_dive));
|
||||
|
@ -573,7 +573,7 @@ bool trial_ascent(struct deco_state *ds, int wait_time, int trial_depth, int sto
|
|||
if (wait_time)
|
||||
add_segment(ds, depth_to_bar(trial_depth, dive),
|
||||
gasmix,
|
||||
wait_time, po2, dive, prefs.decosac);
|
||||
wait_time, po2, dive->dc.divemode, prefs.decosac);
|
||||
if (decoMode() == VPMB && (deco_allowed_depth(tissue_tolerance_calc(ds, dive,depth_to_bar(stoplevel, dive)),
|
||||
surface_pressure, dive, 1)
|
||||
> stoplevel)) {
|
||||
|
@ -588,7 +588,7 @@ bool trial_ascent(struct deco_state *ds, int wait_time, int trial_depth, int sto
|
|||
deltad = trial_depth;
|
||||
add_segment(ds, depth_to_bar(trial_depth, dive),
|
||||
gasmix,
|
||||
TIMESTEP, po2, dive, prefs.decosac);
|
||||
TIMESTEP, po2, dive->dc.divemode, prefs.decosac);
|
||||
if (deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(trial_depth, dive)),
|
||||
surface_pressure, dive, 1) > trial_depth - deltad) {
|
||||
/* We should have stopped */
|
||||
|
@ -781,7 +781,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
|||
do {
|
||||
add_segment(ds, depth_to_bar(depth, dive),
|
||||
&dive->cylinder[current_cylinder].gasmix,
|
||||
timestep, po2, dive, prefs.bottomsac);
|
||||
timestep, po2, dive->dc.divemode, prefs.bottomsac);
|
||||
update_cylinder_pressure(dive, depth, depth, timestep, prefs.bottomsac, &dive->cylinder[current_cylinder], false);
|
||||
clock += timestep;
|
||||
} while (trial_ascent(ds, 0, depth, 0, avg_depth, bottom_time, &dive->cylinder[current_cylinder].gasmix,
|
||||
|
@ -901,7 +901,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
|||
|
||||
add_segment(ds, depth_to_bar(depth, dive),
|
||||
&dive->cylinder[current_cylinder].gasmix,
|
||||
TIMESTEP, po2, dive, prefs.decosac);
|
||||
TIMESTEP, po2, dive->dc.divemode, prefs.decosac);
|
||||
last_segment_min_switch = false;
|
||||
clock += TIMESTEP;
|
||||
depth -= deltad;
|
||||
|
@ -940,7 +940,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
|||
if (!last_segment_min_switch && get_o2(&dive->cylinder[current_cylinder].gasmix) != 1000) {
|
||||
add_segment(ds, depth_to_bar(depth, dive),
|
||||
&dive->cylinder[current_cylinder].gasmix,
|
||||
prefs.min_switch_duration, po2, dive, prefs.decosac);
|
||||
prefs.min_switch_duration, po2, dive->dc.divemode, prefs.decosac);
|
||||
clock += prefs.min_switch_duration;
|
||||
last_segment_min_switch = true;
|
||||
}
|
||||
|
@ -994,7 +994,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
|||
if (!last_segment_min_switch && get_o2(&dive->cylinder[current_cylinder].gasmix) != 1000) {
|
||||
add_segment(ds, depth_to_bar(depth, dive),
|
||||
&dive->cylinder[current_cylinder].gasmix,
|
||||
prefs.min_switch_duration, po2, dive, prefs.decosac);
|
||||
prefs.min_switch_duration, po2, dive->dc.divemode, prefs.decosac);
|
||||
clock += prefs.min_switch_duration;
|
||||
last_segment_min_switch = true;
|
||||
}
|
||||
|
@ -1049,7 +1049,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
|||
}
|
||||
}
|
||||
add_segment(ds, depth_to_bar(depth, dive), &dive->cylinder[stop_cylinder].gasmix,
|
||||
laststoptime, po2, dive, prefs.decosac);
|
||||
laststoptime, po2, dive->dc.divemode, prefs.decosac);
|
||||
last_segment_min_switch = false;
|
||||
decostoptable[decostopcounter].depth = depth;
|
||||
decostoptable[decostopcounter].time = laststoptime;
|
||||
|
|
|
@ -907,7 +907,7 @@ static void setup_gas_sensor_pressure(struct dive *dive, struct divecomputer *dc
|
|||
|
||||
#ifndef SUBSURFACE_MOBILE
|
||||
/* calculate DECO STOP / TTS / NDL */
|
||||
static void calculate_ndl_tts(struct deco_state *ds, struct dive *dive, struct plot_data *entry, struct gasmix *gasmix, double surface_pressure)
|
||||
static void calculate_ndl_tts(struct deco_state *ds, struct dive *dive, struct plot_data *entry, struct gasmix *gasmix, double surface_pressure,enum dive_comp_type divemode)
|
||||
{
|
||||
/* FIXME: This should be configurable */
|
||||
/* ascent speed up to first deco stop */
|
||||
|
@ -942,7 +942,7 @@ static void calculate_ndl_tts(struct deco_state *ds, struct dive *dive, struct p
|
|||
) {
|
||||
entry->ndl_calc += time_stepsize;
|
||||
add_segment(ds, depth_to_bar(entry->depth, dive),
|
||||
gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.bottomsac);
|
||||
gasmix, time_stepsize, entry->o2pressure.mbar, divemode, prefs.bottomsac);
|
||||
}
|
||||
/* we don't need to calculate anything else */
|
||||
return;
|
||||
|
@ -954,7 +954,7 @@ static void calculate_ndl_tts(struct deco_state *ds, struct dive *dive, struct p
|
|||
/* Add segments for movement to stopdepth */
|
||||
for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_step, entry->tts_calc += ascent_s_per_step) {
|
||||
add_segment(ds, depth_to_bar(ascent_depth, dive),
|
||||
gasmix, ascent_s_per_step, entry->o2pressure.mbar, dive, prefs.decosac);
|
||||
gasmix, ascent_s_per_step, entry->o2pressure.mbar, divemode, prefs.decosac);
|
||||
next_stop = ROUND_UP(deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(ascent_depth, dive)),
|
||||
surface_pressure, dive, 1), deco_stepsize);
|
||||
}
|
||||
|
@ -975,13 +975,13 @@ static void calculate_ndl_tts(struct deco_state *ds, struct dive *dive, struct p
|
|||
if (entry->tts_calc > MAX_PROFILE_DECO)
|
||||
break;
|
||||
add_segment(ds, depth_to_bar(ascent_depth, dive),
|
||||
gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.decosac);
|
||||
gasmix, time_stepsize, entry->o2pressure.mbar, divemode, prefs.decosac);
|
||||
|
||||
if (deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(ascent_depth,dive)), surface_pressure, dive, 1) <= next_stop) {
|
||||
/* 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)
|
||||
add_segment(ds, depth_to_bar(ascent_depth, dive),
|
||||
gasmix, ascent_s_per_deco_step, entry->o2pressure.mbar, dive, prefs.decosac);
|
||||
gasmix, ascent_s_per_deco_step, entry->o2pressure.mbar, divemode, prefs.decosac);
|
||||
ascent_depth = next_stop;
|
||||
next_stop -= deco_stepsize;
|
||||
}
|
||||
|
@ -996,6 +996,8 @@ void calculate_deco_information(struct deco_state *ds, struct deco_state *planne
|
|||
double surface_pressure = (dc->surface_pressure.mbar ? dc->surface_pressure.mbar : get_surface_pressure_in_mbar(dive, true)) / 1000.0;
|
||||
bool first_iteration = true;
|
||||
int prev_deco_time = 10000000, time_deep_ceiling = 0;
|
||||
enum dive_comp_type current_divemode;
|
||||
|
||||
if (!in_planner()) {
|
||||
ds->deco_time = 0;
|
||||
} else {
|
||||
|
@ -1010,18 +1012,20 @@ void calculate_deco_information(struct deco_state *ds, struct deco_state *planne
|
|||
}
|
||||
/* For VPM-B outside the planner, iterate until deco time converges (usually one or two iterations after the initial)
|
||||
* Set maximum number of iterations to 10 just in case */
|
||||
|
||||
while ((abs(prev_deco_time - ds->deco_time) >= 30) && (count_iteration < 10)) {
|
||||
int last_ndl_tts_calc_time = 0, first_ceiling = 0, current_ceiling, last_ceiling = 0, final_tts = 0 , time_clear_ceiling = 0;
|
||||
if (decoMode() == VPMB)
|
||||
ds->first_ceiling_pressure.mbar = depth_to_mbar(first_ceiling, dive);
|
||||
struct gasmix *gasmix = NULL;
|
||||
struct event *ev = NULL;
|
||||
struct event *ev = NULL, *ev_dmc = dc->events, *ev_dmt = get_next_divemodechange(&ev_dmc);
|
||||
|
||||
for (i = 1; i < pi->nr; i++) {
|
||||
struct plot_data *entry = pi->entry + i;
|
||||
int j, t0 = (entry - 1)->sec, t1 = entry->sec;
|
||||
int time_stepsize = 20;
|
||||
|
||||
current_divemode = get_divemode_at_time(dc, entry->sec, &ev_dmt);
|
||||
gasmix = get_gasmix(dive, dc, t1, &ev, gasmix);
|
||||
|
||||
entry->ambpressure = depth_to_bar(entry->depth, dive);
|
||||
|
@ -1037,7 +1041,7 @@ void calculate_deco_information(struct deco_state *ds, struct deco_state *planne
|
|||
for (j = t0 + time_stepsize; j <= t1; j += time_stepsize) {
|
||||
int depth = interpolate(entry[-1].depth, entry[0].depth, j - t0, t1 - t0);
|
||||
add_segment(ds, depth_to_bar(depth, dive),
|
||||
gasmix, time_stepsize, entry->o2pressure.mbar, dive, entry->sac);
|
||||
gasmix, time_stepsize, entry->o2pressure.mbar, current_divemode, entry->sac);
|
||||
entry->icd_warning = ds->icd_warning;
|
||||
if ((t1 - j < time_stepsize) && (j < t1))
|
||||
time_stepsize = t1 - j;
|
||||
|
@ -1112,7 +1116,7 @@ void calculate_deco_information(struct deco_state *ds, struct deco_state *planne
|
|||
/* We are going to mess up deco state, so store it for later restore */
|
||||
struct deco_state *cache_data = NULL;
|
||||
cache_deco_state(ds, &cache_data);
|
||||
calculate_ndl_tts(ds, dive, entry, gasmix, surface_pressure);
|
||||
calculate_ndl_tts(ds, dive, entry, gasmix, surface_pressure, current_divemode);
|
||||
if (decoMode() == VPMB && !in_planner() && i == pi->nr - 1)
|
||||
final_tts = entry->tts_calc;
|
||||
/* Restore "real" deco state for next real time step */
|
||||
|
@ -1146,6 +1150,7 @@ void calculate_deco_information(struct deco_state *ds, struct deco_state *planne
|
|||
prev_deco_time = ds->deco_time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
free(cache_data_initial);
|
||||
#if DECO_CALC_DEBUG & 1
|
||||
dump_tissues(ds);
|
||||
|
|
Loading…
Add table
Reference in a new issue