public void Pressure_by_depth_calc_test() { // Reference values according to // Algorithms for computation of fundamental properties of seawater. // Unesco technical papers in marine science vol. 44, 1983, pp. 28 // https://darchive.mblwhoilibrary.org/bitstream/handle/1912/2470/059832eb.pdf double ref_salinity = 35.0; double ref_temperature = 0.0; double[] ref_pressures = new double[] { 5E4, 1E5, 2E5, 3E5, 4E5, 5E5, 6E5, 7E5, 8E5, 9E5, 1E6 }; double[] ref_lats_deg = new double[] { 0.0, 30.0, 45.0, 60.0, 90.0 }; double[,] ref_dpt_lat = { { 496.65, 992.12, 1979.55, 2962.43, 3940.88, 4915.04, 5885.03, 6850.95, 7812.93, 8771.07, 9725.47 }, { 496.00, 990.81, 1976.94, 2958.52, 3935.68, 4908.56, 5877.27, 6841.92, 7802.63, 8759.51, 9712.65 }, { 495.34, 989.50, 1974.33, 2954.61, 3930.49, 4902.08, 5869.51, 6832.89, 7792.33, 8747.95, 9699.84 }, { 494.69, 988.19, 1971.72, 2950.71, 3925.30, 4895.60, 5861.76, 6823.86, 7782.04, 8736.40, 9687.84 }, { 494.03, 986.88, 1969.11, 2946.81, 3920.10, 4889.13, 5854.01, 6814.84, 7771.76, 8724.85, 9674.23 } }; for (int l_idx = 0; l_idx < ref_lats_deg.Length; l_idx++) { for (int p_idx = 0; p_idx < ref_pressures.Length; p_idx++) { double g = PHX.Gravity_constant_wgs84_calc(ref_lats_deg[l_idx]); // taking the water density in the midpoint to consider the compression of water double rho = PHX.Water_density_calc(ref_temperature, ref_pressures[p_idx] / 2.0, ref_salinity); double h_est = PHX.Depth_by_pressure_calc(ref_pressures[p_idx], 0.0, rho, g); // calculated values should deviate less than 0.07% of reference values Assert.AreEqual(h_est, ref_dpt_lat[l_idx, p_idx], ref_dpt_lat[l_idx, p_idx] * 0.0007); } } }
private double getVByProfile(double z) { double t, p, s, v, rho0; if (z < tsp[tsp.Length - 1].Z) { int idx1 = 0, idx2 = tsp.Length - 1; while ((tsp[idx1].Z < z) && (idx1 < tsp.Length - 1)) { idx1++; } while ((z <= tsp[idx2].Z) && (idx2 > idx1 + 1)) { idx2--; } double z1 = tsp[idx1].Z; double t1 = tsp[idx1].T; double s1 = tsp[idx1].S; rho0 = PHX.Water_density_calc(t1, PHX.PHX_ATM_PRESSURE_MBAR, s1); double p1 = PHX.Pressure_by_depth_calc(z1, PHX.PHX_ATM_PRESSURE_MBAR, rho0, g); double z2 = tsp[idx2].Z; double t2 = tsp[idx2].T; double s2 = tsp[idx2].S; double p2 = PHX.Pressure_by_depth_calc(z2, PHX.PHX_ATM_PRESSURE_MBAR, rho0, g); t = PHX.Linterp(z1, t1, z2, t2, z); p = PHX.Linterp(z1, p1, z2, p2, z); s = PHX.Linterp(z1, s1, z2, s2, z); } else { t = tsp[tsp.Length - 1].T; s = tsp[tsp.Length - 1].S; rho0 = PHX.Water_density_calc(t, PHX.PHX_ATM_PRESSURE_MBAR, s); p = PHX.Pressure_by_depth_calc(z, PHX.PHX_ATM_PRESSURE_MBAR, rho0, g); } v = PHX.Speed_of_sound_UNESCO_calc(t, p, s); return(v); }
public void Water_density_calc_test() { // Test according to reference fresh water density from: // Tanaka, M., Girard, G., Davis, R., Peuto, A., & Bignell, N. (2001). // Recommended table for the density of water between 0°C and 40°C based on // recent experimental reports. Metrologia, 38(4), 301–309. doi:10.1088/0026-1394/38/4/3 // double ref_salinity = 0.0; double[] ref_temperatures = new double[] { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0 }; double[] ref_densities = new double[] { 999.8428, 999.9017, 999.9429, 999.9672, 999.9749, 999.9668, 999.9431, 999.9045, 999.8513, 999.7839, 999.7027, 999.6081, 999.5005, 999.3801, 999.2474, 999.1026, 998.9459, 998.7778, 998.5984, 998.4079, 998.2067, 997.9950, 997.7730, 997.5408, 997.2988, 997.0470, 996.7857, 996.5151, 996.2353, 995.9465, 995.6488, 995.3424, 995.0275, 994.7041, 994.3724, 994.0326, 993.6847, 993.3290, 992.9654, 992.5941, 992.2152 }; for (int p_idx = 0; p_idx < ref_densities.Length; p_idx++) { Assert.AreEqual(PHX.Water_density_calc(ref_temperatures[p_idx], PHX.PHX_ATM_PRESSURE_MBAR, ref_salinity), ref_densities[p_idx], 5.2E-2); } // Testing according to fresh & seawater density from: // ITTC – Recommended Procedures 7.5-02-01-03. Fresh Water and Seawater Properties // Effective Date 2011 Revision 02, Updated / Edited by Approved Quality Systems Group of the 28 th ITTC 26 th ITTC 2011 // Date 09/2016 // https://ittc.info/media/7503/75-02-01-03.pdf // From pp. 4-5, Table 1: ref_salinity = 0.0; ref_temperatures = new double[] { 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0 }; ref_densities = new double[] { 999.7025, 999.6079, 999.5004, 999.3801, 999.2474, 999.1026, 998.9461, 998.7780, 998.5986, 998.4083, 998.2072, 997.9955, 997.7735, 997.5414, 997.2994, 997.0476, 996.7864, 996.5158, 996.2360, 995.9471, 995.6495, 995.3431, 995.0281, 994.7048, 994.3731, 994.0333, 993.6855, 993.3298, 992.9663, 992.5951, 992.2164 }; for (int p_idx = 0; p_idx < ref_densities.Length; p_idx++) { Assert.AreEqual(PHX.Water_density_calc(ref_temperatures[p_idx], PHX.PHX_ATM_PRESSURE_MBAR, ref_salinity), ref_densities[p_idx], 5.2E-2); } // From pp. 7-8, Table 3 ref_salinity = 35.16; // +/- 0.007 ref_temperatures = new double[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0 }; ref_densities = new double[] { 1028.0941, 1028.0197, 1027.9327, 1027.8336, 1027.7225, 1027.6000, 1027.4662, 1027.3214, 1027.1659, 1027.0000, 1026.8238, 1026.6376, 1026.4416, 1026.2360, 1026.0210, 1025.7967, 1025.5633, 1025.3210, 1025.0700, 1024.8103, 1024.5421, 1024.2656, 1023.9808, 1023.6881, 1023.3873, 1023.0788, 1022.7626, 1022.4389, 1022.1078, 1021.7694 }; for (int p_idx = 0; p_idx < ref_densities.Length; p_idx++) { Assert.AreEqual(PHX.Water_density_calc(ref_temperatures[p_idx], PHX.PHX_ATM_PRESSURE_MBAR, ref_salinity), ref_densities[p_idx], 0.5); } // From pp. 10-11, Table 4 double ref_temperature = 15.0; double[] ref_salinities = new double[] { 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0 }; ref_densities = new double[] { 1006.7950, 1007.5571, 1008.3191, 1009.0812, 1009.8434, 1010.6056, 1011.3680, 1012.1305, 1012.8932, 1013.6561, 1014.4192, 1015.1824, 1015.9459, 1016.7097, 1017.4736, 1018.2379, 1019.0023, 1019.7670, 1020.5320, 1021.2973, 1022.0628, 1022.8286, 1023.5946, 1024.3609, 1025.1275, 1025.8944, 1026.6615, 1027.4289, 1028.1966, 1028.9646, 1029.7328 }; for (int p_idx = 0; p_idx < ref_densities.Length; p_idx++) { Assert.AreEqual(PHX.Water_density_calc(ref_temperature, PHX.PHX_ATM_PRESSURE_MBAR, ref_salinities[p_idx]), ref_densities[p_idx], 0.2); } // Don't remember where are these values from ), but it should be ok ref_temperature = 0.0; ref_salinity = 35.0; double[] ref_pressures = new double[] { 0.0, 100000.0, 200000.0, 400000.0, 600000.0, 800000.0, 1000000.0 }; ref_densities = new double[] { 1028.13, 1032.85, 1037.47, 1046.40, 1054.95, 1063.15, 1071.04 }; for (int p_idx = 0; p_idx < ref_densities.Length; p_idx++) { Assert.AreEqual(PHX.Water_density_calc(ref_temperature, PHX.PHX_ATM_PRESSURE_MBAR + ref_pressures[p_idx], ref_salinity), ref_densities[p_idx], 0.1); } }
private void OnLBLA(object[] parameters) { // IC_D2H_LBLA $PRWLA,bID,baseLat,baseLon,[baseDpt],baseBat,pingerDataID,pingerData,TOAsecond,MSR_dB BaseIDs baseID = (parameters[0] == null) ? BaseIDs.BASE_INVALID : (BaseIDs)(int)parameters[0]; double baseLat = doubleNullChecker(parameters[1]); double baseLon = doubleNullChecker(parameters[2]); double baseDepth = (parameters[3] == null) ? RWLT.DEFAULT_BASE_DPT_M : (double)parameters[3]; double baseBat = doubleNullChecker(parameters[4]); PingerDataIDs pDataID = (parameters[5] == null) ? PingerDataIDs.DID_INVALID : (PingerDataIDs)(int)parameters[5]; double pData = doubleNullChecker(parameters[6]); double TOAs = doubleNullChecker(parameters[7]); double MSR = doubleNullChecker(parameters[8]); if ((baseID != BaseIDs.BASE_INVALID) && (!double.IsNaN(baseLat)) && (!double.IsNaN(baseLon)) && (!double.IsNaN(baseDepth))) { if ((baseID == auxGNSSBuoyID) && (!AUXGNSSUsed)) { GNSS_RMCSentenceReceived(this, new RMCMessageEventArgs(0xFF, TalkerIdentifiers.GN, GetTimeStamp(), baseLat, baseLon, double.NaN, double.NaN, double.NaN, true)); } LocationUpdatedEvent.Rise(this, new LocationUpdatedEventArgs(baseID.ToString().Replace('_', ' '), baseLat, baseLon, baseDepth, true, GetTimeStamp())); if (!double.IsNaN(MSR)) { BaseMSRs[baseID].Value = MSR; } if (!double.IsNaN(baseBat)) { BaseBatVoltages[baseID].Value = baseBat; } if (gravityAccNeedsUpdate) { gravityAcc = PHX.Gravity_constant_wgs84_calc(baseLat); gravityAccNeedsUpdate = false; } if (pDataID == PingerDataIDs.DID_BAT) { TargetBatVoltage.Value = pData; } else if (pDataID == PingerDataIDs.DID_TMP) { TargetTemperature.Value = pData; if (IsAutoSoundSpeed && TargetPressure.IsInitialized) { Soundspeed = PHX.Speed_of_sound_UNESCO_calc(TargetTemperature.Value, TargetPressure.Value / 2.0, salinity); } } else if (pDataID == PingerDataIDs.DID_PRS) { TargetPressure.Value = pData; if (TargetTemperature.IsInitialized) { if (IsAutoSoundSpeed) { Soundspeed = PHX.Speed_of_sound_UNESCO_calc(TargetTemperature.Value, TargetPressure.Value / 2.0, salinity); } double rho = PHX.Water_density_calc(TargetTemperature.Value, TargetPressure.Value / 2.0, salinity); // p0 is zero, because pinger calibrates surface pressure on start and transmits pressure relative to the surface TargetDepth.Value = PHX.Depth_by_pressure_calc(TargetPressure.Value, 0, rho, gravityAcc); } else if (TargetPressure.IsInitialized) { TargetDepth.Value = PHX.Depth_by_pressure_calc(TargetPressure.Value, 0, PHX.PHX_FWTR_DENSITY_KGM3, gravityAcc); } } else if (pDataID == PingerDataIDs.DID_CODE) { TargetAlarm.Value = (PingerCodeIDs)Enum.ToObject(typeof(PingerCodeIDs), Convert.ToInt32(pData)); } var bases = baseProcessor.ProcessBase(baseID, baseLat, baseLon, baseDepth, TOAs); if (bases != null) { TryLocate(bases); } } OnSystemUpdate(); }