コード例 #1
0
        /// <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);
        }