Localize global planner state

For UI responsiveness, we need to be able to run the planner in the background. This needs the
planner state to be localized (and we need to pass a pointer around).

In order to not let too many lines overrun (and to save typing in the future)
I have renamed instances of struct deco_state to ds. Yes this should have gone
to a separate commit but I accidentally commit --amend'ed it.

Computing of planner variations is temporarily disabled.

Unlock the planner when returning early

So we don't deadlock in add dive and recreational mode (which
use the planner without actually planning).

Signed-off-by: Robert C. Helling <helling@atdotde.de>
This commit is contained in:
Robert C. Helling 2017-11-22 20:42:33 +01:00
parent a9ceecc2e3
commit 8e21a65653
14 changed files with 298 additions and 286 deletions

View file

@ -151,11 +151,7 @@ const double vpmb_conservatism_lvls[] = { 1.0, 1.05, 1.12, 1.22, 1.35 };
#define DECO_STOPS_MULTIPLIER_MM 3000.0
#define NITROGEN_FRACTION 0.79
struct deco_state global_deco_state;
struct deco_state *deco_state = &global_deco_state;
#define TISSUE_ARRAY_SZ sizeof(deco_state->tissue_n2_sat)
#define TISSUE_ARRAY_SZ sizeof(ds->tissue_n2_sat)
int sumx, sum1;
long sumxx;
@ -194,9 +190,9 @@ double solve_cubic2(double B, double C)
// This is a simplified formula avoiding radii. It uses the fact that Boyle's law says
// pV = (G + P_amb) / G^3 is constant to solve for the new gradient G.
double update_gradient(double next_stop_pressure, double first_gradient)
double update_gradient(struct deco_state *ds, double next_stop_pressure, double first_gradient)
{
double B = cube(first_gradient) / (deco_state->first_ceiling_pressure.mbar / 1000.0 + first_gradient);
double B = cube(first_gradient) / (ds->first_ceiling_pressure.mbar / 1000.0 + first_gradient);
double C = next_stop_pressure * B;
double new_gradient = solve_cubic2(B, C);
@ -206,25 +202,25 @@ double update_gradient(double next_stop_pressure, double first_gradient)
return new_gradient;
}
double vpmb_tolerated_ambient_pressure(double reference_pressure, int ci)
double vpmb_tolerated_ambient_pressure(struct deco_state *ds, double reference_pressure, int ci)
{
double n2_gradient, he_gradient, total_gradient;
if (reference_pressure >= deco_state->first_ceiling_pressure.mbar / 1000.0 || !deco_state->first_ceiling_pressure.mbar) {
n2_gradient = deco_state->bottom_n2_gradient[ci];
he_gradient = deco_state->bottom_he_gradient[ci];
if (reference_pressure >= ds->first_ceiling_pressure.mbar / 1000.0 || !ds->first_ceiling_pressure.mbar) {
n2_gradient = ds->bottom_n2_gradient[ci];
he_gradient = ds->bottom_he_gradient[ci];
} else {
n2_gradient = update_gradient(reference_pressure, deco_state->bottom_n2_gradient[ci]);
he_gradient = update_gradient(reference_pressure, deco_state->bottom_he_gradient[ci]);
n2_gradient = update_gradient(ds, reference_pressure, ds->bottom_n2_gradient[ci]);
he_gradient = update_gradient(ds, reference_pressure, ds->bottom_he_gradient[ci]);
}
total_gradient = ((n2_gradient * deco_state->tissue_n2_sat[ci]) + (he_gradient * deco_state->tissue_he_sat[ci])) / (deco_state->tissue_n2_sat[ci] + deco_state->tissue_he_sat[ci]);
total_gradient = ((n2_gradient * ds->tissue_n2_sat[ci]) + (he_gradient * ds->tissue_he_sat[ci])) / (ds->tissue_n2_sat[ci] + ds->tissue_he_sat[ci]);
return deco_state->tissue_n2_sat[ci] + deco_state->tissue_he_sat[ci] + vpmb_config.other_gases_pressure - total_gradient;
return ds->tissue_n2_sat[ci] + ds->tissue_he_sat[ci] + vpmb_config.other_gases_pressure - total_gradient;
}
double tissue_tolerance_calc(const struct dive *dive, double pressure)
double tissue_tolerance_calc(struct deco_state *ds, const struct dive *dive, double pressure)
{
int ci = -1;
double ret_tolerance_limit_ambient_pressure = 0.0;
@ -235,8 +231,8 @@ double tissue_tolerance_calc(const struct dive *dive, double pressure)
double tissue_lowest_ceiling[16];
for (ci = 0; ci < 16; ci++) {
deco_state->buehlmann_inertgas_a[ci] = ((buehlmann_N2_a[ci] * deco_state->tissue_n2_sat[ci]) + (buehlmann_He_a[ci] * deco_state->tissue_he_sat[ci])) / deco_state->tissue_inertgas_saturation[ci];
deco_state->buehlmann_inertgas_b[ci] = ((buehlmann_N2_b[ci] * deco_state->tissue_n2_sat[ci]) + (buehlmann_He_b[ci] * deco_state->tissue_he_sat[ci])) / deco_state->tissue_inertgas_saturation[ci];
ds->buehlmann_inertgas_a[ci] = ((buehlmann_N2_a[ci] * ds->tissue_n2_sat[ci]) + (buehlmann_He_a[ci] * ds->tissue_he_sat[ci])) / ds->tissue_inertgas_saturation[ci];
ds->buehlmann_inertgas_b[ci] = ((buehlmann_N2_b[ci] * ds->tissue_n2_sat[ci]) + (buehlmann_He_b[ci] * ds->tissue_he_sat[ci])) / ds->tissue_inertgas_saturation[ci];
}
if (decoMode() != VPMB) {
@ -244,32 +240,32 @@ double tissue_tolerance_calc(const struct dive *dive, double pressure)
/* tolerated = (tissue_inertgas_saturation - buehlmann_inertgas_a) * buehlmann_inertgas_b; */
tissue_lowest_ceiling[ci] = (deco_state->buehlmann_inertgas_b[ci] * deco_state->tissue_inertgas_saturation[ci] - gf_low * deco_state->buehlmann_inertgas_a[ci] * deco_state->buehlmann_inertgas_b[ci]) /
((1.0 - deco_state->buehlmann_inertgas_b[ci]) * gf_low + deco_state->buehlmann_inertgas_b[ci]);
tissue_lowest_ceiling[ci] = (ds->buehlmann_inertgas_b[ci] * ds->tissue_inertgas_saturation[ci] - gf_low * ds->buehlmann_inertgas_a[ci] * ds->buehlmann_inertgas_b[ci]) /
((1.0 - ds->buehlmann_inertgas_b[ci]) * gf_low + ds->buehlmann_inertgas_b[ci]);
if (tissue_lowest_ceiling[ci] > lowest_ceiling)
lowest_ceiling = tissue_lowest_ceiling[ci];
if (lowest_ceiling > deco_state->gf_low_pressure_this_dive)
deco_state->gf_low_pressure_this_dive = lowest_ceiling;
if (lowest_ceiling > ds->gf_low_pressure_this_dive)
ds->gf_low_pressure_this_dive = lowest_ceiling;
}
for (ci = 0; ci < 16; ci++) {
double tolerated;
if ((surface / deco_state->buehlmann_inertgas_b[ci] + deco_state->buehlmann_inertgas_a[ci] - surface) * gf_high + surface <
(deco_state->gf_low_pressure_this_dive / deco_state->buehlmann_inertgas_b[ci] + deco_state->buehlmann_inertgas_a[ci] - deco_state->gf_low_pressure_this_dive) * gf_low + deco_state->gf_low_pressure_this_dive)
tolerated = (-deco_state->buehlmann_inertgas_a[ci] * deco_state->buehlmann_inertgas_b[ci] * (gf_high * deco_state->gf_low_pressure_this_dive - gf_low * surface) -
(1.0 - deco_state->buehlmann_inertgas_b[ci]) * (gf_high - gf_low) * deco_state->gf_low_pressure_this_dive * surface +
deco_state->buehlmann_inertgas_b[ci] * (deco_state->gf_low_pressure_this_dive - surface) * deco_state->tissue_inertgas_saturation[ci]) /
(-deco_state->buehlmann_inertgas_a[ci] * deco_state->buehlmann_inertgas_b[ci] * (gf_high - gf_low) +
(1.0 - deco_state->buehlmann_inertgas_b[ci]) * (gf_low * deco_state->gf_low_pressure_this_dive - gf_high * surface) +
deco_state->buehlmann_inertgas_b[ci] * (deco_state->gf_low_pressure_this_dive - surface));
if ((surface / ds->buehlmann_inertgas_b[ci] + ds->buehlmann_inertgas_a[ci] - surface) * gf_high + surface <
(ds->gf_low_pressure_this_dive / ds->buehlmann_inertgas_b[ci] + ds->buehlmann_inertgas_a[ci] - ds->gf_low_pressure_this_dive) * gf_low + ds->gf_low_pressure_this_dive)
tolerated = (-ds->buehlmann_inertgas_a[ci] * ds->buehlmann_inertgas_b[ci] * (gf_high * ds->gf_low_pressure_this_dive - gf_low * surface) -
(1.0 - ds->buehlmann_inertgas_b[ci]) * (gf_high - gf_low) * ds->gf_low_pressure_this_dive * surface +
ds->buehlmann_inertgas_b[ci] * (ds->gf_low_pressure_this_dive - surface) * ds->tissue_inertgas_saturation[ci]) /
(-ds->buehlmann_inertgas_a[ci] * ds->buehlmann_inertgas_b[ci] * (gf_high - gf_low) +
(1.0 - ds->buehlmann_inertgas_b[ci]) * (gf_low * ds->gf_low_pressure_this_dive - gf_high * surface) +
ds->buehlmann_inertgas_b[ci] * (ds->gf_low_pressure_this_dive - surface));
else
tolerated = ret_tolerance_limit_ambient_pressure;
deco_state->tolerated_by_tissue[ci] = tolerated;
ds->tolerated_by_tissue[ci] = tolerated;
if (tolerated >= ret_tolerance_limit_ambient_pressure) {
deco_state->ci_pointing_to_guiding_tissue = ci;
ds->ci_pointing_to_guiding_tissue = ci;
ret_tolerance_limit_ambient_pressure = tolerated;
}
}
@ -283,12 +279,12 @@ double tissue_tolerance_calc(const struct dive *dive, double pressure)
reference_pressure = ret_tolerance_limit_ambient_pressure;
ret_tolerance_limit_ambient_pressure = 0.0;
for (ci = 0; ci < 16; ci++) {
double tolerated = vpmb_tolerated_ambient_pressure(reference_pressure, ci);
double tolerated = vpmb_tolerated_ambient_pressure(ds, reference_pressure, ci);
if (tolerated >= ret_tolerance_limit_ambient_pressure) {
deco_state->ci_pointing_to_guiding_tissue = ci;
ds->ci_pointing_to_guiding_tissue = ci;
ret_tolerance_limit_ambient_pressure = tolerated;
}
deco_state->tolerated_by_tissue[ci] = tolerated;
ds->tolerated_by_tissue[ci] = tolerated;
}
// We are doing ok if the gradient was computed within ten centimeters of the ceiling.
} while (fabs(ret_tolerance_limit_ambient_pressure - reference_pressure) > 0.01);
@ -298,12 +294,12 @@ double tissue_tolerance_calc(const struct dive *dive, double pressure)
sumx += plot_depth;
sumxx += plot_depth * plot_depth;
double n2_gradient, he_gradient, total_gradient;
n2_gradient = update_gradient(depth_to_bar(plot_depth, &displayed_dive), deco_state->bottom_n2_gradient[deco_state->ci_pointing_to_guiding_tissue]);
he_gradient = update_gradient(depth_to_bar(plot_depth, &displayed_dive), deco_state->bottom_he_gradient[deco_state->ci_pointing_to_guiding_tissue]);
total_gradient = ((n2_gradient * deco_state->tissue_n2_sat[deco_state->ci_pointing_to_guiding_tissue]) + (he_gradient * deco_state->tissue_he_sat[deco_state->ci_pointing_to_guiding_tissue]))
/ (deco_state->tissue_n2_sat[deco_state->ci_pointing_to_guiding_tissue] + deco_state->tissue_he_sat[deco_state->ci_pointing_to_guiding_tissue]);
n2_gradient = update_gradient(ds, depth_to_bar(plot_depth, &displayed_dive), ds->bottom_n2_gradient[ds->ci_pointing_to_guiding_tissue]);
he_gradient = update_gradient(ds, depth_to_bar(plot_depth, &displayed_dive), ds->bottom_he_gradient[ds->ci_pointing_to_guiding_tissue]);
total_gradient = ((n2_gradient * ds->tissue_n2_sat[ds->ci_pointing_to_guiding_tissue]) + (he_gradient * ds->tissue_he_sat[ds->ci_pointing_to_guiding_tissue]))
/ (ds->tissue_n2_sat[ds->ci_pointing_to_guiding_tissue] + ds->tissue_he_sat[ds->ci_pointing_to_guiding_tissue]);
double buehlmann_gradient = (1.0 / deco_state->buehlmann_inertgas_b[deco_state->ci_pointing_to_guiding_tissue] - 1.0) * depth_to_bar(plot_depth, &displayed_dive) + deco_state->buehlmann_inertgas_a[deco_state->ci_pointing_to_guiding_tissue];
double buehlmann_gradient = (1.0 / ds->buehlmann_inertgas_b[ds->ci_pointing_to_guiding_tissue] - 1.0) * depth_to_bar(plot_depth, &displayed_dive) + ds->buehlmann_inertgas_a[ds->ci_pointing_to_guiding_tissue];
double gf = (total_gradient - vpmb_config.other_gases_pressure) / buehlmann_gradient;
sumxy += gf * plot_depth;
sumy += gf;
@ -362,17 +358,17 @@ double calc_surface_phase(double surface_pressure, double he_pressure, double n2
return 0;
}
void vpmb_start_gradient()
void vpmb_start_gradient(struct deco_state *ds)
{
int ci;
for (ci = 0; ci < 16; ++ci) {
deco_state->initial_n2_gradient[ci] = deco_state->bottom_n2_gradient[ci] = 2.0 * (vpmb_config.surface_tension_gamma / vpmb_config.skin_compression_gammaC) * ((vpmb_config.skin_compression_gammaC - vpmb_config.surface_tension_gamma) / deco_state->n2_regen_radius[ci]);
deco_state->initial_he_gradient[ci] = deco_state->bottom_he_gradient[ci] = 2.0 * (vpmb_config.surface_tension_gamma / vpmb_config.skin_compression_gammaC) * ((vpmb_config.skin_compression_gammaC - vpmb_config.surface_tension_gamma) / deco_state->he_regen_radius[ci]);
ds->initial_n2_gradient[ci] = ds->bottom_n2_gradient[ci] = 2.0 * (vpmb_config.surface_tension_gamma / vpmb_config.skin_compression_gammaC) * ((vpmb_config.skin_compression_gammaC - vpmb_config.surface_tension_gamma) / ds->n2_regen_radius[ci]);
ds->initial_he_gradient[ci] = ds->bottom_he_gradient[ci] = 2.0 * (vpmb_config.surface_tension_gamma / vpmb_config.skin_compression_gammaC) * ((vpmb_config.skin_compression_gammaC - vpmb_config.surface_tension_gamma) / ds->he_regen_radius[ci]);
}
}
void vpmb_next_gradient(double deco_time, double surface_pressure)
void vpmb_next_gradient(struct deco_state *ds, double deco_time, double surface_pressure)
{
int ci;
double n2_b, n2_c;
@ -381,18 +377,18 @@ void vpmb_next_gradient(double deco_time, double surface_pressure)
deco_time /= 60.0;
for (ci = 0; ci < 16; ++ci) {
desat_time = deco_time + calc_surface_phase(surface_pressure, deco_state->tissue_he_sat[ci], deco_state->tissue_n2_sat[ci], log(2.0) / buehlmann_He_t_halflife[ci], log(2.0) / buehlmann_N2_t_halflife[ci]);
desat_time = deco_time + calc_surface_phase(surface_pressure, ds->tissue_he_sat[ci], ds->tissue_n2_sat[ci], log(2.0) / buehlmann_He_t_halflife[ci], log(2.0) / buehlmann_N2_t_halflife[ci]);
n2_b = deco_state->initial_n2_gradient[ci] + (vpmb_config.crit_volume_lambda * vpmb_config.surface_tension_gamma) / (vpmb_config.skin_compression_gammaC * desat_time);
he_b = deco_state->initial_he_gradient[ci] + (vpmb_config.crit_volume_lambda * vpmb_config.surface_tension_gamma) / (vpmb_config.skin_compression_gammaC * desat_time);
n2_b = ds->initial_n2_gradient[ci] + (vpmb_config.crit_volume_lambda * vpmb_config.surface_tension_gamma) / (vpmb_config.skin_compression_gammaC * desat_time);
he_b = ds->initial_he_gradient[ci] + (vpmb_config.crit_volume_lambda * vpmb_config.surface_tension_gamma) / (vpmb_config.skin_compression_gammaC * desat_time);
n2_c = vpmb_config.surface_tension_gamma * vpmb_config.surface_tension_gamma * vpmb_config.crit_volume_lambda * deco_state->max_n2_crushing_pressure[ci];
n2_c = vpmb_config.surface_tension_gamma * vpmb_config.surface_tension_gamma * vpmb_config.crit_volume_lambda * ds->max_n2_crushing_pressure[ci];
n2_c = n2_c / (vpmb_config.skin_compression_gammaC * vpmb_config.skin_compression_gammaC * desat_time);
he_c = vpmb_config.surface_tension_gamma * vpmb_config.surface_tension_gamma * vpmb_config.crit_volume_lambda * deco_state->max_he_crushing_pressure[ci];
he_c = vpmb_config.surface_tension_gamma * vpmb_config.surface_tension_gamma * vpmb_config.crit_volume_lambda * ds->max_he_crushing_pressure[ci];
he_c = he_c / (vpmb_config.skin_compression_gammaC * vpmb_config.skin_compression_gammaC * desat_time);
deco_state->bottom_n2_gradient[ci] = 0.5 * ( n2_b + sqrt(n2_b * n2_b - 4.0 * n2_c));
deco_state->bottom_he_gradient[ci] = 0.5 * ( he_b + sqrt(he_b * he_b - 4.0 * he_c));
ds->bottom_n2_gradient[ci] = 0.5 * ( n2_b + sqrt(n2_b * n2_b - 4.0 * n2_c));
ds->bottom_he_gradient[ci] = 0.5 * ( he_b + sqrt(he_b * he_b - 4.0 * he_c));
}
}
@ -418,18 +414,18 @@ double solve_cubic(double A, double B, double C)
}
void nuclear_regeneration(double time)
void nuclear_regeneration(struct deco_state *ds, double time)
{
time /= 60.0;
int ci;
double crushing_radius_N2, crushing_radius_He;
for (ci = 0; ci < 16; ++ci) {
//rm
crushing_radius_N2 = 1.0 / (deco_state->max_n2_crushing_pressure[ci] / (2.0 * (vpmb_config.skin_compression_gammaC - vpmb_config.surface_tension_gamma)) + 1.0 / get_crit_radius_N2());
crushing_radius_He = 1.0 / (deco_state->max_he_crushing_pressure[ci] / (2.0 * (vpmb_config.skin_compression_gammaC - vpmb_config.surface_tension_gamma)) + 1.0 / get_crit_radius_He());
crushing_radius_N2 = 1.0 / (ds->max_n2_crushing_pressure[ci] / (2.0 * (vpmb_config.skin_compression_gammaC - vpmb_config.surface_tension_gamma)) + 1.0 / get_crit_radius_N2());
crushing_radius_He = 1.0 / (ds->max_he_crushing_pressure[ci] / (2.0 * (vpmb_config.skin_compression_gammaC - vpmb_config.surface_tension_gamma)) + 1.0 / get_crit_radius_He());
//rs
deco_state->n2_regen_radius[ci] = crushing_radius_N2 + (get_crit_radius_N2() - crushing_radius_N2) * (1.0 - exp (-time / vpmb_config.regeneration_time));
deco_state->he_regen_radius[ci] = crushing_radius_He + (get_crit_radius_He() - crushing_radius_He) * (1.0 - exp (-time / vpmb_config.regeneration_time));
ds->n2_regen_radius[ci] = crushing_radius_N2 + (get_crit_radius_N2() - crushing_radius_N2) * (1.0 - exp (-time / vpmb_config.regeneration_time));
ds->he_regen_radius[ci] = crushing_radius_He + (get_crit_radius_He() - crushing_radius_He) * (1.0 - exp (-time / vpmb_config.regeneration_time));
}
}
@ -450,7 +446,7 @@ double calc_inner_pressure(double crit_radius, double onset_tension, double curr
}
// Calculates the crushing pressure in the given moment. Updates crushing_onset_tension and critical radius if needed
void calc_crushing_pressure(double pressure)
void calc_crushing_pressure(struct deco_state *ds, double pressure)
{
int ci;
double gradient;
@ -459,31 +455,31 @@ void calc_crushing_pressure(double pressure)
double n2_inner_pressure, he_inner_pressure;
for (ci = 0; ci < 16; ++ci) {
gas_tension = deco_state->tissue_n2_sat[ci] + deco_state->tissue_he_sat[ci] + vpmb_config.other_gases_pressure;
gas_tension = ds->tissue_n2_sat[ci] + ds->tissue_he_sat[ci] + vpmb_config.other_gases_pressure;
gradient = pressure - gas_tension;
if (gradient <= vpmb_config.gradient_of_imperm) { // permeable situation
n2_crushing_pressure = he_crushing_pressure = gradient;
deco_state->crushing_onset_tension[ci] = gas_tension;
ds->crushing_onset_tension[ci] = gas_tension;
}
else { // impermeable
if (deco_state->max_ambient_pressure >= pressure)
if (ds->max_ambient_pressure >= pressure)
return;
n2_inner_pressure = calc_inner_pressure(get_crit_radius_N2(), deco_state->crushing_onset_tension[ci], pressure);
he_inner_pressure = calc_inner_pressure(get_crit_radius_He(), deco_state->crushing_onset_tension[ci], pressure);
n2_inner_pressure = calc_inner_pressure(get_crit_radius_N2(), ds->crushing_onset_tension[ci], pressure);
he_inner_pressure = calc_inner_pressure(get_crit_radius_He(), ds->crushing_onset_tension[ci], pressure);
n2_crushing_pressure = pressure - n2_inner_pressure;
he_crushing_pressure = pressure - he_inner_pressure;
}
deco_state->max_n2_crushing_pressure[ci] = MAX(deco_state->max_n2_crushing_pressure[ci], n2_crushing_pressure);
deco_state->max_he_crushing_pressure[ci] = MAX(deco_state->max_he_crushing_pressure[ci], he_crushing_pressure);
ds->max_n2_crushing_pressure[ci] = MAX(ds->max_n2_crushing_pressure[ci], n2_crushing_pressure);
ds->max_he_crushing_pressure[ci] = MAX(ds->max_he_crushing_pressure[ci], he_crushing_pressure);
}
deco_state->max_ambient_pressure = MAX(pressure, deco_state->max_ambient_pressure);
ds->max_ambient_pressure = MAX(pressure, ds->max_ambient_pressure);
}
/* add period_in_seconds at the given pressure and gas to the deco calculation */
void add_segment(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, const struct dive *dive, int sac)
{
(void) sac;
int ci;
@ -493,64 +489,64 @@ void add_segment(double pressure, const struct gasmix *gasmix, int period_in_sec
gasmix, (double) ccpo2 / 1000.0, dive->dc.divemode);
for (ci = 0; ci < 16; ci++) {
double pn2_oversat = pressures.n2 - deco_state->tissue_n2_sat[ci];
double phe_oversat = pressures.he - deco_state->tissue_he_sat[ci];
double pn2_oversat = pressures.n2 - ds->tissue_n2_sat[ci];
double phe_oversat = pressures.he - ds->tissue_he_sat[ci];
double n2_f = factor(period_in_seconds, ci, N2);
double he_f = factor(period_in_seconds, ci, HE);
double n2_satmult = pn2_oversat > 0 ? buehlmann_config.satmult : buehlmann_config.desatmult;
double he_satmult = phe_oversat > 0 ? buehlmann_config.satmult : buehlmann_config.desatmult;
deco_state->tissue_n2_sat[ci] += n2_satmult * pn2_oversat * n2_f;
deco_state->tissue_he_sat[ci] += he_satmult * phe_oversat * he_f;
deco_state->tissue_inertgas_saturation[ci] = deco_state->tissue_n2_sat[ci] + deco_state->tissue_he_sat[ci];
ds->tissue_n2_sat[ci] += n2_satmult * pn2_oversat * n2_f;
ds->tissue_he_sat[ci] += he_satmult * phe_oversat * he_f;
ds->tissue_inertgas_saturation[ci] = ds->tissue_n2_sat[ci] + ds->tissue_he_sat[ci];
}
if(decoMode() == VPMB)
calc_crushing_pressure(pressure);
calc_crushing_pressure(ds, pressure);
return;
}
void dump_tissues()
void dump_tissues(struct deco_state *ds)
{
int ci;
printf("N2 tissues:");
for (ci = 0; ci < 16; ci++)
printf(" %6.3e", deco_state->tissue_n2_sat[ci]);
printf(" %6.3e", ds->tissue_n2_sat[ci]);
printf("\nHe tissues:");
for (ci = 0; ci < 16; ci++)
printf(" %6.3e", deco_state->tissue_he_sat[ci]);
printf(" %6.3e", ds->tissue_he_sat[ci]);
printf("\n");
}
void clear_vpmb_state() {
void clear_vpmb_state(struct deco_state *ds) {
int ci;
for (ci = 0; ci < 16; ci++) {
deco_state->max_n2_crushing_pressure[ci] = 0.0;
deco_state->max_he_crushing_pressure[ci] = 0.0;
ds->max_n2_crushing_pressure[ci] = 0.0;
ds->max_he_crushing_pressure[ci] = 0.0;
}
deco_state->max_ambient_pressure = 0;
deco_state->first_ceiling_pressure.mbar = 0;
deco_state->max_bottom_ceiling_pressure.mbar = 0;
ds->max_ambient_pressure = 0;
ds->first_ceiling_pressure.mbar = 0;
ds->max_bottom_ceiling_pressure.mbar = 0;
}
void clear_deco(double surface_pressure)
void clear_deco(struct deco_state *ds, double surface_pressure)
{
int ci;
clear_vpmb_state();
clear_vpmb_state(ds);
for (ci = 0; ci < 16; ci++) {
deco_state->tissue_n2_sat[ci] = (surface_pressure - ((in_planner() && (decoMode() == VPMB)) ? WV_PRESSURE_SCHREINER : WV_PRESSURE)) * N2_IN_AIR / 1000;
deco_state->tissue_he_sat[ci] = 0.0;
deco_state->max_n2_crushing_pressure[ci] = 0.0;
deco_state->max_he_crushing_pressure[ci] = 0.0;
deco_state->n2_regen_radius[ci] = get_crit_radius_N2();
deco_state->he_regen_radius[ci] = get_crit_radius_He();
ds->tissue_n2_sat[ci] = (surface_pressure - ((in_planner() && (decoMode() == VPMB)) ? WV_PRESSURE_SCHREINER : WV_PRESSURE)) * N2_IN_AIR / 1000;
ds->tissue_he_sat[ci] = 0.0;
ds->max_n2_crushing_pressure[ci] = 0.0;
ds->max_he_crushing_pressure[ci] = 0.0;
ds->n2_regen_radius[ci] = get_crit_radius_N2();
ds->he_regen_radius[ci] = get_crit_radius_He();
}
deco_state->gf_low_pressure_this_dive = surface_pressure;
deco_state->gf_low_pressure_this_dive += buehlmann_config.gf_low_position_min;
deco_state->max_ambient_pressure = 0.0;
ds->gf_low_pressure_this_dive = surface_pressure;
ds->gf_low_pressure_this_dive += buehlmann_config.gf_low_position_min;
ds->max_ambient_pressure = 0.0;
}
void cache_deco_state(struct deco_state **cached_datap)
void cache_deco_state(struct deco_state *src, struct deco_state **cached_datap)
{
struct deco_state *data = *cached_datap;
@ -558,23 +554,23 @@ void cache_deco_state(struct deco_state **cached_datap)
data = malloc(sizeof(struct deco_state));
*cached_datap = data;
}
*data = *deco_state;
*data = *src;
}
void restore_deco_state(struct deco_state *data, bool keep_vpmb_state)
void restore_deco_state(struct deco_state *data, struct deco_state *target, bool keep_vpmb_state)
{
if (keep_vpmb_state) {
int ci;
for (ci = 0; ci < 16; ci++) {
data->bottom_n2_gradient[ci] = deco_state->bottom_n2_gradient[ci];
data->bottom_he_gradient[ci] = deco_state->bottom_he_gradient[ci];
data->initial_n2_gradient[ci] = deco_state->initial_n2_gradient[ci];
data->initial_he_gradient[ci] = deco_state->initial_he_gradient[ci];
data->bottom_n2_gradient[ci] = target->bottom_n2_gradient[ci];
data->bottom_he_gradient[ci] = target->bottom_he_gradient[ci];
data->initial_n2_gradient[ci] = target->initial_n2_gradient[ci];
data->initial_he_gradient[ci] = target->initial_he_gradient[ci];
}
data->first_ceiling_pressure = deco_state->first_ceiling_pressure;
data->max_bottom_ceiling_pressure = deco_state->max_bottom_ceiling_pressure;
data->first_ceiling_pressure = target->first_ceiling_pressure;
data->max_bottom_ceiling_pressure = target->max_bottom_ceiling_pressure;
}
*deco_state = *data;
*target = *data;
}
@ -615,15 +611,15 @@ void set_vpmb_conservatism(short conservatism)
vpmb_config.conservatism = conservatism;
}
double get_gf(double ambpressure_bar, const struct dive *dive)
double get_gf(struct deco_state *ds, double ambpressure_bar, const struct dive *dive)
{
double surface_pressure_bar = get_surface_pressure_in_mbar(dive, true) / 1000.0;
double gf_low = buehlmann_config.gf_low;
double gf_high = buehlmann_config.gf_high;
double gf;
if (deco_state->gf_low_pressure_this_dive > surface_pressure_bar)
if (ds->gf_low_pressure_this_dive > surface_pressure_bar)
gf = MAX((double)gf_low, (ambpressure_bar - surface_pressure_bar) /
(deco_state->gf_low_pressure_this_dive - surface_pressure_bar) * (gf_low - gf_high) + gf_high);
(ds->gf_low_pressure_this_dive - surface_pressure_bar) * (gf_low - gf_high) + gf_high);
else
gf = gf_low;
return gf;