struct COEFF_SALINITY
{
/** 'a' series */
const double a0 = 0.0080;
const double a1 = -0.1692;
const double a2 = 25.3851;
const double a3 = 14.0941;
const double a4 = -7.0261;
const double a5 = 2.7081;
/** 'b' series */
const double b0 = 0.0005;
const double b1 = -0.0056;
const double b2 = -0.0066;
const double b3 = -0.0375;
const double b4 = 0.0636;
const double b5 = -0.0144;
/** 'c' series */
const double c0 = 0.6766097;
const double c1 = 2.00564e-2;
const double c2 = 1.104259e-4;
const double c3 = -6.9698e-7;
const double c4 = 1.0031e-9;
/** 'd' series */
const double d1 = 3.426e-2;
const double d2 = 4.464e-4;
const double d3 = 4.215e-1;
const double d4 = -3.107e-3;
/** 'e' series */
const double e1 = 2.070e-5;
const double e2 = -6.370e-10;
const double e3 = 3.989e-15;
/** 'k' series */
const double k = 0.0162;
};
double hillRatioLessThan2Salinity(double tempCelcius);
double salinityFromConductyivity(double condValue, double tempCelcius, double pressureDBar);
/*
Calculates Practical Salinity, SP, from conductivity, C, primarily using
the PSS-78 algorithm. Note that the PSS-78 algorithm for Practical
Salinity is only valid in the range 2 < SP < 42. If the PSS-78
algorithm produces a Practical Salinity that is less than 2 then the
Practical Salinity is recalculated with a modified form of the Hill et
al. (1986) formula. The modification of the Hill et al. (1986)
expression is to ensure that it is exactly consistent with PSS-78
at SP = 2. Note that the input values of conductivity need to be in
units of mS/cm (not S/m).
REFERENCES:
Culkin and Smith, 1980: Determination of the Concentration of Potassium
Chloride Solution Having the Same Electrical Conductivity, at 15C and
Infinite Frequency, as Standard Seawater of Salinity 35.0000
(Chlorinity 19.37394), IEEE J. Oceanic Eng, 5, 22-23.
Hill, K.D., T.M. Dauphinee & D.J. Woods, 1986: The extension of the
Practical Salinity Scale 1978 to low salinities. IEEE J. Oceanic Eng.,
11, 109 - 112.
IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of
seawater - 2010: Calculation and use of thermodynamic properties.
Intergovernmental Oceanographic Commission, Manuals and Guides No. 56,
UNESCO (English), 196 pp. Available from http://www.TEOS-10.org
See appendix E of this TEOS-10 Manual.
Unesco, 1983: Algorithms for computation of fundamental properties of
seawater. Unesco Technical Papers in Marine Science, 44, 53 pp.
This function adapted from TEOS 10 (thermodynamic Equation of Seawater)
Gibbs-SeaWater (GSW) Oceanographic Toolbox from http://www.TEOS-10.org
*/
double salinityFromConductyivity(double condValue, double tempCelcius, double pressureDBar)
{
/** Conductivity at (SP=35, t_68=15, p=0) [mS/cm] */
double const conductivity3515 = 42.9140;
/** use COEFF_SALINITY */
COEFF_SALINITY coeff;
double t68 = tempCelcius * 1.00024;
double ft68 = (t68 - 15.0) / (1.0 + coeff.k * (t68 - 15.0));
/**
The dimensionless conductivity ratio, R, is the conductivity input 'condValue': C,
divided by the present estimate of C(SP=35, t_68=15, p=0) which is
42.9140 mS/cm (=4.29140 S/m), (Culkin and Smith, 1980).
*/
double R = condValue / conductivity3515; /** 0.023302418791070513 = 1./42.9140 */
/**rt_lc corresponds to rt as defined in the UNESCO 44 (1983) routines.*/
double rt_lc = coeff.c0 + (
coeff.c1 + (
coeff.c2 + (
coeff.c3 + coeff.c4 * t68
) * t68
) * t68
) * t68;
double rp = 1e0 + (pressureDBar * (coeff.e1 + coeff.e2 * pressureDBar + coeff.e3 * pressureDBar * pressureDBar))
/ (1e0 + coeff.d1 * t68 + coeff.d2 * t68 * t68 + (coeff.d3 + coeff.d4*t68) * R);
double rt = R / (rp * rt_lc);
if (rt < 0.0)
{
return -9999; /** invalid value*/
}
double rtx = sqrt(rt);
double salinityPPT = coeff.a0 + (
coeff.a1 + (
coeff.a2 + (coeff.a3 + (coeff.a4 + coeff.a5 * rtx) * rtx) * rtx
) * rtx
) * rtx + (
coeff.b0 + (
coeff.b1 + (coeff.b2 + (coeff.b3 + (coeff.b4 + coeff.b5 * rtx) * rtx) * rtx) * rtx
) * rtx
) * ft68;
/**
The following section of the code is designed for SP < 2 based on the
Hill et al. (1986) algorithm. This algorithm is adjusted so that it is
exactly equal to the PSS-78 algorithm at SP = 2.
*/
if (salinityPPT < 2)
{
double hill_ratio = hillRatioLessThan2Salinity(tempCelcius);
double x = 400.0 * rt;
double sqrty = 10.0 * rtx;
double part1 = 1.0 + (x * (1.5 + x));
double part2 = 1.0 + (sqrty * (1.0 + sqrty*(1.0 + sqrty)));
double sp_hill_raw = salinityPPT - (coeff.a0 / part1) - (coeff.b0 * ft68 / part2);
salinityPPT = hill_ratio * sp_hill_raw;
}
/** This line ensures that SP is non-negative. */
if (salinityPPT < 0.0)
{
salinityPPT = -9999;
}
return salinityPPT;
}
/*
Calculates the Hill ratio, which is the adjustment needed to apply for
Practical Salinities smaller than 2. This ratio is defined at a
Practical Salinity = 2 and in-situ temperature, t using PSS-78. The Hill
ratio is the ratio of 2 to the output of the Hill et al. (1986) formula
for Practical Salinity at the conductivity ratio, Rt, at which Practical
Salinity on the PSS-78 scale is exactly 2.
REFERENCES:
Hill, K.D., T.M. Dauphinee & D.J. Woods, 1986: The extension of the
Practical Salinity Scale 1978 to low salinities. IEEE J. Oceanic Eng.,
11, 109 - 112.
IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of
seawater - 2010: Calculation and use of thermodynamic properties.
Intergovernmental Oceanographic Commission, Manuals and Guides No. 56,
UNESCO (English), 196 pp. Available from http://www.TEOS-10.org
See appendix E of this TEOS-10 Manual.
McDougall T.J. and S.J. Wotherspoon, 2013: A simple modification of
Newton's method to achieve convergence of order 1 + sqrt(2). Applied
Mathematics Letters, 29, 20-25.
Unesco, 1983: Algorithms for computation of fundamental properties of
seawater. Unesco Technical Papers in Marine Science, 44, 53 pp.
This function adapted from TEOS 10 (thermodynamic Equation of Seawater)
Gibbs-SeaWater (GSW) Oceanographic Toolbox from http://www.TEOS-10.org
*/
double hillRatioLessThan2Salinity(double tempCelcius)
{
/** use COEFF_SALINITY */
COEFF_SALINITY coeff;
const double
g0 = 2.641463563366498e-1, g1 = 2.007883247811176e-4,
g2 = -4.107694432853053e-6, g3 = 8.401670882091225e-8,
g4 = -1.711392021989210e-9, g5 = 3.374193893377380e-11,
g6 = -5.923731174730784e-13, g7 = 8.057771569962299e-15,
g8 = -7.054313817447962e-17, g9 = 2.859992717347235e-19,
sp2 = 2.0;
double t68 = tempCelcius * 1.00024;
double ft68 = (t68 - 15.0) / (1.0 + coeff.k * (t68 - 15.0));
/**
------------------------------------------------------------------------
Find the initial estimates of Rtx (Rtx0) and of the derivative dSP_dRtx
at SP = 2.
------------------------------------------------------------------------
*/
double rtx0 = g0 + (g1 + (g2 + (g3 + (g4 + (g5 + (g6 + (g7 + (g8 + g9
* t68) * t68) * t68) * t68) * t68) * t68) * t68) * t68) * t68;
double dsp_drtx = coeff.a1 + (2 * coeff.a2 + (3 * coeff.a3 + (4 * coeff.a4 + 5 * coeff.a5 * rtx0) * rtx0) * rtx0)
* rtx0 + (coeff.b1 + (2 * coeff.b2 + (3 * coeff.b3 + (4 * coeff.b4 + 5 * coeff.b5
* rtx0) * rtx0) * rtx0) * rtx0) * ft68;
/**
-------------------------------------------------------------------------
Begin a single modified Newton-Raphson iteration to find Rt at SP = 2.
-------------------------------------------------------------------------
*/
double sp_est = coeff.a0 + (coeff.a1 + (coeff.a2 + (coeff.a3 + (coeff.a4 + coeff.a5
* rtx0 ) * rtx0) * rtx0) * rtx0) * rtx0
+ (coeff.b0 + (coeff.b1 + (coeff.b2 + (coeff.b3 + (coeff.b4 + coeff.b5
* rtx0) * rtx0) * rtx0) * rtx0) * rtx0) * ft68;
double rtx = rtx0 - (sp_est - sp2) / dsp_drtx;
double rtxm = 0.5 * (rtx + rtx0);
dsp_drtx = coeff.a1 + (2 * coeff.a2 + (3 * coeff.a3 + (4 * coeff.a4 + 5 * coeff.a5
* rtxm) * rtxm) * rtxm) * rtxm
+ (coeff.b1 + (2 * coeff.b2 + (3 * coeff.b3 + (4 * coeff.b4 + 5 * coeff.b5
* rtxm) * rtxm) * rtxm) * rtxm) * ft68;
rtx = rtx0 - (sp_est - sp2) / dsp_drtx;
/**
This is the end of one full iteration of the modified Newton-Raphson
iterative equation solver. The error in Rtx at this point is equivalent
to an error in SP of 9e-16 psu.
*/
double x = 400.0 * rtx * rtx;
double sqrty = 10.0 * rtx;
double part1 = 1.0 + (x * (1.5 + x));
double part2 = 1.0 + sqrty * (1.0 + (sqrty * (1.0 + sqrty)));
double sp_hill_raw_at_sp2 = sp2 - (coeff.a0 / part1) - (coeff.b0 * ft68 / part2);
return (sp2 / sp_hill_raw_at_sp2);
}
const double PRESSURE_SEA_LEVEL_DBAR = 10.1325;
void setup() {
// Untuk konversi perlu 3 parameter:
// Suhu air dalam derajat selsius;
// Tekanan udara dalam Desibar;
// dan Konduktivitas itu sendiri dalam mS/cm
// Tolong perhatikan unit satuannya yah
Serial.begin(115200);
double conductivityMSCM = 12.88;
double temperatureCelcius = 25.00;
double airPressureDBar = 10.1325;
double salinityPPT = salinityFromConductyivity(
conductivityMSCM,
temperatureCelcius,
airPressureDBar);
Serial.printf("salinity ppt: %.15f\n", salinityPPT); // 20.009869599086951
conductivityMSCM = 34.5600;
temperatureCelcius = 4.4036;
airPressureDBar = 1000;
salinityPPT = salinityFromConductyivity(
conductivityMSCM,
temperatureCelcius,
airPressureDBar);
Serial.printf("salinity ppt: %.15f\n", salinityPPT); // 36.400308494388170
conductivityMSCM = 2.893;
temperatureCelcius = 25;
airPressureDBar = PRESSURE_SEA_LEVEL_DBAR;
salinityPPT = salinityFromConductyivity(
conductivityMSCM,
temperatureCelcius,
airPressureDBar);
Serial.printf("salinity ppt: %.15f\n", salinityPPT); // 1.5
conductivityMSCM = 23.730019;
temperatureCelcius = 26.405396;
airPressureDBar = PRESSURE_SEA_LEVEL_DBAR;
salinityPPT = salinityFromConductyivity(
conductivityMSCM,
temperatureCelcius,
airPressureDBar);
Serial.printf("salinity ppt: %.15f\n", salinityPPT);
}
void loop() {
// put your main code here, to run repeatedly:
delay(10); // this speeds up the simulation
}