[PATCH 2/2] Correctly calculate SAC rate in the presense of surface events

Linus Torvalds torvalds at linux-foundation.org
Sun Feb 24 10:59:07 PST 2013


From: Linus Torvalds <torvalds at linux-foundation.org>
Date: Sun, 24 Feb 2013 10:50:18 -0800
Subject: [PATCH 2/2] Correctly calculate SAC rate in the presense of surface events

This assumes that you are not breathing your cylinders while at the
surface, which may or may not be correct, but is usually the right
thing.  Regardless, we're better off giving a conservative (higher) SAC
rate estimate for a diver that breathes his cylinder at the surface too
than giving an artificially low one because the diver ended up using his
snorkel and we didn't take that into account.

NOTE! This basically calculates a better duration and average depth than
the ones we end up showing in the dive list.  Maybe we should actually
show this "no-surface-time" duration and average depth instead of the
ones we do show?

That's a separate question, though.

Added a test-case for the surface case to the sac-test.xml dives.

Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---

Ok, the code makes sense and gets the right answer for the new test-case. 

What do people think we should show for the dive duration field in the 
dive list for that last sac-test dive? We spent 30 minutes on the dive 
end-to-end, but only 25 minutes actually under water. Is it a 30-minute 
dive, or a 25-minute one? Is the average depth 10m (which is what we use 
for SAC calculations) or 8.33m (which is the average over the whole 30 
minutes)?

 divelist.c         | 65 ++++++++++++++++++++++++++++++++++++++----------------
 dives/sac-test.xml | 19 ++++++++++++++++
 2 files changed, 65 insertions(+), 19 deletions(-)

diff --git a/divelist.c b/divelist.c
index 143f4d43c8f4..501cf0487b60 100644
--- a/divelist.c
+++ b/divelist.c
@@ -719,38 +719,65 @@ static double calculate_airuse(struct dive *dive)
 	return airuse;
 }
 
+/*
+ * Calculate how long we were actually under water, and the average
+ * depth while under water.
+ *
+ * This ignores any surface time in the middle of the dive.
+ */
+static int calculate_duration(struct dive *dive, struct divecomputer *dc, int *meandepth)
+{
+	int duration, i;
+	int lasttime, lastdepth, depthtime;
+
+	duration = 0;
+	lasttime = 0;
+	lastdepth = 0;
+	depthtime = 0;
+	for (i = 0; i < dc->samples; i++) {
+		struct sample *sample = dc->sample + i;
+		int time = sample->time.seconds;
+		int depth = sample->depth.mm;
+
+		/* We ignore segments at the surface */
+		if (depth > SURFACE_THRESHOLD || lastdepth > SURFACE_THRESHOLD) {
+			duration += time - lasttime;
+			depthtime += (time - lasttime)*(depth+lastdepth)/2;
+		}
+		lastdepth = depth;
+		lasttime = time;
+	}
+	if (duration) {
+		if (meandepth)
+			*meandepth = depthtime / duration;
+		return duration;
+	}
+
+	/* No samples? */
+	if (meandepth)
+		*meandepth = dive->meandepth.mm;
+	return dive->duration.seconds;
+}
+
 /* this only uses the first divecomputer to calculate the SAC rate */
 static int calculate_sac(struct dive *dive)
 {
 	struct divecomputer *dc = &dive->dc;
 	double airuse, pressure, sac;
-	int duration, i;
+	int duration, meandepth;
 
 	airuse = calculate_airuse(dive);
 	if (!airuse)
 		return 0;
-	duration = dc->duration.seconds;
-	if (!duration)
-		return 0;
+
+	duration = calculate_duration(dive, dc, &meandepth);
 
 	/* find and eliminate long surface intervals */
+	if (!duration)
+		return 0;
 
-	for (i = 0; i < dc->samples; i++) {
-		if (dc->sample[i].depth.mm < 100) { /* less than 10cm */
-			int end = i + 1;
-			while (end < dc->samples && dc->sample[end].depth.mm < 100)
-				end++;
-			/* we only want the actual surface time during a dive */
-			if (end < dc->samples) {
-				end--;
-				duration -= dc->sample[end].time.seconds -
-						dc->sample[i].time.seconds;
-				i = end + 1;
-			}
-		}
-	}
 	/* Mean pressure in ATM (SAC calculations are in atm*l/min) */
-	pressure = (double) depth_to_mbar(dc->meandepth.mm, dive) / SURFACE_PRESSURE;
+	pressure = (double) depth_to_mbar(meandepth, dive) / SURFACE_PRESSURE;
 	sac = airuse / pressure * 60 / duration;
 
 	/* milliliters per minute.. */
diff --git a/dives/sac-test.xml b/dives/sac-test.xml
index b5f0149bbe67..14ee3f17b964 100644
--- a/dives/sac-test.xml
+++ b/dives/sac-test.xml
@@ -46,5 +46,24 @@ We have exactly 100 ATM of gas in 15l of cylinder, average 20m for 25min</notes>
   <sample time='25:00 min' depth='0.0 m' />
   </divecomputer>
 </dive>
+<dive number='4' date='2013-02-24' time='12:26:04' duration='25:00 min'>
+  <location>SAC test dive 3</location>
+  <notes>SAC should be 20l/min (0.7063 cuft/min)
+This adds a 5-minute surface time to the middle of the dive.
+We have exactly 100 ATM of gas in 15l of cylinder, average 20m for 25min</notes>
+  <cylinder size='10 l' description='10l' start='202.6 bar' end='101.3 bar' />
+  <cylinder size='5 l' description='10l' start='202.6 bar' end='101.3 bar' />
+  <divecomputer>
+  <event time='22:00 min' name='gaschange' />
+  <depth max='20.0 m' mean='10.0 m' />
+  <sample time='0:00 min' depth='0.0 m' />
+  <sample time='5:00 min' depth='20.0 m' />
+  <sample time='10:00 min' depth='40.0 m' />
+  <sample time='15:00 min' depth='0.0 m' />
+  <sample time='20:00 min' depth='0.0 m' />
+  <sample time='25:00 min' depth='40.0 m' />
+  <sample time='30:00 min' depth='0.0 m' />
+  </divecomputer>
+</dive>
 </dives>
 </divelog>
-- 
1.8.2.rc0.16.g20a599e



More information about the subsurface mailing list