/// /// Copyright (c) 2013-2015 Sensus Metering Systems /// using System; using System.Collections.Generic; using log4net; namespace TBF.BenchControl { public static class Formulas { private static readonly ILog log = LogManager.GetLogger(typeof(Formulas)); /// /// Calculate density of distilled water from temperature /// /// Temperature in [degC] /// Density in [kg/m3] public static double DistilledWaterDensityFromTemp(float t) { double tt = (double)t; const double a0 = 999.842594; const double a1 = 0.06793952; const double a2 = -0.00909529; const double a3 = 0.0001001685; const double a4 = -0.000001120083; const double a5 = 6.536332e-09; return ((((a5 * tt + a4) * tt + a3) * tt + a2) * tt + a1) * tt + a0; } /// /// Calculate corrected (real) water density from temperature /// /// Temperature in [degC] /// Density in [kg/m3] public static double WaterDensityFromTemp(float t) { double realDensity = Program.LocalSettings.RealDensity; float atTemperature = Program.LocalSettings.AtTemperature; double c_rho = realDensity / DistilledWaterDensityFromTemp(atTemperature); return c_rho * DistilledWaterDensityFromTemp(t); } public static float AirDensityFromAmbientVales(float tempC, float pressureBar, float humiPct) { double pressurePa = 100000.0 * (double)pressureBar; /// [Pa] double tempKelvin = 273.15 + (double)tempC; double coef1 = 1.2811805 / 10000.0 * tempKelvin * tempKelvin - 1.950987 / 100.0 * tempKelvin + 34.04926034 - 6.353631 * 1000.0 / tempKelvin; double coef3 = humiPct / 100.0 * System.Math.Exp(coef1) / pressurePa; double airDensityKgm3 = 0.00348353 * pressurePa * (1.0 - 0.378 * coef3) / tempKelvin; /// kg/m3 return (float)airDensityKgm3; } /// /// Convert 'pulses' to 'volume', prevent division by zero /// public static double VolumeFromPulses(int pulses, double pulsesPerLiter) { if (pulsesPerLiter <= double.Epsilon) return 0; return Convert.ToDouble(pulses) / pulsesPerLiter; } /// /// Calculate the error in % from 'measured' and 'true' volume, prevent division by zero /// public static double ErrorFromVolumes(double measuredVolume, double trueVolume) { if (trueVolume <= float.Epsilon) { if (measuredVolume <= float.Epsilon) { log.WarnFormat("ErrorFromVolumes({0},{1}) returns {2}", measuredVolume, trueVolume, 99.0); return 99.0; } log.WarnFormat("ErrorFromVolumes({0},{1}) returns {2}", measuredVolume, trueVolume, 99.0); return 99.0; } double error = 100.0 * (measuredVolume - trueVolume) / trueVolume; log.InfoFormat("ErrorFromVolumes({0},{1}) returns {2}", measuredVolume, trueVolume, error); return error; } /// /// Calculates corrected value form a list of corrections by interpolation. /// It is assumed that values in the list 'corrections' are sorted. /// /// Raw uncorrected value /// Sorted (value, correction) pairs /// Corrected value public static double CorrectedValue(double rawValue, IList corrections) { if (corrections == null || corrections.Count == 0) return rawValue; if (rawValue < corrections[0].Measurement) { return rawValue + corrections[0].Correction; } int count = corrections.Count; for (int i = 1; i < count; i++) { if (rawValue < corrections[i].Measurement) { double d1 = rawValue - corrections[i-1].Measurement; double d2 = corrections[i].Measurement - rawValue; double corr; if (d1 + d2 <= float.Epsilon) { corr = (corrections[i - 1].Correction + corrections[i].Correction) / 2.0; } else { corr = (corrections[i - 1].Correction * d2 + corrections[i].Correction * d1) / (d1 + d2); } return rawValue + corr; } } return rawValue + corrections[count - 1].Correction; } } }