VPMB profile: use bottom_time to calculate deco_time in planner

This corrects the issue where the displayed ceiling in the profile was
"broken" by the planner, especially for shorter and shallower dives.

Also fixes issue outside of planner where the deepest VPM-B ceiling was shown
too early, messing up the deco_time calculation.

VPM-B plans respond to change in O2% in gas as expected (in my testing)

Fixes: #630

Signed-off-by: Rick Walsh <rickmwalsh@gmail.com>
This commit is contained in:
Rick Walsh 2017-10-27 10:06:11 +11:00 committed by Robert C. Helling
parent d470ef05e0
commit 04383e27e5
2 changed files with 24 additions and 13 deletions

View file

@ -34,6 +34,7 @@ int decostoplevels_imperial[] = { 0, 3048, 6096, 9144, 12192, 15240, 18288, 2133
325120, 345440, 365760, 386080 }; 325120, 345440, 365760, 386080 };
double plangflow, plangfhigh; double plangflow, plangfhigh;
int bottom_time = 0;
extern double regressiona(); extern double regressiona();
extern double regressionb(); extern double regressionb();
@ -669,7 +670,7 @@ bool plan(struct diveplan *diveplan, struct dive *dive, int timestep, struct dec
bool stopping = false; bool stopping = false;
bool pendinggaschange = false; bool pendinggaschange = false;
int clock, previous_point_time; int clock, previous_point_time;
int avg_depth, max_depth, bottom_time = 0; int avg_depth, max_depth;
int last_ascend_rate; int last_ascend_rate;
int best_first_ascend_cylinder; int best_first_ascend_cylinder;
struct gasmix gas, bottom_gas; struct gasmix gas, bottom_gas;
@ -1066,6 +1067,7 @@ bool plan(struct diveplan *diveplan, struct dive *dive, int timestep, struct dec
diveplan->eff_gflow = lrint(100.0 * (regressiona() * first_stop_depth + regressionb())); diveplan->eff_gflow = lrint(100.0 * (regressiona() * first_stop_depth + regressionb()));
} }
create_dive_from_plan(diveplan, dive, is_planner); create_dive_from_plan(diveplan, dive, is_planner);
add_plan_to_notes(diveplan, dive, show_disclaimer, error); add_plan_to_notes(diveplan, dive, show_disclaimer, error);
fixup_dc_duration(&dive->dc); fixup_dc_duration(&dive->dc);

View file

