Centralising and redefining values as integers

This patch centralizes the definition for surface pressure, oxygen in
air, (re)defines all such values as plain integers and adapts calculations.

It eliminates 11 (!) occurrences of definitions for surface pressure and
also a few for oxygen in air.

It also rewrites the calculation for EAD, END and EADD using the new
definitons, harmonizing it for OC and CC and fixes a bug for EADD OC
calculation.

And finally it removes the unneeded variable entry_ead in gtk-gui.c.

Jan

Signed-off-by: Jan Schubert <Jan.Schubert@GMX.li>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Jan Schubert 2013-01-14 23:53:38 +01:00 committed by Dirk Hohndel
parent 2e53a41525
commit 90d3c5614a
11 changed files with 51 additions and 48 deletions

4
deco.c
View file

@ -134,7 +134,7 @@ static double tissue_tolerance_calc(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 fo2 = gasmix->o2.permille ? gasmix->o2.permille : 209;
int fo2 = gasmix->o2.permille ? gasmix->o2.permille : O2_IN_AIR;
double ppn2 = (pressure - WV_PRESSURE) * (1000 - fo2 - gasmix->he.permille) / 1000.0;
double pphe = (pressure - WV_PRESSURE) * gasmix->he.permille / 1000.0;
@ -206,7 +206,7 @@ void clear_deco(double surface_pressure)
{
int ci;
for (ci = 0; ci < 16; ci++) {
tissue_n2_sat[ci] = (surface_pressure - WV_PRESSURE) * N2_IN_AIR;
tissue_n2_sat[ci] = (surface_pressure - WV_PRESSURE) * N2_IN_AIR / 1000;
tissue_he_sat[ci] = 0.0;
tissue_tolerated_ambient_pressure[ci] = 0.0;
}

4
dive.c
View file

@ -269,8 +269,8 @@ static void sanitize_gasmix(struct gasmix *mix)
if (!he) {
if (!o2)
return;
/* 20.9% or 21% O2 is just air */
if (o2 >= 209 && o2 <= 210) {
/* 20.8% to 21% O2 is just air */
if (o2 >= (O2_IN_AIR - 1) && o2 <= (O2_IN_AIR + 1)) {
mix->o2.permille = 0;
return;
}

19
dive.h
View file

@ -11,11 +11,13 @@
#include <libxml/tree.h>
#include <openssl/sha.h>
#define O2_IN_AIR 0.20942
#define N2_IN_AIR 0.78084 // has been set to 0.7902 before to ignore other components of air
#define O2_DENSITY 1.429 // Gramm/Liter
#define N2_DENSITY 1.251
#define HE_DENSITY 0.1786
#define O2_IN_AIR 209 // permille
#define N2_IN_AIR 781
#define O2_DENSITY 1429 // mg/Liter
#define N2_DENSITY 1251
#define HE_DENSITY 179
#define SURFACE_PRESSURE 1013 // mbar
#define SURFACE_PRESSURE_STRING "1013"
/*
@ -215,12 +217,12 @@ static inline int to_PSI(pressure_t pressure)
static inline double bar_to_atm(double bar)
{
return bar / 1.01325;
return bar / SURFACE_PRESSURE * 1000;
}
static inline double to_ATM(pressure_t pressure)
{
return pressure.mbar / 1013.25;
return pressure.mbar / SURFACE_PRESSURE;
}
static inline int mbar_to_PSI(int mbar)
@ -346,7 +348,7 @@ struct dive {
static inline int depth_to_mbar(int depth, struct dive *dive)
{
double specific_weight = 1.03 * 0.981;
int surface_pressure = 1013;
int surface_pressure = SURFACE_PRESSURE;
if (dive->salinity)
specific_weight = dive->salinity / 10000.0 * 0.981;
if (dive->surface_pressure.mbar)
@ -583,7 +585,6 @@ extern const char *subsurface_gettext_domainpath(char *);
extern gboolean subsurface_os_feature_available(os_feature_t);
extern void subsurface_command_line_init(gint *, gchar ***);
extern void subsurface_command_line_exit(gint *, gchar ***);
#define AIR_PERMILLE 209
#define FRACTION(n,x) ((unsigned)(n)/(x)),((unsigned)(n)%(x))

View file

@ -525,7 +525,7 @@ static void get_dive_gas(struct dive *dive, int *o2_p, int *he_p, int *o2low_p)
if (cylinder_none(cyl))
continue;
if (!o2)
o2 = AIR_PERMILLE;
o2 = O2_IN_AIR;
if (o2 < mino2)
mino2 = o2;
if (he > maxhe)
@ -539,7 +539,7 @@ newmax:
maxo2 = o2;
}
/* All air? Show/sort as "air"/zero */
if (!maxhe && maxo2 == AIR_PERMILLE && mino2 == maxo2)
if (!maxhe && maxo2 == O2_IN_AIR && mino2 == maxo2)
maxo2 = mino2 = 0;
*o2_p = maxo2;
*he_p = maxhe;
@ -721,7 +721,7 @@ static int active_o2(struct dive *dive, struct divecomputer *dc, duration_t time
struct event *event = dc->events;
if (!o2permille)
o2permille = AIR_PERMILLE;
o2permille = O2_IN_AIR;
for (event = dc->events; event; event = event->next) {
if (event->time.seconds > time.seconds)
@ -849,7 +849,7 @@ static int get_divenr(struct dive *dive)
return divenr;
}
static struct gasmix air = { .o2.permille = 209 };
static struct gasmix air = { .o2.permille = O2_IN_AIR };
/* take into account previous dives until there is a 48h gap between dives */
double init_decompression(struct dive *dive)
@ -881,7 +881,7 @@ double init_decompression(struct dive *dive)
/* again skip dives from different trips */
if (dive->divetrip && dive->divetrip != pdive->divetrip)
continue;
surface_pressure = pdive->surface_pressure.mbar ? pdive->surface_pressure.mbar / 1000.0 : 1.013;
surface_pressure = (pdive->surface_pressure.mbar ? pdive->surface_pressure.mbar : SURFACE_PRESSURE) / 1000;
if (!deco_init) {
clear_deco(surface_pressure);
deco_init = TRUE;
@ -907,7 +907,7 @@ double init_decompression(struct dive *dive)
/* add the final surface time */
if (lasttime && dive->when > lasttime) {
surface_time = dive->when - lasttime;
surface_pressure = dive->surface_pressure.mbar ? dive->surface_pressure.mbar / 1000.0 : 1.013;
surface_pressure = (dive->surface_pressure.mbar ? dive->surface_pressure.mbar : SURFACE_PRESSURE) / 1000;
tissue_tolerance = add_segment(surface_pressure, &air, surface_time, 0.0, dive);
#if DECO_CALC_DEBUG & 2
printf("after surface intervall of %d:%02u\n", FRACTION(surface_time,60));
@ -915,7 +915,7 @@ double init_decompression(struct dive *dive)
#endif
}
if (!deco_init) {
double surface_pressure = dive->surface_pressure.mbar ? dive->surface_pressure.mbar / 1000.0 : 1.013;
double surface_pressure = (dive->surface_pressure.mbar ? dive->surface_pressure.mbar : SURFACE_PRESSURE) / 1000;
clear_deco(surface_pressure);
#if DECO_CALC_DEBUG & 2
printf("no previous dive\n");

View file

@ -422,7 +422,7 @@ static void show_cylinder(cylinder_t *cyl, struct cylinder_widget *cylinder)
o2 = cyl->gasmix.o2.permille / 10.0;
he = cyl->gasmix.he.permille / 10.0;
if (!o2)
o2 = AIR_PERMILLE / 10.0;
o2 = O2_IN_AIR / 10.0;
gtk_spin_button_set_value(GTK_SPIN_BUTTON(cylinder->o2), o2);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(cylinder->he), he);
}

View file

@ -531,7 +531,7 @@ static void preferences_dialog(GtkWidget *w, gpointer data)
{
int result;
GtkWidget *dialog, *notebook, *font, *frame, *box, *vbox, *button, *xmlfile_button;
GtkWidget *entry_po2, *entry_pn2, *entry_phe, *entry_mod, *entry_ead, *entry_gflow, *entry_gfhigh;
GtkWidget *entry_po2, *entry_pn2, *entry_phe, *entry_mod, *entry_gflow, *entry_gfhigh;
const char *current_default, *new_default;
char threshold_text[10], mod_text[10], utf8_buf[128];
struct preferences oldprefs = prefs;

View file

@ -127,7 +127,7 @@ static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t
he = gasmix.helium * 1000 + 0.5;
/* Ignore bogus data - libdivecomputer does some crazy stuff */
if (o2 + he <= AIR_PERMILLE || o2 >= 1000)
if (o2 + he <= O2_IN_AIR || o2 >= 1000)
o2 = 0;
if (he < 0 || he >= 800 || o2+he >= 1000)
he = 0;

View file

@ -677,7 +677,7 @@ void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int second
int value;
if (!o2)
o2 = AIR_PERMILLE;
o2 = O2_IN_AIR;
o2 = (o2+5) / 10;
he = (he+5) / 10;
value = o2 + (he << 16);

View file

@ -162,7 +162,7 @@ struct dive *create_dive_from_plan(struct diveplan *diveplan)
struct dive *dive;
struct divedatapoint *dp;
struct divecomputer *dc;
int oldo2 = AIR_PERMILLE, oldhe = 0;
int oldo2 = O2_IN_AIR, oldhe = 0;
int lasttime = 0;
if (!diveplan || !diveplan->dp)
@ -425,7 +425,7 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep)
int *stoplevels;
if (!diveplan->surface_pressure)
diveplan->surface_pressure = 1013;
diveplan->surface_pressure = SURFACE_PRESSURE;
if (*divep)
delete_single_dive(dive_table.nr - 1);
*divep = dive = create_dive_from_plan(diveplan);
@ -566,7 +566,7 @@ static int validate_gas(const char *text, int *o2_p, int *he_p)
return 0;
if (!strcasecmp(text, "air")) {
o2 = AIR_PERMILLE; he = 0; text += 3;
o2 = O2_IN_AIR; he = 0; text += 3;
} else if (!strncasecmp(text, "ean", 3)) {
o2 = get_permille(text+3, &text); he = 0;
} else {
@ -909,7 +909,7 @@ void input_plan()
{
GtkWidget *planner, *content, *vbox, *hbox, *outervbox, *add_row, *deltat, *label, *surfpres;
char starttimebuf[64] = "+60:00";
char pressurebuf[64] = "1013";
char pressurebuf[64] = SURFACE_PRESSURE_STRING;
if (diveplan.dp)
free_dps(diveplan.dp);
@ -950,7 +950,7 @@ void input_plan()
gtk_widget_add_events(surfpres, GDK_FOCUS_CHANGE_MASK);
g_signal_connect(surfpres, "focus-out-event", G_CALLBACK(surfpres_focus_out_cb), NULL);
diveplan.when = time(NULL) + 3600;
diveplan.surface_pressure = 1013;
diveplan.surface_pressure = SURFACE_PRESSURE;
nr_waypoints = 4;
add_waypoint_widgets(vbox, 0);
add_waypoint_widgets(vbox, 1);

View file

@ -556,7 +556,7 @@ static void setup_pp_limits(struct graphics_context *gc, struct plot_info *pi)
* we use 1.5 times the corresponding pressure as maximum partial
* pressure the graph seems to look fine*/
maxdepth = get_maxdepth(pi);
gc->topy = 1.5 * (maxdepth + 10000) / 10000.0 * 1.01325;
gc->topy = 1.5 * (maxdepth + 10000) / 10000.0 * SURFACE_PRESSURE / 1000;
gc->bottomy = -gc->topy / 20;
}
@ -1815,7 +1815,7 @@ static void calculate_deco_information(struct dive *dive, struct divecomputer *d
{
int i;
double amb_pressure;
double surface_pressure = (dive->surface_pressure.mbar ? dive->surface_pressure.mbar : 1013) / 1000.0;
double surface_pressure = (dive->surface_pressure.mbar ? dive->surface_pressure.mbar : SURFACE_PRESSURE) / 1000.0;
for (i = 1; i < pi->nr; i++) {
int fo2, fhe, j, t0, t1;
@ -1824,36 +1824,37 @@ static void calculate_deco_information(struct dive *dive, struct divecomputer *d
int cylinderindex = entry->cylinderindex;
amb_pressure = depth_to_mbar(entry->depth, dive) / 1000.0;
fo2 = dive->cylinder[cylinderindex].gasmix.o2.permille ? : AIR_PERMILLE;
fo2 = dive->cylinder[cylinderindex].gasmix.o2.permille ? : O2_IN_AIR;
fhe = dive->cylinder[cylinderindex].gasmix.he.permille;
double ratio = (double)fhe / (1000.0 - fo2);
if (entry->po2) {
/* we have an O2 partial pressure in the sample - so this
* is likely a CC dive... use that instead of the value
* from the cylinder info */
double po2 = entry->po2 > amb_pressure ? amb_pressure : entry->po2;
double ratio = (double)fhe / (1000.0 - fo2);
entry->po2 = po2;
entry->phe = (amb_pressure - po2) * ratio;
entry->pn2 = amb_pressure - po2 - entry->phe;
entry->po2 = po2;
entry->ead = (entry->depth + 10000) *
(entry->po2+(amb_pressure-entry->po2)*(1-ratio))/amb_pressure - 10000;
entry->end = (entry->depth + 10000) *
(amb_pressure-entry->po2)*(1-ratio)/amb_pressure/N2_IN_AIR - 10000;
entry->eadd = (entry->depth + 10000) *
(entry->po2/amb_pressure * O2_DENSITY + entry->pn2/amb_pressure * N2_DENSITY +
entry->phe/amb_pressure * HE_DENSITY) /
(O2_IN_AIR * O2_DENSITY + N2_IN_AIR * N2_DENSITY) -10000;
} else {
entry->po2 = fo2 / 1000.0 * amb_pressure;
entry->phe = fhe / 1000.0 * amb_pressure;
entry->pn2 = (1000 - fo2 - fhe) / 1000.0 * amb_pressure;
entry->ead = (entry->depth + 10000) * (1000 - fhe) / 1000.0 - 10000;
entry->end = (entry->depth + 10000) * (1000 - fo2 - fhe) / 1000.0 / N2_IN_AIR - 10000;
entry->eadd = (entry->depth + 10000) * (fo2 * O2_DENSITY + (1-fo2-fhe) * N2_DENSITY + fhe * HE_DENSITY) / (O2_IN_AIR * O2_DENSITY + N2_IN_AIR * N2_DENSITY) -10000;
}
entry->mod = (prefs.mod_ppO2/fo2*1000 - 1) * 10000;
/* Calculate MOD, EAD, END and EADD based on partial pressures calculated before
* so there is no difference in calculating between OC and CC
* EAD takes O2 + N2 (air) into account
* END just uses N2 */
entry->mod = (prefs.mod_ppO2 / fo2 * 1000 - 1) * 10000;
entry->ead = (entry->depth + 10000) *
(entry->po2 + (amb_pressure - entry->po2) * (1 - ratio)) / amb_pressure - 10000;
entry->end = (entry->depth + 10000) *
(amb_pressure - entry->po2) * (1 - ratio) / amb_pressure / N2_IN_AIR * 1000 - 10000;
entry->eadd = (entry->depth + 10000) *
(entry->po2 / amb_pressure * O2_DENSITY + entry->pn2 / amb_pressure *
N2_DENSITY + entry->phe / amb_pressure * HE_DENSITY) /
(O2_IN_AIR * O2_DENSITY + N2_IN_AIR * N2_DENSITY) * 1000 -10000;
if(entry->mod <0)
entry->mod=0;
if(entry->ead <0)
@ -1862,6 +1863,7 @@ static void calculate_deco_information(struct dive *dive, struct divecomputer *d
entry->end=0;
if(entry->eadd <0)
entry->eadd=0;
if (entry->po2 > pi->maxpp && prefs.pp_graphs.po2)
pi->maxpp = entry->po2;
if (entry->phe > pi->maxpp && prefs.pp_graphs.phe)

View file

@ -576,7 +576,7 @@ static void show_single_dive_stats(struct dive *dive)
end = cyl->end.mbar ? : cyl->sample_end.mbar;
if (!cylinder_none(cyl)) {
/* 0% O2 strangely means air, so 21% - I don't like that at all */
int o2 = cyl->gasmix.o2.permille ? : AIR_PERMILLE;
int o2 = cyl->gasmix.o2.permille ? : O2_IN_AIR;
if (offset > 0) {
snprintf(buf+offset, 80-offset, ", ");
offset += 2;