Round gas depth properly

The D in MOD, EAD, END, and EADD stands for "depth" and
as such these should be mm in int rather than double.

The intermediate fn2 and fhe2, however, as intermediate
value should not be rounded to an integer.

The upshot of this is a litle more numerical stability.
It should lead to more stable values in TestProfile
when run on architectures with different floating
point precision.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
This commit is contained in:
Robert C. Helling 2021-12-03 14:59:36 +01:00
parent cbe6d89767
commit 9fd531dcc5
7 changed files with 31237 additions and 31232 deletions

View file

@ -41,7 +41,7 @@ const char *divemode_text_ui[] = {
// For writing/reading files.
const char *divemode_text[] = {"OC", "CCR", "PSCR", "Freedive"};
static int calculate_depth_to_mbar(int depth, pressure_t surface_pressure, int salinity);
static double calculate_depth_to_mbarf(int depth, pressure_t surface_pressure, int salinity);
/*
* The legacy format for sample pressures has a single pressure
@ -657,7 +657,7 @@ void update_setpoint_events(const struct dive *dive, struct divecomputer *dc)
gasmix = get_gasmix_from_event(dive, ev);
next = get_next_event(ev, "gaschange");
}
fill_pressures(&pressures, calculate_depth_to_mbar(dc->sample[i].depth.mm, dc->surface_pressure, 0), gasmix ,0, dc->divemode);
fill_pressures(&pressures, lrint(calculate_depth_to_mbarf(dc->sample[i].depth.mm, dc->surface_pressure, 0)), gasmix ,0, dc->divemode);
if (abs(dc->sample[i].setpoint.mbar - (int)(1000 * pressures.o2)) <= 50)
dc->sample[i].setpoint.mbar = 0;
}
@ -3209,7 +3209,7 @@ static double salinity_to_specific_weight(int salinity)
/* Pa = N/m^2 - so we determine the weight (in N) of the mass of 10m
* of water (and use standard salt water at 1.03kg per liter if we don't know salinity)
* and add that to the surface pressure (or to 1013 if that's unknown) */
static int calculate_depth_to_mbar(int depth, pressure_t surface_pressure, int salinity)
static double calculate_depth_to_mbarf(int depth, pressure_t surface_pressure, int salinity)
{
double specific_weight;
int mbar = surface_pressure.mbar;
@ -3221,13 +3221,17 @@ static int calculate_depth_to_mbar(int depth, pressure_t surface_pressure, int s
if (salinity < 500)
salinity += FRESHWATER_SALINITY;
specific_weight = salinity_to_specific_weight(salinity);
mbar += lrint(depth * specific_weight);
return mbar;
return mbar + depth * specific_weight;
}
int depth_to_mbar(int depth, const struct dive *dive)
{
return calculate_depth_to_mbar(depth, dive->surface_pressure, dive->salinity);
return lrint(calculate_depth_to_mbarf(depth, dive->surface_pressure, dive->salinity));
}
double depth_to_mbarf(int depth, const struct dive *dive)
{
return calculate_depth_to_mbarf(depth, dive->surface_pressure, dive->salinity);
}
double depth_to_bar(int depth, const struct dive *dive)

View file

@ -102,6 +102,7 @@ extern fraction_t best_he(depth_t depth, const struct dive *dive, bool o2narcoti
extern int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null);
extern int depth_to_mbar(int depth, const struct dive *dive);
extern double depth_to_mbarf(int depth, const struct dive *dive);
extern double depth_to_bar(int depth, const struct dive *dive);
extern double depth_to_atm(int depth, const struct dive *dive);
extern int rel_mbar_to_depth(int mbar, const struct dive *dive);

View file

@ -1236,15 +1236,15 @@ static void calculate_gas_information_new(const struct dive *dive, const struct
enum divemode_t current_divemode = UNDEF_COMP_TYPE;
for (i = 1; i < pi->nr; i++) {
int fn2, fhe;
double fn2, fhe;
struct plot_data *entry = pi->entry + i;
gasmix = get_gasmix(dive, dc, entry->sec, &evg, gasmix);
amb_pressure = depth_to_bar(entry->depth, dive);
current_divemode = get_current_divemode(dc, entry->sec, &evd, &current_divemode);
fill_pressures(&entry->pressures, amb_pressure, gasmix, (current_divemode == OC) ? 0.0 : entry->o2pressure.mbar / 1000.0, current_divemode);
fn2 = (int)(1000.0 * entry->pressures.n2 / amb_pressure);
fhe = (int)(1000.0 * entry->pressures.he / amb_pressure);
fn2 = 1000.0 * entry->pressures.n2 / amb_pressure;
fhe = 1000.0 * entry->pressures.he / amb_pressure;
if (dc->divemode == PSCR) { // OC pO2 is calulated for PSCR with or without external PO2 monitoring.
struct gasmix gasmix2 = get_gasmix(dive, dc, entry->sec, &evg, gasmix);
entry->scr_OC_pO2.mbar = (int) depth_to_mbar(entry->depth, dive) * get_o2(gasmix2) / 1000;
@ -1255,14 +1255,14 @@ static void calculate_gas_information_new(const struct dive *dive, const struct
* END takes O + N (air) into account ("Narcotic" for trimix dives)
* EAD just uses N ("Air" for nitrox dives) */
pressure_t modpO2 = { .mbar = (int)(prefs.modpO2 * 1000) };
entry->mod = (double)gas_mod(gasmix, modpO2, dive, 1).mm;
entry->end = (entry->depth + 10000) * (1000 - fhe) / 1000.0 - 10000;
entry->ead = (entry->depth + 10000) * fn2 / (double)N2_IN_AIR - 10000;
entry->eadd = (entry->depth + 10000) *
entry->mod = gas_mod(gasmix, modpO2, dive, 1).mm;
entry->end = mbar_to_depth(lrint(depth_to_mbarf(entry->depth, dive) * (1000 - fhe) / 1000.0), dive);
entry->ead = mbar_to_depth(lrint(depth_to_mbarf(entry->depth, dive) * fn2 / (double)N2_IN_AIR), dive);
entry->eadd = mbar_to_depth(lrint(depth_to_mbarf(entry->depth, dive) *
(entry->pressures.o2 / amb_pressure * O2_DENSITY +
entry->pressures.n2 / amb_pressure * N2_DENSITY +
entry->pressures.he / amb_pressure * HE_DENSITY) /
(O2_IN_AIR * O2_DENSITY + N2_IN_AIR * N2_DENSITY) * 1000 - 10000;
(O2_IN_AIR * O2_DENSITY + N2_IN_AIR * N2_DENSITY) * 1000), dive);
entry->density = gas_density(gasmix, depth_to_mbar(entry->depth, dive));
if (entry->mod < 0)
entry->mod = 0;
@ -1452,22 +1452,22 @@ static void plot_string(const struct dive *d, const struct plot_info *pi, int id
if (prefs.pp_graphs.phe && entry->pressures.he > 0)
put_format_loc(b, translate("gettextFromC", "pHe: %.2fbar\n"), entry->pressures.he);
if (prefs.mod && entry->mod > 0) {
mod = lrint(get_depth_units(lrint(entry->mod), NULL, &depth_unit));
mod = lrint(get_depth_units(entry->mod, NULL, &depth_unit));
put_format_loc(b, translate("gettextFromC", "MOD: %d%s\n"), mod, depth_unit);
}
eadd = lrint(get_depth_units(lrint(entry->eadd), NULL, &depth_unit));
eadd = lrint(get_depth_units(entry->eadd, NULL, &depth_unit));
if (prefs.ead) {
switch (pi->dive_type) {
case NITROX:
if (entry->ead > 0) {
ead = lrint(get_depth_units(lrint(entry->ead), NULL, &depth_unit));
ead = lrint(get_depth_units(entry->ead, NULL, &depth_unit));
put_format_loc(b, translate("gettextFromC", "EAD: %d%s\nEADD: %d%s / %.1fg/\n"), ead, depth_unit, eadd, depth_unit, entry->density);
break;
}
case TRIMIX:
if (entry->end > 0) {
end = lrint(get_depth_units(lrint(entry->end), NULL, &depth_unit));
end = lrint(get_depth_units(entry->end, NULL, &depth_unit));
put_format_loc(b, translate("gettextFromC", "END: %d%s\nEADD: %d%s / %.1fg/\n"), end, depth_unit, eadd, depth_unit, entry->density);
break;
}

View file

@ -58,7 +58,7 @@ struct plot_data {
pressure_t o2sensor[3]; //for rebreathers with up to 3 PO2 sensors
pressure_t o2setpoint;
pressure_t scr_OC_pO2;
double mod, ead, end, eadd;
int mod, ead, end, eadd;
velocity_t velocity;
int speed;
// stats over 9 minute window:

View file

@ -77,10 +77,10 @@ static void put_pd(struct membuffer *b, const struct plot_info *pi, int idx)
put_int(b, entry->o2sensor[2].mbar);
put_int(b, entry->o2setpoint.mbar);
put_int(b, entry->scr_OC_pO2.mbar);
put_double(b, entry->mod);
put_double(b, entry->ead);
put_double(b, entry->end);
put_double(b, entry->eadd);
put_int(b, entry->mod);
put_int(b, entry->ead);
put_int(b, entry->end);
put_int(b, entry->eadd);
switch (entry->velocity) {
case STABLE:
put_csv_string(b, "STABLE");

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff