This patch makes deco_allowed_depth() work both for Buehlmann as well as
VPM-B (as long as the VPM-B internal variable total_gradient[] is valid).
As a bonus, in VPM-B mode, in the planner, the ceilings are VPM-B ceilings
and not Buehlmann GF.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
V-Planner reccomends smaller values for the VPM with the Boyles
compensation. Also missing units comments were added.
Signed-off-by: Jan Darowski <jan.darowski@gmail.com>
Now, we calculate the volume of free gas not only based on the deco
time but also time on the surface, needed for the full desaturation.
Signed-off-by: Jan Darowski <jan.darowski@gmail.com>
This is a very basic implementation that uses bin search for solving the cubic.
It's not called anywhere at this stage, needs to be changed to analytic solution.
Signed-off-by: Jan Darowski <jan.darowski@gmail.com>
Include units in the comments of VPM structure definition. We should
confirm the units surface_tension_gamma and skin_compression_gammaC.
Signed-off-by: Rick Walsh <rickmwalsh@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Adopt the same critical radii used by Eric Baker's original VPM Fortran
code and V-Planner.
Standard critical volume lambda = 7500 fsw-min (numerous sources). We need
to convert it properly.
λ = 7500 fsw-min
= 7500/33 = 227.2727 ata-min
= 227.2727 * 1.01325 bar-min
= 230.284 bar-min
Signed-off-by: Rick Walsh <rickmwalsh@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
It improves (increases) gradients for all the compartments,
so more free gas can be created in the divers body. Next gradients
will converge, so the volume won't exceed the safe limit, indicated
by the crit_volume_lambda parameter.
Function takes time of the last deco in seconds.
Requires vpmb_start_gradient() to be run before.
Signed-off-by: Jan Darowski <jan.darowski@gmail.com>
Check during the trial_ascent() if existing pressure gradient is
smaller than previously calculated max gradient. If not, ascent
is impossible from the vpm-b's point of view.
Signed-off-by: Jan Darowski <jan.darowski@gmail.com>
Calculate the max difference between tissue saturation and ambient
pressure that can be accepted during the ascent.
Partial results are kept for later improving in next CVA iterations
Signed-off-by: Jan Darowski <jan.darowski@gmail.com>
This function calculates the size of nuclei at the end of deco,
then simulates their regeneration, to the moment before the deco.
This is redundant as nuclear regeneration is a very slow process.
Function should be called with time in seconds, just before the ascent.
Signed-off-by: Jan Darowski <jan.darowski@gmail.com>
According to mathematica
In[4]:= f[x_] := x^3 - b x^2 - c
In[18]:= Solve[f[x] == 0, x]
Out[18]= {{x ->
1/3 (b + (
2^(1/3) b^2)/(2 b^3 + 27 c + 3 Sqrt[3] Sqrt[4 b^3 c + 27 c^2])^(
1/3) + (2 b^3 + 27 c + 3 Sqrt[3] Sqrt[4 b^3 c + 27 c^2])^(1/3)/
2^(1/3))}, {x ->
b/3 - ((1 + I Sqrt[3]) b^2)/(
3 2^(2/3) (2 b^3 + 27 c + 3 Sqrt[3] Sqrt[4 b^3 c + 27 c^2])^(
1/3)) - ((1 - I Sqrt[3]) (2 b^3 + 27 c +
3 Sqrt[3] Sqrt[4 b^3 c + 27 c^2])^(1/3))/(6 2^(1/3))}, {x ->
b/3 - ((1 - I Sqrt[3]) b^2)/(
3 2^(2/3) (2 b^3 + 27 c + 3 Sqrt[3] Sqrt[4 b^3 c + 27 c^2])^(
1/3)) - ((1 + I Sqrt[3]) (2 b^3 + 27 c +
3 Sqrt[3] Sqrt[4 b^3 c + 27 c^2])^(1/3))/(6 2^(1/3))}}
For the values of b and c encounterd in the algorithm, the first solution is in fact the
only real one that we are after. So we can use this solution instead of doing a binary
search for the root of the cubic.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Jan Darowski <jan.darowski@gmail.com>
Add new structures holding vpm-b state.
Add function calculating current crushing pressure.
Call it from add_segment() on every ambient pressure change.
It determines what pressure acts on nuclei during the descent
and thus their size at the beggining of the deco.
Signed-off-by: Jan Darowski <jan.darowski@gmail.com>
This function calculates the pressure inside the nucleon
during the impermeable phase.
In the original code, Newton's method is used, for simplicity, we
use binary search for finding cubic equations root.
Signed-off-by: Jan Darowski <jan.darowski@gmail.com>
Created vpmb_config structure based on buehlmann_config.
Set it's default values to ones taken from the existing C implementation.
Signed-off-by: Jan Darowski <jan.darowski@gmail.com>
The ratio between SAC and oxygen metabolism rate can be assumed constant
but not the metabolism rate. So we better base our calculation on the ratio
that uses the SAC from the preferences as that pairs well with the O2
consumption from the preferences.
Hence we ran remove the sac parameter from fill_pressures().
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Calculations for passive semi-closed rebreathers are pretty much like OC
except the pO2 is lower bey a certain (SAC dependent) factor. This patch
introduces the corresponding calculations in case dctype == PSCR which is
so far never set and there is currently no UI for these calculations. As
pO2 is SAC dependent it takes a certain attempt at getting it and drops to
defaults from the prefs otherwise.
As there is no UI at this point and I also don't have any dives, this has
not received much testing, yet, but it compiles. At least.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In the transition to the partial pressure helper function,
the water vapor component of the breathing gas had been dropped.
This had a significant effect on deco times for deep dives.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This patch responds to the side effects that the CCR code has had with
respect to ceilings in OC dives and dive plans. Dive ceilings are now
calculated correctly again.
The following were performed:
1) remove the oxygen sensor and setpoint fields from the gas_pressures
structure.
2) Re-insert setpoint and oxygen sensor fields in the plot_data structure.
3) Remove the algorithm that reads the o2 sensor data and calculates the
pressures.po2 value from function fill_pressures() in dive.c and save
it as a separate function calc_ccr_po2() in profile.c.
4) Activate calc_ccr_po2 from function fill_pressures() in profile.c.
5) Move the relative position of the call to fill_pressures() within the
function create_polt_info_new() in profile.c.
Signed-off-by: willem ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This patch does three things:
1) A new function fill_o2_values() is added to profile.c. This
fills all oxygen sesnsor and setpoint values that have been
zeroed before in order to save space in the dive log. This
recreates the full set of sensor values obtained from the
original CCR xml log file.
2) Function fill_o2_values() is activated in function create_
plot_info_new() in profile.c
3) The calling parameters to function fill_pressures() in dive.c
are changed. The last parameter is now a pointer to a structure
of divecomputer. This will be needed in the last patch of the
present series of three patches.
[Dirk Hohndel: minor whitespace cleanup]
Signed-off-by: willem ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This adds a toolbox icon to turn on a tissue plot inspired by the bar
graph of the Sherwater Petrel,
It shows the inert gas partial pressures for individual compartments. If
they are below the ambient pressure (grey line) they are shown in units of
the ambient pressure, if they are above, the excess is shown as a
percentage of the allowed overpressure for plain Buehlmann. So it has the
same units as a gradient factor. Thus also the a gradient factor line (for
the current depth) is shown.
The different tissues get different colors, greener for the faster ones and bluer
for the slower ones.
Positioning and on/off icon action still need some tender loving care.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This patch introduces a new structure holding partial pressures (doubles in bar) for
all three gases and a helper function to compute them from gasmix (which holds fractions)
and ambient pressure. Currentlty this works for OC and CCR, to be extended later to PSCR.
Currently the dive_comp_type argument is unused.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In a dive, when you choose a very low GFlow (like 5 or 9) and a trimix
with quite some He (12/48 in the example) and descend fast, the ceiling
seems to do strange things in the first minutes of the dive (very very
deep for example or jumping around).
To understand what is going on we have to recall what gradient factors do
in detail: Plain Buehlmann gives you for each tissue a maximal inert gas
pressure that is a straight line when plotted against the ambient
pressure. So for each depth (=ambient pressure) there is a maximally
allowed over-pressure.
The idea of gradient factors is that one does not use all the possible
over-pressure that Buehlmann gives us but only a depth dependent fraction.
GFhigh is the fraction of the possible over-pressure at the surface while
GFlow is the fraction at the first deco stop. In between, the fraction is
linearly interpolated. As the Buehlmann over-pressure is increasing with
depth and typically also the allowed overpressure after applications of
gradient factors increases with depth or said differently: the tissue
saturation has to be lower if the diver wants to ascent.
The main problem is: What is the first stop (where to apply GFlow)? In a
planned dive, we could take the first deco stop, but in a real dive from a
dive computer download it is impossible to say what constitutes a stop and
what is only a slow ascent?
What I have used so far is not exactly the first stop but rather the first
theoretical stop: During all of the dive, I have calculated the ceiling
under the assumption that GFlow applies everywhere (and not just at a
single depth). The deepest of these ceilings I have used as the “first
stop depth”, the depth at which GFlow applies.
Even more, I only wanted to use the information that a diver has during
the dive, so I actually only considered the ceilings in the past (and not
in the future of a given sample).
But this brings with it the problem that early in the dive, in particular
during the descent the lowest ceiling so far is very shallow (as not much
gas has built up in the body so far).
This problem now interferes with a second one: If at the start of the dive
when the all compartments have 790mbar N2 the diver starts breathing a
He-heavy mix (like 12/48) and descents fast the He builds up in the
tissues before the N2 can diffuse out. So right at the start, we already
encounter high tissue loadings.
If now we have a large difference between GFhigh and GFlow but they apply
at very similar depth (the surface and a very shallow depth of the deepest
ceiling (which for a non-decompression dive would be theoretically at
negative depth) so far) it can happen that the linear interpolation as
opposite slope then in the typical case above: The allowed over-pressure
is degreasing with depth, shallower depth do not require lower gas loading
in the tissue (i.e. can be reached after further off-gasing) but but
tolerate higher loadings. In that situation the ceiling disappears (or is
rather a floor).
So far, I got rid of that problem, by stating that the minimum depth for
GFlow was 20m (after all, GFlow is about deep stops, so it should better
not be too shallow). Now the dive reported in ticket #549 takes values to
an extreme in such away that 20m (which is determined by
buehlmann_config.gf_low_position_min in deco.c) was not enough to prevent
this inversion problem (or in a milder form that the interpolation of
gradient factors is in fact an extrapolation with quite extreme values).
This patch that gets rid of the problem for the dive described above but
still it is possible to find (more extreme) parameter choices that lead to
non-realistic ceilings.
Let me close by pointing out that all this is only about the descent, as
it is about too shallow depth for GFlow. So no real deco (i.e. later part
of the dive) is inflicted. This is only about a theoretical ceiling
displayed possibly in the first minutes of a dive. So this is more an
aesthetically than a practical problem.
Fixes#549
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Lets just use pO₂ instead of PO2, ppO2, ppO₂, PO₂.
They all mean the same, but it's better to be
consistent
Signed-off-by: Henrik Brautaset Aronsen <subsurface@henrik.synth.no>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
I know everyone will hate it.
Go ahead. Complain. Call me names.
At least now things are consistent and reproducible.
If you want changes, have your complaint come with a patch to
scripts/whitespace.pl so that we can automate it.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This re-organizes the saturation calculations to be in my opinion
clearer: we used to have the "one second" case completely separate from
the "generic interval" case, and this undoes that.
It *does* keep the special static cache for the one-second buehlmann
factors, and expands that with a *dynamic* cache for each tissue index
that contains the previous value of the buehlmann factor for a
particular duration.
The point is, usually we end up using some fixed duration, so the cache
hit ratio is quite high. And doing a memory load from a cache is *much*
faster than calculating exponentials.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Earlier we converted the C++ code to using true/false, and this converts
the C code to using the same style.
We already depended on stdbool.h in subsurfacestartup.[ch], and we build
with -std=gnu99 so nobody could build subsurface without a c99 compiler.
[Dirk Hohndel: small change suggested by Thiago Macieira: don't include
stdbool.h for C++]
Signed-off-by: Anton Lundin <glance@acc.umu.se>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
These adds some ifdef's around some debug functions to disable them when
not using them.
Signed-off-by: Anton Lundin <glance@acc.umu.se>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
I always worry if these are worth following up on - but these seem pretty
clear and obvious to me. As far as the planner is concerned, depth is
unsigned.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
- remove the build flags and libraries from the Makefile / Configure.mk
- remove the glib types (gboolean, gchar, gint64, gint)
- comment out / hack around gettext
- replace the glib file helper functions
- replace g_ascii_strtod
- replace g_build_filename
- use environment variables instead of g_get_home_dir() & g_get_user_name()
- comment out GPS string parsing (uses glib utf8 macros)
This needs massive cleanup, but it's a snapshot of what I have right now, in
case people want to look at it.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
I think that displaying tissue loadings either as pressure or as
percentages is not very intuitive but that it makes much more sense when
translated to ceiling depths.
This change enables just that for the 16 tissues in our calculated ceiling
and visualizes this in the profile graph.
There is a checkbox in the preferences to turn this on. If enabled, all
tissues having non-trivial ceilings are also shown in the info box.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The biggest problem here was that bool has different sizes in C and C++
code. So using this in a structure shared between the two sides wasn't a
smart idea.
Instead I went with 'short', but that caused problems with Qt being to
smart for its own good and not doing the right thing when dealing with
'boolean' settings and a short value. This may be something in the way I
implemented things (as I doubt that something this fundamental would be
broken) but the workaround implemented here (explicitly using 0 or 1
depending on the value of the boolean) seems to work.
I also decided to get rid of the confusion of where gflow/gfhigh are
floating point (0..1) and when they are integers (0..100). We now use
integers anywhere outside of deco.c.
I also applied some serious spelling corrections to the preferences
dialog's ui file.
Finally, this enables the code that selects which partial pressure graph
to show.
Still to do: font size, metric/imperial logic
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
They do the "02=0 means air" thing autmatically, and make for less
typing. So use them more widely in places that looked up the o2 and he
permille values of a gasmix.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
There are two ways to look at surface pressure. One is to say "what was
the surface pressure during that dive?" - in that case we now return an
average over the pressure reported by the different divecomputers (or the
standard 1013mbar if none reported any).
Or you want to do specific calculations for a specific divecomputer - in
which case we access only the pressure reported by THAT divecomputer, if
present (and fall back to the previous case, otherwise).
We still have lots of places in Subsurface that only act on the first
divecomputer. As a side effect of this change we now make this more
obvious as we in those cases pass a pointer to the first divecomputer
explicitly to the calculations.
Either way, this commit should prevent us from ever mistakenly basing our
calculations on a surface pressure of 0 (which is the initial bug in
deco.c that triggered all this).
Similar changes need to be made for other elements that we currently only
use from the first divecomputer, i.e., salinity.
Reported-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
It wasn't really used. The only reader of that array was the same thing
that wrote the entry, so instead of storing it in the array (and never
using it ever after), just use the calculation directly, and remove the
array entirely.
This makes it much easier to see that the gradient factors are not used
for any long-term state. We use them only for the pressure tolerance
calculations at that particular point, and there is no "history"
associated with it.
This matters mainly because it means that we can do all the deco
initialization and setup without worrying about exactly which gradient
factors we will use. And we can use different gradient factors for
diving and planning and no-fly calculations without the GF choice
affecting the tissue state.
Acked-by: Robert C. Helling <helling@lmu.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We'll want to use a 'static const' gasmix for the upcoming no-fly-time
code, so prepare for it by just marking the read-only gasmix argument as
'const'.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This moves some double/floating handling for po2 to plain integer. There
are still non int values around (also for phe and po2) in the plot area.
Signed-off-by: Jan Schubert <Jan.Schubert@GMX.li>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Mostly coding style and whitespace changes plus making lots of functions
static that have no need to be extern. This also helped find a bit of code
that is actually no longer used.
This should have absolutely no functional impact - all changes should be
purely cosmetic. But it removes a bunch of lines of code and makes the
rest easier to read.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This moves the fields 'duration', 'surfacetime', 'maxdepth',
'meandepth', 'airtemp', 'watertemp', 'salinity' and 'surface_pressure'
to the per-divecomputer data structure. They are filled in by the dive
computer, and normally not edited.
NOTE! All actual *use* of this data was then changed from dive->field to
dive->dc.field programmatically with a shell-script and sed, and the
result then edited for details. So while the XML save and restore code
has been updated, all the displaying etc will currently always just show
the first dive computer entry.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This patch centralizes the definition for surface pressure, oxygen in
air, (re)defines all such values as plain integers and adapts calculations.
It eliminates 11 (!) occurrences of definitions for surface pressure and
also a few for oxygen in air.
It also rewrites the calculation for EAD, END and EADD using the new
definitons, harmonizing it for OC and CC and fixes a bug for EADD OC
calculation.
And finally it removes the unneeded variable entry_ead in gtk-gui.c.
Jan
Signed-off-by: Jan Schubert <Jan.Schubert@GMX.li>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
- MOD: Maximum Operation Depth based on a configurable limit
- EAD: Equivalent Air Depth considering N2 and (!) O2 narcotic
- END: Equivalent Nitrogen (Narcotic) Depth considering just N2 narcotic
(ignoring O2)
- EADD: Equivalent Air Density Depth
Please note that some people and even diving organisations have opposite
definitions for EAD and END. Considering A stands for Air, lets choose the
above. And considering N for Nitrogen it also fits in this scheme.
This patch moves N2_IN_AIR from deco.c to dive.h as this is already used
in several places and might be useful for future use also. It also
respecifies N2_IN_AIR to a more correct value of 78,084%, the former one
also included all other gases than oxygen appearing in air. If someone
needs to use the former value it would be more correct to use 1-O2_IN_AIR
instead.
Signed-off-by: Jan Schubert / Jan.Schubert@GMX.li
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This moves the point where GF_low applies up which implies that at all
shallower depth (i.e. during deco) a lower GF results which makes the deco
longer compared to the previous implementation.
Of course, "GF_low" applies at first deco stop is a bit tricky since the
depth of the first deco stop again depends on GF_low, i.e. there is
another equation to solve. You can do this by inverting the equation for
the ambient pressure and use GF_low as the gradient factor. This yields
amb = (b * M_value_corrected - GF_low * a * b) / ((1-b) * GF_low + b)
Signed-off-by: Robert C. Helling helling@atdotde.de
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In commit d163a68ac69e "Clean up the rewritten deco.c" I apparently made
one more change than I intended - I changed the last deco stop back to 3m
instead of allowing the smooth mode to go all the way back to 0 without
any discrete steps.
This fixes that mistake.
Reported-by: Robert C. Helling <helling@lmu.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>