@ -31,6 +31,7 @@ static struct plot_data *last_pi_entry_new = NULL;
void populate_pressure_information(struct dive *, struct divecomputer *, struct plot_info *, int); void populate_pressure_information(struct dive *, struct divecomputer *, struct plot_info *, int);
extern bool in_planner(); extern bool in_planner();
extern int bottom_time;
#ifdef DEBUG_PI #ifdef DEBUG_PI
/* debugging tool - not normally used */ /* debugging tool - not normally used */
@ -954,19 +955,25 @@ static void calculate_ndl_tts(struct dive *dive, struct plot_data *entry, struct
*/ */
void calculate_deco_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi, bool print_mode) void calculate_deco_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi, bool print_mode)
{ {
int i, count_iteration = 0; int i, count_iteration = 0, deco_time;
double surface_pressure = (dc->surface_pressure.mbar ? dc->surface_pressure.mbar : get_surface_pressure_in_mbar(dive, true)) / 1000.0; double surface_pressure = (dc->surface_pressure.mbar ? dc->surface_pressure.mbar : get_surface_pressure_in_mbar(dive, true)) / 1000.0;
bool first_iteration = true; bool first_iteration = true;
int deco_time = 0, prev_deco_time = 10000000; int prev_deco_time = 10000000, time_deep_ceiling = 0;
if (in_planner())
deco_time = pi->maxtime - bottom_time;
else
deco_time = 0;
struct deco_state *cache_data_initial = NULL; struct deco_state *cache_data_initial = NULL;
/* For VPM-B outside the planner, cache the initial deco state for CVA iterations */ /* For VPM-B outside the planner, cache the initial deco state for CVA iterations */
if (decoMode() == VPMB && !in_planner()) if (decoMode() == VPMB) {
cache_deco_state(&cache_data_initial); cache_deco_state(&cache_data_initial);
}
/* For VPM-B outside the planner, iterate until deco time converges (usually one or two iterations after the initial) /* 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 */ * Set maximum number of iterations to 10 just in case */
while ((abs(prev_deco_time - deco_time) >= 30) && (count_iteration < 10)) { while ((abs(prev_deco_time - deco_time) >= 30) && (count_iteration < 10)) {
int last_ndl_tts_calc_time = 0, first_ceiling = 0, current_ceiling, last_ceiling, final_tts = 0 , time_clear_ceiling = 0, time_deep_ceiling = 0; int last_ndl_tts_calc_time = 0, first_ceiling = 0, current_ceiling, last_ceiling, final_tts = 0 , time_clear_ceiling = 0;
deco_state->first_ceiling_pressure.mbar = depth_to_mbar(first_ceiling, dive); if (decoMode() == VPMB)
deco_state->first_ceiling_pressure.mbar = depth_to_mbar(first_ceiling, dive);
struct gasmix *gasmix = NULL; struct gasmix *gasmix = NULL;
struct event *ev = NULL; struct event *ev = NULL;
@ -1001,9 +1008,9 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
if (decoMode() == VPMB && last_ceiling >= first_ceiling && first_iteration == true) { if (decoMode() == VPMB && last_ceiling >= first_ceiling && first_iteration == true) {
nuclear_regeneration(t1); nuclear_regeneration(t1);
vpmb_start_gradient(); vpmb_start_gradient();
/* For CVA calculations, start by guessing deco time = dive time remaining */ /* For CVA iterations, calculate next gradient */
deco_time = pi->maxtime - t1; if (!first_iteration || in_planner())
vpmb_next_gradient(deco_time, surface_pressure / 1000.0); vpmb_next_gradient(deco_time, surface_pressure / 1000.0);
} }
entry->ceiling = deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(entry->depth, dive)), surface_pressure, dive, !prefs.calcceiling3m); entry->ceiling = deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(entry->depth, dive)), surface_pressure, dive, !prefs.calcceiling3m);
if (prefs.calcceiling3m) if (prefs.calcceiling3m)
@ -1011,9 +1018,10 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
else else
current_ceiling = entry->ceiling; current_ceiling = entry->ceiling;
last_ceiling = current_ceiling; last_ceiling = current_ceiling;
/* If using VPM-B outside the planner, take first_ceiling_pressure as the deepest ceiling */ /* If using VPM-B, take first_ceiling_pressure as the deepest ceiling */
if (decoMode() == VPMB) { if (decoMode() == VPMB) {
if (current_ceiling > first_ceiling) { if (current_ceiling >= first_ceiling ||
time_deep_ceiling == t0 && entry->depth == (entry - 1)->depth) {
time_deep_ceiling = t1; time_deep_ceiling = t1;
first_ceiling = current_ceiling; first_ceiling = current_ceiling;
deco_state->first_ceiling_pressure.mbar = depth_to_mbar(first_ceiling, dive); deco_state->first_ceiling_pressure.mbar = depth_to_mbar(first_ceiling, dive);
@ -1021,7 +1029,8 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
nuclear_regeneration(t1); nuclear_regeneration(t1);
vpmb_start_gradient(); vpmb_start_gradient();
/* For CVA calculations, start by guessing deco time = dive time remaining */ /* For CVA calculations, start by guessing deco time = dive time remaining */
deco_time = pi->maxtime - t1; if (!in_planner())
deco_time = pi->maxtime - t1;
vpmb_next_gradient(deco_time, surface_pressure / 1000.0); vpmb_next_gradient(deco_time, surface_pressure / 1000.0);
} }
} }
@ -1083,7 +1092,7 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
count_iteration ++; count_iteration ++;
restore_deco_state(cache_data_initial, true); restore_deco_state(cache_data_initial, true);
} else { } else {
// With Buhlmann, or not in planner, iterating isn't needed. This makes the while condition false. // With Buhlmann iterating isn't needed. This makes the while condition false.
prev_deco_time = deco_time = 0; prev_deco_time = deco_time = 0;
} }
} }