core: pass depth_t to depth_to_* functions

This is a drop in the ocean. Make the usage of the unit-types a
bit more consistent throughout the code base.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-12-13 18:20:05 +01:00 committed by Michael Keller
parent 661ce3f9c7
commit da17f6a08c
13 changed files with 216 additions and 212 deletions

View file

@ -544,21 +544,20 @@ void deco_state_cache::restore(struct deco_state *target, bool keep_vpmb_state)
*target = *data;
}
int deco_allowed_depth(double tissues_tolerance, double surface_pressure, const struct dive *dive, bool smooth)
depth_t deco_allowed_depth(double tissues_tolerance, double surface_pressure, const struct dive *dive, bool smooth)
{
int depth;
double pressure_delta;
/* Avoid negative depths */
pressure_delta = tissues_tolerance > surface_pressure ? tissues_tolerance - surface_pressure : 0.0;
depth = dive->rel_mbar_to_depth(lrint(pressure_delta * 1000));
depth_t depth = dive->rel_mbar_to_depth(lrint(pressure_delta * 1000));
if (!smooth)
depth = lrint(ceil(depth / DECO_STOPS_MULTIPLIER_MM) * DECO_STOPS_MULTIPLIER_MM);
depth.mm = lrint(ceil(depth.mm / DECO_STOPS_MULTIPLIER_MM) * DECO_STOPS_MULTIPLIER_MM);
if (depth > 0 && depth < buehlmann_config.last_deco_stop_in_mtr * 1000)
depth = buehlmann_config.last_deco_stop_in_mtr * 1000;
if (depth.mm > 0 && depth.mm < buehlmann_config.last_deco_stop_in_mtr * 1000)
depth.mm = buehlmann_config.last_deco_stop_in_mtr * 1000;
return depth;
}
@ -631,12 +630,13 @@ void update_regression(struct deco_state *ds, const struct dive *dive)
ds->sumx += ds->plot_depth;
ds->sumxx += (long)ds->plot_depth * ds->plot_depth;
double n2_gradient, he_gradient, total_gradient;
n2_gradient = update_gradient(ds, dive->depth_to_bar(ds->plot_depth), ds->bottom_n2_gradient[ds->ci_pointing_to_guiding_tissue]);
he_gradient = update_gradient(ds, dive->depth_to_bar(ds->plot_depth), ds->bottom_he_gradient[ds->ci_pointing_to_guiding_tissue]);
depth_t plot_depth { .mm = ds->plot_depth };
n2_gradient = update_gradient(ds, dive->depth_to_bar(plot_depth), ds->bottom_n2_gradient[ds->ci_pointing_to_guiding_tissue]);
he_gradient = update_gradient(ds, dive->depth_to_bar(plot_depth), 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 / ds->buehlmann_inertgas_b[ds->ci_pointing_to_guiding_tissue] - 1.0) * dive->depth_to_bar(ds->plot_depth) + ds->buehlmann_inertgas_a[ds->ci_pointing_to_guiding_tissue];
double buehlmann_gradient = (1.0 / ds->buehlmann_inertgas_b[ds->ci_pointing_to_guiding_tissue] - 1.0) * dive->depth_to_bar(plot_depth) + ds->buehlmann_inertgas_a[ds->ci_pointing_to_guiding_tissue];
double gf = (total_gradient - vpmb_config.other_gases_pressure) / buehlmann_gradient;
ds->sumxy += gf * ds->plot_depth;
ds->sumy += gf;

View file

