diff options
Diffstat (limited to 'core/profile.c')
-rw-r--r-- | core/profile.c | 98 |
1 files changed, 52 insertions, 46 deletions
diff --git a/core/profile.c b/core/profile.c index 697ebe1c0..5a88e20c6 100644 --- a/core/profile.c +++ b/core/profile.c @@ -903,7 +903,7 @@ static void setup_gas_sensor_pressure(struct dive *dive, struct divecomputer *dc #ifndef SUBSURFACE_MOBILE /* calculate DECO STOP / TTS / NDL */ -static void calculate_ndl_tts(struct dive *dive, struct plot_data *entry, struct gasmix *gasmix, double surface_pressure) +static void calculate_ndl_tts(struct deco_state *ds, struct dive *dive, struct plot_data *entry, struct gasmix *gasmix, double surface_pressure) { /* FIXME: This should be configurable */ /* ascent speed up to first deco stop */ @@ -916,8 +916,9 @@ static void calculate_ndl_tts(struct dive *dive, struct plot_data *entry, struct const int time_stepsize = 60; const int deco_stepsize = 3000; /* at what depth is the current deco-step? */ - int next_stop = ROUND_UP(deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(entry->depth, dive)), - surface_pressure, dive, 1), deco_stepsize); + int next_stop = ROUND_UP(deco_allowed_depth( + tissue_tolerance_calc(ds, dive, depth_to_bar(entry->depth, dive)), + surface_pressure, dive, 1), deco_stepsize); int ascent_depth = entry->depth; /* 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 */ @@ -931,10 +932,13 @@ static void calculate_ndl_tts(struct dive *dive, struct plot_data *entry, struct return; } /* 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(dive, depth_to_bar(entry->depth, dive)), surface_pressure, dive, 1) <= 0) { + while (entry->ndl_calc < MAX_PROFILE_DECO && + deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(entry->depth, dive)), + surface_pressure, dive, 1) <= 0 + ) { entry->ndl_calc += time_stepsize; - add_segment(depth_to_bar(entry->depth, dive), - gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.bottomsac); + add_segment(ds, depth_to_bar(entry->depth, dive), + gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.bottomsac); } /* we don't need to calculate anything else */ return; @@ -945,9 +949,10 @@ static void calculate_ndl_tts(struct dive *dive, struct plot_data *entry, struct /* Add segments for movement to stopdepth */ for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_step, entry->tts_calc += ascent_s_per_step) { - add_segment(depth_to_bar(ascent_depth, dive), + add_segment(ds, depth_to_bar(ascent_depth, dive), gasmix, ascent_s_per_step, entry->o2pressure.mbar, dive, prefs.decosac); - next_stop = ROUND_UP(deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(ascent_depth, dive)), surface_pressure, dive, 1), deco_stepsize); + next_stop = ROUND_UP(deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(ascent_depth, dive)), + surface_pressure, dive, 1), deco_stepsize); } ascent_depth = next_stop; @@ -965,13 +970,13 @@ static void calculate_ndl_tts(struct dive *dive, struct plot_data *entry, struct entry->tts_calc += time_stepsize; if (entry->tts_calc > MAX_PROFILE_DECO) break; - add_segment(depth_to_bar(ascent_depth, dive), + add_segment(ds, depth_to_bar(ascent_depth, dive), gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.decosac); - if (deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(ascent_depth,dive)), surface_pressure, dive, 1) <= next_stop) { + if (deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(ascent_depth,dive)), surface_pressure, dive, 1) <= next_stop) { /* move to the next stop and add the travel between stops */ for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_deco_step, entry->tts_calc += ascent_s_per_deco_step) - add_segment(depth_to_bar(ascent_depth, dive), + add_segment(ds, depth_to_bar(ascent_depth, dive), gasmix, ascent_s_per_deco_step, entry->o2pressure.mbar, dive, prefs.decosac); ascent_depth = next_stop; next_stop -= deco_stepsize; @@ -981,26 +986,26 @@ static void calculate_ndl_tts(struct dive *dive, struct plot_data *entry, struct /* Let's try to do some deco calculations. */ -void calculate_deco_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi, bool print_mode) +void calculate_deco_information(struct deco_state *ds, struct dive *dive, struct divecomputer *dc, struct plot_info *pi, bool print_mode) { int i, count_iteration = 0; double surface_pressure = (dc->surface_pressure.mbar ? dc->surface_pressure.mbar : get_surface_pressure_in_mbar(dive, true)) / 1000.0; bool first_iteration = true; int prev_deco_time = 10000000, time_deep_ceiling = 0; if (!in_planner()) - deco_state->deco_time = 0; + ds->deco_time = 0; struct deco_state *cache_data_initial = NULL; lock_planner(); /* For VPM-B outside the planner, cache the initial deco state for CVA iterations */ if (decoMode() == VPMB) { - cache_deco_state(&cache_data_initial); + cache_deco_state(ds, &cache_data_initial); } /* For VPM-B outside the planner, iterate until deco time converges (usually one or two iterations after the initial) * Set maximum number of iterations to 10 just in case */ - while ((abs(prev_deco_time - deco_state->deco_time) >= 30) && (count_iteration < 10)) { + 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, final_tts = 0 , time_clear_ceiling = 0; if (decoMode() == VPMB) - deco_state->first_ceiling_pressure.mbar = depth_to_mbar(first_ceiling, dive); + ds->first_ceiling_pressure.mbar = depth_to_mbar(first_ceiling, dive); struct gasmix *gasmix = NULL; struct event *ev = NULL; @@ -1012,7 +1017,7 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru gasmix = get_gasmix(dive, dc, t1, &ev, gasmix); entry->ambpressure = depth_to_bar(entry->depth, dive); - entry->gfline = get_gf(entry->ambpressure, dive) * (100.0 - AMB_PERCENTAGE) + AMB_PERCENTAGE; + entry->gfline = get_gf(ds, entry->ambpressure, dive) * (100.0 - AMB_PERCENTAGE) + AMB_PERCENTAGE; if (t0 > t1) { fprintf(stderr, "non-monotonous dive stamps %d %d\n", t0, t1); int xchg = t1; @@ -1023,7 +1028,7 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru time_stepsize = t1 - t0; for (j = t0 + time_stepsize; j <= t1; j += time_stepsize) { int depth = interpolate(entry[-1].depth, entry[0].depth, j - t0, t1 - t0); - add_segment(depth_to_bar(depth, dive), + add_segment(ds, depth_to_bar(depth, dive), gasmix, time_stepsize, entry->o2pressure.mbar, dive, entry->sac); if ((t1 - j < time_stepsize) && (j < t1)) time_stepsize = t1 - j; @@ -1033,15 +1038,15 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru } else { /* Keep updating the VPM-B gradients until the start of the ascent phase of the dive. */ if (decoMode() == VPMB && last_ceiling >= first_ceiling && first_iteration == true) { - nuclear_regeneration(t1); - vpmb_start_gradient(); + nuclear_regeneration(ds, t1); + vpmb_start_gradient(ds); /* For CVA iterations, calculate next gradient */ if (!first_iteration || in_planner()) - vpmb_next_gradient(deco_state->deco_time, surface_pressure / 1000.0); + vpmb_next_gradient(ds, ds->deco_time, surface_pressure / 1000.0); } - entry->ceiling = deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(entry->depth, dive)), surface_pressure, dive, !prefs.calcceiling3m); + entry->ceiling = deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(entry->depth, dive)), surface_pressure, dive, !prefs.calcceiling3m); if (prefs.calcceiling3m) - current_ceiling = deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(entry->depth, dive)), surface_pressure, dive, true); + current_ceiling = deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(entry->depth, dive)), surface_pressure, dive, true); else current_ceiling = entry->ceiling; last_ceiling = current_ceiling; @@ -1051,16 +1056,16 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru (time_deep_ceiling == t0 && entry->depth == (entry - 1)->depth)) { time_deep_ceiling = t1; first_ceiling = current_ceiling; - deco_state->first_ceiling_pressure.mbar = depth_to_mbar(first_ceiling, dive); + ds->first_ceiling_pressure.mbar = depth_to_mbar(first_ceiling, dive); if (first_iteration) { - nuclear_regeneration(t1); - vpmb_start_gradient(); + nuclear_regeneration(ds, t1); + vpmb_start_gradient(ds); /* For CVA calculations, deco time = dive time remaining is a good guess, but we want to over-estimate deco_time for the first iteration so it converges correctly, so add 30min*/ if (!in_planner()) - deco_state->deco_time = pi->maxtime - t1 + 1800; - vpmb_next_gradient(deco_state->deco_time, surface_pressure / 1000.0); + ds->deco_time = pi->maxtime - t1 + 1800; + vpmb_next_gradient(ds, ds->deco_time, surface_pressure / 1000.0); } } // Use the point where the ceiling clears as the end of deco phase for CVA calculations @@ -1071,11 +1076,11 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru } } for (j = 0; j < 16; j++) { - double m_value = deco_state->buehlmann_inertgas_a[j] + entry->ambpressure / deco_state->buehlmann_inertgas_b[j]; - entry->ceilings[j] = deco_allowed_depth(deco_state->tolerated_by_tissue[j], surface_pressure, dive, 1); - entry->percentages[j] = deco_state->tissue_inertgas_saturation[j] < entry->ambpressure ? - lrint(deco_state->tissue_inertgas_saturation[j] / entry->ambpressure * AMB_PERCENTAGE) : - lrint(AMB_PERCENTAGE + (deco_state->tissue_inertgas_saturation[j] - entry->ambpressure) / (m_value - entry->ambpressure) * (100.0 - AMB_PERCENTAGE)); + double m_value = ds->buehlmann_inertgas_a[j] + entry->ambpressure / ds->buehlmann_inertgas_b[j]; + entry->ceilings[j] = deco_allowed_depth(ds->tolerated_by_tissue[j], surface_pressure, dive, 1); + entry->percentages[j] = ds->tissue_inertgas_saturation[j] < entry->ambpressure ? + lrint(ds->tissue_inertgas_saturation[j] / entry->ambpressure * AMB_PERCENTAGE) : + lrint(AMB_PERCENTAGE + (ds->tissue_inertgas_saturation[j] - entry->ambpressure) / (m_value - entry->ambpressure) * (100.0 - AMB_PERCENTAGE)); } /* should we do more calculations? @@ -1097,39 +1102,39 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru /* We are going to mess up deco state, so store it for later restore */ struct deco_state *cache_data = NULL; - cache_deco_state(&cache_data); - calculate_ndl_tts(dive, entry, gasmix, surface_pressure); + cache_deco_state(ds, &cache_data); + calculate_ndl_tts(ds, dive, entry, gasmix, surface_pressure); if (decoMode() == VPMB && !in_planner() && i == pi->nr - 1) final_tts = entry->tts_calc; /* Restore "real" deco state for next real time step */ - restore_deco_state(cache_data, decoMode() == VPMB); + restore_deco_state(cache_data, ds, decoMode() == VPMB); free(cache_data); } } if (decoMode() == VPMB && !in_planner()) { int this_deco_time; - prev_deco_time = deco_state->deco_time; + prev_deco_time = ds->deco_time; // Do we need to update deco_time? if (final_tts > 0) - deco_state->deco_time = last_ndl_tts_calc_time + final_tts - time_deep_ceiling; + ds->deco_time = last_ndl_tts_calc_time + final_tts - time_deep_ceiling; else if (time_clear_ceiling > 0) /* Consistent with planner, deco_time ends after ascending (20s @9m/min from 3m) * at end of whole minute after clearing ceiling. The deepest ceiling when planning a dive * comes typically 10-60s after the end of the bottom time, so add 20s to the calculated * deco time. */ - deco_state->deco_time = ROUND_UP(time_clear_ceiling - time_deep_ceiling + 20, 60) + 20; - vpmb_next_gradient(deco_state->deco_time, surface_pressure / 1000.0); + ds->deco_time = ROUND_UP(time_clear_ceiling - time_deep_ceiling + 20, 60) + 20; + vpmb_next_gradient(ds, ds->deco_time, surface_pressure / 1000.0); final_tts = 0; last_ndl_tts_calc_time = 0; first_ceiling = 0; first_iteration = false; count_iteration ++; - this_deco_time = deco_state->deco_time; - restore_deco_state(cache_data_initial, true); - deco_state->deco_time = this_deco_time; + this_deco_time = ds->deco_time; + restore_deco_state(cache_data_initial, ds, true); + ds->deco_time = this_deco_time; } else { // With Buhlmann iterating isn't needed. This makes the while condition false. - prev_deco_time = deco_state->deco_time = 0; + prev_deco_time = ds->deco_time = 0; } } free(cache_data_initial); @@ -1299,7 +1304,8 @@ void create_plot_info_new(struct dive *dive, struct divecomputer *dc, struct plo { int o2, he, o2max; #ifndef SUBSURFACE_MOBILE - init_decompression(dive); + struct deco_state plot_deco_state; + init_decompression(&plot_deco_state, dive); #endif /* Create the new plot data */ free((void *)last_pi_entry_new); @@ -1327,7 +1333,7 @@ void create_plot_info_new(struct dive *dive, struct divecomputer *dc, struct plo fill_o2_values(dive, dc, pi); /* .. and insert the O2 sensor data having 0 values. */ calculate_sac(dive, dc, pi); /* Calculate sac */ #ifndef SUBSURFACE_MOBILE - calculate_deco_information(dive, dc, pi, false); /* and ceiling information, using gradient factor values in Preferences) */ + calculate_deco_information(&plot_deco_state, dive, dc, pi, false); /* and ceiling information, using gradient factor values in Preferences) */ #endif calculate_gas_information_new(dive, dc, pi); /* Calculate gas partial pressures */ |