mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Clean up the rewritten deco.c
In commit a7902f279a57 "Rewrite of the deco code" Robert kept the old code that he replaced around; I removed all that as it's in the git history if we ever need to look at it again but doesn't really help us in the file as it is. I also removed constants, variables and config parameters that aren't used in the new implementation and did some coding style / formatting changes to make deco.c more consistent with the rest of Subsurface. I also updated the comments at the top of the file to reflect reality. I did one change that actually affects the code. In the explanation of his changes Robert said that gf_low_pressure_this_dive is initialized to the exquivalent of 20m, yet his code added the surface pressure twice. I decided to change the default config value from 3 (bar) to 2 so that this indeed reflects (about) 20m (as in the code below surface_pressure is added to this value). Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
67d59ff018
commit
fc8b37d86b
1 changed files with 24 additions and 103 deletions
127
deco.c
127
deco.c
|
@ -1,18 +1,19 @@
|
||||||
/* calculate deco values
|
/* calculate deco values
|
||||||
* based on Bühlmann ZHL-16b
|
* based on Bühlmann ZHL-16b
|
||||||
* based on an implemention by heinrichs weikamp for the DR5
|
* based on an implemention by heinrichs weikamp for the DR5
|
||||||
* the original file doesn't carry a license and is used here with
|
* the original file was given to Subsurface under the GPLv2
|
||||||
* the permission of Matthias Heinrichs
|
* by Matthias Heinrichs
|
||||||
*
|
*
|
||||||
* The implementation below is (C) Dirk Hohndel 2012 and released under the GPLv2
|
* The implementation below is a fairly complete rewrite since then
|
||||||
|
* (C) Robert C. Helling 2013 and released under the GPLv2
|
||||||
*
|
*
|
||||||
* clear_deco() - call to initialize for a new deco calculation
|
* add_segment() - add <seconds> at the given pressure, breathing gasmix
|
||||||
* add_segment(pressure, gasmix, seconds) - add <seconds> at the given pressure, breathing gasmix
|
* deco_allowed_depth() - ceiling based on lead tissue, surface pressure, 3m increments or smooth
|
||||||
* deco_allowed_depth(tissues_tolerance, surface_pressure, dive, smooth)
|
* set_gf() - set Buehlmann gradient factors
|
||||||
* - ceiling based on lead tissue, surface pressure, 3m increments or smooth
|
* clear_deco()
|
||||||
* set_gf(gflow, gfhigh) - set Buehlmann gradient factors
|
* cache_deco_state()
|
||||||
* void cache_deco_state(tissue_tolerance, char **datap) - cache the relevant data allocate memory if needed
|
* restore_deco_state()
|
||||||
* double restore_deco_state(char *data) - restore the state and return the tissue_tolerance
|
* dump_tissues()
|
||||||
*/
|
*/
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -22,16 +23,12 @@
|
||||||
struct buehlmann_config {
|
struct buehlmann_config {
|
||||||
double satmult; //! safety at inert gas accumulation as percentage of effect (more than 100).
|
double satmult; //! safety at inert gas accumulation as percentage of effect (more than 100).
|
||||||
double desatmult; //! safety at inert gas depletion as percentage of effect (less than 100).
|
double desatmult; //! safety at inert gas depletion as percentage of effect (less than 100).
|
||||||
double safety_dist_deco_stop;//! assumed distance to official decompression where decompression takes places.
|
|
||||||
int last_deco_stop_in_mtr; //! depth of last_deco_stop.
|
int last_deco_stop_in_mtr; //! depth of last_deco_stop.
|
||||||
double gf_high; //! gradient factor high (at surface).
|
double gf_high; //! gradient factor high (at surface).
|
||||||
double gf_low; //! gradient factor low (at bottom/start of deco calculation).
|
double gf_low; //! gradient factor low (at bottom/start of deco calculation).
|
||||||
double gf_low_position_min; //! gf_low_position below surface_min_shallow.
|
double gf_low_position_min; //! gf_low_position below surface_min_shallow.
|
||||||
double gf_low_position_max; //! gf_low_position below surface_max_depth.
|
|
||||||
double gf_high_emergency; //! emergency gf factors
|
|
||||||
double gf_low_emergency; //! gradient factor low (at bottom/start of deco calculation).
|
|
||||||
};
|
};
|
||||||
struct buehlmann_config buehlmann_config = { 1.0, 1.01, 0.5, 0, 0.75, 0.35, 3.0, 6.0, 0.95, 0.95 };
|
struct buehlmann_config buehlmann_config = { 1.0, 1.01, 3, 0.75, 0.35, 2.0 };
|
||||||
struct dive_data {
|
struct dive_data {
|
||||||
double pressure; //! pesent ambient pressure
|
double pressure; //! pesent ambient pressure
|
||||||
double surface; //! pressure at water surface
|
double surface; //! pressure at water surface
|
||||||
|
@ -82,10 +79,6 @@ const double buehlmann_He_factor_expositon_one_second[] = {
|
||||||
|
|
||||||
#define WV_PRESSURE 0.0627 /* water vapor pressure */
|
#define WV_PRESSURE 0.0627 /* water vapor pressure */
|
||||||
#define N2_IN_AIR 0.7902
|
#define N2_IN_AIR 0.7902
|
||||||
#define DIST_FROM_3_MTR 0.28
|
|
||||||
#define PRESSURE_CHANGE_3M 0.3
|
|
||||||
#define TOLERANCE 0.02
|
|
||||||
|
|
||||||
#define DECO_STOPS_MULTIPLIER_MM 3000.0
|
#define DECO_STOPS_MULTIPLIER_MM 3000.0
|
||||||
|
|
||||||
double tissue_n2_sat[16];
|
double tissue_n2_sat[16];
|
||||||
|
@ -95,38 +88,6 @@ int ci_pointing_to_guiding_tissue;
|
||||||
double gf_low_pressure_this_dive;
|
double gf_low_pressure_this_dive;
|
||||||
#define TISSUE_ARRAY_SZ sizeof(tissue_n2_sat)
|
#define TISSUE_ARRAY_SZ sizeof(tissue_n2_sat)
|
||||||
|
|
||||||
/* static double actual_gradient_limit_obsolete(const struct dive_data *data) */
|
|
||||||
/* { */
|
|
||||||
/* double pressure_diff, limit_at_position; */
|
|
||||||
/* double gf_high = buehlmann_config.gf_high; */
|
|
||||||
/* double gf_low = buehlmann_config.gf_low; */
|
|
||||||
|
|
||||||
/* pressure_diff = data->pressure - data->surface; */
|
|
||||||
|
|
||||||
/* if (pressure_diff > TOLERANCE) { */
|
|
||||||
/* if (pressure_diff < gf_low_position_this_dive) */
|
|
||||||
/* limit_at_position = gf_high - ((gf_high - gf_low) * pressure_diff / gf_low_position_this_dive); */
|
|
||||||
/* else */
|
|
||||||
/* limit_at_position = gf_low; */
|
|
||||||
/* } else { */
|
|
||||||
/* limit_at_position = gf_high; */
|
|
||||||
/* } */
|
|
||||||
/* return limit_at_position; */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/* static double gradient_factor_calculation_obsolete(const struct dive_data *data) */
|
|
||||||
/* { */
|
|
||||||
/* double tissue_inertgas_saturation; */
|
|
||||||
|
|
||||||
/* tissue_inertgas_saturation = tissue_n2_sat[ci_pointing_to_guiding_tissue] + */
|
|
||||||
/* tissue_he_sat[ci_pointing_to_guiding_tissue]; */
|
|
||||||
/* if (tissue_inertgas_saturation < data->pressure) */
|
|
||||||
/* return 0.0; */
|
|
||||||
/* else */
|
|
||||||
/* return (tissue_inertgas_saturation - data->pressure) / */
|
|
||||||
/* (tissue_inertgas_saturation - tissue_tolerated_ambient_pressure[ci_pointing_to_guiding_tissue]); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
static double tissue_tolerance_calc(const struct dive *dive)
|
static double tissue_tolerance_calc(const struct dive *dive)
|
||||||
{
|
{
|
||||||
int ci = -1;
|
int ci = -1;
|
||||||
|
@ -144,13 +105,12 @@ static double tissue_tolerance_calc(const struct dive *dive)
|
||||||
|
|
||||||
/* tissue_tolerated_ambient_pressure[ci] = (tissue_inertgas_saturation - buehlmann_inertgas_a) * buehlmann_inertgas_b; */
|
/* tissue_tolerated_ambient_pressure[ci] = (tissue_inertgas_saturation - buehlmann_inertgas_a) * buehlmann_inertgas_b; */
|
||||||
|
|
||||||
tissue_tolerated_ambient_pressure[ci] = (-buehlmann_inertgas_a * buehlmann_inertgas_b * (gf_high * gf_low_pressure_this_dive - gf_low * surface)
|
tissue_tolerated_ambient_pressure[ci] = (-buehlmann_inertgas_a * buehlmann_inertgas_b * (gf_high * gf_low_pressure_this_dive - gf_low * surface) -
|
||||||
- (1.0 - buehlmann_inertgas_b) * (gf_high - gf_low) * gf_low_pressure_this_dive * surface
|
(1.0 - buehlmann_inertgas_b) * (gf_high - gf_low) * gf_low_pressure_this_dive * surface +
|
||||||
+ buehlmann_inertgas_b * (gf_low_pressure_this_dive - surface) * tissue_inertgas_saturation)
|
buehlmann_inertgas_b * (gf_low_pressure_this_dive - surface) * tissue_inertgas_saturation) /
|
||||||
/
|
(-buehlmann_inertgas_a * buehlmann_inertgas_b * (gf_high - gf_low) +
|
||||||
(-buehlmann_inertgas_a * buehlmann_inertgas_b * (gf_high - gf_low)
|
(1.0 - buehlmann_inertgas_b)*(gf_low * gf_low_pressure_this_dive - gf_high * surface) +
|
||||||
+ (1.0 - buehlmann_inertgas_b)*(gf_low * gf_low_pressure_this_dive - gf_high * surface)
|
buehlmann_inertgas_b * (gf_low_pressure_this_dive - surface));
|
||||||
+ buehlmann_inertgas_b * (gf_low_pressure_this_dive - surface));
|
|
||||||
|
|
||||||
if (tissue_tolerated_ambient_pressure[ci] > ret_tolerance_limit_ambient_pressure)
|
if (tissue_tolerated_ambient_pressure[ci] > ret_tolerance_limit_ambient_pressure)
|
||||||
{
|
{
|
||||||
|
@ -161,7 +121,7 @@ static double tissue_tolerance_calc(const struct dive *dive)
|
||||||
return ret_tolerance_limit_ambient_pressure;
|
return ret_tolerance_limit_ambient_pressure;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add a second 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, struct gasmix *gasmix, int period_in_seconds, double ccpo2, const struct dive *dive)
|
double add_segment(double pressure, struct gasmix *gasmix, int period_in_seconds, double ccpo2, const struct dive *dive)
|
||||||
{
|
{
|
||||||
int ci;
|
int ci;
|
||||||
|
@ -239,7 +199,7 @@ void clear_deco(double surface_pressure)
|
||||||
tissue_he_sat[ci] = 0.0;
|
tissue_he_sat[ci] = 0.0;
|
||||||
tissue_tolerated_ambient_pressure[ci] = 0.0;
|
tissue_tolerated_ambient_pressure[ci] = 0.0;
|
||||||
}
|
}
|
||||||
gf_low_pressure_this_dive = surface_pressure+ buehlmann_config.gf_low_position_min;
|
gf_low_pressure_this_dive = surface_pressure + buehlmann_config.gf_low_position_min;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cache_deco_state(double tissue_tolerance, char **cached_datap)
|
void cache_deco_state(double tissue_tolerance, char **cached_datap)
|
||||||
|
@ -287,59 +247,20 @@ unsigned int deco_allowed_depth(double tissues_tolerance, double surface_pressur
|
||||||
unsigned int depth;
|
unsigned int depth;
|
||||||
double pressure_delta;
|
double pressure_delta;
|
||||||
|
|
||||||
pressure_delta = tissues_tolerance > surface_pressure ? tissues_tolerance - surface_pressure : 0.0; /* Avoid negative depths */
|
/* Avoid negative depths */
|
||||||
|
pressure_delta = tissues_tolerance > surface_pressure ? tissues_tolerance - surface_pressure : 0.0;
|
||||||
|
|
||||||
/* gboolean below_gradient_limit; */
|
|
||||||
/* double new_gradient_factor; */
|
|
||||||
/* double pressure_delta = tissues_tolerance - surface_pressure; */
|
|
||||||
/* struct dive_data mydata; */
|
|
||||||
/* int bail = 1000; */
|
|
||||||
|
|
||||||
/* if (pressure_delta > 0) { */
|
|
||||||
/* if (!smooth) { */
|
|
||||||
/* multiples_of_3m = (pressure_delta + DIST_FROM_3_MTR) / 0.3; */
|
|
||||||
/* depth = 3000 * multiples_of_3m; */
|
|
||||||
/* } else { */
|
|
||||||
/* depth = rel_mbar_to_depth(pressure_delta * 1000, dive); */
|
|
||||||
/* } */
|
|
||||||
/* } else { */
|
|
||||||
/* depth = 0; */
|
|
||||||
/* } */
|
|
||||||
/* mydata.pressure = depth_to_mbar(depth, dive) / 1000.0; */
|
|
||||||
/* mydata.surface = surface_pressure; */
|
|
||||||
|
|
||||||
/* new_gradient_factor = gradient_factor_calculation(&mydata); */
|
|
||||||
/* below_gradient_limit = (new_gradient_factor < actual_gradient_limit(&mydata)); */
|
|
||||||
/* while(!below_gradient_limit) */
|
|
||||||
/* { */
|
|
||||||
/* /\* we run into bugs where this turns into an infinite loop; so add */
|
|
||||||
/* * some bailout code that prints a warning but prevents the code from hanging *\/ */
|
|
||||||
/* if (--bail == 0) { */
|
|
||||||
/* printf("WARNING!!!\n==========\nThe deco_allowed_depth() loop appears to hang.\nBailing out.\n"); */
|
|
||||||
/* break; */
|
|
||||||
/* } */
|
|
||||||
/* if (!smooth) */
|
|
||||||
/* mydata.pressure += PRESSURE_CHANGE_3M; */
|
|
||||||
/* else */
|
|
||||||
/* mydata.pressure += PRESSURE_CHANGE_3M / 30; /\* 4in / 10cm instead *\/ */
|
|
||||||
/* new_gradient_factor = gradient_factor_calculation(&mydata); */
|
|
||||||
/* below_gradient_limit = (new_gradient_factor < actual_gradient_limit(&mydata)); */
|
|
||||||
/* } */
|
|
||||||
/* depth = rel_mbar_to_depth((mydata.pressure - surface_pressure) * 1000, dive); */
|
|
||||||
|
|
||||||
depth = rel_mbar_to_depth(pressure_delta * 1000, dive);
|
depth = rel_mbar_to_depth(pressure_delta * 1000, dive);
|
||||||
|
|
||||||
if(!smooth)
|
if(!smooth)
|
||||||
depth = ceil(depth / DECO_STOPS_MULTIPLIER_MM) * DECO_STOPS_MULTIPLIER_MM;
|
depth = ceil(depth / DECO_STOPS_MULTIPLIER_MM) * DECO_STOPS_MULTIPLIER_MM;
|
||||||
|
|
||||||
if(depth > 0 && depth < buehlmann_config.last_deco_stop_in_mtr * 1000)
|
if(depth > 0 && depth < buehlmann_config.last_deco_stop_in_mtr * 1000)
|
||||||
depth = buehlmann_config.last_deco_stop_in_mtr * 1000;
|
depth = buehlmann_config.last_deco_stop_in_mtr * 1000;
|
||||||
|
|
||||||
return depth;
|
return depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void set_gf(double gflow, double gfhigh)
|
void set_gf(double gflow, double gfhigh)
|
||||||
{
|
{
|
||||||
if (gflow != -1.0)
|
if (gflow != -1.0)
|
||||||
|
|
Loading…
Add table
Reference in a new issue