@ -46,7 +46,7 @@ struct deco_state {
extern const double buehlmann_N2_t_halflife[];
extern int deco_allowed_depth(double tissues_tolerance, double surface_pressure, const struct dive *dive, bool smooth);
extern depth_t deco_allowed_depth(double tissues_tolerance, double surface_pressure, const struct dive *dive, bool smooth);
double get_gf(struct deco_state *ds, double ambpressure_bar, const struct dive *dive);
extern void clear_deco(struct deco_state *ds, double surface_pressure, bool in_planner);

View file

@ -472,7 +472,7 @@ static int same_rounded_pressure(pressure_t a, pressure_t b)
return abs((a - b).mbar) <= 500;
}
static double calculate_depth_to_mbarf(int depth, pressure_t surface_pressure, int salinity);
static double calculate_depth_to_mbarf(depth_t depth, pressure_t surface_pressure, int salinity);
/* this gets called when the dive mode has changed (so OC vs. CC)
* there are two places we might have setpoints... events or in the samples
@ -496,7 +496,7 @@ void update_setpoint_events(const struct dive *dive, struct divecomputer *dc)
gasmix_loop loop(*dive, *dc);
for (auto &sample: dc->samples) {
struct gasmix gasmix = loop.at(sample.time.seconds).first;
gas_pressures pressures = fill_pressures(lrint(calculate_depth_to_mbarf(sample.depth.mm, dc->surface_pressure, 0)), gasmix ,0, dc->divemode);
gas_pressures pressures = fill_pressures(lrint(calculate_depth_to_mbarf(sample.depth, dc->surface_pressure, 0)), gasmix ,0, dc->divemode);
if (abs(sample.setpoint.mbar - (int)(1000 * pressures.o2)) <= 50)
sample.setpoint = 0_baro2;
}
@ -2329,7 +2329,7 @@ fraction_t dive::best_o2(depth_t depth, bool in_planner) const
fraction_t fo2;
int po2 = in_planner ? prefs.bottompo2 : (int)(prefs.modpO2 * 1000.0);
fo2.permille = (po2 * 100 / depth_to_mbar(depth.mm)) * 10; //use integer arithmetic to round down to nearest percent
fo2.permille = (po2 * 100 / depth_to_mbar(depth)) * 10; //use integer arithmetic to round down to nearest percent
// Don't permit >100% O2
// TODO: use std::min, once we have comparison
if (fo2.permille > 1000)
@ -2342,8 +2342,8 @@ fraction_t dive::best_he(depth_t depth, bool o2narcotic, fraction_t fo2) const
{
fraction_t fhe;
int pnarcotic, ambient;
pnarcotic = depth_to_mbar(prefs.bestmixend.mm);
ambient = depth_to_mbar(depth.mm);
pnarcotic = depth_to_mbar(prefs.bestmixend);
ambient = depth_to_mbar(depth);
if (o2narcotic) {
fhe.permille = (100 - 100 * pnarcotic / ambient) * 10; //use integer arithmetic to round up to nearest percent
} else {
@ -2384,7 +2384,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 double calculate_depth_to_mbarf(int depth, pressure_t surface_pressure, int salinity)
static double calculate_depth_to_mbarf(depth_t depth, pressure_t surface_pressure, int salinity)
{
if (!surface_pressure.mbar)
surface_pressure = 1_atm;
@ -2393,15 +2393,15 @@ static double calculate_depth_to_mbarf(int depth, pressure_t surface_pressure, i
if (salinity < 500)
salinity += FRESHWATER_SALINITY;
double specific_weight = salinity_to_specific_weight(salinity);
return surface_pressure.mbar + depth * specific_weight;
return surface_pressure.mbar + depth.mm * specific_weight;
}
int dive::depth_to_mbar(int depth) const
int dive::depth_to_mbar(depth_t depth) const
{
return lrint(depth_to_mbarf(depth));
}
double dive::depth_to_mbarf(int depth) const
double dive::depth_to_mbarf(depth_t depth) const
{
// For downloaded and planned dives, use DC's values
int salinity = dcs[0].salinity;
@ -2414,12 +2414,12 @@ double dive::depth_to_mbarf(int depth) const
return calculate_depth_to_mbarf(depth, surface_pressure, salinity);
}
double dive::depth_to_bar(int depth) const
double dive::depth_to_bar(depth_t depth) const
{
return depth_to_mbar(depth) / 1000.0;
}
double dive::depth_to_atm(int depth) const
double dive::depth_to_atm(depth_t depth) const
{
return mbar_to_atm(depth_to_mbar(depth));
}
@ -2428,7 +2428,7 @@ double dive::depth_to_atm(int depth) const
* (that's the one that some dive computers like the Uemis Zurich
* provide - for the other models that do this libdivecomputer has to
* take care of this, but the Uemis we support natively */
int dive::rel_mbar_to_depth(int mbar) const
depth_t dive::rel_mbar_to_depth(int mbar) const
{
// For downloaded and planned dives, use DC's salinity. Manual dives, use user's salinity
int salinity = is_dc_manually_added_dive(&dcs[0]) ? user_salinity : dcs[0].salinity;
@ -2437,10 +2437,11 @@ int dive::rel_mbar_to_depth(int mbar) const
/* whole mbar gives us cm precision */
double specific_weight = salinity_to_specific_weight(salinity);
return int_cast<int>(mbar / specific_weight);
depth_t res { .mm = int_cast<int>(mbar / specific_weight) };
return res;
}
int dive::mbar_to_depth(int mbar) const
depth_t dive::mbar_to_depth(int mbar) const
{
// For downloaded and planned dives, use DC's pressure. Manual dives, use user's pressure
pressure_t surface_pressure = is_dc_manually_added_dive(&dcs[0])
@ -2456,7 +2457,7 @@ int dive::mbar_to_depth(int mbar) const
/* MOD rounded to multiples of roundto mm */
depth_t dive::gas_mod(struct gasmix mix, pressure_t po2_limit, int roundto) const
{
double depth = (double) mbar_to_depth(po2_limit.mbar * 1000 / get_o2(mix));
double depth = (double) mbar_to_depth(po2_limit.mbar * 1000 / get_o2(mix)).mm;
// Rounding should be towards lower=safer depths but we give a bit
// of fudge to all to switch to o2 at 6m. So from .9 we round up.
return depth_t { .mm = (int)(depth / roundto + 0.1) * roundto };
@ -2465,7 +2466,7 @@ depth_t dive::gas_mod(struct gasmix mix, pressure_t po2_limit, int roundto) cons
/* Maximum narcotic depth rounded to multiples of roundto mm */
depth_t dive::gas_mnd(struct gasmix mix, depth_t end, int roundto) const
{
pressure_t ppo2n2 { .mbar = depth_to_mbar(end.mm) };
pressure_t ppo2n2 { .mbar = depth_to_mbar(end) };
int maxambient = prefs.o2narcotic ?
int_cast<int>(ppo2n2.mbar / (1 - get_he(mix) / 1000.0))
@ -2475,7 +2476,8 @@ depth_t dive::gas_mnd(struct gasmix mix, depth_t end, int roundto) const
:
// Actually: Infinity
1000000;
return depth_t { .mm = int_cast<int>(((double)mbar_to_depth(maxambient)) / roundto) * roundto };
double depth = static_cast<double>(mbar_to_depth(maxambient).mm);
return depth_t { .mm = int_cast<int>(depth / roundto) * roundto };
}
std::string dive::get_country() const

View file

@ -116,12 +116,12 @@ struct dive {
std::string get_country() const;
std::string get_location() const;
int depth_to_mbar(int depth) const;
double depth_to_mbarf(int depth) const;
double depth_to_bar(int depth) const;
double depth_to_atm(int depth) const;
int rel_mbar_to_depth(int mbar) const;
int mbar_to_depth(int mbar) const;
int depth_to_mbar(depth_t depth) const;
double depth_to_mbarf(depth_t depth) const;
double depth_to_bar(depth_t depth) const;
double depth_to_atm(depth_t depth) const;
depth_t rel_mbar_to_depth(int mbar) const;
depth_t mbar_to_depth(int mbar) const;
pressure_t calculate_surface_pressure() const;
pressure_t un_fixup_surface_pressure() const;

View file

@ -116,16 +116,18 @@ static int get_sample_o2(const struct dive &dive, const struct divecomputer *dc,
{
int po2i, po2f, po2;
// Use sensor[0] if available
depth_t depth = sample.depth;
depth_t pdepth = psample.depth;
if ((dc->divemode == CCR || dc->divemode == PSCR) && sample.o2sensor[0].mbar) {
po2i = psample.o2sensor[0].mbar;
po2f = sample.o2sensor[0].mbar; // then use data from the first o2 sensor
po2 = (po2f + po2i) / 2;
} else if (sample.setpoint.mbar > 0) {
po2 = std::min((int) sample.setpoint.mbar,
dive.depth_to_mbar(sample.depth.mm));
dive.depth_to_mbar(depth));
} else {
double amb_presure = dive.depth_to_bar(sample.depth.mm);
double pamb_pressure = dive.depth_to_bar(psample.depth.mm );
double amb_presure = dive.depth_to_bar(depth);
double pamb_pressure = dive.depth_to_bar(pdepth);
if (dc->divemode == PSCR) {
po2i = pscr_o2(pamb_pressure, dive.get_gasmix_at_time(*dc, psample.time));
po2f = pscr_o2(amb_presure, dive.get_gasmix_at_time(*dc, sample.time));
@ -154,6 +156,8 @@ static int calculate_otu(const struct dive &dive)
int po2i, po2f;
double pm;
int t = (sample.time - psample.time).seconds;
depth_t depth = sample.depth;
depth_t pdepth = psample.depth;
// if there is sensor data use sensor[0]
if ((dc->divemode == CCR || dc->divemode == PSCR) && sample.o2sensor[0].mbar) {
po2i = psample.o2sensor[0].mbar;
@ -161,15 +165,15 @@ static int calculate_otu(const struct dive &dive)
} else {
if (sample.setpoint.mbar > 0) {
po2f = std::min((int) sample.setpoint.mbar,
dive.depth_to_mbar(sample.depth.mm));
dive.depth_to_mbar(depth));
if (psample.setpoint.mbar > 0)
po2i = std::min((int) psample.setpoint.mbar,
dive.depth_to_mbar(psample.depth.mm));
dive.depth_to_mbar(pdepth));
else
po2i = po2f;
} else { // For OC and rebreather without o2 sensor/setpoint
double amb_presure = dive.depth_to_bar(sample.depth.mm);
double pamb_pressure = dive.depth_to_bar(psample.depth.mm);
double amb_presure = dive.depth_to_bar(depth);
double pamb_pressure = dive.depth_to_bar(pdepth);
if (dc->divemode == PSCR) {
po2i = pscr_o2(pamb_pressure, dive.get_gasmix_at_time(*dc, psample.time));
po2f = pscr_o2(amb_presure, dive.get_gasmix_at_time(*dc, sample.time));
@ -394,7 +398,7 @@ static int calculate_sac(const struct dive &dive)
{
const struct divecomputer *dc = &dive.dcs[0];
double airuse, pressure, sac;
int duration, meandepth;
int duration;
airuse = calculate_airuse(dive);
if (!airuse)
@ -404,12 +408,11 @@ static int calculate_sac(const struct dive &dive)
if (!duration)
return 0;
meandepth = dc->meandepth.mm;
if (!meandepth)
if (!dc->meandepth.mm)
return 0;
/* Mean pressure in ATM (SAC calculations are in atm*l/min) */
pressure = dive.depth_to_atm(meandepth);
pressure = dive.depth_to_atm(dc->meandepth);
sac = airuse / pressure * 60 / duration;
/* milliliters per minute.. */
@ -429,7 +432,7 @@ static void add_dive_to_deco(struct deco_state *ds, const struct dive &dive, boo
int j;
for (j = t0; j < t1; j++) {
int depth = interpolate(psample.depth.mm, sample.depth.mm, j - t0, t1 - t0);
depth_t depth = { .mm = interpolate(psample.depth.mm, sample.depth.mm, j - t0, t1 - t0) };
auto gasmix = loop.at(j).first;
add_segment(ds, dive.depth_to_bar(depth), gasmix, 1, sample.setpoint.mbar,
loop_d.at(j), dive.sac,

View file

@ -280,9 +280,9 @@ static void fill_missing_tank_pressures(const struct dive *dive, struct plot_inf
static inline int calc_pressure_time(const struct dive *dive, const struct plot_data &a, const struct plot_data &b)
{
int time = b.sec - a.sec;
int depth = (a.depth + b.depth) / 2;
depth_t depth { .mm = (a.depth + b.depth) / 2 };
if (depth <= SURFACE_THRESHOLD)
if (depth.mm <= SURFACE_THRESHOLD)
return 0;
return dive->depth_to_mbar(depth) * time;

View file

@ -29,18 +29,19 @@
static constexpr int base_timestep = 2; // seconds
static int decostoplevels_metric[] = { 0, 3000, 6000, 9000, 12000, 15000, 18000, 21000, 24000, 27000,
30000, 33000, 36000, 39000, 42000, 45000, 48000, 51000, 54000, 57000,
60000, 63000, 66000, 69000, 72000, 75000, 78000, 81000, 84000, 87000,
90000, 100000, 110000, 120000, 130000, 140000, 150000, 160000, 170000,
180000, 190000, 200000, 220000, 240000, 260000, 280000, 300000,
320000, 340000, 360000, 380000 };
static int decostoplevels_imperial[] = { 0, 3048, 6096, 9144, 12192, 15240, 18288, 21336, 24384, 27432,
30480, 33528, 36576, 39624, 42672, 45720, 48768, 51816, 54864, 57912,
60960, 64008, 67056, 70104, 73152, 76200, 79248, 82296, 85344, 88392,
91440, 101600, 111760, 121920, 132080, 142240, 152400, 162560, 172720,
182880, 193040, 203200, 223520, 243840, 264160, 284480, 304800,
325120, 345440, 365760, 386080 };
static std::vector<depth_t> decostoplevels_metric = { 0_m, 3_m, 6_m, 9_m, 12_m, 15_m, 18_m, 21_m, 24_m, 27_m,
30_m, 33_m, 36_m, 39_m, 42_m, 45_m, 48_m, 51_m, 54_m, 57_m,
60_m, 63_m, 66_m, 69_m, 72_m, 75_m, 78_m, 81_m, 84_m, 87_m,
90_m, 100_m, 110_m, 120_m, 130_m, 140_m, 150_m, 160_m, 170_m,
180_m, 190_m, 200_m, 220_m, 240_m, 260_m, 280_m, 300_m,
320_m, 340_m, 360_m, 380_m };
// Note: for fractional feet (e.g. 333.33 ft), we use mm, since currently our custom depth literals only support integers.
static std::vector<depth_t> decostoplevels_imperial = { 0_ft, 10_ft, 20_ft, 30_ft, 40_ft, 50_ft, 60_ft, 70_ft, 80_ft, 90_ft,
100_ft, 110_ft, 120_ft, 130_ft, 140_ft, 150_ft, 160_ft, 170_ft, 180_ft, 190_ft,
200_ft, 210_ft, 220_ft, 230_ft, 240_ft, 250_ft, 260_ft, 270_ft, 280_ft, 290_ft,
300_ft, 101600_mm, 111760_mm, 400_ft, 132080_mm, 142240_mm, 500_ft, 162560_mm, 172720_mm,
600_ft, 193040_mm, 203200_mm, 223520_mm, 800_ft, 264160_mm, 284480_mm, 1000_ft,
325120_mm, 345440_mm, 1200_ft, 386080_mm };
#if DEBUG_PLAN
void dump_plan(struct diveplan *diveplan)
@ -103,11 +104,11 @@ static void interpolate_transition(struct deco_state *ds, struct dive *dive, dur
int32_t j;
for (j = t0.seconds; j < t1.seconds; j++) {
int depth = interpolate(d0.mm, d1.mm, j - t0.seconds, t1.seconds - t0.seconds);
depth_t depth = depth_t { .mm = interpolate(d0.mm, d1.mm, j - t0.seconds, t1.seconds - t0.seconds) };
add_segment(ds, dive->depth_to_bar(depth), gasmix, 1, po2.mbar, divemode, prefs.bottomsac, true);
}
if (d1.mm > d0.mm)
calc_crushing_pressure(ds, dive->depth_to_bar(d1.mm));
calc_crushing_pressure(ds, dive->depth_to_bar(d1));
}
/* returns the tissue tolerance at the end of this (partial) dive */
@ -153,7 +154,7 @@ static int tissue_at_end(struct deco_state *ds, struct dive *dive, const struct
nuclear_regeneration(ds, t0.seconds);
vpmb_start_gradient(ds);
ceiling_pressure.mbar = dive->depth_to_mbar(deco_allowed_depth(tissue_tolerance_calc(ds, dive,
dive->depth_to_bar(lastdepth.mm), true),
dive->depth_to_bar(lastdepth), true),
dive->surface_pressure.mbar / 1000.0,
dive,
1));
@ -184,7 +185,7 @@ static void update_cylinder_pressure(struct dive *d, int old_depth, int new_dept
if (!cyl)
return;
mean_depth.mm = (old_depth + new_depth) / 2;
gas_used.mliter = lrint(d->depth_to_atm(mean_depth.mm) * sac / 60 * duration * factor / 1000);
gas_used.mliter = lrint(d->depth_to_atm(mean_depth) * sac / 60 * duration * factor / 1000);
cyl->gas_used += gas_used;
if (in_deco)
cyl->deco_gas_used += gas_used;
@ -400,39 +401,39 @@ static std::vector<gaschanges> analyze_gaslist(const struct diveplan &diveplan,
}
/* sort all the stops into one ordered list */
static std::vector<int> sort_stops(int dstops[], size_t dnr, std::vector<gaschanges> gstops)
static std::vector<depth_t> sort_stops(const std::vector<depth_t> &dstops, size_t dnr, const std::vector<gaschanges> &gstops)
{
int total = dnr + gstops.size();
std::vector<int> stoplevels(total);
int total = static_cast<int>(dnr + gstops.size());
std::vector<depth_t> stoplevels(total);
/* Can't happen. */
if (dnr == 0)
return std::vector<int>();
return {};
/* no gaschanges */
if (gstops.empty()) {
std::copy(dstops, dstops + dnr, stoplevels.begin());
std::copy(dstops.begin(), dstops.begin() + dnr, stoplevels.begin());
return stoplevels;
}
int i = static_cast<int>(total) - 1;
int gi = static_cast<int>(gstops.size()) - 1;
int di = static_cast<int>(dnr) - 1;
while (i >= 0) {
if (dstops[di] > gstops[gi].depth) {
if (dstops[di].mm > gstops[gi].depth) {
stoplevels[i] = dstops[di];
di--;
} else if (dstops[di] == gstops[gi].depth) {
} else if (dstops[di].mm == gstops[gi].depth) {
stoplevels[i] = dstops[di];
di--;
gi--;
} else {
stoplevels[i] = gstops[gi].depth;
stoplevels[i].mm = gstops[gi].depth;
gi--;
}
i--;
if (di < 0) {
while (gi >= 0)
stoplevels[i--] = gstops[gi--].depth;
stoplevels[i--].mm = gstops[gi--].depth;
break;
}
if (gi < 0) {
@ -442,33 +443,33 @@ static std::vector<int> sort_stops(int dstops[], size_t dnr, std::vector<gaschan
}
}
while (i >= 0)
stoplevels[i--] = 0;
stoplevels[i--].mm = 0;
#if DEBUG_PLAN & 16
int k;
for (k = static_cast<int>(gstops.size()) + dnr - 1; k >= 0; k--) {
printf("stoplevel[%d]: %5.2lfm\n", k, stoplevels[k] / 1000.0);
if (stoplevels[k] == 0)
printf("stoplevel[%d]: %5.2lfm\n", k, stoplevels[k].mm / 1000.0);
if (stoplevels[k].mm == 0)
break;
}
#endif
return stoplevels;
}
int ascent_velocity(int depth, int avg_depth, int)
int ascent_velocity(depth_t depth, int avg_depth, int)
{
/* We need to make this configurable */
/* As an example (and possibly reasonable default) this is the Tech 1 provedure according
* to http://www.globalunderwaterexplorers.org/files/Standards_and_Procedures/SOP_Manual_Ver2.0.2.pdf */
if (depth * 4 > avg_depth * 3) {
if (depth.mm * 4 > avg_depth * 3) {
return prefs.ascrate75;
} else {
if (depth * 2 > avg_depth) {
if (depth.mm * 2 > avg_depth) {
return prefs.ascrate50;
} else {
if (depth > 6000)
if (depth.mm > 6000)
return prefs.ascratestops;
else
return prefs.ascratelast6m;
@ -476,24 +477,24 @@ int ascent_velocity(int depth, int avg_depth, int)
}
}
static void track_ascent_gas(int depth, struct dive *dive, int cylinder_id, int avg_depth, int bottom_time, bool safety_stop, enum divemode_t divemode)
static void track_ascent_gas(depth_t depth, struct dive *dive, int cylinder_id, int avg_depth, int bottom_time, bool safety_stop, enum divemode_t divemode)
{
cylinder_t *cylinder = dive->get_cylinder(cylinder_id);
while (depth > 0) {
while (depth.mm > 0) {
int deltad = ascent_velocity(depth, avg_depth, bottom_time) * base_timestep;
if (deltad > depth)
deltad = depth;
update_cylinder_pressure(dive, depth, depth - deltad, base_timestep, prefs.decosac, cylinder, true, divemode);
if (depth <= 5000 && depth >= (5000 - deltad) && safety_stop) {
if (deltad > depth.mm)
deltad = depth.mm;
update_cylinder_pressure(dive, depth.mm, depth.mm - deltad, base_timestep, prefs.decosac, cylinder, true, divemode);
if (depth.mm <= 5000 && depth.mm >= (5000 - deltad) && safety_stop) {
update_cylinder_pressure(dive, 5000, 5000, 180, prefs.decosac, cylinder, true, divemode);
safety_stop = false;
}
depth -= deltad;
depth.mm -= deltad;
}
}
// Determine whether ascending to the next stop will break the ceiling. Return true if the ascent is ok, false if it isn't.
static bool trial_ascent(struct deco_state *ds, int wait_time, int trial_depth, int stoplevel, int avg_depth, int bottom_time, struct gasmix gasmix, int po2, double surface_pressure, struct dive *dive, enum divemode_t divemode)
static bool trial_ascent(struct deco_state *ds, int wait_time, depth_t trial_depth, depth_t stoplevel, int avg_depth, int bottom_time, struct gasmix gasmix, int po2, double surface_pressure, struct dive *dive, enum divemode_t divemode)
{
bool clear_to_ascend = true;
@ -510,29 +511,29 @@ static bool trial_ascent(struct deco_state *ds, int wait_time, int trial_depth,
if (decoMode(true) == VPMB) {
double tolerance_limit = tissue_tolerance_calc(ds, dive, dive->depth_to_bar(stoplevel), true);
update_regression(ds, dive);
if (deco_allowed_depth(tolerance_limit, surface_pressure, dive, 1) > stoplevel) {
if (deco_allowed_depth(tolerance_limit, surface_pressure, dive, 1).mm > stoplevel.mm) {
trial_cache.restore(ds, false);
return false;
}
}
while (trial_depth > stoplevel) {
while (trial_depth.mm > stoplevel.mm) {
double tolerance_limit;
int deltad = ascent_velocity(trial_depth, avg_depth, bottom_time) * base_timestep;
if (deltad > trial_depth) /* don't test against depth above surface */
deltad = trial_depth;
if (deltad > trial_depth.mm) /* don't test against depth above surface */
deltad = trial_depth.mm;
add_segment(ds, dive->depth_to_bar(trial_depth),
gasmix,
base_timestep, po2, divemode, prefs.decosac, true);
tolerance_limit = tissue_tolerance_calc(ds, dive, dive->depth_to_bar(trial_depth), true);
if (decoMode(true) == VPMB)
update_regression(ds, dive);
if (deco_allowed_depth(tolerance_limit, surface_pressure, dive, 1) > trial_depth - deltad) {
if (deco_allowed_depth(tolerance_limit, surface_pressure, dive, 1).mm > trial_depth.mm - deltad) {
/* We should have stopped */
clear_to_ascend = false;
break;
}
trial_depth -= deltad;
trial_depth.mm -= deltad;
}
trial_cache.restore(ds, false);
return clear_to_ascend;
@ -561,7 +562,7 @@ static bool enough_gas(const struct dive *dive, int current_cylinder)
* leap is a guess for the maximum but there is no guarantee that leap is an upper limit.
* So we always test at the upper bundary, not in the middle!
*/
static int wait_until(struct deco_state *ds, struct dive *dive, int clock, int min, int leap, int stepsize, int depth, int target_depth, int avg_depth, int bottom_time, struct gasmix gasmix, int po2, double surface_pressure, enum divemode_t divemode)
static int wait_until(struct deco_state *ds, struct dive *dive, int clock, int min, int leap, int stepsize, depth_t depth, depth_t target_depth, int avg_depth, int bottom_time, struct gasmix gasmix, int po2, double surface_pressure, enum divemode_t divemode)
{
// When a deco stop exceeds two days, there is something wrong...
if (min >= 48 * 3600)
@ -605,7 +606,6 @@ static void average_max_depth(const struct diveplan &dive, int *avg_depth, int *
std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, struct dive *dive, int dcNr, int timestep, deco_state_cache &cache, bool is_planner, bool show_disclaimer)
{
int bottom_depth;
int bottom_gi;
int bottom_stopidx;
bool is_final_plan = true;
@ -616,10 +616,6 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
int transitiontime, gi;
int current_cylinder, stop_cylinder;
size_t stopidx;
int depth;
int *decostoplevels;
size_t decostoplevelcount;
std::vector<int> stoplevels;
bool stopping = false;
bool pendinggaschange = false;
int clock, previous_point_time;
@ -631,7 +627,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
int break_cylinder = -1, breakfrom_cylinder = 0;
bool last_segment_min_switch = false;
planner_error_t error = PLAN_OK;
int first_stop_depth = 0;
depth_t first_stop_depth;
int laststoptime = timestep;
bool o2breaking = false;
struct divecomputer *dc = dive->get_dc(dcNr);
@ -656,22 +652,17 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
create_dive_from_plan(diveplan, dive, dc, is_planner);
// Do we want deco stop array in metres or feet?
if (prefs.units.length == units::METERS ) {
decostoplevels = decostoplevels_metric;
decostoplevelcount = std::size(decostoplevels_metric);
} else {
decostoplevels = decostoplevels_imperial;
decostoplevelcount = std::size(decostoplevels_imperial);
}
auto &decostoplevels = prefs.units.length == units::METERS ?
decostoplevels_metric : decostoplevels_imperial;
/* If the user has selected last stop to be at 6m/20', we need to get rid of the 3m/10' stop.
* Otherwise reinstate the last stop 3m/10' stop.
* Remark: not reentrant, but the user probably won't change preferences while this is running.
*/
if (prefs.last_stop)
*(decostoplevels + 1) = 0;
decostoplevels[1].mm = 0;
else
*(decostoplevels + 1) = M_OR_FT(3,10);
decostoplevels[1].mm = M_OR_FT(3,10);
/* Let's start at the last 'sample', i.e. the last manually entered waypoint. */
const struct sample &sample = dc->samples.back();
@ -686,7 +677,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
gas = dive->get_cylinder(current_cylinder)->gasmix;
po2 = sample.setpoint.mbar;
depth = sample.depth.mm;
depth_t depth = sample.depth;
average_max_depth(diveplan, &avg_depth, &max_depth);
last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time);
@ -695,7 +686,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
/* Attn: for manually entered dives, we depend on the last segment having the
* same ascent rate as in fake_dc(). If you change it here, also change it there.
*/
transitiontime = lrint(depth / (double)prefs.ascratelast6m);
transitiontime = lrint(depth.mm / (double)prefs.ascratelast6m);
plan_add_segment(diveplan, transitiontime, 0, current_cylinder, po2, false, divemode);
create_dive_from_plan(diveplan, dive, dc, is_planner);
return {};
@ -703,26 +694,26 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
#if DEBUG_PLAN & 4
printf("gas %s\n", gas.name().c_str());
printf("depth %5.2lfm \n", depth / 1000.0);
printf("depth %5.2lfm \n", depth.mm / 1000.0);
printf("current_cylinder %i\n", current_cylinder);
#endif
/* Find the gases available for deco */
bool inappropriate_cylinder_use = false;
std::vector<gaschanges> gaschanges = analyze_gaslist(diveplan, dive, dcNr, depth, &best_first_ascend_cylinder, divemode == CCR && !prefs.dobailout, inappropriate_cylinder_use);
std::vector<gaschanges> gaschanges = analyze_gaslist(diveplan, dive, dcNr, depth.mm, &best_first_ascend_cylinder, divemode == CCR && !prefs.dobailout, inappropriate_cylinder_use);
if (inappropriate_cylinder_use) {
error = PLAN_ERROR_INAPPROPRIATE_GAS;
}
/* Find the first potential decostopdepth above current depth */
for (stopidx = 0; stopidx < decostoplevelcount; stopidx++)
if (decostoplevels[stopidx] > depth)
for (stopidx = 0; stopidx < decostoplevels.size(); stopidx++)
if (decostoplevels[stopidx].mm > depth.mm)
break;
if (stopidx > 0)
stopidx--;
/* Stoplevels are either depths of gas changes or potential deco stop depths. */
stoplevels = sort_stops(decostoplevels, stopidx + 1, gaschanges);
std::vector<depth_t> stoplevels = sort_stops(decostoplevels, stopidx + 1, gaschanges);
stopidx += gaschanges.size();
gi = static_cast<int>(gaschanges.size()) - 1;
@ -739,9 +730,9 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
add_segment(ds, dive->depth_to_bar(depth),
dive->get_cylinder(current_cylinder)->gasmix,
timestep, po2, divemode, prefs.bottomsac, true);
update_cylinder_pressure(dive, depth, depth, timestep, prefs.bottomsac, dive->get_cylinder(current_cylinder), false, divemode);
update_cylinder_pressure(dive, depth.mm, depth.mm, timestep, prefs.bottomsac, dive->get_cylinder(current_cylinder), false, divemode);
clock += timestep;
} while (trial_ascent(ds, 0, depth, 0, avg_depth, bottom_time, dive->get_cylinder(current_cylinder)->gasmix,
} while (trial_ascent(ds, 0, depth, 0_m, avg_depth, bottom_time, dive->get_cylinder(current_cylinder)->gasmix,
po2, diveplan.surface_pressure.mbar / 1000.0, dive, divemode) &&
enough_gas(dive, current_cylinder) && clock < 6 * 3600);
@ -749,24 +740,24 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
// In the best of all worlds, we would roll back also the last add_segment in terms of caching deco state, but
// let's ignore that since for the eventual ascent in recreational mode, nobody looks at the ceiling anymore,
// so we don't really have to compute the deco state.
update_cylinder_pressure(dive, depth, depth, -timestep, prefs.bottomsac, dive->get_cylinder(current_cylinder), false, divemode);
update_cylinder_pressure(dive, depth.mm, depth.mm, -timestep, prefs.bottomsac, dive->get_cylinder(current_cylinder), false, divemode);
clock -= timestep;
plan_add_segment(diveplan, clock - previous_point_time, depth, current_cylinder, po2, true, divemode);
plan_add_segment(diveplan, clock - previous_point_time, depth.mm, current_cylinder, po2, true, divemode);
previous_point_time = clock;
do {
/* Ascend to surface */
int deltad = ascent_velocity(depth, avg_depth, bottom_time) * base_timestep;
if (ascent_velocity(depth, avg_depth, bottom_time) != last_ascend_rate) {
plan_add_segment(diveplan, clock - previous_point_time, depth, current_cylinder, po2, false, divemode);
plan_add_segment(diveplan, clock - previous_point_time, depth.mm, current_cylinder, po2, false, divemode);
previous_point_time = clock;
last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time);
}
if (depth - deltad < 0)
deltad = depth;
if (depth.mm - deltad < 0)
deltad = depth.mm;
clock += base_timestep;
depth -= deltad;
if (depth <= 5000 && depth >= (5000 - deltad) && safety_stop) {
depth.mm -= deltad;
if (depth.mm <= 5000 && depth.mm >= (5000 - deltad) && safety_stop) {
plan_add_segment(diveplan, clock - previous_point_time, 5000, current_cylinder, po2, false, divemode);
previous_point_time = clock;
clock += 180;
@ -774,7 +765,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
previous_point_time = clock;
safety_stop = false;
}
} while (depth > 0);
} while (depth.mm > 0);
plan_add_segment(diveplan, clock - previous_point_time, 0, current_cylinder, po2, false, divemode);
create_dive_from_plan(diveplan, dive, dc, is_planner);
diveplan.add_plan_to_notes(*dive, show_disclaimer, error);
@ -789,7 +780,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
#if DEBUG_PLAN & 16
printf("switch to gas %d (%d/%d) @ %5.2lfm\n", best_first_ascend_cylinder,
(get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[best_first_ascend_cylinder].depth / 1000.0);
(get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[best_first_ascend_cylinder].depth.mm / 1000.0);
#endif
}
@ -802,13 +793,13 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
add_segment(ds, dive->depth_to_bar(depth),
dive->get_cylinder(current_cylinder)->gasmix,
bailoutsegment, po2, divemode, prefs.bottomsac, true);
plan_add_segment(diveplan, bailoutsegment, depth, current_cylinder, po2, false, divemode);
plan_add_segment(diveplan, bailoutsegment, depth.mm, current_cylinder, po2, false, divemode);
bottom_time += bailoutsegment;
}
previous_deco_time = 100000000;
ds->deco_time = 10000000;
bottom_cache.cache(ds); // Lets us make several iterations
bottom_depth = depth;
depth_t bottom_depth = depth;
bottom_gi = gi;
bottom_gas = gas;
bottom_stopidx = stopidx;
@ -830,7 +821,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
gas = bottom_gas;
stopping = false;
bool decodive = false;
first_stop_depth = 0;
first_stop_depth = 0_m;
stopidx = bottom_stopidx;
ds->first_ceiling_pressure.mbar = dive->depth_to_mbar(
deco_allowed_depth(tissue_tolerance_calc(ds, dive, dive->depth_to_bar(depth), true),
@ -854,15 +845,15 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
/* We will break out when we hit the surface */
do {
/* Ascend to next stop depth */
int deltad = ascent_velocity(depth, avg_depth, bottom_time) * base_timestep;
depth_t deltad { .mm = ascent_velocity(depth, avg_depth, bottom_time) * base_timestep };
if (ascent_velocity(depth, avg_depth, bottom_time) != last_ascend_rate) {
if (is_final_plan)
plan_add_segment(diveplan, clock - previous_point_time, depth, current_cylinder, po2, false, divemode);
plan_add_segment(diveplan, clock - previous_point_time, depth.mm, current_cylinder, po2, false, divemode);
previous_point_time = clock;
stopping = false;
last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time);
}
if (depth - deltad < stoplevels[stopidx])
if (depth.mm - deltad.mm < stoplevels[stopidx].mm)
deltad = depth - stoplevels[stopidx];
add_segment(ds, dive->depth_to_bar(depth),
@ -873,13 +864,13 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
depth -= deltad;
/* Print VPM-Gradient as gradient factor, this has to be done from within deco.cpp */
if (decodive)
ds->plot_depth = depth;
} while (depth > 0 && depth > stoplevels[stopidx]);
ds->plot_depth = depth.mm;
} while (depth.mm > 0 && depth.mm > stoplevels[stopidx].mm);
if (depth <= 0)
if (depth.mm <= 0)
break; /* We are at the surface */
if (gi >= 0 && stoplevels[stopidx] <= gaschanges[gi].depth) {
if (gi >= 0 && stoplevels[stopidx].mm <= gaschanges[gi].depth) {
/* We have reached a gas change.
* Record this in the dive plan */
@ -893,7 +884,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
!trial_ascent(ds, 0, depth, stoplevels[stopidx - 1], avg_depth, bottom_time,
dive->get_cylinder(current_cylinder)->gasmix, po2, diveplan.surface_pressure.mbar / 1000.0, dive, divemode) || get_o2(dive->get_cylinder(current_cylinder)->gasmix) < 160) {
if (is_final_plan)
plan_add_segment(diveplan, clock - previous_point_time, depth, current_cylinder, po2, false, divemode);
plan_add_segment(diveplan, clock - previous_point_time, depth.mm, current_cylinder, po2, false, divemode);
stopping = true;
previous_point_time = clock;
current_cylinder = gaschanges[gi].gasidx;
@ -928,7 +919,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
/* Check if ascending to next stop is clear, go back and wait if we hit the ceiling on the way */
if (trial_ascent(ds, 0, depth, stoplevels[stopidx], avg_depth, bottom_time,
dive->get_cylinder(current_cylinder)->gasmix, po2, diveplan.surface_pressure.mbar / 1000.0, dive, divemode)) {
decostoptable.push_back( decostop { depth, 0 });
decostoptable.push_back( decostop { depth.mm, 0 });
break; /* We did not hit the ceiling */
}
@ -941,7 +932,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
/* The last segment was an ascend segment.
* Add a waypoint for start of this deco stop */
if (is_final_plan)
plan_add_segment(diveplan, clock - previous_point_time, depth, current_cylinder, po2, false, divemode);
plan_add_segment(diveplan, clock - previous_point_time, depth.mm, current_cylinder, po2, false, divemode);
previous_point_time = clock;
stopping = true;
}
@ -972,7 +963,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
bottom_time, dive->get_cylinder(current_cylinder)->gasmix, po2, diveplan.surface_pressure.mbar / 1000.0, divemode);
laststoptime = new_clock - clock;
/* Finish infinite deco */
if (laststoptime >= 48 * 3600 && depth >= 6000) {
if (laststoptime >= 48 * 3600 && depth.mm >= 6000) {
error = PLAN_ERROR_TIMEOUT;
break;
@ -998,7 +989,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
o2break_next = true;
breakfrom_cylinder = current_cylinder;
if (is_final_plan)
plan_add_segment(diveplan, laststoptime, depth, current_cylinder, po2, false, divemode);
plan_add_segment(diveplan, laststoptime, depth.mm, current_cylinder, po2, false, divemode);
previous_point_time = clock + laststoptime;
current_cylinder = break_cylinder;
}
@ -1009,7 +1000,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
o2breaking = true;
o2break_next = false;
if (is_final_plan)
plan_add_segment(diveplan, laststoptime, depth, current_cylinder, po2, false, divemode);
plan_add_segment(diveplan, laststoptime, depth.mm, current_cylinder, po2, false, divemode);
previous_point_time = clock + laststoptime;
current_cylinder = breakfrom_cylinder;
}
@ -1018,7 +1009,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
add_segment(ds, dive->depth_to_bar(depth), dive->get_cylinder(stop_cylinder)->gasmix,
laststoptime, po2, divemode, prefs.decosac, true);
last_segment_min_switch = false;
decostoptable.push_back(decostop { depth, laststoptime } );
decostoptable.push_back(decostop { depth.mm, laststoptime } );
clock += laststoptime;
if (!o2breaking)
@ -1027,7 +1018,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
if (stopping) {
/* Next we will ascend again. Add a waypoint if we have spend deco time */
if (is_final_plan)
plan_add_segment(diveplan, clock - previous_point_time, depth, current_cylinder, po2, false, divemode);
plan_add_segment(diveplan, clock - previous_point_time, depth.mm, current_cylinder, po2, false, divemode);
previous_point_time = clock;
stopping = false;
}
@ -1042,7 +1033,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
plan_add_segment(diveplan, clock - previous_point_time, 0, current_cylinder, po2, false, divemode);
if (decoMode(true) == VPMB) {
diveplan.eff_gfhigh = lrint(100.0 * regressionb(ds));
diveplan.eff_gflow = lrint(100.0 * (regressiona(ds) * first_stop_depth + regressionb(ds)));
diveplan.eff_gflow = lrint(100.0 * (regressiona(ds) * first_stop_depth.mm + regressionb(ds)));
}
if (prefs.surface_segment != 0) {

View file

@ -58,6 +58,7 @@ struct diveplan {
struct deco_state_cache;
extern int get_cylinderid_at_time(struct dive *dive, struct divecomputer *dc, duration_t time);
extern int ascent_velocity(depth_t depth, int avg_depth, int);
extern const char *get_planner_disclaimer();
void plan_add_segment(struct diveplan &diveplan, int duration, int depth, int cylinderid, int po2, bool entered, enum divemode_t divemode);

View file

@ -346,7 +346,7 @@ void diveplan::add_plan_to_notes(struct dive &dive, bool show_disclaimer, planne
if (isobaric_counterdiffusion(lastprintgasmix, newgasmix, &icdvalues)) // Do icd calulations
icdwarning = true;
if (icdvalues.dN2 > 0) { // If the gas change involved helium as well as an increase in nitrogen..
icdbuf += icd_entry(&icdvalues, icdtableheader, dp->time, dive.depth_to_mbar(dp->depth.mm), lastprintgasmix, newgasmix); // .. then print calculations to buffer.
icdbuf += icd_entry(&icdvalues, icdtableheader, dp->time, dive.depth_to_mbar(dp->depth), lastprintgasmix, newgasmix); // .. then print calculations to buffer.
icdtableheader = false;
}
}
@ -367,7 +367,7 @@ void diveplan::add_plan_to_notes(struct dive &dive, bool show_disclaimer, planne
if (isobaric_counterdiffusion(lastprintgasmix, gasmix, &icdvalues)) // Do icd calculations
icdwarning = true;
if (icdvalues.dN2 > 0) { // If the gas change involved helium as well as an increase in nitrogen..
icdbuf += icd_entry(&icdvalues, icdtableheader, lasttime, dive.depth_to_mbar(dp->depth.mm), lastprintgasmix, gasmix); // .. then print data to buffer.
icdbuf += icd_entry(&icdvalues, icdtableheader, lasttime, dive.depth_to_mbar(dp->depth), lastprintgasmix, gasmix); // .. then print data to buffer.
icdtableheader = false;
}
}
@ -398,7 +398,7 @@ void diveplan::add_plan_to_notes(struct dive &dive, bool show_disclaimer, planne
if (isobaric_counterdiffusion(lastprintgasmix, newgasmix, &icdvalues)) // Do icd calculations
icdwarning = true;
if (icdvalues.dN2 > 0) { // If the gas change involved helium as well as an increase in nitrogen..
icdbuf += icd_entry(&icdvalues, icdtableheader, dp->time, dive.depth_to_mbar(dp->depth.mm), lastprintgasmix, newgasmix); // ... then print data to buffer.
icdbuf += icd_entry(&icdvalues, icdtableheader, dp->time, dive.depth_to_mbar(dp->depth), lastprintgasmix, newgasmix); // ... then print data to buffer.
icdtableheader = false;
}
}
@ -510,7 +510,7 @@ void diveplan::add_plan_to_notes(struct dive &dive, bool show_disclaimer, planne
/* Calculate minimum gas volume. */
volume_t mingasv;
mingasv.mliter = lrint(prefs.sacfactor / 100.0 * prefs.problemsolvingtime * prefs.bottomsac
* dive.depth_to_bar(lastbottomdp->depth.mm)
* dive.depth_to_bar(lastbottomdp->depth)
+ prefs.sacfactor / 100.0 * cyl.deco_gas_used.mliter);
/* Calculate minimum gas pressure for cyclinder. */
lastbottomdp->minimum_gas.mbar = lrint(isothermal_pressure(cyl.gasmix, 1.0,
@ -589,7 +589,7 @@ void diveplan::add_plan_to_notes(struct dive &dive, bool show_disclaimer, planne
struct gasmix gasmix = dive.get_cylinder(dp.cylinderid)->gasmix;
divemode_t current_divemode = loop.at(dp.time);
amb = dive.depth_to_atm(dp.depth.mm);
amb = dive.depth_to_atm(dp.depth);
gas_pressures pressures = fill_pressures(amb, gasmix, (current_divemode == OC) ? 0.0 : amb * gasmix.o2.permille / 1000.0, current_divemode);
if (pressures.o2 > (dp.entered ? prefs.bottompo2 : prefs.decopo2) / 1000.0) {

View file

@ -17,6 +17,7 @@
#include "sample.h"
#include "subsurface-string.h"
#include "planner.h"
#include "profile.h"
#include "gaspressures.h"
#include "deco.h"
@ -32,7 +33,6 @@
#define MAX_PROFILE_DECO 7200
int ascent_velocity(int depth, int avg_depth, int bottom_time);
#ifdef DEBUG_PI
/* debugging tool - not normally used */
@ -46,6 +46,7 @@ static void dump_pi(const struct plot_info &pi)
pi.maxpressure, pi.mintemp, pi.maxtemp);
for (i = 0; i < pi.nr; i++) {
struct plot_data &entry = pi.entry[i];
depth_t depth { .mm = entry.depth };
printf(" entry[%d]:{cylinderindex:%d sec:%d pressure:{%d,%d}\n"
" time:%d:%02d temperature:%d depth:%d stopdepth:%d stoptime:%d ndl:%d smoothed:%d po2:%lf phe:%lf pn2:%lf sum-pp %lf}\n",
i, entry.sensor[0], entry.sec,
@ -111,7 +112,6 @@ static int get_local_sac(struct plot_info &pi, int idx1, int idx2, struct dive *
struct plot_data &entry1 = pi.entry[idx1];
struct plot_data &entry2 = pi.entry[idx2];
int duration = entry2.sec - entry1.sec;
int depth;
pressure_t a, b;
double atm;
@ -123,7 +123,7 @@ static int get_local_sac(struct plot_info &pi, int idx1, int idx2, struct dive *
return 0;
/* Mean pressure in ATM */
depth = (entry1.depth + entry2.depth) / 2;
depth_t depth {.mm = (entry1.depth + entry2.depth) / 2 };
atm = dive->depth_to_atm(depth);
cyl = dive->get_cylinder(index);
@ -492,7 +492,7 @@ static int sac_between(const struct dive *dive, const struct plot_info &pi, int
do {
const struct plot_data &entry = pi.entry[first];
const struct plot_data &next = pi.entry[first + 1];
int depth = (entry.depth + next.depth) / 2;
depth_t depth { .mm = (entry.depth + next.depth) / 2 };
int time = next.sec - entry.sec;
double atm = dive->depth_to_atm(depth);
@ -766,10 +766,10 @@ static void calculate_ndl_tts(struct deco_state *ds, const struct dive *dive, st
const int time_stepsize = 60;
const int deco_stepsize = M_OR_FT(3, 10);
/* at what depth is the current deco-step? */
depth_t ascent_depth { .mm = entry.depth };
int next_stop = round_up(deco_allowed_depth(
tissue_tolerance_calc(ds, dive, dive->depth_to_bar(entry.depth), in_planner),
surface_pressure, dive, 1), deco_stepsize);
int ascent_depth = entry.depth;
tissue_tolerance_calc(ds, dive, dive->depth_to_bar(ascent_depth), in_planner),
surface_pressure, dive, 1).mm, deco_stepsize);
/* at what time should we give up and say that we got enuff NDL? */
/* If iterating through a dive, entry.tts_calc needs to be reset */
entry.tts_calc = 0;
@ -783,11 +783,11 @@ static void calculate_ndl_tts(struct deco_state *ds, const struct dive *dive, st
}
/* stop if the ndl is above max_ndl seconds, and call it plenty of time */
while (entry.ndl_calc < MAX_PROFILE_DECO &&
deco_allowed_depth(tissue_tolerance_calc(ds, dive, dive->depth_to_bar(entry.depth), in_planner),
surface_pressure, dive, 1) <= 0
deco_allowed_depth(tissue_tolerance_calc(ds, dive, dive->depth_to_bar(ascent_depth), in_planner),
surface_pressure, dive, 1).mm <= 0
) {
entry.ndl_calc += time_stepsize;
add_segment(ds, dive->depth_to_bar(entry.depth),
add_segment(ds, dive->depth_to_bar(ascent_depth),
gasmix, time_stepsize, entry.o2pressure.mbar, divemode, prefs.bottomsac, in_planner);
}
/* we don't need to calculate anything else */
@ -798,13 +798,13 @@ static void calculate_ndl_tts(struct deco_state *ds, const struct dive *dive, st
entry.in_deco_calc = true;
/* Add segments for movement to stopdepth */
for (; ascent_depth > next_stop; ascent_depth -= ascent_s_per_step * ascent_velocity(ascent_depth, entry.running_sum / entry.sec, 0), entry.tts_calc += ascent_s_per_step) {
for (; ascent_depth.mm > next_stop; ascent_depth.mm -= ascent_s_per_step * ascent_velocity(ascent_depth, entry.running_sum / entry.sec, 0), entry.tts_calc += ascent_s_per_step) {
add_segment(ds, dive->depth_to_bar(ascent_depth),
gasmix, ascent_s_per_step, entry.o2pressure.mbar, divemode, prefs.decosac, in_planner);
next_stop = round_up(deco_allowed_depth(tissue_tolerance_calc(ds, dive, dive->depth_to_bar(ascent_depth), in_planner),
surface_pressure, dive, 1), deco_stepsize);
surface_pressure, dive, 1).mm, deco_stepsize);
}
ascent_depth = next_stop;
ascent_depth.mm = next_stop;
/* And how long is the current deco-step? */
entry.stoptime_calc = 0;
@ -814,7 +814,7 @@ static void calculate_ndl_tts(struct deco_state *ds, const struct dive *dive, st
/* And how long is the total TTS */
while (next_stop >= 0) {
/* save the time for the first stop to show in the graph */
if (ascent_depth == entry.stopdepth_calc)
if (ascent_depth.mm == entry.stopdepth_calc)
entry.stoptime_calc += time_stepsize;
entry.tts_calc += time_stepsize;
@ -823,12 +823,12 @@ static void calculate_ndl_tts(struct deco_state *ds, const struct dive *dive, st
add_segment(ds, dive->depth_to_bar(ascent_depth),
gasmix, time_stepsize, entry.o2pressure.mbar, divemode, prefs.decosac, in_planner);
if (deco_allowed_depth(tissue_tolerance_calc(ds, dive, dive->depth_to_bar(ascent_depth), in_planner), surface_pressure, dive, 1) <= next_stop) {
if (deco_allowed_depth(tissue_tolerance_calc(ds, dive, dive->depth_to_bar(ascent_depth), in_planner), surface_pressure, dive, 1).mm <= next_stop) {
/* move to the next stop and add the travel between stops */
for (; ascent_depth > next_stop; ascent_depth -= ascent_s_per_deco_step * ascent_velocity(ascent_depth, entry.running_sum / entry.sec, 0), entry.tts_calc += ascent_s_per_deco_step)
for (; ascent_depth.mm > next_stop; ascent_depth.mm -= ascent_s_per_deco_step * ascent_velocity(ascent_depth, entry.running_sum / entry.sec, 0), entry.tts_calc += ascent_s_per_deco_step)
add_segment(ds, dive->depth_to_bar(ascent_depth),
gasmix, ascent_s_per_deco_step, entry.o2pressure.mbar, divemode, prefs.decosac, in_planner);
ascent_depth = next_stop;
ascent_depth.mm = next_stop;
next_stop -= deco_stepsize;
}
}
@ -862,7 +862,8 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
* Set maximum number of iterations to 10 just in case */
while ((abs(prev_deco_time - ds->deco_time) >= 30) && (count_iteration < 10)) {
int last_ndl_tts_calc_time = 0, first_ceiling = 0, current_ceiling, last_ceiling = 0, final_tts = 0 , time_clear_ceiling = 0;
depth_t first_ceiling, current_ceiling, last_ceiling;
int last_ndl_tts_calc_time = 0, final_tts = 0 , time_clear_ceiling = 0;
if (decoMode(in_planner) == VPMB)
ds->first_ceiling_pressure.mbar = dive->depth_to_mbar(first_ceiling);
@ -871,12 +872,14 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
for (i = 1; i < pi.nr; i++) {
struct plot_data &entry = pi.entry[i];
struct plot_data &prev = pi.entry[i - 1];
int j, t0 = prev.sec, t1 = entry.sec;
int time_stepsize = 20, max_ceiling = -1;
int t0 = prev.sec, t1 = entry.sec;
int time_stepsize = 20;
depth_t max_ceiling;
depth_t depth { .mm = entry.depth };
divemode_t current_divemode = loop_d.at(entry.sec);
struct gasmix gasmix = loop.at(t1).first;
entry.ambpressure = dive->depth_to_bar(entry.depth);
entry.ambpressure = dive->depth_to_bar(depth);
entry.gfline = get_gf(ds, entry.ambpressure, dive) * (100.0 - AMB_PERCENTAGE) + AMB_PERCENTAGE;
if (t0 > t1) {
report_info("non-monotonous dive stamps %d %d", t0, t1);
@ -884,9 +887,9 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
}
if (t0 != t1 && t1 - t0 < time_stepsize)
time_stepsize = t1 - t0;
for (j = t0 + time_stepsize; j <= t1; j += time_stepsize) {
int depth = interpolate(prev.depth, entry.depth, j - t0, t1 - t0);
add_segment(ds, dive->depth_to_bar(depth),
for (int j = t0 + time_stepsize; j <= t1; j += time_stepsize) {
depth_t new_depth { .mm = interpolate(prev.depth, depth.mm, j - t0, t1 - t0) };
add_segment(ds, dive->depth_to_bar(new_depth),
gasmix, time_stepsize, entry.o2pressure.mbar, current_divemode, entry.sac, in_planner);
entry.icd_warning = ds->icd_warning;
if ((t1 - j < time_stepsize) && (j < t1))
@ -896,23 +899,23 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
entry.ceiling = prev.ceiling;
} else {
/* Keep updating the VPM-B gradients until the start of the ascent phase of the dive. */
if (decoMode(in_planner) == VPMB && last_ceiling >= first_ceiling && first_iteration == true) {
if (decoMode(in_planner) == VPMB && last_ceiling.mm >= first_ceiling.mm && first_iteration == true) {
nuclear_regeneration(ds, t1);
vpmb_start_gradient(ds);
/* For CVA iterations, calculate next gradient */
if (!first_iteration || in_planner)
vpmb_next_gradient(ds, ds->deco_time, surface_pressure / 1000.0, in_planner);
}
entry.ceiling = deco_allowed_depth(tissue_tolerance_calc(ds, dive, dive->depth_to_bar(entry.depth), in_planner), surface_pressure, dive, !prefs.calcceiling3m);
entry.ceiling = deco_allowed_depth(tissue_tolerance_calc(ds, dive, dive->depth_to_bar(depth), in_planner), surface_pressure, dive, !prefs.calcceiling3m).mm;
if (prefs.calcceiling3m)
current_ceiling = deco_allowed_depth(tissue_tolerance_calc(ds, dive, dive->depth_to_bar(entry.depth), in_planner), surface_pressure, dive, true);
current_ceiling = deco_allowed_depth(tissue_tolerance_calc(ds, dive, dive->depth_to_bar(depth), in_planner), surface_pressure, dive, true);
else
current_ceiling = entry.ceiling;
current_ceiling.mm = entry.ceiling;
last_ceiling = current_ceiling;
/* If using VPM-B, take first_ceiling_pressure as the deepest ceiling */
if (decoMode(in_planner) == VPMB) {
if (current_ceiling >= first_ceiling ||
(time_deep_ceiling == t0 && entry.depth == prev.depth)) {
if (current_ceiling.mm >= first_ceiling.mm ||
(time_deep_ceiling == t0 && depth.mm == prev.depth)) {
time_deep_ceiling = t1;
first_ceiling = current_ceiling;
ds->first_ceiling_pressure.mbar = dive->depth_to_mbar(first_ceiling);
@ -928,7 +931,7 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
}
}
// Use the point where the ceiling clears as the end of deco phase for CVA calculations
if (current_ceiling > 0)
if (current_ceiling.mm > 0)
time_clear_ceiling = 0;
else if (time_clear_ceiling == 0 && t1 > time_deep_ceiling)
time_clear_ceiling = t1;
@ -936,12 +939,12 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
}
entry.surface_gf = 0.0;
entry.current_gf = 0.0;
for (j = 0; j < 16; j++) {
for (int j = 0; j < 16; j++) {
double m_value = ds->buehlmann_inertgas_a[j] + entry.ambpressure / ds->buehlmann_inertgas_b[j];
double surface_m_value = ds->buehlmann_inertgas_a[j] + surface_pressure / ds->buehlmann_inertgas_b[j];
entry.ceilings[j] = deco_allowed_depth(ds->tolerated_by_tissue[j], surface_pressure, dive, 1);
if (entry.ceilings[j] > max_ceiling)
max_ceiling = entry.ceilings[j];
entry.ceilings[j] = deco_allowed_depth(ds->tolerated_by_tissue[j], surface_pressure, dive, 1).mm;
if (entry.ceilings[j] > max_ceiling.mm)
max_ceiling.mm = entry.ceilings[j];
double current_gf = (ds->tissue_inertgas_saturation[j] - entry.ambpressure) / (m_value - entry.ambpressure);
entry.percentages[j] = ds->tissue_inertgas_saturation[j] < entry.ambpressure ?
lrint(ds->tissue_inertgas_saturation[j] / entry.ambpressure * AMB_PERCENTAGE) :
@ -960,9 +963,9 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
// marker should be handled differently!
// Don't scream if we violate the ceiling by a few cm.
if (in_planner && !pi.waypoint_above_ceiling &&
entry.depth < max_ceiling - 100 && entry.sec > 0) {
depth.mm < max_ceiling.mm - 100 && entry.sec > 0) {
struct dive *non_const_dive = (struct dive *)dive; // cast away const!
add_event(&non_const_dive->dcs[0], entry.sec, SAMPLE_EVENT_CEILING, -1, max_ceiling / 1000,
add_event(&non_const_dive->dcs[0], entry.sec, SAMPLE_EVENT_CEILING, -1, max_ceiling.mm / 1000,
translate("gettextFromC", "planned waypoint above ceiling"));
pi.waypoint_above_ceiling = true;
}
@ -1009,7 +1012,7 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
vpmb_next_gradient(ds, ds->deco_time, surface_pressure / 1000.0, in_planner);
final_tts = 0;
last_ndl_tts_calc_time = 0;
first_ceiling = 0;
first_ceiling = 0_m;
first_iteration = false;
count_iteration ++;
this_deco_time = ds->deco_time;
@ -1109,16 +1112,17 @@ static void calculate_gas_information_new(const struct dive *dive, const struct
for (i = 1; i < pi.nr; i++) {
double fn2, fhe;
struct plot_data &entry = pi.entry[i];
depth_t depth { .mm = entry.depth };
auto gasmix = loop.at(entry.sec).first;
amb_pressure = dive->depth_to_bar(entry.depth);
amb_pressure = dive->depth_to_bar(depth);
divemode_t current_divemode = loop_d.at(entry.sec);
entry.pressures = fill_pressures(amb_pressure, gasmix, (current_divemode == OC) ? 0.0 : entry.o2pressure.mbar / 1000.0, current_divemode);
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 = loop.at(entry.sec).first;
entry.scr_OC_pO2.mbar = (int) dive->depth_to_mbar(entry.depth) * get_o2(gasmix2) / 1000;
entry.scr_OC_pO2.mbar = (int) dive->depth_to_mbar(depth) * get_o2(gasmix2) / 1000;
}
/* Calculate MOD, EAD, END and EADD based on partial pressures calculated before
@ -1127,13 +1131,13 @@ static void calculate_gas_information_new(const struct dive *dive, const struct
* EAD just uses N ("Air" for nitrox dives) */
pressure_t modpO2 = { .mbar = (int)(prefs.modpO2 * 1000) };
entry.mod = dive->gas_mod(gasmix, modpO2, 1).mm;
entry.end = dive->mbar_to_depth(lrint(dive->depth_to_mbarf(entry.depth) * (1000 - fhe) / 1000.0));
entry.ead = dive->mbar_to_depth(lrint(dive->depth_to_mbarf(entry.depth) * fn2 / (double)N2_IN_AIR));
entry.eadd = dive->mbar_to_depth(lrint(dive->depth_to_mbarf(entry.depth) *
entry.end = dive->mbar_to_depth(lrint(dive->depth_to_mbarf(depth) * (1000 - fhe) / 1000.0)).mm;
entry.ead = dive->mbar_to_depth(lrint(dive->depth_to_mbarf(depth) * fn2 / (double)N2_IN_AIR)).mm;
entry.eadd = dive->mbar_to_depth(lrint(dive->depth_to_mbarf(depth) *
(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));
(O2_IN_AIR * O2_DENSITY + N2_IN_AIR * N2_DENSITY) * 1000)).mm;
entry.density = gas_density(entry.pressures);
if (entry.mod < 0)
entry.mod = 0;
@ -1162,6 +1166,7 @@ static void fill_o2_values(const struct dive *dive, const struct divecomputer *d
for (i = 0; i < pi.nr; i++) {
struct plot_data &entry = pi.entry[i];
depth_t depth { .mm = entry.depth };
if (dc->divemode == CCR || (dc->divemode == PSCR && dc->no_o2sensors)) {
if (i == 0) { // For 1st iteration, initialise the last_sensor values
@ -1174,7 +1179,7 @@ static void fill_o2_values(const struct dive *dive, const struct divecomputer *d
else
entry.o2sensor[j] = last_sensor[j];
} // having initialised the empty o2 sensor values for this point on the profile,
amb_pressure.mbar = dive->depth_to_mbar(entry.depth);
amb_pressure.mbar = dive->depth_to_mbar(depth);
o2pressure.mbar = calculate_ccr_po2(entry, dc); // ...calculate the po2 based on the sensor data
entry.o2pressure.mbar = std::min(o2pressure.mbar, amb_pressure.mbar);
} else {
@ -1265,9 +1270,10 @@ static std::vector<std::string> plot_string(const struct dive *d, const struct p
int decimals, cyl;
const char *unit;
const struct plot_data &entry = pi.entry[idx];
depth_t depth { .mm = entry.depth };
std::vector<std::string> res;
depthvalue = get_depth_units(entry.depth, NULL, &depth_unit);
depthvalue = get_depth_units(depth.mm, NULL, &depth_unit);
res.push_back(casprintf_loc(translate("gettextFromC", "@: %d:%02d"), FRACTION_TUPLE(entry.sec, 60)));
res.push_back(casprintf_loc(translate("gettextFromC", "D: %.1f%s"), depthvalue, depth_unit));
for (cyl = 0; cyl < pi.nr_cylinders; cyl++) {
@ -1579,7 +1585,7 @@ std::vector<std::string> compare_samples(const struct dive *d, const struct plot
const char *volume_unit;
/* Mean pressure in ATM */
double atm = d->depth_to_atm(avg_depth);
double atm = d->depth_to_atm(depth_t { .mm = avg_depth });
/* milliliters per minute */
int sac = lrint(total_volume_used / atm * 60 / delta_time);

View file

@ -248,7 +248,7 @@ void uemis::event(struct dive *dive, struct divecomputer *dc, struct sample *sam
* flags[3].bit0 | flags[5].bit1 != 0 ==> in deco
* flags[0].bit7 == 1 ==> Safety Stop
* otherwise NDL */
stopdepth = dive->rel_mbar_to_depth(u_sample->hold_depth);
stopdepth = dive->rel_mbar_to_depth(u_sample->hold_depth).mm;
if ((flags[3] & 1) | (flags[5] & 2)) {
/* deco */
sample->in_deco = true;
@ -344,7 +344,7 @@ void uemis::parse_divelog_binary(std::string_view base64, struct dive *dive)
}
sample = prepare_sample(dc);
sample->time.seconds = u_sample->dive_time;
sample->depth.mm = dive->rel_mbar_to_depth(u_sample->water_pressure);
sample->depth = dive->rel_mbar_to_depth(u_sample->water_pressure);
sample->temperature.mkelvin = C_to_mkelvin(u_sample->dive_temperature / 10.0);
add_sample_pressure(sample, active, (u_sample->tank_pressure_high * 256 + u_sample->tank_pressure_low) * 10);
sample->cns = u_sample->cns;

View file

@ -144,7 +144,8 @@ void TabDiveInformation::updateProfile()
continue;
volumes.append(get_volume_string(gases[i], true));
if (duration[i]) {
sac.mliter = lrint(gases[i].mliter / (currentDive->depth_to_atm(mean[i]) * duration[i] / 60));
depth_t mean_depth = { .mm = mean[i] }; // Will be removed in upcoming commit
sac.mliter = lrint(gases[i].mliter / (currentDive->depth_to_atm(mean_depth) * duration[i] / 60));
SACs.append(get_volume_string(sac, true).append(tr("/min")));
}
}

View file

@ -578,7 +578,7 @@ void TestPlan::testVpmbMetric45m30minTx()
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
QCOMPARE(lrint(dp == testPlan.dp.end() ? 0.0 : dp->minimum_gas.mbar / 1000.0), 108l);
// print first ceiling
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar).mm * 0.001);
// check benchmark run time of 141 minutes, and known Subsurface runtime of 139 minutes
//QVERIFY(compareDecoTime(dive.dcs[0].duration.seconds, 141u * 60u + 20u, 139u * 60u + 20u));
}
@ -604,7 +604,7 @@ void TestPlan::testVpmbMetric60m10minTx()
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
QCOMPARE(lrint(dp == testPlan.dp.end() ? 0.0 : dp->minimum_gas.mbar / 1000.0), 162l);
// print first ceiling
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar).mm * 0.001);
// check benchmark run time of 141 minutes, and known Subsurface runtime of 139 minutes
//QVERIFY(compareDecoTime(dive.dcs[0].duration.seconds, 141u * 60u + 20u, 139u * 60u + 20u));
}
@ -630,7 +630,7 @@ void TestPlan::testVpmbMetric60m30minAir()
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
QCOMPARE(lrint(dp == testPlan.dp.end() ? 0.0 : dp->minimum_gas.mbar / 1000.0), 180l);
// print first ceiling
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar).mm * 0.001);
// check benchmark run time of 141 minutes, and known Subsurface runtime of 139 minutes
QVERIFY(compareDecoTime(dive.dcs[0].duration.seconds, 141u * 60u + 20u, 139u * 60u + 20u));
}
@ -656,7 +656,7 @@ void TestPlan::testVpmbMetric60m30minEan50()
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
QCOMPARE(lrint(dp == testPlan.dp.end() ? 0.0 : dp->minimum_gas.mbar / 1000.0), 155l);
// print first ceiling
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar).mm * 0.001);
QVERIFY(dive.dcs[0].events.size() >= 1);
// check first gas change to EAN50 at 21m
struct event *ev = &dive.dcs[0].events[0];
@ -688,7 +688,7 @@ void TestPlan::testVpmbMetric60m30minTx()
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
QCOMPARE(lrint(dp == testPlan.dp.end() ? 0.0 : dp->minimum_gas.mbar / 1000.0), 159l);
// print first ceiling
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar).mm * 0.001);
// check first gas change to EAN50 at 21m
QVERIFY(dive.dcs[0].events.size() >= 1);
struct event *ev = &dive.dcs[0].events[0];
@ -720,7 +720,7 @@ void TestPlan::testVpmbMetric100m60min()
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
QCOMPARE(lrint(dp == testPlan.dp.end() ? 0.0 : dp->minimum_gas.mbar / 1000.0), 157l);
// print first ceiling
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar).mm * 0.001);
QVERIFY(dive.dcs[0].events.size() >= 2);
// check first gas change to EAN50 at 21m
struct event *ev = &dive.dcs[0].events[0];
@ -780,7 +780,7 @@ void TestPlan::testVpmbMetricMultiLevelAir()
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
QCOMPARE(lrint(dp == testPlan.dp.end() ? 0.0 : dp->minimum_gas.mbar / 1000.0), 101l);
// print first ceiling
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar).mm * 0.001);
// check benchmark run time of 167 minutes, and known Subsurface runtime of 169 minutes
QVERIFY(compareDecoTime(dive.dcs[0].duration.seconds, 167u * 60u + 20u, 169u * 60u + 20u));
}
@ -806,7 +806,7 @@ void TestPlan::testVpmbMetric100m10min()
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
QCOMPARE(lrint(dp == testPlan.dp.end() ? 0.0 : dp->minimum_gas.mbar / 1000.0), 175l);
// print first ceiling
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar).mm * 0.001);
QVERIFY(dive.dcs[0].events.size() >= 2);
// check first gas change to EAN50 at 21m
struct event *ev = &dive.dcs[0].events[0];
@ -849,7 +849,7 @@ void TestPlan::testVpmbMetricRepeat()
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
QCOMPARE(lrint(dp == testPlan.dp.end() ? 0.0 : dp->minimum_gas.mbar / 1000.0), 61l);
// print first ceiling
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar).mm * 0.001);
// check benchmark run time of 27 minutes, and known Subsurface runtime of 28 minutes
QVERIFY(compareDecoTime(dive.dcs[0].duration.seconds, 27u * 60u + 20u, 27u * 60u + 20u));
@ -867,7 +867,7 @@ void TestPlan::testVpmbMetricRepeat()
dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
QCOMPARE(lrint(dp == testPlan.dp.end() ? 0.0 : dp->minimum_gas.mbar / 1000.0), 85l);
// print first ceiling
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar).mm * 0.001);
QVERIFY(dive.dcs[0].events.size() >= 3);
// check first gas change to 21/35 at 63m
struct event *ev = &dive.dcs[0].events[0];
@ -902,7 +902,7 @@ void TestPlan::testVpmbMetricRepeat()
dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
QCOMPARE(lrint(dp == testPlan.dp.end() ? 0.0 : dp->minimum_gas.mbar / 1000.0), 61l);
// print first ceiling
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar).mm * 0.001);
// check runtime is exactly the same as the first time
int finalDiveRunTimeSeconds = dive.dcs[0].duration.seconds;