mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Calculate ceiling only when it is needed
So far, add_segment() returned a tissue tolerance (i.e. ceiling) computed just in its return statement. This tissue_tolerance needed to be dragged around until it was needed or be dropped if not needed at all. As for VPM-B, this ceiling computation is a bit expensive, this patch calls the computation function tissue_tolerance_calc() when the value is actually needed and not before. This changes the signature of some functions. Signed-off-by: Robert C. Helling <helling@atdotde.de> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
d9306125d9
commit
bd8126a709
5 changed files with 68 additions and 78 deletions
20
deco.c
20
deco.c
|
@ -230,7 +230,7 @@ double vpmb_tolerated_ambient_pressure(double reference_pressure, int ci)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static double tissue_tolerance_calc(const struct dive *dive, double pressure)
|
double tissue_tolerance_calc(const struct dive *dive, double pressure)
|
||||||
{
|
{
|
||||||
int ci = -1;
|
int ci = -1;
|
||||||
double ret_tolerance_limit_ambient_pressure = 0.0;
|
double ret_tolerance_limit_ambient_pressure = 0.0;
|
||||||
|
@ -485,7 +485,7 @@ void calc_crushing_pressure(double pressure)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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, int sac)
|
void 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;
|
||||||
|
@ -508,7 +508,7 @@ double add_segment(double pressure, const struct gasmix *gasmix, int period_in_s
|
||||||
tissue_he_sat[ci] += he_satmult * phe_oversat * he_f;
|
tissue_he_sat[ci] += he_satmult * phe_oversat * he_f;
|
||||||
}
|
}
|
||||||
calc_crushing_pressure(pressure);
|
calc_crushing_pressure(pressure);
|
||||||
return tissue_tolerance_calc(dive, pressure);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_tissues()
|
void dump_tissues()
|
||||||
|
@ -540,12 +540,12 @@ void clear_deco(double surface_pressure)
|
||||||
max_ambient_pressure = 0.0;
|
max_ambient_pressure = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cache_deco_state(double tissue_tolerance, char **cached_datap)
|
void cache_deco_state(char **cached_datap)
|
||||||
{
|
{
|
||||||
char *data = *cached_datap;
|
char *data = *cached_datap;
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
data = malloc(2 * TISSUE_ARRAY_SZ + 2 * sizeof(double) + sizeof(int));
|
data = malloc(2 * TISSUE_ARRAY_SZ + sizeof(double) + sizeof(int));
|
||||||
*cached_datap = data;
|
*cached_datap = data;
|
||||||
}
|
}
|
||||||
memcpy(data, tissue_n2_sat, TISSUE_ARRAY_SZ);
|
memcpy(data, tissue_n2_sat, TISSUE_ARRAY_SZ);
|
||||||
|
@ -554,26 +554,18 @@ void cache_deco_state(double tissue_tolerance, char **cached_datap)
|
||||||
data += TISSUE_ARRAY_SZ;
|
data += TISSUE_ARRAY_SZ;
|
||||||
memcpy(data, &gf_low_pressure_this_dive, sizeof(double));
|
memcpy(data, &gf_low_pressure_this_dive, sizeof(double));
|
||||||
data += sizeof(double);
|
data += sizeof(double);
|
||||||
memcpy(data, &tissue_tolerance, sizeof(double));
|
|
||||||
data += sizeof(double);
|
|
||||||
memcpy(data, &ci_pointing_to_guiding_tissue, sizeof(int));
|
memcpy(data, &ci_pointing_to_guiding_tissue, sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
double restore_deco_state(char *data)
|
void restore_deco_state(char *data)
|
||||||
{
|
{
|
||||||
double tissue_tolerance;
|
|
||||||
|
|
||||||
memcpy(tissue_n2_sat, data, TISSUE_ARRAY_SZ);
|
memcpy(tissue_n2_sat, data, TISSUE_ARRAY_SZ);
|
||||||
data += TISSUE_ARRAY_SZ;
|
data += TISSUE_ARRAY_SZ;
|
||||||
memcpy(tissue_he_sat, data, TISSUE_ARRAY_SZ);
|
memcpy(tissue_he_sat, data, TISSUE_ARRAY_SZ);
|
||||||
data += TISSUE_ARRAY_SZ;
|
data += TISSUE_ARRAY_SZ;
|
||||||
memcpy(&gf_low_pressure_this_dive, data, sizeof(double));
|
memcpy(&gf_low_pressure_this_dive, data, sizeof(double));
|
||||||
data += sizeof(double);
|
data += sizeof(double);
|
||||||
memcpy(&tissue_tolerance, data, sizeof(double));
|
|
||||||
data += sizeof(double);
|
|
||||||
memcpy(&ci_pointing_to_guiding_tissue, data, sizeof(int));
|
memcpy(&ci_pointing_to_guiding_tissue, data, sizeof(int));
|
||||||
|
|
||||||
return tissue_tolerance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int deco_allowed_depth(double tissues_tolerance, double surface_pressure, struct dive *dive, bool smooth)
|
unsigned int deco_allowed_depth(double tissues_tolerance, double surface_pressure, struct dive *dive, bool smooth)
|
||||||
|
|
7
dive.h
7
dive.h
|
@ -790,16 +790,17 @@ 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, int sac);
|
extern void 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);
|
||||||
extern void set_gf(short gflow, short gfhigh, bool gf_low_at_maxdepth);
|
extern void set_gf(short gflow, short gfhigh, bool gf_low_at_maxdepth);
|
||||||
extern void cache_deco_state(double, char **datap);
|
extern void cache_deco_state(char **datap);
|
||||||
extern double restore_deco_state(char *data);
|
extern void restore_deco_state(char *data);
|
||||||
extern void nuclear_regeneration(double time);
|
extern void nuclear_regeneration(double time);
|
||||||
extern void vpmb_start_gradient();
|
extern void vpmb_start_gradient();
|
||||||
extern void vpmb_next_gradient(double deco_time, double surface_pressure);
|
extern void vpmb_next_gradient(double deco_time, double surface_pressure);
|
||||||
|
extern double tissue_tolerance_calc(const struct dive *dive, double pressure);
|
||||||
|
|
||||||
/* this should be converted to use our types */
|
/* this should be converted to use our types */
|
||||||
struct divedatapoint {
|
struct divedatapoint {
|
||||||
|
|
10
divelist.c
10
divelist.c
|
@ -364,12 +364,12 @@ double init_decompression(struct dive *dive)
|
||||||
unsigned int surface_time;
|
unsigned int surface_time;
|
||||||
timestamp_t when, lasttime = 0, laststart = 0;
|
timestamp_t when, lasttime = 0, laststart = 0;
|
||||||
bool deco_init = false;
|
bool deco_init = false;
|
||||||
double tissue_tolerance, surface_pressure;
|
double surface_pressure;
|
||||||
|
|
||||||
if (!dive)
|
if (!dive)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
tissue_tolerance = surface_pressure = get_surface_pressure_in_mbar(dive, true) / 1000.0;
|
surface_pressure = get_surface_pressure_in_mbar(dive, true) / 1000.0;
|
||||||
divenr = get_divenr(dive);
|
divenr = get_divenr(dive);
|
||||||
when = dive->when;
|
when = dive->when;
|
||||||
i = divenr;
|
i = divenr;
|
||||||
|
@ -415,7 +415,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, prefs.decosac);
|
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();
|
||||||
|
@ -426,7 +426,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, prefs.decosac);
|
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();
|
||||||
|
@ -440,7 +440,7 @@ double init_decompression(struct dive *dive)
|
||||||
dump_tissues();
|
dump_tissues();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return tissue_tolerance;
|
return tissue_tolerance_calc(dive, surface_pressure);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_cylinder_related_info(struct dive *dive)
|
void update_cylinder_related_info(struct dive *dive)
|
||||||
|
|
74
planner.c
74
planner.c
|
@ -101,43 +101,39 @@ int get_gasidx(struct dive *dive, struct gasmix *mix)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
double interpolate_transition(struct dive *dive, duration_t t0, duration_t t1, depth_t d0, depth_t d1, const struct gasmix *gasmix, o2pressure_t po2)
|
void interpolate_transition(struct dive *dive, duration_t t0, duration_t t1, depth_t d0, depth_t d1, const struct gasmix *gasmix, o2pressure_t po2)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
double tissue_tolerance = 0.0;
|
|
||||||
|
|
||||||
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, prefs.bottomsac);
|
add_segment(depth_to_mbar(depth, dive) / 1000.0, gasmix, 1, po2.mbar, dive, prefs.bottomsac);
|
||||||
}
|
}
|
||||||
if (d1.mm > d0.mm)
|
if (d1.mm > d0.mm)
|
||||||
calc_crushing_pressure(depth_to_mbar(d1.mm, &displayed_dive) / 1000.0);
|
calc_crushing_pressure(depth_to_mbar(d1.mm, &displayed_dive) / 1000.0);
|
||||||
|
|
||||||
return tissue_tolerance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns the tissue tolerance at the end of this (partial) dive */
|
/* returns the tissue tolerance at the end of this (partial) dive */
|
||||||
double tissue_at_end(struct dive *dive, char **cached_datap)
|
void tissue_at_end(struct dive *dive, char **cached_datap)
|
||||||
{
|
{
|
||||||
struct divecomputer *dc;
|
struct divecomputer *dc;
|
||||||
struct sample *sample, *psample;
|
struct sample *sample, *psample;
|
||||||
int i;
|
int i;
|
||||||
depth_t lastdepth = {};
|
depth_t lastdepth = {};
|
||||||
duration_t t0 = {}, t1 = {};
|
duration_t t0 = {}, t1 = {};
|
||||||
double tissue_tolerance;
|
|
||||||
struct gasmix gas;
|
struct gasmix gas;
|
||||||
|
|
||||||
if (!dive)
|
if (!dive)
|
||||||
return 0.0;
|
return;
|
||||||
if (*cached_datap) {
|
if (*cached_datap) {
|
||||||
tissue_tolerance = restore_deco_state(*cached_datap);
|
restore_deco_state(*cached_datap);
|
||||||
} else {
|
} else {
|
||||||
tissue_tolerance = init_decompression(dive);
|
init_decompression(dive);
|
||||||
cache_deco_state(tissue_tolerance, cached_datap);
|
cache_deco_state(cached_datap);
|
||||||
}
|
}
|
||||||
dc = &dive->dc;
|
dc = &dive->dc;
|
||||||
if (!dc->samples)
|
if (!dc->samples)
|
||||||
return tissue_tolerance;
|
return;
|
||||||
psample = sample = dc->sample;
|
psample = sample = dc->sample;
|
||||||
|
|
||||||
for (i = 0; i < dc->samples; i++, sample++) {
|
for (i = 0; i < dc->samples; i++, sample++) {
|
||||||
|
@ -145,11 +141,10 @@ double tissue_at_end(struct dive *dive, char **cached_datap)
|
||||||
get_gas_at_time(dive, dc, t0, &gas);
|
get_gas_at_time(dive, dc, t0, &gas);
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
lastdepth = psample->depth;
|
lastdepth = psample->depth;
|
||||||
tissue_tolerance = interpolate_transition(dive, t0, t1, lastdepth, sample->depth, &gas, sample->setpoint);
|
interpolate_transition(dive, t0, t1, lastdepth, sample->depth, &gas, sample->setpoint);
|
||||||
psample = sample;
|
psample = sample;
|
||||||
t0 = t1;
|
t0 = t1;
|
||||||
}
|
}
|
||||||
return tissue_tolerance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -870,7 +865,7 @@ void track_ascent_gas(int depth, cylinder_t *cylinder, int avg_depth, int bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine whether ascending to the next stop will break the ceiling. Return true if the ascent is ok, false if it isn't.
|
// Determine whether ascending to the next stop will break the ceiling. Return true if the ascent is ok, false if it isn't.
|
||||||
bool trial_ascent(int trial_depth, int stoplevel, int avg_depth, int bottom_time, double tissue_tolerance, struct gasmix *gasmix, int po2, double surface_pressure)
|
bool trial_ascent(int trial_depth, int stoplevel, int avg_depth, int bottom_time, struct gasmix *gasmix, int po2, double surface_pressure)
|
||||||
{
|
{
|
||||||
|
|
||||||
bool clear_to_ascend = true;
|
bool clear_to_ascend = true;
|
||||||
|
@ -879,18 +874,21 @@ bool trial_ascent(int trial_depth, int stoplevel, int avg_depth, int bottom_time
|
||||||
// For consistency with other VPM-B implementations, we should not start the ascent while the ceiling is
|
// For consistency with other VPM-B implementations, we should not start the ascent while the ceiling is
|
||||||
// deeper than the next stop (thus the offgasing during the ascent is ignored).
|
// deeper than the next stop (thus the offgasing during the ascent is ignored).
|
||||||
// However, we still need to make sure we don't break the ceiling due to on-gassing during ascent.
|
// However, we still need to make sure we don't break the ceiling due to on-gassing during ascent.
|
||||||
if (prefs.deco_mode == VPMB && (deco_allowed_depth(tissue_tolerance, surface_pressure, &displayed_dive, 1) > stoplevel))
|
if (prefs.deco_mode == VPMB && (deco_allowed_depth(tissue_tolerance_calc(&displayed_dive,
|
||||||
|
depth_to_mbar(stoplevel, &displayed_dive)),
|
||||||
|
surface_pressure, &displayed_dive, 1) > stoplevel))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cache_deco_state(tissue_tolerance, &trial_cache);
|
cache_deco_state(&trial_cache);
|
||||||
while (trial_depth > stoplevel) {
|
while (trial_depth > stoplevel) {
|
||||||
int deltad = ascent_velocity(trial_depth, avg_depth, bottom_time) * TIMESTEP;
|
int deltad = ascent_velocity(trial_depth, avg_depth, bottom_time) * TIMESTEP;
|
||||||
if (deltad > trial_depth) /* don't test against depth above surface */
|
if (deltad > trial_depth) /* don't test against depth above surface */
|
||||||
deltad = trial_depth;
|
deltad = trial_depth;
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(trial_depth, &displayed_dive) / 1000.0,
|
add_segment(depth_to_mbar(trial_depth, &displayed_dive) / 1000.0,
|
||||||
gasmix,
|
gasmix,
|
||||||
TIMESTEP, po2, &displayed_dive, prefs.decosac);
|
TIMESTEP, po2, &displayed_dive, prefs.decosac);
|
||||||
if (deco_allowed_depth(tissue_tolerance, surface_pressure, &displayed_dive, 1) > trial_depth - deltad) {
|
if (deco_allowed_depth(tissue_tolerance_calc(&displayed_dive, depth_to_mbar(trial_depth, &displayed_dive) / 1000.0),
|
||||||
|
surface_pressure, &displayed_dive, 1) > trial_depth - deltad) {
|
||||||
/* We should have stopped */
|
/* We should have stopped */
|
||||||
clear_to_ascend = false;
|
clear_to_ascend = false;
|
||||||
break;
|
break;
|
||||||
|
@ -936,7 +934,6 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
int current_cylinder;
|
int current_cylinder;
|
||||||
unsigned int stopidx;
|
unsigned int stopidx;
|
||||||
int depth;
|
int depth;
|
||||||
double tissue_tolerance = 0.0;
|
|
||||||
struct gaschanges *gaschanges = NULL;
|
struct gaschanges *gaschanges = NULL;
|
||||||
int gaschangenr;
|
int gaschangenr;
|
||||||
int *decostoplevels;
|
int *decostoplevels;
|
||||||
|
@ -1031,7 +1028,7 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
gi = gaschangenr - 1;
|
gi = gaschangenr - 1;
|
||||||
|
|
||||||
/* Set tissue tolerance and initial vpmb gradient at start of ascent phase */
|
/* Set tissue tolerance and initial vpmb gradient at start of ascent phase */
|
||||||
tissue_tolerance = tissue_at_end(&displayed_dive, cached_datap);
|
tissue_at_end(&displayed_dive, cached_datap);
|
||||||
nuclear_regeneration(clock);
|
nuclear_regeneration(clock);
|
||||||
vpmb_start_gradient();
|
vpmb_start_gradient();
|
||||||
|
|
||||||
|
@ -1039,10 +1036,10 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
bool safety_stop = prefs.safetystop && max_depth >= 10000;
|
bool safety_stop = prefs.safetystop && max_depth >= 10000;
|
||||||
track_ascent_gas(depth, &displayed_dive.cylinder[current_cylinder], avg_depth, bottom_time, safety_stop);
|
track_ascent_gas(depth, &displayed_dive.cylinder[current_cylinder], avg_depth, bottom_time, safety_stop);
|
||||||
// How long can we stay at the current depth and still directly ascent to the surface?
|
// How long can we stay at the current depth and still directly ascent to the surface?
|
||||||
while (trial_ascent(depth, 0, avg_depth, bottom_time, tissue_tolerance, &displayed_dive.cylinder[current_cylinder].gasmix,
|
while (trial_ascent(depth, 0, avg_depth, bottom_time, &displayed_dive.cylinder[current_cylinder].gasmix,
|
||||||
po2, diveplan->surface_pressure / 1000.0) &&
|
po2, diveplan->surface_pressure / 1000.0) &&
|
||||||
enough_gas(current_cylinder)) {
|
enough_gas(current_cylinder)) {
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
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, prefs.bottomsac);
|
DECOTIMESTEP, po2, &displayed_dive, prefs.bottomsac);
|
||||||
update_cylinder_pressure(&displayed_dive, depth, depth, DECOTIMESTEP, prefs.bottomsac, &displayed_dive.cylinder[current_cylinder], false);
|
update_cylinder_pressure(&displayed_dive, depth, depth, DECOTIMESTEP, prefs.bottomsac, &displayed_dive.cylinder[current_cylinder], false);
|
||||||
|
@ -1062,9 +1059,9 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
if (depth - deltad < 0)
|
if (depth - deltad < 0)
|
||||||
deltad = depth;
|
deltad = depth;
|
||||||
|
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
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, prefs.decosac);
|
TIMESTEP, po2, &displayed_dive, prefs.decosac);
|
||||||
clock += TIMESTEP;
|
clock += TIMESTEP;
|
||||||
depth -= deltad;
|
depth -= deltad;
|
||||||
if (depth <= 5000 && depth >= (5000 - deltad) && safety_stop) {
|
if (depth <= 5000 && depth >= (5000 - deltad) && safety_stop) {
|
||||||
|
@ -1099,10 +1096,10 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// VPM-B or Buehlmann Deco
|
// VPM-B or Buehlmann Deco
|
||||||
tissue_tolerance = tissue_at_end(&displayed_dive, cached_datap);
|
tissue_at_end(&displayed_dive, cached_datap);
|
||||||
previous_deco_time = 100000000;
|
previous_deco_time = 100000000;
|
||||||
deco_time = 10000000;
|
deco_time = 10000000;
|
||||||
cache_deco_state(tissue_tolerance, &bottom_cache); // Lets us make several iterations
|
cache_deco_state(&bottom_cache); // Lets us make several iterations
|
||||||
bottom_depth = depth;
|
bottom_depth = depth;
|
||||||
bottom_gi = gi;
|
bottom_gi = gi;
|
||||||
bottom_gas = gas;
|
bottom_gas = gas;
|
||||||
|
@ -1115,7 +1112,7 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
vpmb_next_gradient(deco_time, diveplan->surface_pressure / 1000.0);
|
vpmb_next_gradient(deco_time, diveplan->surface_pressure / 1000.0);
|
||||||
|
|
||||||
previous_deco_time = deco_time;
|
previous_deco_time = deco_time;
|
||||||
tissue_tolerance = restore_deco_state(bottom_cache);
|
restore_deco_state(bottom_cache);
|
||||||
|
|
||||||
depth = bottom_depth;
|
depth = bottom_depth;
|
||||||
gi = bottom_gi;
|
gi = bottom_gi;
|
||||||
|
@ -1127,7 +1124,8 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
breaktime = -1;
|
breaktime = -1;
|
||||||
breakcylinder = 0;
|
breakcylinder = 0;
|
||||||
o2time = 0;
|
o2time = 0;
|
||||||
first_ceiling_pressure.mbar = depth_to_mbar(deco_allowed_depth(tissue_tolerance,
|
first_ceiling_pressure.mbar = depth_to_mbar(deco_allowed_depth(tissue_tolerance_calc(&displayed_dive,
|
||||||
|
depth_to_mbar(depth, &displayed_dive) / 1000.0),
|
||||||
diveplan->surface_pressure / 1000.0,
|
diveplan->surface_pressure / 1000.0,
|
||||||
&displayed_dive,
|
&displayed_dive,
|
||||||
1),
|
1),
|
||||||
|
@ -1154,7 +1152,7 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
if (depth - deltad < stoplevels[stopidx])
|
if (depth - deltad < stoplevels[stopidx])
|
||||||
deltad = depth - stoplevels[stopidx];
|
deltad = depth - stoplevels[stopidx];
|
||||||
|
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
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, prefs.decosac);
|
TIMESTEP, po2, &displayed_dive, prefs.decosac);
|
||||||
clock += TIMESTEP;
|
clock += TIMESTEP;
|
||||||
|
@ -1179,7 +1177,7 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
|
|
||||||
if (current_cylinder != gaschanges[gi].gasidx) {
|
if (current_cylinder != gaschanges[gi].gasidx) {
|
||||||
if (!prefs.switch_at_req_stop ||
|
if (!prefs.switch_at_req_stop ||
|
||||||
!trial_ascent(depth, stoplevels[stopidx - 1], avg_depth, bottom_time, tissue_tolerance,
|
!trial_ascent(depth, stoplevels[stopidx - 1], avg_depth, bottom_time,
|
||||||
&displayed_dive.cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0) || get_o2(&displayed_dive.cylinder[current_cylinder].gasmix) < 160) {
|
&displayed_dive.cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0) || get_o2(&displayed_dive.cylinder[current_cylinder].gasmix) < 160) {
|
||||||
current_cylinder = gaschanges[gi].gasidx;
|
current_cylinder = gaschanges[gi].gasidx;
|
||||||
gas = displayed_dive.cylinder[current_cylinder].gasmix;
|
gas = displayed_dive.cylinder[current_cylinder].gasmix;
|
||||||
|
@ -1188,7 +1186,7 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
(get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[gi].depth / 1000.0);
|
(get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[gi].depth / 1000.0);
|
||||||
#endif
|
#endif
|
||||||
/* Stop for the minimum duration to switch gas */
|
/* Stop for the minimum duration to switch gas */
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
||||||
&displayed_dive.cylinder[current_cylinder].gasmix,
|
&displayed_dive.cylinder[current_cylinder].gasmix,
|
||||||
prefs.min_switch_duration, po2, &displayed_dive, prefs.decosac);
|
prefs.min_switch_duration, po2, &displayed_dive, prefs.decosac);
|
||||||
clock += prefs.min_switch_duration;
|
clock += prefs.min_switch_duration;
|
||||||
|
@ -1208,7 +1206,7 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
/* Save the current state and try to ascend to the next stopdepth */
|
/* Save the current state and try to ascend to the next stopdepth */
|
||||||
while (1) {
|
while (1) {
|
||||||
/* Check if ascending to next stop is clear, go back and wait if we hit the ceiling on the way */
|
/* Check if ascending to next stop is clear, go back and wait if we hit the ceiling on the way */
|
||||||
if (trial_ascent(depth, stoplevels[stopidx], avg_depth, bottom_time, tissue_tolerance,
|
if (trial_ascent(depth, stoplevels[stopidx], avg_depth, bottom_time,
|
||||||
&displayed_dive.cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0))
|
&displayed_dive.cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0))
|
||||||
break; /* We did not hit the ceiling */
|
break; /* We did not hit the ceiling */
|
||||||
|
|
||||||
|
@ -1234,7 +1232,7 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
(get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[gi + 1].depth / 1000.0);
|
(get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[gi + 1].depth / 1000.0);
|
||||||
#endif
|
#endif
|
||||||
/* Stop for the minimum duration to switch gas */
|
/* Stop for the minimum duration to switch gas */
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
||||||
&displayed_dive.cylinder[current_cylinder].gasmix,
|
&displayed_dive.cylinder[current_cylinder].gasmix,
|
||||||
prefs.min_switch_duration, po2, &displayed_dive, prefs.decosac);
|
prefs.min_switch_duration, po2, &displayed_dive, prefs.decosac);
|
||||||
clock += prefs.min_switch_duration;
|
clock += prefs.min_switch_duration;
|
||||||
|
@ -1247,7 +1245,7 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool
|
||||||
int this_decotimestep;
|
int this_decotimestep;
|
||||||
this_decotimestep = DECOTIMESTEP - clock % DECOTIMESTEP;
|
this_decotimestep = DECOTIMESTEP - clock % DECOTIMESTEP;
|
||||||
|
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0,
|
||||||
&displayed_dive.cylinder[current_cylinder].gasmix,
|
&displayed_dive.cylinder[current_cylinder].gasmix,
|
||||||
this_decotimestep, po2, &displayed_dive, prefs.decosac);
|
this_decotimestep, po2, &displayed_dive, prefs.decosac);
|
||||||
clock += this_decotimestep;
|
clock += this_decotimestep;
|
||||||
|
|
35
profile.c
35
profile.c
|
@ -758,7 +758,7 @@ static void setup_gas_sensor_pressure(struct dive *dive, struct divecomputer *dc
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate DECO STOP / TTS / NDL */
|
/* calculate DECO STOP / TTS / NDL */
|
||||||
static void calculate_ndl_tts(double tissue_tolerance, struct plot_data *entry, struct dive *dive, double surface_pressure)
|
static void calculate_ndl_tts(struct plot_data *entry, struct dive *dive, double surface_pressure)
|
||||||
{
|
{
|
||||||
/* FIXME: This should be configurable */
|
/* FIXME: This should be configurable */
|
||||||
/* ascent speed up to first deco stop */
|
/* ascent speed up to first deco stop */
|
||||||
|
@ -771,7 +771,8 @@ static void calculate_ndl_tts(double tissue_tolerance, struct plot_data *entry,
|
||||||
const int time_stepsize = 60;
|
const int time_stepsize = 60;
|
||||||
const int deco_stepsize = 3000;
|
const int deco_stepsize = 3000;
|
||||||
/* at what depth is the current deco-step? */
|
/* at what depth is the current deco-step? */
|
||||||
int next_stop = ROUND_UP(deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1), deco_stepsize);
|
int next_stop = ROUND_UP(deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_mbar(entry->depth, dive) / 1000.0),
|
||||||
|
surface_pressure, dive, 1), deco_stepsize);
|
||||||
int ascent_depth = entry->depth;
|
int ascent_depth = entry->depth;
|
||||||
/* at what time should we give up and say that we got enuff NDL? */
|
/* at what time should we give up and say that we got enuff NDL? */
|
||||||
const int max_ndl = 7200;
|
const int max_ndl = 7200;
|
||||||
|
@ -785,9 +786,9 @@ static void calculate_ndl_tts(double tissue_tolerance, struct plot_data *entry,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* stop if the ndl is above max_ndl seconds, and call it plenty of time */
|
/* stop if the ndl is above max_ndl seconds, and call it plenty of time */
|
||||||
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_calc(dive, depth_to_mbar(entry->depth, dive) / 1000.0), 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,
|
add_segment(depth_to_mbar(entry->depth, dive) / 1000.0,
|
||||||
&dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.bottomsac);
|
&dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.bottomsac);
|
||||||
}
|
}
|
||||||
/* we don't need to calculate anything else */
|
/* we don't need to calculate anything else */
|
||||||
|
@ -799,9 +800,9 @@ 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,
|
add_segment(depth_to_mbar(ascent_depth, dive) / 1000.0,
|
||||||
&dive->cylinder[cylinderindex].gasmix, ascent_s_per_step, entry->o2pressure.mbar, dive, prefs.decosac);
|
&dive->cylinder[cylinderindex].gasmix, ascent_s_per_step, entry->o2pressure.mbar, 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_calc(dive, depth_to_mbar(ascent_depth, dive) / 1000.0), surface_pressure, dive, 1), deco_stepsize);
|
||||||
}
|
}
|
||||||
ascent_depth = next_stop;
|
ascent_depth = next_stop;
|
||||||
|
|
||||||
|
@ -817,10 +818,10 @@ static void calculate_ndl_tts(double tissue_tolerance, struct plot_data *entry,
|
||||||
entry->stoptime_calc += time_stepsize;
|
entry->stoptime_calc += time_stepsize;
|
||||||
|
|
||||||
entry->tts_calc += time_stepsize;
|
entry->tts_calc += time_stepsize;
|
||||||
tissue_tolerance = add_segment(depth_to_mbar(ascent_depth, dive) / 1000.0,
|
add_segment(depth_to_mbar(ascent_depth, dive) / 1000.0,
|
||||||
&dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.decosac);
|
&dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.decosac);
|
||||||
|
|
||||||
if (deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1) <= next_stop) {
|
if (deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_mbar(ascent_depth,dive) / 1000.0), 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,
|
||||||
|
@ -837,7 +838,6 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
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;
|
||||||
double tissue_tolerance = 0;
|
|
||||||
int last_ndl_tts_calc_time = 0;
|
int last_ndl_tts_calc_time = 0;
|
||||||
for (i = 1; i < pi->nr; i++) {
|
for (i = 1; i < pi->nr; i++) {
|
||||||
struct plot_data *entry = pi->entry + i;
|
struct plot_data *entry = pi->entry + i;
|
||||||
|
@ -853,16 +853,15 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
|
||||||
time_stepsize = t1 - t0;
|
time_stepsize = t1 - t0;
|
||||||
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,
|
add_segment(depth_to_mbar(depth, dive) / 1000.0,
|
||||||
&dive->cylinder[entry->cylinderindex].gasmix, time_stepsize, entry->o2pressure.mbar, dive, entry->sac);
|
&dive->cylinder[entry->cylinderindex].gasmix, time_stepsize, entry->o2pressure.mbar, dive, entry->sac);
|
||||||
tissue_tolerance = min_pressure;
|
|
||||||
if ((t1 - j < time_stepsize) && (j < t1))
|
if ((t1 - j < time_stepsize) && (j < t1))
|
||||||
time_stepsize = t1 - j;
|
time_stepsize = t1 - j;
|
||||||
}
|
}
|
||||||
if (t0 == t1)
|
if (t0 == t1)
|
||||||
entry->ceiling = (entry - 1)->ceiling;
|
entry->ceiling = (entry - 1)->ceiling;
|
||||||
else
|
else
|
||||||
entry->ceiling = deco_allowed_depth(tissue_tolerance, surface_pressure, dive, !prefs.calcceiling3m);
|
entry->ceiling = deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_mbar(entry->depth, dive) / 1000.0), surface_pressure, dive, !prefs.calcceiling3m);
|
||||||
for (j = 0; j < 16; j++) {
|
for (j = 0; j < 16; j++) {
|
||||||
double m_value = buehlmann_inertgas_a[j] + entry->ambpressure / buehlmann_inertgas_b[j];
|
double m_value = buehlmann_inertgas_a[j] + entry->ambpressure / buehlmann_inertgas_b[j];
|
||||||
entry->ceilings[j] = deco_allowed_depth(tolerated_by_tissue[j], surface_pressure, dive, 1);
|
entry->ceilings[j] = deco_allowed_depth(tolerated_by_tissue[j], surface_pressure, dive, 1);
|
||||||
|
@ -887,10 +886,10 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
|
||||||
|
|
||||||
/* We are going to mess up deco state, so store it for later restore */
|
/* We are going to mess up deco state, so store it for later restore */
|
||||||
char *cache_data = NULL;
|
char *cache_data = NULL;
|
||||||
cache_deco_state(tissue_tolerance, &cache_data);
|
cache_deco_state(&cache_data);
|
||||||
calculate_ndl_tts(tissue_tolerance, entry, dive, surface_pressure);
|
calculate_ndl_tts(entry, dive, surface_pressure);
|
||||||
/* Restore "real" deco state for next real time step */
|
/* Restore "real" deco state for next real time step */
|
||||||
tissue_tolerance = restore_deco_state(cache_data);
|
restore_deco_state(cache_data);
|
||||||
free(cache_data);
|
free(cache_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue