示例#1
0
        /// <summary>
        /// Main Streamflow Disaggregation script
        /// Follows procedures laid out by UofI's A.Acharya and Dr.Ryu
        /// We programmed a monthly-to-daily-disaggregation method in 2012 initially
        /// based on some research by University of Idaho academics; the paper that the
        /// program is based can be found in the links below. We've since made several
        /// modifications to the program mainly to make it more robust in the sense that
        /// it handles more cases that would have resulted in errors and to
        /// make the mass-balancing more appropriate.
        ///
        /// Published Journal Article - http://ascelibrary.org/doi/abs/10.1061/(ASCE)HE.1943-5584.0000818
        ///Article Manuscript - http://water.cals.uidaho.edu/publications/SimpleDisaggregation_Acharya_2013.pdf
        /// </summary>
        /// <param name="daily">daily series (cfs)</param>
        /// <param name="monthly">monthly series (cfs or acre-feet)</param>
        /// <returns></returns>
        public static Series RMSEInterp(Series daily, Series monthly)
        {
            // Generates the monthly totals for the RMS calculations in cu.ft/month
            Series SSmonthTot = MonthSum(Math.MonthlyAverage(daily));
            Series TSmonthTot = MonthSum(ConvertAcreFeetToCfs(monthly));

            // Builds a Series to keep track of the corresponding year with the minimum RMSe
            Series TSrms = RMSEGenerateMatchList(SSmonthTot, TSmonthTot);

            // New series for the estimated daily value
            Series TSdaily = new Series();

            // Loop to calculate the daily estimate
            for (int i = 0; i < TSrms.Count; i++)
            {
                int targetYear = Convert.ToInt16(TSrms[i].Value);
                int sourceYear = TSrms[i].DateTime.Year;

                // Leap Years are fun! Catch leap/non-leap year mismatches.
                // If the target is a leap year, this leaves 2-29 empty
                DateTime tLookup;
                if (TSrms[i].DateTime.Month == 2 && (DateTime.IsLeapYear(targetYear) ^ DateTime.IsLeapYear(sourceYear)))
                {
                    tLookup = new DateTime(targetYear, TSrms[i].DateTime.Month, 28);
                }
                else
                {
                    tLookup = new DateTime(targetYear, TSrms[i].DateTime.Month, TSrms[i].DateTime.Day);
                }

                // Calculates daily ratio of the monthly total for the SS
                double   SSmatchMonthly = SSmonthTot.Lookup(tLookup);
                DateTime tStart         = new DateTime(targetYear, TSrms[i].DateTime.Month, 1);
                Series   SSmatchDaily   = TimeSeries.Math.FillMissingWithZero(daily.Subset(tStart, tLookup));
                Series   SSratioTemp    = SSmatchDaily / SSmatchMonthly;

                // Catches NaN values if the SS monthly data is zero and leap day mass balance problems
                Series SSratio      = new Series();
                double leapDayRatio = 0.0;
                for (int x = 0; x < SSratioTemp.Count; x++)
                {
                    Point ptX = SSratioTemp[x];
                    if (ptX.Value.ToString() == "NaN" || SSmatchMonthly == 0.0)
                    {
                        SSratio.Add(ptX.DateTime, 0.0);
                        continue;
                    }
                    // Catches TS leap years and ensures that mass balance is preserved with Feb-29th
                    if (DateTime.IsLeapYear(sourceYear) && !DateTime.IsLeapYear(targetYear) &&
                        SSratio.MinDateTime.Month == 2)
                    {
                        leapDayRatio = leapDayRatio + (ptX.Value / 28.0);
                        SSratio.Add(ptX.DateTime, ptX.Value - (ptX.Value / 28.0));
                    }
                    else if (!DateTime.IsLeapYear(sourceYear) && DateTime.IsLeapYear(targetYear) &&
                             SSratio.MinDateTime.Month == 2)
                    {
                        leapDayRatio = daily[new DateTime(SSratioTemp.MaxDateTime.Year, 2, 29)].Value / SSmatchMonthly;
                        SSratio.Add(ptX.DateTime, ptX.Value + (leapDayRatio / 27.0));
                    }
                    else
                    {
                        SSratio.Add(ptX);
                    }
                }

                // Calculates the estimated daily for the TS given the monthly total and SS ratio
                TSdaily = RMSEGenerateDaily(TSdaily, TSmonthTot.Lookup(TSrms[i].DateTime.Date), SSmatchDaily, SSratio,
                                            targetYear, sourceYear, leapDayRatio);
            }

            return(TSdaily);
        }