subsurface/subsurface-core/gas-model.c
Linus Torvalds a173a3ce79 gas model: simplify and improve our Z factor calculations
Lubomir found better compressibility data for the pure gases that we
need for scuba, making the air table superfluous: we get good values
from just regular linear mixing of the Oxygen, Nitrogen and Helium
calculations.

Also, rather than using a quintic polynomial, a cubic one does
sufficiently well, making for smaller code and fewer coefficients.

And judging by the reactions from people on G+ (as well as just looking
at how good the fit is with the air data), this is all the right way to
do this, and this thus removes the Redlich-Kwong equation.

All-credit-goes-to: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2016-03-03 14:19:45 -08:00

75 lines
1.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* gas-model.c */
/* gas compressibility model */
#include <stdio.h>
#include <stdlib.h>
#include "dive.h"
/*
* Generic cubic polynomial
*/
static double cubic(double bar, const double coefficient[])
{
double x0 = 1.0,
x1 = bar,
x2 = x1*x1,
x3 = x2*x1;
return x0 * coefficient[0] +
x1 * coefficient[1] +
x2 * coefficient[2] +
x3 * coefficient[3];
}
/*
* Cubic least-square coefficients for O2/N2/He based on data from
*
* PERRYS CHEMICAL ENGINEERS HANDBOOK SEVENTH EDITION
*
* with the lookup and curve fitting by Lubomir.
*
* NOTE! Helium coefficients are a linear mix operation between the
* 323K and one for 273K isotherms, to make everything be at 300K.
*/
static const double o2_coefficients[4] = {
+1.00117935180448264158,
-0.00074149079841471884,
+0.00000291901111247509,
-0.00000000162092217461
};
static const double n2_coefficients[4] = {
+1.00030344355797817778,
-0.00022528077251905598,
+0.00000295430303276288,
-0.00000000210649996337
};
static const double he_coefficients[4] = {
+1.00000137322788319261,
+0.000488393024887620665,
-0.000000054210166760015,
+0.000000000010908069275
};
static double o2_compressibility_factor(double bar) { return cubic(bar, o2_coefficients); }
static double n2_compressibility_factor(double bar) { return cubic(bar, n2_coefficients); }
static double he_compressibility_factor(double bar) { return cubic(bar, he_coefficients); }
/*
* We end up using a simple linear mix of the gas-specific functions.
*/
double gas_compressibility_factor(struct gasmix *gas, double bar)
{
double o2, n2, he; // Z factors
double of, nf, hf; // gas fractions ("partial pressures")
o2 = o2_compressibility_factor(bar);
n2 = n2_compressibility_factor(bar);
he = he_compressibility_factor(bar);
of = get_o2(gas) / 1000.0;
hf = get_he(gas) / 1000.0;
nf = 1.0 - of - nf;
return o2*of + n2*nf + he*hf;
}