summaryrefslogtreecommitdiffstats
path: root/subsurface-core
diff options
context:
space:
mode:
Diffstat (limited to 'subsurface-core')
-rw-r--r--subsurface-core/dive.c71
1 files changed, 30 insertions, 41 deletions
diff --git a/subsurface-core/dive.c b/subsurface-core/dive.c
index e06a25fa4..4108c0942 100644
--- a/subsurface-core/dive.c
+++ b/subsurface-core/dive.c
@@ -847,57 +847,46 @@ static void update_min_max_temperatures(struct dive *dive, temperature_t tempera
}
/*
+ * This gives an interative solution of hte Redlich-Kwong equation for the compressibility factor
+ * according to https://en.wikipedia.org/wiki/Redlich–Kwong_equation_of_state
+ * in terms of the reduced temperature T/T_crit and pressure p/p_crit.
+ *
+ * Iterate this three times for good results in our pressur range.
+ *
+ */
+
+double redlich_kwong_equation(double t_red, double p_red, double z_init)
+{
+ return (1.0/(1.0 - 0.08664*p_red/(t_red * z_init)) -
+ 0.42748/(sqrt(t_red * t_red * t_red) * ((t_red*z_init/p_red + 0.08664))));
+}
+
+/*
* At high pressures air becomes less compressible, and
* does not follow the ideal gas law any more.
- *
- * NOTE! The compressibility doesn't just depend on the
- * gas, but on temperature too. However, this currently
- * just follows the 300K curve for air, and ignores the
- * gasmix. And the temperature we don't really even have
- * a way to try to take into account.
*/
-#define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
+#define STANDARD_TEMPERATURE 293.0
+
double gas_compressibility_factor(struct gasmix *gas, double bar)
{
- static const struct z_factor {
- double bar, z_factor;
- } air_table[] = {
- { 1, 0.9999 },
- { 5, 0.9987 },
- { 10, 0.9974 },
- { 20, 0.9950 },
- { 40, 0.9917 },
- { 60, 0.9901 },
- { 80, 0.9903 },
- { 100, 0.9930 },
- { 150, 1.0074 },
- { 200, 1.0326 },
- { 250, 1.0669 },
- { 300, 1.1089 },
- { 400, 1.2073 },
- { 500, 1.3163 }
- };
- const struct z_factor *n;
- int i;
+ /* Critical points according to https://en.wikipedia.org/wiki/Critical_point_(thermodynamics) */
- for (i = 0; i < ARRAY_SIZE(air_table); i++) {
- const struct z_factor *n = air_table+i;
- double frac;
+ double tcn2 = 126.2;
+ double tco2 = 154.6;
+ double tche = 5.19;
- if (n->bar < bar)
- continue;
- if (!i)
- return n->z_factor;
+ double pcn2 = 33.9;
+ double pco2 = 50.5;
+ double pche = 2.27;
- /* How far from this one? */
- frac = (n->bar - bar) / (n->bar - n[-1].bar);
+ double tc, pc;
- /* Silly linear interpolation */
- return frac*n[-1].z_factor + (1.0-frac)*n->z_factor;
- }
+ tc = (tco2 * get_o2(gas) + tche * get_he(gas) + tcn2 * (1000 - get_o2(gas) - get_he(gas))) / 1000.0;
+ pc = (pco2 * get_o2(gas) + pche * get_he(gas) + pcn2 * (1000 - get_o2(gas) - get_he(gas))) / 1000.0;
- /* Over 500 bar? We make shit up */
- return air_table[ARRAY_SIZE(air_table)-1].z_factor;
+ return (redlich_kwong_equation(STANDARD_TEMPERATURE/tc, bar/pc,
+ redlich_kwong_equation(STANDARD_TEMPERATURE/tc, bar/pc,
+ redlich_kwong_equation(STANDARD_TEMPERATURE/tc, bar/pc,1.0))));
}
int gas_volume(cylinder_t *cyl, pressure_t p)