public static ArrayClass MakeData(EnsembleDataDesignParam param) { ArrayClass data = new ArrayClass(); //E000008 data.E_EnsembleNumber = param.TemplateData.E_EnsembleNumber; data.E_Cells = param.TemplateData.E_Cells; data.E_Beams = param.TemplateData.E_Beams; data.E_PingCount = param.TemplateData.E_PingCount; data.E_Status = 0; data.YYYY = DateTime.Now.Year; data.MM = DateTime.Now.Month; data.DD = DateTime.Now.Day; data.HH = DateTime.Now.Hour; data.mm = DateTime.Now.Minute; data.SS = DateTime.Now.Second; data.hsec = DateTime.Now.Millisecond / 10; //其他 for (int i = 0; i < data.Bins.Length; i++) { data.Bins[i] = (int)data.E_Cells; } for (int i = 0; i < data.Beams.Length; i++) { data.Beams[i] = (int)data.E_Beams; } data.AmplitudeAvailable = true; data.AncillaryAvailable = true; data.BottomTrackAvailable = true; data.CorrelationAvailable = true; data.EarthAvailable = true; data.EnsembleDataAvailable = true; data.InstrumentAvailable = true; data.NmeaAvailable = true; data.VelocityAvailable = true; data.XfrmNAvailable = true; Random random = new Random(); for (int i = 0; i < data.E_Cells; i++) { //E000002 data.Instrument[0, i] = (float)(Math.Sin(Math.PI / 4) * param.ReferEarthVelocity * (1 + random.NextDouble() * param.NoiseSize)); data.Instrument[1, i] = (float)(Math.Cos(Math.PI / 4) * param.ReferEarthVelocity * (1 + random.NextDouble() * param.NoiseSize)); data.Instrument[2, i] = 0; data.Instrument[3, i] = 0; //E000001 data.Velocity[0, i] = 0; data.Velocity[1, i] = data.Instrument[0, i] * 2 * Math.Sign(param.BeamAngle / 180.0 * Math.PI); data.Velocity[2, i] = 0; data.Velocity[3, i] = data.Instrument[1, i] * 2 * Math.Sign(param.BeamAngle / 180.0 * Math.PI);; //E000003 data.Earth[0, i] = data.Instrument[0, i]; data.Earth[1, i] = data.Instrument[1, i]; data.Earth[2, i] = 0; data.Earth[3, i] = 0; //E000004 double a = Math.Sin(Math.PI / 4 + i / (double)data.E_Cells * Math.PI * 3 / 4); data.Amplitude[0, i] = (float)(a * param.ReferAmplitude * (1 + random.NextDouble() * param.NoiseSize)); data.Amplitude[1, i] = (float)(a * param.ReferAmplitude * (1 + random.NextDouble() * param.NoiseSize)); data.Amplitude[2, i] = (float)(a * param.ReferAmplitude * (1 + random.NextDouble() * param.NoiseSize)); data.Amplitude[3, i] = (float)(a * param.ReferAmplitude * (1 + random.NextDouble() * param.NoiseSize)); //E000005 data.Correlation[0, i] = (float)(param.ReferCorrelation * (1 + random.NextDouble() * param.NoiseSize)); data.Correlation[1, i] = (float)(param.ReferCorrelation * (1 + random.NextDouble() * param.NoiseSize)); data.Correlation[2, i] = (float)(param.ReferCorrelation * (1 + random.NextDouble() * param.NoiseSize)); data.Correlation[3, i] = (float)(param.ReferCorrelation * (1 + random.NextDouble() * param.NoiseSize)); //E000006 data.BeamN[0, i] = (int)param.TemplateData.E_EnsembleNumber; data.BeamN[1, i] = (int)param.TemplateData.E_EnsembleNumber; data.BeamN[2, i] = (int)param.TemplateData.E_EnsembleNumber; data.BeamN[3, i] = (int)param.TemplateData.E_EnsembleNumber; //E000007 data.XfrmN[0, i] = (int)param.TemplateData.E_EnsembleNumber; data.XfrmN[1, i] = (int)param.TemplateData.E_EnsembleNumber; data.XfrmN[2, i] = (int)param.TemplateData.E_EnsembleNumber; data.XfrmN[3, i] = (int)param.TemplateData.E_EnsembleNumber; } //E000009 data.A_FirstCellDepth = param.ReferDepth / data.E_Cells; data.A_CellSize = data.A_FirstCellDepth; data.A_FirstPingSeconds = param.TemplateData.A_FirstPingSeconds; data.A_LastPingSeconds = param.TemplateData.A_LastPingSeconds; data.A_Heading = 0; data.A_Pitch = 0; data.A_Roll = 0; data.A_WaterTemperature = param.TemplateData.A_WaterTemperature; data.A_BoardTemperature = param.TemplateData.A_BoardTemperature; data.A_Salinity = param.TemplateData.A_Salinity; data.A_Pressure = param.TemplateData.A_Pressure; data.A_Depth = param.TemplateData.A_Depth; data.A_SpeedOfSound = param.TemplateData.A_SpeedOfSound; //E000010 data.B_FirstPingSeconds = param.TemplateData.B_FirstPingSeconds; data.B_LastPingSeconds = param.TemplateData.B_LastPingSeconds; data.B_Heading = 0; data.B_Pitch = 0; data.B_Roll = 0; data.B_WaterTemperature = param.TemplateData.B_WaterTemperature; data.B_BoardTemperature = param.TemplateData.B_BoardTemperature; data.B_Salinity = param.TemplateData.B_Salinity; data.B_Pressure = param.TemplateData.B_Pressure; data.B_Depth = data.A_CellSize * data.E_Cells; data.B_SpeedOfSound = param.TemplateData.B_SpeedOfSound; data.B_Status = 0; data.B_Beams = param.TemplateData.B_Beams; data.B_PingCount = param.TemplateData.B_PingCount; data.B_Range[0] = (float)(data.B_Depth * (1 + random.NextDouble() * param.NoiseSize)); data.B_Range[1] = (float)(data.B_Depth * (1 + random.NextDouble() * param.NoiseSize)); data.B_Range[2] = (float)(data.B_Depth * (1 + random.NextDouble() * param.NoiseSize)); data.B_Range[3] = (float)(data.B_Depth * (1 + random.NextDouble() * param.NoiseSize)); data.B_SNR[0] = 0; data.B_SNR[1] = 0; data.B_SNR[2] = 0; data.B_SNR[3] = 0; data.B_Amplitude[0] = param.ReferAmplitude; data.B_Amplitude[1] = param.ReferAmplitude; data.B_Amplitude[2] = param.ReferAmplitude; data.B_Amplitude[3] = param.ReferAmplitude; data.B_Correlation[0] = param.ReferCorrelation; data.B_Correlation[1] = param.ReferCorrelation; data.B_Correlation[2] = param.ReferCorrelation; data.B_Correlation[3] = param.ReferCorrelation; data.B_Instrument[0] = (float)(Math.Sin(Math.PI / 4) * param.ReferEarthVelocity * (1 + random.NextDouble() * param.NoiseSize)); data.B_Instrument[1] = (float)(-Math.Cos(Math.PI / 4) * param.ReferEarthVelocity * (1 + random.NextDouble() * param.NoiseSize)); data.B_Instrument[2] = 0; data.B_Instrument[3] = 0; data.B_Velocity[0] = 0; data.B_Velocity[1] = data.B_Instrument[0] * 2 * Math.Sign(param.BeamAngle / 180.0 * Math.PI); data.B_Velocity[2] = data.B_Instrument[1] * 2 * Math.Sign(param.BeamAngle / 180.0 * Math.PI);; data.B_Velocity[3] = 0; data.B_Earth[0] = data.B_Instrument[0]; data.B_Earth[1] = data.B_Instrument[1]; data.B_Earth[2] = 0; data.B_Earth[3] = 0; data.B_BeamN[0] = data.B_PingCount; data.B_BeamN[1] = data.B_PingCount; data.B_BeamN[2] = data.B_PingCount; data.B_BeamN[3] = data.B_PingCount; data.B_XfrmN[0] = data.B_PingCount; data.B_XfrmN[1] = data.B_PingCount; data.B_XfrmN[2] = data.B_PingCount; data.B_XfrmN[3] = data.B_PingCount; data.B_EarthN[0] = data.B_PingCount; data.B_EarthN[1] = data.B_PingCount; data.B_EarthN[2] = data.B_PingCount; data.B_EarthN[3] = data.B_PingCount; return(data); }
/// <summary> /// 计算实测单元流量 /// </summary> /// <param name="src">参与计算的数据</param> /// <param name="boatVelocity">船速(地理坐标系下)</param> /// <param name="dTime">时间差</param> /// <returns>单元流量信息集合</returns> public EnsembleFlowInfo CalculateEnsembleFlow(ArrayClass src, EarthVelocity boatVelocity, double dTime) { EnsembleFlowInfo ensembleFlow = new EnsembleFlowInfo(); ensembleFlow.Valid = false; if (Math.Abs(boatVelocity.EastVelocity) > 80 || Math.Abs(boatVelocity.NorthVelocity) > 80) { return(ensembleFlow); } //单元大小 double Da = src.A_CellSize; if (Da < 1e-6) { return(ensembleFlow); } //底跟踪四个波束中的最小深度 double Dmin = double.NaN; //计算四个波束的平均深度 int num = 0; double depthSum = 0; foreach (double d in src.B_Range) { if (d < 1e-6) { continue; } if (double.IsNaN(Dmin)) { Dmin = d; } else { if (d < Dmin) { Dmin = d; } } num++; depthSum += d; } if (num == 0) { return(ensembleFlow); } double Davg = depthSum / num; //有效单元的可能最大深度 double DLGmax = Dmin * Math.Cos(beamAngle / 180.0 * Math.PI) + draft - Math.Max((pulseLength + pulseLag) / 2.0, Da / 2.0); //水面到水底的距离 double Dtotal = Davg + draft; //第一个有效单元 MeasuredBinInfo firstValid = new MeasuredBinInfo(); firstValid.Status = BinFlowStatus.Bad; //最后一个有效单元 MeasuredBinInfo lastValid = new MeasuredBinInfo(); //单元深度 double binDepth = src.A_FirstCellDepth + draft; //实测累计流量 double SumMeasuredFlow = 0; //累计东向水速 double SumEastVelocity = 0; //累计北向水速 double SumNorthVelocity = 0; //GoodBin个数 int GoodBinCount = 0; List <MeasuredBinInfo> binsInfoArray = new List <MeasuredBinInfo>(); // 保存有效单元的索引号 List <int> validBinsIndex = new List <int>(); for (int i = 0; binDepth < DLGmax && i < src.E_Cells && i * 4 < src.Earth.Length; i++, binDepth += Da) { //获取矢量交叉乘积 double xi = CrossProduct(src.Earth[0, i], src.Earth[1, i], boatVelocity.EastVelocity, boatVelocity.NorthVelocity); MeasuredBinInfo binInfo = new MeasuredBinInfo(); binInfo.Depth = binDepth; binInfo.Flow = xi * dTime * Da; binInfo.Status = (IsGoodBin(src, i) ? BinFlowStatus.Good : BinFlowStatus.Bad); binsInfoArray.Add(binInfo); if (binInfo.Status == BinFlowStatus.Good) { if (firstValid.Status == BinFlowStatus.Bad) { firstValid = binInfo; } lastValid = binInfo; SumMeasuredFlow += binInfo.Flow; SumEastVelocity += src.Earth[0, i]; SumNorthVelocity += src.Earth[1, i]; GoodBinCount++; //保存一个有效单元索引 validBinsIndex.Add(i); } } ensembleFlow.BinsInfo = binsInfoArray.ToArray(); if (firstValid.Status == BinFlowStatus.Bad) { return(ensembleFlow); } //第一个有效单元的深度 double Dtop = firstValid.Depth; //最后一个有效单元的深度 double Dlg = lastValid.Depth; double Z3 = Dtotal; double Z2 = Dtotal - Dtop + Da / 2.0; double Z1 = Dtotal - Dlg - Da / 2.0; //实测流量 ensembleFlow.MeasuredFlow = dTime * (Z2 - Z1) * CrossProduct(SumEastVelocity / GoodBinCount, SumNorthVelocity / GoodBinCount, boatVelocity.EastVelocity, boatVelocity.NorthVelocity); //顶部流量 switch (topMode) { case TopFlowMode.Constants: ensembleFlow.TopFlow = firstValid.Flow / Da * (Z3 - Z2); break; case TopFlowMode.PowerFunction: { double a = exponent + 1; ensembleFlow.TopFlow = SumMeasuredFlow * (Math.Pow(Z3, a) - Math.Pow(Z2, a)) / (Math.Pow(Z2, a) - Math.Pow(Z1, a)); } break; case TopFlowMode.Slope: { //用于外延计算的 validbins 数量不足,则降为常数法计算 if (validBinsIndex.Count < 6) { ensembleFlow.TopFlow = firstValid.Flow / Da * (Z3 - Z2); break; } else { // validbin 的信息,三个列表是索引对应同一个 validbin // 每个 validbin 的深度信息 List <double> binsDepth = new List <double>(); // 每个 validbin 的东向速度 List <double> binsEastVelocity = new List <double>(); // 每个 validbin 的北向速度 List <double> binsNorthVelocity = new List <double>(); for (int i = 0; i < 3; i++) { // validbin 索引号 int bin_index = validBinsIndex[i]; // validbin 深度(从水面起) double bin_depth = src.A_FirstCellDepth + draft + bin_index * Da; // 东向和北向速度 double bin_east_vel = src.Earth[0, bin_index]; double bin_north_vel = src.Earth[1, bin_index]; //加入列表 binsDepth.Add(bin_depth); binsEastVelocity.Add(bin_east_vel); binsNorthVelocity.Add(bin_north_vel); } // 外延计算 // 外延的深度位置(从水面起算) double dep = (Z3 - Z2) / 2; // 外延计算东向速度 Slope east_slope = new Slope(); east_slope.setXYs(binsDepth.ToArray(), binsEastVelocity.ToArray()); double east_vel; try { east_vel = east_slope.calY(dep); } // 外延失败,斜角为90度,转而采用常数法 catch (DivideByZeroException) { ensembleFlow.TopFlow = firstValid.Flow / Da * (Z3 - Z2); break; } //外延计算北向速度 Slope north_slope = new Slope(); north_slope.setXYs(binsDepth.ToArray(), binsNorthVelocity.ToArray()); double north_vel; try { north_vel = north_slope.calY(dep); } // 外延失败,斜角为90度,转而采用常数法 catch (DivideByZeroException) { ensembleFlow.TopFlow = firstValid.Flow / Da * (Z3 - Z2); break; } // 计算流量 ensembleFlow.TopFlow = dTime * (Z3 - Z2) * CrossProduct(east_vel, north_vel, boatVelocity.EastVelocity, boatVelocity.NorthVelocity); break; } } default: break; } //底部流量 switch (bottomMode) { case BottomFlowMode.Constants: ensembleFlow.BottomFlow = lastValid.Flow / Da * Z1; break; case BottomFlowMode.PowerFunction: { double a = exponent + 1; ensembleFlow.BottomFlow = SumMeasuredFlow * Math.Pow(Z1, a) / (Math.Pow(Z2, a) - Math.Pow(Z1, a)); } break; default: break; } ensembleFlow.Valid = true; return(ensembleFlow); }
/// <summary> /// 判断是否为一个GoodBin /// </summary> /// <param name="src">参与计算数据</param> /// <param name="binIndex">bin的索引号</param> /// <returns>是否为GoodBin</returns> protected bool IsGoodBin(ArrayClass src, int binIndex) { try { int count = 0; for (int i = 0; i < 4; i++) { if (src.Amplitude[i, binIndex] < minAmplitude) { count++; } } if (count > 1) { return(false); } count = 0; for (int i = 0; i < 4; i++) { if (src.Correlation[i, binIndex] < minCorrelation) { count++; } } if (count > 1) { return(false); } //JZH 2012-02-06 JZH 取消旧判断方法 //if (src.BeamN[0, binIndex] < minNG3 // || src.BeamN[1, binIndex] < minNG3 // || src.BeamN[2, binIndex] < minNG3 // || src.BeamN[3, binIndex] < minNG4) // return false; //if (src.Earth[0, binIndex] > 88 // || src.Earth[1, binIndex] > 88 // || src.Earth[2, binIndex] > 88 // || src.Earth[3, binIndex] > 88 // ) // return false; //JZH 2012-02-06 新判断方法 if (src.Earth[0, binIndex] > 88 || src.Earth[1, binIndex] > 88 || src.Earth[2, binIndex] > 88 // || src.Earth[3, binIndex] > 88 ) { return(false); } } catch { return(false); } return(true); }
/// <summary> /// 计算表层和底层平均流速 /// </summary> /// <param name="src">参与计算的数据</param> public void CalculateAverageVelocity(ArrayClass src, ref double dTopVx, ref double dTopVy, ref double dBottomVx, ref double dBottomVy) { //单元大小 double Da = src.A_CellSize; if (Da < 1e-6) { return; } //底跟踪四个波束中的最小深度 double Dmin = double.NaN; //计算四个波束的平均深度 int num = 0; double depthSum = 0; foreach (double d in src.B_Range) { if (d < 1e-6) { continue; } if (double.IsNaN(Dmin)) { Dmin = d; } else { if (d < Dmin) { Dmin = d; } } num++; depthSum += d; } if (num == 0) { return; } double Davg = depthSum / num; //有效单元的可能最大深度 double DLGmax = Dmin * Math.Cos(beamAngle / 180.0 * Math.PI) + draft - Math.Max((pulseLength + pulseLag) / 2.0, Da / 2.0); //水面到水底的距离 double Dtotal = Davg + draft; //第一个有效单元 MeasuredBinInfo firstValid = new MeasuredBinInfo(); firstValid.Status = BinFlowStatus.Bad; //最后一个有效单元 MeasuredBinInfo lastValid = new MeasuredBinInfo(); //单元深度 double binDepth = src.A_FirstCellDepth + draft; //累计东向水速 double SumEastVelocity = 0; //累计北向水速 double SumNorthVelocity = 0; for (int i = 0; binDepth < DLGmax && i < src.E_Cells && i * 4 < src.Earth.Length; i++, binDepth += Da) { MeasuredBinInfo binInfo = new MeasuredBinInfo(); binInfo.Depth = binDepth; binInfo.Status = (IsGoodBin(src, i) ? BinFlowStatus.Good : BinFlowStatus.Bad); if (binInfo.Status == BinFlowStatus.Good) { if (firstValid.Status == BinFlowStatus.Bad) { firstValid = binInfo; } lastValid = binInfo; SumEastVelocity += src.Earth[0, i]; SumNorthVelocity += src.Earth[1, i]; } } if (firstValid.Status == BinFlowStatus.Bad) { return; } //第一个有效单元的深度 double Dtop = firstValid.Depth; //最后一个有效单元的深度 double Dlg = lastValid.Depth; double Z3 = Dtotal; double Z2 = Dtotal - Dtop + Da / 2.0; double Z1 = Dtotal - Dlg - Da / 2.0; //表层流速 double a = exponent + 1; dTopVx = SumEastVelocity * Da / (Dtop - Da / 2.0) * (Math.Pow(Z3, a) - Math.Pow(Z2, a)) / (Math.Pow(Z2, a) - Math.Pow(Z1, a)); dTopVy = SumNorthVelocity * Da / (Dtop - Da / 2.0) * (Math.Pow(Z3, a) - Math.Pow(Z2, a)) / (Math.Pow(Z2, a) - Math.Pow(Z1, a)); //底部流速 dBottomVx = SumEastVelocity * Da / Z1 * Math.Pow(Z1, a) / (Math.Pow(Z2, a) - Math.Pow(Z1, a)); dBottomVy = SumNorthVelocity * Da / Z1 * Math.Pow(Z1, a) / (Math.Pow(Z2, a) - Math.Pow(Z1, a)); }