mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
Cleanup: move gas-functions to own translation unit
But only functions that operate only on gases. Functions concerning cylinders or dives remain in dive.c or are moved to equipment.c Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
8352274758
commit
619d3fb1fd
8 changed files with 174 additions and 149 deletions
|
@ -86,6 +86,8 @@ set(SUBSURFACE_CORE_LIB_SRCS
|
|||
file.h
|
||||
format.cpp
|
||||
format.h
|
||||
gas.c
|
||||
gas.h
|
||||
gas-model.c
|
||||
gaspressures.c
|
||||
gaspressures.h
|
||||
|
|
106
core/dive.c
106
core/dive.c
|
@ -866,13 +866,6 @@ static void update_min_max_temperatures(struct dive *dive, temperature_t tempera
|
|||
}
|
||||
}
|
||||
|
||||
int gas_volume(const cylinder_t *cyl, pressure_t p)
|
||||
{
|
||||
double bar = p.mbar / 1000.0;
|
||||
double z_factor = gas_compressibility_factor(cyl->gasmix, bar);
|
||||
return lrint(cyl->type.size.mliter * bar_to_atm(bar) / z_factor);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the cylinder tank pressures are within half a bar
|
||||
* (about 8 PSI) of the sample pressures, we consider it
|
||||
|
@ -948,31 +941,6 @@ void update_setpoint_events(const struct dive *dive, struct divecomputer *dc)
|
|||
}
|
||||
}
|
||||
|
||||
void sanitize_gasmix(struct gasmix *mix)
|
||||
{
|
||||
unsigned int o2, he;
|
||||
|
||||
o2 = mix->o2.permille;
|
||||
he = mix->he.permille;
|
||||
|
||||
/* Regular air: leave empty */
|
||||
if (!he) {
|
||||
if (!o2)
|
||||
return;
|
||||
/* 20.8% to 21% O2 is just air */
|
||||
if (gasmix_is_air(*mix)) {
|
||||
mix->o2.permille = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sane mix? */
|
||||
if (o2 <= 1000 && he <= 1000 && o2 + he <= 1000)
|
||||
return;
|
||||
fprintf(stderr, "Odd gasmix: %u O2 %u He\n", o2, he);
|
||||
memset(mix, 0, sizeof(*mix));
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the size/workingpressure looks like some standard cylinder
|
||||
* size, eg "AL80".
|
||||
|
@ -1059,23 +1027,6 @@ static void sanitize_cylinder_info(struct dive *dive)
|
|||
}
|
||||
}
|
||||
|
||||
/* Perform isobaric counterdiffusion calculations for gas changes in trimix dives.
|
||||
* Here we use the rule-of-fifths where, during a change involving trimix gas, the increase in nitrogen
|
||||
* should not exceed one fifth of the decrease in helium.
|
||||
* Parameters: 1) pointers to two gas mixes, the gas being switched from and the gas being switched to.
|
||||
* 2) a pointer to an icd_data structure.
|
||||
* Output: i) The icd_data stucture is filled with the delta_N2 and delta_He numbers (as permille).
|
||||
* ii) Function returns a boolean indicating an exceeding of the rule-of-fifths. False = no icd problem.
|
||||
*/
|
||||
bool isobaric_counterdiffusion(struct gasmix oldgasmix, struct gasmix newgasmix, struct icd_data *results)
|
||||
{
|
||||
if (!prefs.show_icd)
|
||||
return false;
|
||||
results->dN2 = get_he(oldgasmix) + get_o2(oldgasmix) - get_he(newgasmix) - get_o2(newgasmix);
|
||||
results->dHe = get_he(newgasmix) - get_he(oldgasmix);
|
||||
return get_he(oldgasmix) > 0 && results->dN2 > 0 && results->dHe < 0 && get_he(oldgasmix) && results->dN2 > 0 && 5 * results->dN2 > -results->dHe;
|
||||
}
|
||||
|
||||
/* some events should never be thrown away */
|
||||
static bool is_potentially_redundant(const struct event *event)
|
||||
{
|
||||
|
@ -1464,29 +1415,6 @@ static void fixup_dive_pressures(struct dive *dive, struct divecomputer *dc)
|
|||
simplify_dc_pressures(dc);
|
||||
}
|
||||
|
||||
int find_best_gasmix_match(struct gasmix mix, const cylinder_t array[], unsigned int used)
|
||||
{
|
||||
int i;
|
||||
int best = -1, score = INT_MAX;
|
||||
|
||||
for (i = 0; i < MAX_CYLINDERS; i++) {
|
||||
const cylinder_t *match;
|
||||
int distance;
|
||||
|
||||
if (used & (1 << i))
|
||||
continue;
|
||||
match = array + i;
|
||||
if (cylinder_nodata(match))
|
||||
continue;
|
||||
distance = gasmix_distance(mix, match->gasmix);
|
||||
if (distance >= score)
|
||||
continue;
|
||||
best = i;
|
||||
score = distance;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
/*
|
||||
* Match a gas change event against the cylinders we have
|
||||
*/
|
||||
|
@ -2031,17 +1959,6 @@ extern int get_cylinder_idx_by_use(const struct dive *dive, enum cylinderuse cyl
|
|||
return -1; // negative number means cylinder_use_type not found in list of cylinders
|
||||
}
|
||||
|
||||
int gasmix_distance(struct gasmix a, struct gasmix b)
|
||||
{
|
||||
int a_o2 = get_o2(a), b_o2 = get_o2(b);
|
||||
int a_he = get_he(a), b_he = get_he(b);
|
||||
int delta_o2 = a_o2 - b_o2, delta_he = a_he - b_he;
|
||||
|
||||
delta_he = delta_he * delta_he;
|
||||
delta_o2 = delta_o2 * delta_o2;
|
||||
return delta_he + delta_o2;
|
||||
}
|
||||
|
||||
/* fill_pressures(): Compute partial gas pressures in bar from gasmix and ambient pressures, possibly for OC or CCR, to be
|
||||
* extended to PSCT. This function does the calculations of gas pressures applicable to a single point on the dive profile.
|
||||
* The structure "pressures" is used to return calculated gas pressures to the calling software.
|
||||
|
@ -2052,7 +1969,7 @@ int gasmix_distance(struct gasmix a, struct gasmix b)
|
|||
* divemode = the dive mode pertaining to this point in the dive profile.
|
||||
* This function called by: calculate_gas_information_new() in profile.c; add_segment() in deco.c.
|
||||
*/
|
||||
extern void fill_pressures(struct gas_pressures *pressures, const double amb_pressure, struct gasmix mix, double po2, enum divemode_t divemode)
|
||||
void fill_pressures(struct gas_pressures *pressures, const double amb_pressure, struct gasmix mix, double po2, enum divemode_t divemode)
|
||||
{
|
||||
if ((divemode != OC) && po2) { // This is a rebreather dive where pressures->o2 is defined
|
||||
if (po2 >= amb_pressure) {
|
||||
|
@ -2180,20 +2097,6 @@ void cylinder_renumber(struct dive *dive, int mapping[])
|
|||
dc_cylinder_renumber(dive, dc, mapping);
|
||||
}
|
||||
|
||||
static bool gasmix_is_invalid(struct gasmix mix)
|
||||
{
|
||||
return mix.o2.permille < 0;
|
||||
}
|
||||
|
||||
int same_gasmix(struct gasmix a, struct gasmix b)
|
||||
{
|
||||
if (gasmix_is_invalid(a) || gasmix_is_invalid(b))
|
||||
return 0;
|
||||
if (gasmix_is_air(a) && gasmix_is_air(b))
|
||||
return 1;
|
||||
return a.o2.permille == b.o2.permille && a.he.permille == b.he.permille;
|
||||
}
|
||||
|
||||
int same_gasmix_cylinder(cylinder_t *cyl, int cylid, struct dive *dive, bool check_unused)
|
||||
{
|
||||
struct gasmix mygas = cyl->gasmix;
|
||||
|
@ -3922,13 +3825,6 @@ fraction_t best_he(depth_t depth, const struct dive *dive)
|
|||
return fhe;
|
||||
}
|
||||
|
||||
bool gasmix_is_air(struct gasmix gasmix)
|
||||
{
|
||||
int o2 = gasmix.o2.permille;
|
||||
int he = gasmix.he.permille;
|
||||
return (he == 0) && (o2 == 0 || ((o2 >= O2_IN_AIR - 1) && (o2 <= O2_IN_AIR + 1)));
|
||||
}
|
||||
|
||||
void invalidate_dive_cache(struct dive *dive)
|
||||
{
|
||||
memset(dive->git_id, 0, 20);
|
||||
|
|
34
core/dive.h
34
core/dive.h
|
@ -27,13 +27,6 @@ extern const char *cylinderuse_text[];
|
|||
extern const char *divemode_text_ui[];
|
||||
extern const char *divemode_text[];
|
||||
|
||||
struct icd_data { // This structure provides communication between function isobaric_counterdiffusion() and the calling software.
|
||||
int dN2; // The change in fraction (permille) of nitrogen during the change
|
||||
int dHe; // The change in fraction (permille) of helium during the change
|
||||
};
|
||||
|
||||
extern bool isobaric_counterdiffusion(struct gasmix oldgasmix, struct gasmix newgasmix, struct icd_data *results);
|
||||
|
||||
/*
|
||||
* Events are currently based straight on what libdivecomputer gives us.
|
||||
* We need to wrap these into our own events at some point to remove some of the limitations.
|
||||
|
@ -63,35 +56,8 @@ struct event {
|
|||
|
||||
extern int event_is_gaschange(const struct event *ev);
|
||||
|
||||
/* Volume in mliter of a cylinder at pressure 'p' */
|
||||
extern int gas_volume(const cylinder_t *cyl, pressure_t p);
|
||||
extern double gas_compressibility_factor(struct gasmix gas, double bar);
|
||||
extern double isothermal_pressure(struct gasmix gas, double p1, int volume1, int volume2);
|
||||
extern double gas_density(struct gasmix gas, int pressure);
|
||||
extern int same_gasmix(struct gasmix a, struct gasmix b);
|
||||
|
||||
static inline int get_o2(struct gasmix mix)
|
||||
{
|
||||
return mix.o2.permille ?: O2_IN_AIR;
|
||||
}
|
||||
|
||||
static inline int get_he(struct gasmix mix)
|
||||
{
|
||||
return mix.he.permille;
|
||||
}
|
||||
|
||||
struct gas_pressures {
|
||||
double o2, n2, he;
|
||||
};
|
||||
|
||||
extern void fill_pressures(struct gas_pressures *pressures, const double amb_pressure, struct gasmix mix, double po2, enum divemode_t dctype);
|
||||
|
||||
extern void sanitize_gasmix(struct gasmix *mix);
|
||||
extern int gasmix_distance(struct gasmix a, struct gasmix b);
|
||||
extern int find_best_gasmix_match(struct gasmix mix, const cylinder_t array[], unsigned int used);
|
||||
|
||||
extern bool gasmix_is_air(struct gasmix gasmix);
|
||||
|
||||
/* Linear interpolation between 'a' and 'b', when we are 'part'way into the 'whole' distance from a to b */
|
||||
static inline int interpolate(int a, int b, int part, int whole)
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include "equipment.h"
|
||||
#include "gettext.h"
|
||||
#include "dive.h"
|
||||
|
@ -101,6 +102,36 @@ const char *gasname(struct gasmix gasmix)
|
|||
return gas;
|
||||
}
|
||||
|
||||
int gas_volume(const cylinder_t *cyl, pressure_t p)
|
||||
{
|
||||
double bar = p.mbar / 1000.0;
|
||||
double z_factor = gas_compressibility_factor(cyl->gasmix, bar);
|
||||
return lrint(cyl->type.size.mliter * bar_to_atm(bar) / z_factor);
|
||||
}
|
||||
|
||||
int find_best_gasmix_match(struct gasmix mix, const cylinder_t array[], unsigned int used)
|
||||
{
|
||||
int i;
|
||||
int best = -1, score = INT_MAX;
|
||||
|
||||
for (i = 0; i < MAX_CYLINDERS; i++) {
|
||||
const cylinder_t *match;
|
||||
int distance;
|
||||
|
||||
if (used & (1 << i))
|
||||
continue;
|
||||
match = array + i;
|
||||
if (cylinder_nodata(match))
|
||||
continue;
|
||||
distance = gasmix_distance(mix, match->gasmix);
|
||||
if (distance >= score)
|
||||
continue;
|
||||
best = i;
|
||||
score = distance;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
bool weightsystem_none(const weightsystem_t *ws)
|
||||
{
|
||||
return !ws->weight.grams && !ws->description;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#ifndef EQUIPMENT_H
|
||||
#define EQUIPMENT_H
|
||||
|
||||
#include "units.h"
|
||||
#include "gas.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -10,15 +10,6 @@ extern "C" {
|
|||
|
||||
struct dive;
|
||||
|
||||
// o2 == 0 && he == 0 -> air
|
||||
// o2 < 0 -> invalid
|
||||
struct gasmix {
|
||||
fraction_t o2;
|
||||
fraction_t he;
|
||||
};
|
||||
static const struct gasmix gasmix_invalid = { { -1 }, { -1 } };
|
||||
static const struct gasmix gasmix_air = { { 0 }, { 0 } };
|
||||
|
||||
enum cylinderuse {OC_GAS, DILUENT, OXYGEN, NOT_USED, NUM_GAS_USE}; // The different uses for cylinders
|
||||
|
||||
typedef struct
|
||||
|
@ -63,6 +54,8 @@ extern bool weightsystem_none(const weightsystem_t *ws);
|
|||
extern void remove_cylinder(struct dive *dive, int idx);
|
||||
extern void remove_weightsystem(struct dive *dive, int idx);
|
||||
extern void reset_cylinders(struct dive *dive, bool track_gas);
|
||||
extern int gas_volume(const cylinder_t *cyl, pressure_t p); /* Volume in mliter of a cylinder at pressure 'p' */
|
||||
extern int find_best_gasmix_match(struct gasmix mix, const cylinder_t array[], unsigned int used);
|
||||
#ifdef DEBUG_CYL
|
||||
extern void dump_cylinders(struct dive *dive, bool verbose);
|
||||
#endif
|
||||
|
|
79
core/gas.c
Normal file
79
core/gas.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "gas.h"
|
||||
#include "pref.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Perform isobaric counterdiffusion calculations for gas changes in trimix dives.
|
||||
* Here we use the rule-of-fifths where, during a change involving trimix gas, the increase in nitrogen
|
||||
* should not exceed one fifth of the decrease in helium.
|
||||
* Parameters: 1) pointers to two gas mixes, the gas being switched from and the gas being switched to.
|
||||
* 2) a pointer to an icd_data structure.
|
||||
* Output: i) The icd_data stucture is filled with the delta_N2 and delta_He numbers (as permille).
|
||||
* ii) Function returns a boolean indicating an exceeding of the rule-of-fifths. False = no icd problem.
|
||||
*/
|
||||
bool isobaric_counterdiffusion(struct gasmix oldgasmix, struct gasmix newgasmix, struct icd_data *results)
|
||||
{
|
||||
if (!prefs.show_icd)
|
||||
return false;
|
||||
results->dN2 = get_he(oldgasmix) + get_o2(oldgasmix) - get_he(newgasmix) - get_o2(newgasmix);
|
||||
results->dHe = get_he(newgasmix) - get_he(oldgasmix);
|
||||
return get_he(oldgasmix) > 0 && results->dN2 > 0 && results->dHe < 0 && get_he(oldgasmix) && results->dN2 > 0 && 5 * results->dN2 > -results->dHe;
|
||||
}
|
||||
|
||||
static bool gasmix_is_invalid(struct gasmix mix)
|
||||
{
|
||||
return mix.o2.permille < 0;
|
||||
}
|
||||
|
||||
int same_gasmix(struct gasmix a, struct gasmix b)
|
||||
{
|
||||
if (gasmix_is_invalid(a) || gasmix_is_invalid(b))
|
||||
return 0;
|
||||
if (gasmix_is_air(a) && gasmix_is_air(b))
|
||||
return 1;
|
||||
return a.o2.permille == b.o2.permille && a.he.permille == b.he.permille;
|
||||
}
|
||||
|
||||
void sanitize_gasmix(struct gasmix *mix)
|
||||
{
|
||||
unsigned int o2, he;
|
||||
|
||||
o2 = mix->o2.permille;
|
||||
he = mix->he.permille;
|
||||
|
||||
/* Regular air: leave empty */
|
||||
if (!he) {
|
||||
if (!o2)
|
||||
return;
|
||||
/* 20.8% to 21% O2 is just air */
|
||||
if (gasmix_is_air(*mix)) {
|
||||
mix->o2.permille = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sane mix? */
|
||||
if (o2 <= 1000 && he <= 1000 && o2 + he <= 1000)
|
||||
return;
|
||||
fprintf(stderr, "Odd gasmix: %u O2 %u He\n", o2, he);
|
||||
memset(mix, 0, sizeof(*mix));
|
||||
}
|
||||
|
||||
int gasmix_distance(struct gasmix a, struct gasmix b)
|
||||
{
|
||||
int a_o2 = get_o2(a), b_o2 = get_o2(b);
|
||||
int a_he = get_he(a), b_he = get_he(b);
|
||||
int delta_o2 = a_o2 - b_o2, delta_he = a_he - b_he;
|
||||
|
||||
delta_he = delta_he * delta_he;
|
||||
delta_o2 = delta_o2 * delta_o2;
|
||||
return delta_he + delta_o2;
|
||||
}
|
||||
|
||||
bool gasmix_is_air(struct gasmix gasmix)
|
||||
{
|
||||
int o2 = gasmix.o2.permille;
|
||||
int he = gasmix.he.permille;
|
||||
return (he == 0) && (o2 == 0 || ((o2 >= O2_IN_AIR - 1) && (o2 <= O2_IN_AIR + 1)));
|
||||
}
|
57
core/gas.h
Normal file
57
core/gas.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#ifndef GAS_H
|
||||
#define GAS_H
|
||||
|
||||
#include "units.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
// o2 == 0 && he == 0 -> air
|
||||
// o2 < 0 -> invalid
|
||||
struct gasmix {
|
||||
fraction_t o2;
|
||||
fraction_t he;
|
||||
};
|
||||
static const struct gasmix gasmix_invalid = { { -1 }, { -1 } };
|
||||
static const struct gasmix gasmix_air = { { 0 }, { 0 } };
|
||||
|
||||
struct icd_data { // This structure provides communication between function isobaric_counterdiffusion() and the calling software.
|
||||
int dN2; // The change in fraction (permille) of nitrogen during the change
|
||||
int dHe; // The change in fraction (permille) of helium during the change
|
||||
};
|
||||
|
||||
extern bool isobaric_counterdiffusion(struct gasmix oldgasmix, struct gasmix newgasmix, struct icd_data *results);
|
||||
|
||||
extern double gas_compressibility_factor(struct gasmix gas, double bar);
|
||||
extern double isothermal_pressure(struct gasmix gas, double p1, int volume1, int volume2);
|
||||
extern double gas_density(struct gasmix gas, int pressure);
|
||||
extern int same_gasmix(struct gasmix a, struct gasmix b);
|
||||
|
||||
static inline int get_o2(struct gasmix mix)
|
||||
{
|
||||
return mix.o2.permille ?: O2_IN_AIR;
|
||||
}
|
||||
|
||||
static inline int get_he(struct gasmix mix)
|
||||
{
|
||||
return mix.he.permille;
|
||||
}
|
||||
|
||||
struct gas_pressures {
|
||||
double o2, n2, he;
|
||||
};
|
||||
|
||||
extern void sanitize_gasmix(struct gasmix *mix);
|
||||
extern int gasmix_distance(struct gasmix a, struct gasmix b);
|
||||
|
||||
extern bool gasmix_is_air(struct gasmix gasmix);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -67,6 +67,7 @@ SOURCES += ../../subsurface-mobile-main.cpp \
|
|||
../../core/deco.c \
|
||||
../../core/divesite.c \
|
||||
../../core/equipment.c \
|
||||
../../core/gas.c \
|
||||
../../core/membuffer.c \
|
||||
../../core/sha1.c \
|
||||
../../core/strtod.c \
|
||||
|
|
Loading…
Reference in a new issue