[PATCH 1/2] Calculate VPM-B ceiling outside of planner

Rick Walsh rickmwalsh at gmail.com
Sat Oct 24 18:07:29 PDT 2015


Doing VPM-B calculations for dives outside of the planner has not been
possible because real dive data does not record either:
	- reference pressure for the Boyle's law compensation (i.e.
first_stop_pressure), or
	- deco_time for the vpmb_next_gradient function used to do the CVA
calculations

However, we can infer these values to be:
	- first_stop_pressure is the deepest ceiling in the dive
	- deco_time is dive time remaining

These assumptions avoid having to do CVA iterations to calculate the
optimum deco profile.  Instead, we base it off the profile that was
actually dived.  For a planned dive, the resulting ceiling matches the
ceiling displayed in the planner very well.

Signed-off-by: Rick Walsh <rickmwalsh at gmail.com>
---

I think this is good, but Robert and Dirk, please comment.

TODO:
Allow setting prefs.deco_mode in the general preferences, not just the planner

 deco.c    |  4 ++--
 profile.c | 34 ++++++++++++++++++++++++++++++++--
 2 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/deco.c b/deco.c
index 86acc03..506d8b5 100644
--- a/deco.c
+++ b/deco.c
@@ -244,7 +244,7 @@ double tissue_tolerance_calc(const struct dive *dive, double pressure)
 	double lowest_ceiling = 0.0;
 	double tissue_lowest_ceiling[16];
 
-	if (prefs.deco_mode != VPMB || !in_planner()) {
+	if (prefs.deco_mode != VPMB) {
 		for (ci = 0; ci < 16; ci++) {
 			tissue_inertgas_saturation[ci] = tissue_n2_sat[ci] + tissue_he_sat[ci];
 			buehlmann_inertgas_a[ci] = ((buehlmann_N2_a[ci] * tissue_n2_sat[ci]) + (buehlmann_He_a[ci] * tissue_he_sat[ci])) / tissue_inertgas_saturation[ci];
@@ -509,7 +509,7 @@ void add_segment(double pressure, const struct gasmix *gasmix, int period_in_sec
 		tissue_n2_sat[ci] += n2_satmult * pn2_oversat * n2_f;
 		tissue_he_sat[ci] += he_satmult * phe_oversat * he_f;
 	}
-	if(prefs.deco_mode == VPMB && in_planner())
+	if(prefs.deco_mode == VPMB)
 		calc_crushing_pressure(pressure);
 	return;
 }
diff --git a/profile.c b/profile.c
index d39133c..cbeb383 100644
--- a/profile.c
+++ b/profile.c
@@ -28,6 +28,9 @@ unsigned int dc_number = 0;
 static struct plot_data *last_pi_entry_new = NULL;
 void populate_pressure_information(struct dive *, struct divecomputer *, struct plot_info *, int);
 
+extern bool in_planner();
+extern pressure_t first_ceiling_pressure;
+
 #ifdef DEBUG_PI
 /* debugging tool - not normally used */
 static void dump_pi(struct plot_info *pi)
@@ -930,6 +933,8 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
 	int i;
 	double surface_pressure = (dc->surface_pressure.mbar ? dc->surface_pressure.mbar : get_surface_pressure_in_mbar(dive, true)) / 1000.0;
 	int last_ndl_tts_calc_time = 0;
+	int first_ceiling;
+	bool first_ceiling_pressure_set = false;
 	for (i = 1; i < pi->nr; i++) {
 		struct plot_data *entry = pi->entry + i;
 		int j, t0 = (entry - 1)->sec, t1 = entry->sec;
@@ -955,10 +960,35 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
 			if ((t1 - j < time_stepsize) && (j < t1))
 				time_stepsize = t1 - j;
 		}
-		if (t0 == t1)
+		if (t0 == t1) {
 			entry->ceiling = (entry - 1)->ceiling;
-		else
+		} else {
+			/* Keep updating the VPM-B gradients until we start the ascent phase of the dive. */
+			if (prefs.deco_mode == VPMB && !in_planner() && !first_ceiling_pressure_set) {
+				nuclear_regeneration(t0);
+				vpmb_start_gradient();
+				/* Instead of doing CVA iterations (as in the planner), we can just take deco_time as dive time remaining */
+				vpmb_next_gradient(pi->maxtime - t0, surface_pressure / 1000.0);
+			}
 			entry->ceiling = deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(entry->depth, dive)), surface_pressure, dive, !prefs.calcceiling3m);
+			/* If using VPM-B outside the planner, take first_ceiling_pressure as the deepest ceiling */
+			if (prefs.deco_mode == VPMB && !in_planner()) {
+				/* if first_ceiling_pressure hasn't been set yet, and this entry's ceiling is shallower
+				 * than the previous entry's, then locally the deeperst ceiling is previous entry's ceiling */
+				if (first_ceiling_pressure_set == false) {
+					if (entry->ceiling < (entry - 1)->ceiling) {
+						first_ceiling = (entry - 1)->ceiling;
+						first_ceiling_pressure.mbar = depth_to_mbar(first_ceiling, dive);
+						first_ceiling_pressure_set = true;
+					}
+				} else {
+					/* if this entry's ceiling is deeper than the currently set first_ceiling_pressure
+					 * then we unset first_ceiling_pressure so that the deepest ceiling with be found */
+					if (entry->ceiling > first_ceiling)
+						first_ceiling_pressure_set = false;
+				}
+			}
+		}
 		for (j = 0; j < 16; j++) {
 			double m_value = buehlmann_inertgas_a[j] + entry->ambpressure / buehlmann_inertgas_b[j];
 			entry->ceilings[j] = deco_allowed_depth(tolerated_by_tissue[j], surface_pressure, dive, 1);
-- 
2.4.3



More information about the subsurface mailing list