using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using DotSpatial.Data;
using System.Windows.Forms;

namespace SMAT_CE
{
    class VisibilityCommonClass
    {
        public static DateTime _beginTime;//记录开始时间
        public static DateTime _endTime;//记录结束时间
        public static string _resultFilePath = "";
        public static bool VisibilityAnalysis(BaseScenario baseScenario)
        {
            if (!(baseScenario.configuration is VisibilityAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                VisibilityAnalysisConfiguration visibilityAnalysisConfiguration = baseScenario.configuration as VisibilityAnalysisConfiguration;
                //根据Choose Desired Output中选择的IMPROVE algorithm读取monitor data
                _beginTime = DateTime.Now;
                CommonClass.CurrentLog = "Read monitor data \"" + Path.GetFileName(visibilityAnalysisConfiguration.dataInputV.monitorDataFileNewAlgorithm) + "\".";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                Dictionary<string, VisibilityMonitor> dicVisibilityMonitors = null;
                string isReadOK = "";
                if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseOldVersionforIMPROVEAlgorithm)
                {

                }
                else if (visibilityAnalysisConfiguration.dataInputV.isCheckedForecastIMPROVEAdvanced)
                {
                    ReCalculateFutureVisibility(visibilityAnalysisConfiguration, dicVisibilityMonitors);
                }
                else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseNewVersionforIMPROVEAlgorithm)
                {
                    //CommonClass.CurrentBaseScenario.log.lstLog.Add("Loading monitor data...");
                    //CommonClass.CurrentLog = "Loading monitor data...";
                    _beginTime = DateTime.Now;
                    List<string> lstClassIArea = new List<string>();
                    //read monitor data
                    isReadOK = GetMonitorDataForNewIMPORVEAlgorithm(visibilityAnalysisConfiguration, ref dicVisibilityMonitors, ref lstClassIArea);
                    if (dicVisibilityMonitors.Count <= 0 || isReadOK == "unknow")//error message when loading file
                    {
                        CommonClass.CurrentLog = "Fail to read monitor data \"" + Path.GetFileName(visibilityAnalysisConfiguration.dataInputV.monitorDataFileNewAlgorithm) + "\".";
                        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                        return false;
                    }

                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentLog = "Finish reading monitor data: " + CommonClass.TotalTime + " s.";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    _beginTime = DateTime.Now;

                    //else
                    //{
                    //    if (isReadOK == "errorRow")
                    //    {
                    //        CommonClass.CurrentLog = "There are errors in the monitor file of " + visibilityAnalysisConfiguration.dataInputV.monitorDataFileNewAlgorithm + ". The error rows were removed.";
                    //        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    //    }
                    //}
                    //read file：156-Class1-coordinates-all site names.csv，class 1 area与monitors之间的对应关系
                    Dictionary<string, MonitorClass1AreaIdentifiers> dicClass1AreaMonitorsIdentifiersLocations = new Dictionary<string, MonitorClass1AreaIdentifiers>();
                    GetClassIAreaIdentifiers(visibilityAnalysisConfiguration, ref dicClass1AreaMonitorsIdentifiersLocations);

                    //先读取baseline/future model data中的id，经纬度用于计算gridcell
                    //--------------------------baseline model data---------------------------------------
                    Dictionary<string, VisibilityModelData> dicVisibilityModelData = new Dictionary<string, VisibilityModelData>();
                    GetModelDataAllID(visibilityAnalysisConfiguration, ref dicVisibilityModelData);
                    if (dicVisibilityModelData.Count <= 0)
                    {
                        CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(visibilityAnalysisConfiguration.dataInputV.baselineModelDataFile) + "\".";
                        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                        return false;
                    }
                    //CommonClass.CurrentBaseScenario.log.lstLog.Add("Computing geometry...");
                    //CommonClass.CurrentLog = "Computing geometry...";
                    //--------------计算RRF-------------
                    //-------------(1)根据choose desired output窗体的选项：Use model grid cells at monitor/Use model grid cells at Class 1 area centroid,判断monitors/Class 1 area属于哪个网格
                    //--------------首先得到monitor属于哪个网格-------简单的方法可以判断以最近的点作为它的网格。首先可以求出第一个网格的大小，在小于一倍网格宽度和长度的最大值求最近点
                    #region
                    //------monitor in grid cell-----------
                    Dictionary<string, string> dicMonitorInModel = new Dictionary<string, string>();
                    GetGridcellForMonitors(visibilityAnalysisConfiguration, ref dicMonitorInModel, dicClass1AreaMonitorsIdentifiersLocations, dicVisibilityModelData, dicVisibilityMonitors);

                    if (!CommonClass.IsBatch)
                    {
                        if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName)
                            _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName;
                    }
                    else
                    {
                        if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName)
                            _resultFilePath = CommonClass.ResultFilePath + @"\" + visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName;
                    }
                    if (!Directory.Exists(_resultFilePath))
                        System.IO.Directory.CreateDirectory(_resultFilePath);
                    SaveClass1AreaImproveMonitorsIdentifiersLocations(CommonClass.CurrentBaseScenario, dicClass1AreaMonitorsIdentifiersLocations, dicMonitorInModel);
                    //----------get all the grid cell needed-------------
                    Dictionary<string, VisibilityModelData> dicModelDataVisibilityUsed = new Dictionary<string, VisibilityModelData>();
                    GetGridcellNeeded(visibilityAnalysisConfiguration, ref dicModelDataVisibilityUsed, dicClass1AreaMonitorsIdentifiersLocations, dicMonitorInModel, dicVisibilityMonitors, dicVisibilityModelData);

                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish computing geometry: " + CommonClass.TotalTime + " s.");
                    CommonClass.CurrentLog = "Finish computing geometry: " + CommonClass.TotalTime + " s.";

                    dicVisibilityModelData.Clear();
                    //CommonClass.CurrentBaseScenario.log.lstLog.Add("Loading model data...");
                    //CommonClass.CurrentLog = "Loading model data...";
                    _beginTime = DateTime.Now;
                    CommonClass.CurrentLog = "Read model data \"" + Path.GetFileName(visibilityAnalysisConfiguration.dataInputV.baselineModelDataFile) + "\".";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    //-------read baseline/future model data-------------
                    isReadOK = GetModelDataNeeded(visibilityAnalysisConfiguration, ref dicModelDataVisibilityUsed);
                    switch (isReadOK)//error message when loading file
                    {
                        case "wrongBaseline":
                            CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(visibilityAnalysisConfiguration.dataInputV.baselineModelDataFile) + "\".";
                            CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                            return false;
                        case "wrongFuture":
                            CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(visibilityAnalysisConfiguration.dataInputV.forecastModelDataFile) + "\".";
                            CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                            return false;
                        case "unknow":
                            CommonClass.CurrentLog = "Fail to read the model data.";
                            CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                            return false;
                    }
                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentLog = "Finish reading model data: " + CommonClass.TotalTime + " s.";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                    //-------------计算RRF---------------
                    //然后根据data input 窗体中选择的using model data：3*3，1*1等得到monitors的model值
                    //CommonClass.CurrentBaseScenario.log.lstLog.Add("Generating RRFs and computing forecast...");
                    //CommonClass.CurrentLog = "Generating RRFs and computing forecast...";
                    _beginTime = DateTime.Now;
                    Dictionary<string, VisibilityModelData> dicUsedModelData = new Dictionary<string, VisibilityModelData>();
                    Dictionary<string, ForecastedVisibility> dicVisibilityForecastedValue = new Dictionary<string, ForecastedVisibility>();
                    Dictionary<int, List<string>> dicMonitorYears = new Dictionary<int, List<string>>();
                    int startYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear);
                    int endYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.endMonitorYear);
                    int minYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.minYearsForValidVisibilityMonitors);
                    for (int i = 0; i < (endYear - startYear + 1) - minYear + 1; i++)
                    {
                        List<string> lst = new List<string>();
                        for (int j = 0; j < minYear; j++)
                        {
                            lst.Add((startYear + i + j).ToString());
                        }
                        dicMonitorYears.Add(i, lst);
                    }

                    foreach (KeyValuePair<string, MonitorClass1AreaIdentifiers> k in dicClass1AreaMonitorsIdentifiersLocations)
                    {
                        if (k.Key.Replace("\"", "") == "EANE" || k.Key.Replace("\"", "") == "FLTO" || k.Key.Replace("\"", "") == "MABE"
                            || k.Key.Replace("\"", "") == "WEEL" || k.Key.Replace("\"", "") == "HOOV")
                        {
                            //string s = "";
                        }
                        if (!dicVisibilityMonitors.ContainsKey(k.Value.monitorID))
                        {
                            continue;
                        }
                        if (!dicMonitorInModel.ContainsKey(k.Key) || !dicVisibilityMonitors[k.Value.monitorID].dicNewIMPROVE.ContainsKey(visibilityAnalysisConfiguration.filteringV.baseModelYear)) continue;
                        bool isOK = false;
                        foreach (KeyValuePair<int, List<string>> kin in dicMonitorYears)
                        {
                            if (dicVisibilityMonitors[k.Value.monitorID].dicNewIMPROVE.Where(p => kin.Value.Contains(p.Key)).Count() == minYear)
                            {
                                isOK = true;
                                break;
                            }
                        }
                        if (!isOK) continue;
                        int Col = Convert.ToInt32(dicMonitorInModel[k.Key]) / 1000;
                        int Row = Convert.ToInt32(dicMonitorInModel[k.Key]) % 1000;
                        List<string> lstSurround = new List<string>();
                        switch (visibilityAnalysisConfiguration.dataInputV.temporalAdjustmentAtMonitorGrid)
                        {
                            case "1x1":
                                lstSurround.Add(dicMonitorInModel[k.Key]);
                                break;
                            case "3x3":
                                for (int i3 = -1; i3 <= 1; i3++)
                                {
                                    for (int j3 = -1; j3 <= 1; j3++)
                                    {
                                        lstSurround.Add(((Col + i3) * 1000 + (Row + j3)).ToString());
                                    }
                                }
                                break;
                            case "5x5":
                                for (int i5 = -2; i5 <= 2; i5++)
                                {
                                    for (int j5 = -2; j5 <= 2; j5++)
                                    {
                                        lstSurround.Add(((Col + i5) * 1000 + (Row + j5)).ToString());
                                    }

                                }
                                break;
                            case "7x7":
                                for (int i7 = -3; i7 <= 3; i7++)
                                {
                                    for (int j7 = -3; j7 <= 3; j7++)
                                    {
                                        lstSurround.Add(((Col + i7) * 1000 + (Row + j7)).ToString());
                                    }
                                }
                                break;
                        }
                        var query = dicModelDataVisibilityUsed.Where(p => lstSurround.Contains(p.Key));
                        int iQueryCount = query.Count();
                        //暂时计算rrf时全部求mean。
                        if (iQueryCount > 0)
                        {
                            List<double> lstVisibilityTemp = new List<double>();
                            //---save used grid cell------
                            if (!dicUsedModelData.ContainsKey(dicMonitorInModel[k.Key]))
                            {
                                dicUsedModelData.Add(dicMonitorInModel[k.Key], new VisibilityModelData()
                                {
                                    id = dicMonitorInModel[k.Key],
                                    type = dicModelDataVisibilityUsed[dicMonitorInModel[k.Key]].type,
                                    gridcellLat = dicModelDataVisibilityUsed[dicMonitorInModel[k.Key]].gridcellLat,
                                    gridcellLong = dicModelDataVisibilityUsed[dicMonitorInModel[k.Key]].gridcellLong,
                                    dicBaselineModel = new Dictionary<string, ModelDataVisibility>(),
                                    dicFutureModel = new Dictionary<string, ModelDataVisibility>(),
                                });
                            }
                            Dictionary<string, string> dicDays = new Dictionary<string, string>();
                            foreach (KeyValuePair<string, NewImproveMonitors> kDays in dicVisibilityMonitors[k.Value.monitorID].dicNewIMPROVE[visibilityAnalysisConfiguration.filteringV.baseModelYear])
                            {
                                dicDays.Add(kDays.Key, Convert.ToInt32(kDays.Value.group) == 90 ? "worst" : "best");
                            }

                            Dictionary<string, ModelDataVisibility> dicVmBaseline = new Dictionary<string, ModelDataVisibility>();
                            Dictionary<string, ModelDataVisibility> dicVmFuture = new Dictionary<string, ModelDataVisibility>();
                            Dictionary<string, ModelDataVisibility> dicVmBaselineBest = new Dictionary<string, ModelDataVisibility>();
                            Dictionary<string, ModelDataVisibility> dicVmBaselineWorst = new Dictionary<string, ModelDataVisibility>();
                            Dictionary<string, ModelDataVisibility> dicVmFutureBest = new Dictionary<string, ModelDataVisibility>();
                            Dictionary<string, ModelDataVisibility> dicVmFutureWorst = new Dictionary<string, ModelDataVisibility>();

                            #region
                            for (int i = 0; i < iQueryCount; i++)
                            {
                                KeyValuePair<string, VisibilityModelData> kin = query.ToArray()[i];
                                foreach (KeyValuePair<string, ModelDataVisibility> kBase in kin.Value.dicBaselineModel)
                                {
                                    if (!dicDays.ContainsKey(kBase.Key)) continue;
                                    if (query.ToArray()[i].Key == dicMonitorInModel[k.Key] && !dicUsedModelData[dicMonitorInModel[k.Key]].dicBaselineModel.ContainsKey(kBase.Key))
                                    {
                                        dicUsedModelData[dicMonitorInModel[k.Key]].dicBaselineModel.Add(kBase.Key, new ModelDataVisibility()
                                        {
                                            crustal = kBase.Value.crustal,
                                            so4 = kBase.Value.so4,
                                            ec = kBase.Value.ec,
                                            no3 = kBase.Value.no3,
                                            oc = kBase.Value.oc,
                                            cm = kBase.Value.cm,
                                            visibilityRank = dicDays[kBase.Key],
                                        });
                                    }
                                    if (dicVmBaseline.ContainsKey(kBase.Key))
                                    {
                                        dicVmBaseline[kBase.Key].crustal += kBase.Value.crustal;
                                        dicVmBaseline[kBase.Key].so4 += kBase.Value.so4;
                                        dicVmBaseline[kBase.Key].ec += kBase.Value.ec;
                                        dicVmBaseline[kBase.Key].no3 += kBase.Value.no3;
                                        dicVmBaseline[kBase.Key].oc += kBase.Value.oc;
                                        dicVmBaseline[kBase.Key].cm += kBase.Value.cm;
                                        dicVmBaseline[kBase.Key].visibilityRank = dicDays[kBase.Key];
                                    }
                                    else
                                    {
                                        dicVmBaseline.Add(kBase.Key, new ModelDataVisibility()
                                        {
                                            crustal = kBase.Value.crustal,
                                            so4 = kBase.Value.so4,
                                            ec = kBase.Value.ec,
                                            no3 = kBase.Value.no3,
                                            oc = kBase.Value.oc,
                                            cm = kBase.Value.cm,
                                            visibilityRank = dicDays[kBase.Key],
                                        });
                                    }
                                }

                                foreach (KeyValuePair<string, ModelDataVisibility> kFuture in kin.Value.dicFutureModel)
                                {
                                    if (!dicDays.ContainsKey(kFuture.Key)) continue;
                                    if (query.ToArray()[i].Key == dicMonitorInModel[k.Key] && !dicUsedModelData[dicMonitorInModel[k.Key]].dicFutureModel.ContainsKey(kFuture.Key))
                                    {
                                        dicUsedModelData[dicMonitorInModel[k.Key]].dicFutureModel.Add(kFuture.Key, new ModelDataVisibility()
                                        {
                                            crustal = kFuture.Value.crustal,
                                            so4 = kFuture.Value.so4,
                                            ec = kFuture.Value.ec,
                                            no3 = kFuture.Value.no3,
                                            oc = kFuture.Value.oc,
                                            cm = kFuture.Value.cm,
                                            visibilityRank = dicDays[kFuture.Key],
                                        });
                                    }
                                    if (dicVmFuture.ContainsKey(kFuture.Key))
                                    {
                                        dicVmFuture[kFuture.Key].crustal += kFuture.Value.crustal;
                                        dicVmFuture[kFuture.Key].so4 += kFuture.Value.so4;
                                        dicVmFuture[kFuture.Key].ec += kFuture.Value.ec;
                                        dicVmFuture[kFuture.Key].no3 += kFuture.Value.no3;
                                        dicVmFuture[kFuture.Key].oc += kFuture.Value.oc;
                                        dicVmFuture[kFuture.Key].cm += kFuture.Value.cm;
                                        dicVmFuture[kFuture.Key].visibilityRank = dicDays[kFuture.Key];
                                    }
                                    else
                                    {
                                        dicVmFuture.Add(kFuture.Key, new ModelDataVisibility()
                                        {
                                            crustal = kFuture.Value.crustal,
                                            so4 = kFuture.Value.so4,
                                            ec = kFuture.Value.ec,
                                            no3 = kFuture.Value.no3,
                                            oc = kFuture.Value.oc,
                                            cm = kFuture.Value.cm,
                                            visibilityRank = dicDays[kFuture.Key],
                                        });
                                    }
                                }
                            }
                            #endregion
                            //求3x3网格均值
                            #region
                            foreach (KeyValuePair<string, ModelDataVisibility> kBase in dicVmBaseline)
                            {
                                if (!dicDays.ContainsKey(kBase.Key)) continue;
                                kBase.Value.crustal = kBase.Value.crustal / iQueryCount;
                                kBase.Value.so4 = kBase.Value.so4 / iQueryCount;
                                kBase.Value.ec = kBase.Value.ec / iQueryCount;
                                kBase.Value.no3 = kBase.Value.no3 / iQueryCount;
                                kBase.Value.oc = kBase.Value.oc / iQueryCount;
                                kBase.Value.cm = kBase.Value.cm / iQueryCount;
                            }

                            foreach (KeyValuePair<string, ModelDataVisibility> kFuture in dicVmFuture)
                            {
                                if (!dicDays.ContainsKey(kFuture.Key)) continue;
                                kFuture.Value.crustal = kFuture.Value.crustal / iQueryCount;
                                kFuture.Value.so4 = kFuture.Value.so4 / iQueryCount;
                                kFuture.Value.ec = kFuture.Value.ec / iQueryCount;
                                kFuture.Value.no3 = kFuture.Value.no3 / iQueryCount;
                                kFuture.Value.oc = kFuture.Value.oc / iQueryCount;
                                kFuture.Value.cm = kFuture.Value.cm / iQueryCount;
                            }

                            //---------------根据best和worst对model求日均值，然后计算RRF----------
                            dicVmBaselineBest.Add(k.Key, new ModelDataVisibility()
                            {
                                crustal = dicVmBaseline.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.crustal).Average(),
                                so4 = dicVmBaseline.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.so4).Average(),
                                ec = dicVmBaseline.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.ec).Average(),
                                no3 = dicVmBaseline.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.no3).Average(),
                                oc = dicVmBaseline.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.oc).Average(),
                                cm = dicVmBaseline.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.cm).Average(),
                                visibilityRank = "best",
                            });

                            dicVmBaselineWorst.Add(k.Key, new ModelDataVisibility()
                            {
                                crustal = dicVmBaseline.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.crustal).Average(),
                                so4 = dicVmBaseline.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.so4).Average(),
                                ec = dicVmBaseline.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.ec).Average(),
                                no3 = dicVmBaseline.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.no3).Average(),
                                oc = dicVmBaseline.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.oc).Average(),
                                cm = dicVmBaseline.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.cm).Average(),
                                visibilityRank = "worst",
                            });

                            dicVmFutureBest.Add(k.Key, new ModelDataVisibility()
                            {
                                crustal = dicVmFuture.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.crustal).Average(),
                                so4 = dicVmFuture.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.so4).Average(),
                                ec = dicVmFuture.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.ec).Average(),
                                no3 = dicVmFuture.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.no3).Average(),
                                oc = dicVmFuture.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.oc).Average(),
                                cm = dicVmFuture.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.cm).Average(),
                                visibilityRank = "best",
                            });

                            dicVmFutureWorst.Add(k.Key, new ModelDataVisibility()
                            {
                                crustal = dicVmFuture.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.crustal).Average(),
                                so4 = dicVmFuture.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.so4).Average(),
                                ec = dicVmFuture.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.ec).Average(),
                                no3 = dicVmFuture.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.no3).Average(),
                                oc = dicVmFuture.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.oc).Average(),
                                cm = dicVmFuture.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.cm).Average(),
                                visibilityRank = "worst",
                            });

                            //------------判断是否满足最小值要求------------------
                            foreach (KeyValuePair<string, ModelDataVisibility> item in dicVmBaselineBest)
                            {
                                if (item.Value.crustal < CommonClass.RrfLimit) item.Value.crustal = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.so4 < CommonClass.RrfLimit) item.Value.so4 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.ec < CommonClass.RrfLimit) item.Value.ec = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.no3 < CommonClass.RrfLimit) item.Value.no3 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.oc < CommonClass.RrfLimit) item.Value.oc = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.cm < CommonClass.RrfLimit) item.Value.cm = Convert.ToSingle(CommonClass.RrfLimit);
                            }

                            foreach (KeyValuePair<string, ModelDataVisibility> item in dicVmBaselineWorst)
                            {
                                if (item.Value.crustal < CommonClass.RrfLimit) item.Value.crustal = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.so4 < CommonClass.RrfLimit) item.Value.so4 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.ec < CommonClass.RrfLimit) item.Value.ec = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.no3 < CommonClass.RrfLimit) item.Value.no3 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.oc < CommonClass.RrfLimit) item.Value.oc = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.cm < CommonClass.RrfLimit) item.Value.cm = Convert.ToSingle(CommonClass.RrfLimit);
                            }

                            foreach (KeyValuePair<string, ModelDataVisibility> item in dicVmFutureBest)
                            {
                                if (item.Value.crustal < CommonClass.RrfLimit) item.Value.crustal = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.so4 < CommonClass.RrfLimit) item.Value.so4 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.ec < CommonClass.RrfLimit) item.Value.ec = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.no3 < CommonClass.RrfLimit) item.Value.no3 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.oc < CommonClass.RrfLimit) item.Value.oc = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.cm < CommonClass.RrfLimit) item.Value.cm = Convert.ToSingle(CommonClass.RrfLimit);
                            }

                            foreach (KeyValuePair<string, ModelDataVisibility> item in dicVmFutureWorst)
                            {
                                if (item.Value.crustal < CommonClass.RrfLimit) item.Value.crustal = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.so4 < CommonClass.RrfLimit) item.Value.so4 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.ec < CommonClass.RrfLimit) item.Value.ec = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.no3 < CommonClass.RrfLimit) item.Value.no3 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.oc < CommonClass.RrfLimit) item.Value.oc = Convert.ToSingle(CommonClass.RrfLimit);
                                if (item.Value.cm < CommonClass.RrfLimit) item.Value.cm = Convert.ToSingle(CommonClass.RrfLimit);
                            }

                            #endregion
                            dicVisibilityForecastedValue.Add(k.Value.id, new ForecastedVisibility()
                            {
                                id = k.Value.id,
                                type = k.Value.type,
                                lat = k.Value.classIlat,
                                longitude = k.Value.classIlong,
                                monitorID = k.Value.monitorID,
                                monitorLat = k.Value.monitorLat,
                                monitorLongitude = k.Value.monitorLong,
                                gridcell = dicMonitorInModel[k.Key],
                                gridcellLat = dicModelDataVisibilityUsed[dicMonitorInModel[k.Key]].gridcellLat,
                                gridcellLong = dicModelDataVisibilityUsed[dicMonitorInModel[k.Key]].gridcellLong,
                                rrfbCrustal = dicVmFutureBest[k.Key].crustal / dicVmBaselineBest[k.Key].crustal,
                                rrfbSO4 = dicVmFutureBest[k.Key].so4 / dicVmBaselineBest[k.Key].so4,
                                rrfbEC = dicVmFutureBest[k.Key].ec / dicVmBaselineBest[k.Key].ec,
                                rrfbNO3 = dicVmFutureBest[k.Key].no3 / dicVmBaselineBest[k.Key].no3,
                                rrfbOC = dicVmFutureBest[k.Key].oc / dicVmBaselineBest[k.Key].oc,
                                rrfbCM = dicVmFutureBest[k.Key].cm / dicVmBaselineBest[k.Key].cm,
                                rrfwCrustal = dicVmFutureWorst[k.Key].crustal / dicVmBaselineWorst[k.Key].crustal,
                                rrfwSO4 = dicVmFutureWorst[k.Key].so4 / dicVmBaselineWorst[k.Key].so4,
                                rrfwEC = dicVmFutureWorst[k.Key].ec / dicVmBaselineWorst[k.Key].ec,
                                rrfwNO3 = dicVmFutureWorst[k.Key].no3 / dicVmBaselineWorst[k.Key].no3,
                                rrfwOC = dicVmFutureWorst[k.Key].oc / dicVmBaselineWorst[k.Key].oc,
                                rrfwCM = dicVmFutureWorst[k.Key].cm / dicVmBaselineWorst[k.Key].cm,
                                //rrfbCrustal = Math.Round(dicVmFutureBest[k.Key].crustal / dicVmBaselineBest[k.Key].crustal, 4),
                                //rrfbSO4 = Math.Round(dicVmFutureBest[k.Key].so4 / dicVmBaselineBest[k.Key].so4, 4),
                                //rrfbEC = Math.Round(dicVmFutureBest[k.Key].ec / dicVmBaselineBest[k.Key].ec, 4),
                                //rrfbNO3 = Math.Round(dicVmFutureBest[k.Key].no3 / dicVmBaselineBest[k.Key].no3, 4),
                                //rrfbOC = Math.Round(dicVmFutureBest[k.Key].oc / dicVmBaselineBest[k.Key].oc, 4),
                                //rrfbCM = Math.Round(dicVmFutureBest[k.Key].cm / dicVmBaselineBest[k.Key].cm, 4),
                                //rrfwCrustal = Math.Round(dicVmFutureWorst[k.Key].crustal / dicVmBaselineWorst[k.Key].crustal, 4),
                                //rrfwSO4 = Math.Round(dicVmFutureWorst[k.Key].so4 / dicVmBaselineWorst[k.Key].so4, 4),
                                //rrfwEC = Math.Round(dicVmFutureWorst[k.Key].ec / dicVmBaselineWorst[k.Key].ec, 4),
                                //rrfwNO3 = Math.Round(dicVmFutureWorst[k.Key].no3 / dicVmBaselineWorst[k.Key].no3, 4),
                                //rrfwOC = Math.Round(dicVmFutureWorst[k.Key].oc / dicVmBaselineWorst[k.Key].oc, 4),
                                //rrfwCM = Math.Round(dicVmFutureWorst[k.Key].cm / dicVmBaselineWorst[k.Key].cm, 4),
                                dicForecastedVisibilityValues = new Dictionary<string, ForecastedVisibilityDataAttribute>(),
                            });
                        }
                    }
                    #endregion

                    //生成used model data--baseline/future
                    SaveUsedModelDataReference(CommonClass.CurrentBaseScenario, dicUsedModelData, visibilityAnalysisConfiguration.filteringV.baseModelYear);
                    dicUsedModelData.Clear();
                    GC.Collect();

                    //----------先确定其他年份中的best & worst days，然后根据RRF计算future concentration values
                    #region
                    foreach (KeyValuePair<string, VisibilityMonitor> k in dicVisibilityMonitors)
                    {
                        List<string> lst = dicClass1AreaMonitorsIdentifiersLocations.Where(p => p.Value.monitorID == k.Key).Select(p => p.Key).ToList();
                        for (int i = 0; i < lst.Count(); i++)
                        {
                            if (!dicVisibilityForecastedValue.ContainsKey(lst[i])) continue;
                            if (lst[i] == "ANAD")
                            {
                            }
                            foreach (KeyValuePair<string, Dictionary<string, NewImproveMonitors>> kYear in k.Value.dicNewIMPROVE)
                            {
                                foreach (KeyValuePair<string, NewImproveMonitors> kDay in kYear.Value)
                                {
                                    //NO2默认情况下为0
                                    double NO2 = 0;
                                    //base dv
                                    kDay.Value.baseBext = 2.2 * kDay.Value.fsrh * kDay.Value.smallAmmSO4 + 4.8 * kDay.Value.flrh * kDay.Value.largeAmmSO4
                                          + 2.4 * kDay.Value.fsrh * kDay.Value.smallAmmNO3 + 5.1 * kDay.Value.flrh * kDay.Value.largeAmmNO3
                                          + 2.8 * kDay.Value.smallOMC + 6.1 * kDay.Value.largeOMC
                                          + 10 * kDay.Value.ec + kDay.Value.crustal + 0.6 * kDay.Value.cm + kDay.Value.ssRayleigh
                                          + 1.7 * kDay.Value.fssrh * kDay.Value.seaSalt + 0.33 * NO2;
                                    //kDay.Value.tbext = kDay.Value.baseBext;
                                    kDay.Value.baseDV = 10 * Math.Log(kDay.Value.baseBext / 10);

                                    //future dv,先依据best/worst rrf计算future values，然后再计算total extinction和dv
                                    //对于future values的计算，large和small amm_so4，amm_no3和amm_omc的计算不能直接乘以RRF，而是amm_so4*RRF，amm_no3*RRF和amm_omc*RRF,再按比例进行分配
                                    if (kDay.Value.group == 10)
                                    {
                                        kDay.Value.futureAmmSO4 = dicVisibilityForecastedValue[lst[i]].rrfbSO4 * kDay.Value.ammSO4;
                                        if (kDay.Value.futureAmmSO4 < 20)
                                            kDay.Value.futureLargeAmmSO4 = kDay.Value.futureAmmSO4 * kDay.Value.futureAmmSO4 / 20;
                                        else
                                            kDay.Value.futureLargeAmmSO4 = kDay.Value.futureAmmSO4;
                                        kDay.Value.futureSmallAmmSO4 = kDay.Value.futureAmmSO4 - kDay.Value.futureLargeAmmSO4;


                                        kDay.Value.futurAmmNO3 = dicVisibilityForecastedValue[lst[i]].rrfbNO3 * kDay.Value.ammNO3;
                                        if (kDay.Value.futurAmmNO3 < 20)
                                            kDay.Value.futureLargeAmmNO3 = kDay.Value.futurAmmNO3 * kDay.Value.futurAmmNO3 / 20;
                                        else
                                            kDay.Value.futureLargeAmmNO3 = kDay.Value.futurAmmNO3;
                                        kDay.Value.futureSmallAmmNO3 = kDay.Value.futurAmmNO3 - kDay.Value.futureLargeAmmNO3;

                                        kDay.Value.futureOMC = dicVisibilityForecastedValue[lst[i]].rrfbOC * kDay.Value.omc;
                                        if (kDay.Value.futureOMC < 20)
                                            kDay.Value.futureLargeOMC = kDay.Value.futureOMC * kDay.Value.futureOMC / 20;
                                        else
                                            kDay.Value.futureLargeOMC = kDay.Value.futureOMC;
                                        kDay.Value.futureSmallOMC = kDay.Value.futureOMC - kDay.Value.futureLargeOMC;

                                        kDay.Value.futureCrustal = dicVisibilityForecastedValue[lst[i]].rrfbCrustal * kDay.Value.crustal;
                                        kDay.Value.futureEC = dicVisibilityForecastedValue[lst[i]].rrfbEC * kDay.Value.ec;
                                        kDay.Value.futureCm = dicVisibilityForecastedValue[lst[i]].rrfbCM * kDay.Value.cm;
                                    }
                                    else if (kDay.Value.group == 90)
                                    {
                                        kDay.Value.futureAmmSO4 = dicVisibilityForecastedValue[lst[i]].rrfwSO4 * kDay.Value.ammSO4;
                                        if (kDay.Value.futureAmmSO4 < 20)
                                            kDay.Value.futureLargeAmmSO4 = kDay.Value.futureAmmSO4 * kDay.Value.futureAmmSO4 / 20;
                                        else
                                            kDay.Value.futureLargeAmmSO4 = kDay.Value.futureAmmSO4;
                                        kDay.Value.futureSmallAmmSO4 = kDay.Value.futureAmmSO4 - kDay.Value.futureLargeAmmSO4;


                                        kDay.Value.futurAmmNO3 = dicVisibilityForecastedValue[lst[i]].rrfwNO3 * kDay.Value.ammNO3;
                                        if (kDay.Value.futurAmmNO3 < 20)
                                            kDay.Value.futureLargeAmmNO3 = kDay.Value.futurAmmNO3 * kDay.Value.futurAmmNO3 / 20;
                                        else
                                            kDay.Value.futureLargeAmmNO3 = kDay.Value.futurAmmNO3;
                                        kDay.Value.futureSmallAmmNO3 = kDay.Value.futurAmmNO3 - kDay.Value.futureLargeAmmNO3;

                                        kDay.Value.futureOMC = dicVisibilityForecastedValue[lst[i]].rrfwOC * kDay.Value.omc;
                                        if (kDay.Value.futureOMC < 20)
                                            kDay.Value.futureLargeOMC = kDay.Value.futureOMC * kDay.Value.futureOMC / 20;
                                        else
                                            kDay.Value.futureLargeOMC = kDay.Value.futureOMC;
                                        kDay.Value.futureSmallOMC = kDay.Value.futureOMC - kDay.Value.futureLargeOMC;

                                        kDay.Value.futureCrustal = dicVisibilityForecastedValue[lst[i]].rrfwCrustal * kDay.Value.crustal;
                                        kDay.Value.futureEC = dicVisibilityForecastedValue[lst[i]].rrfwEC * kDay.Value.ec;
                                        kDay.Value.futureCm = dicVisibilityForecastedValue[lst[i]].rrfwCM * kDay.Value.cm;
                                    }
                                    kDay.Value.futureBext = 2.2 * kDay.Value.fsrh * kDay.Value.futureSmallAmmSO4 + 4.8 * kDay.Value.flrh * kDay.Value.futureLargeAmmSO4
                                         + 2.4 * kDay.Value.fsrh * kDay.Value.futureSmallAmmNO3 + 5.1 * kDay.Value.flrh * kDay.Value.futureLargeAmmNO3
                                         + 2.8 * kDay.Value.futureSmallOMC + 6.1 * kDay.Value.futureLargeOMC
                                         + 10 * kDay.Value.futureEC + kDay.Value.futureCrustal + 0.6 * kDay.Value.futureCm + kDay.Value.ssRayleigh
                                         + 1.7 * kDay.Value.fssrh * kDay.Value.seaSalt + 0.33 * NO2;
                                    kDay.Value.futureDV = 10 * Math.Log(kDay.Value.futureBext / 10);

                                    kDay.Value.future_e_amm_so4 = 2.2 * kDay.Value.fsrh * kDay.Value.futureSmallAmmSO4 + 4.8 * kDay.Value.flrh * kDay.Value.futureLargeAmmSO4;
                                    kDay.Value.future_e_amm_no3 = 2.4 * kDay.Value.fsrh * kDay.Value.futureSmallAmmNO3 + 5.1 * kDay.Value.flrh * kDay.Value.futureLargeAmmNO3;
                                    kDay.Value.future_e_omc = 2.8 * kDay.Value.futureSmallOMC + 6.1 * kDay.Value.futureLargeOMC;
                                    kDay.Value.future_e_ec = 10 * kDay.Value.futureEC;
                                    kDay.Value.future_e_crustal = kDay.Value.futureCrustal;
                                    kDay.Value.future_e_cm = 0.6 * kDay.Value.futureCm;
                                    kDay.Value.future_e_sea_salt = 1.7 * kDay.Value.fssrh * kDay.Value.seaSalt;
                                    kDay.Value.future_tbext = kDay.Value.futureBext;

                                }
                            }
                        }

                    }
                    #endregion
                    //计算每年的dv_best和dv_worst
                    #region
                    foreach (KeyValuePair<string, VisibilityMonitor> k in dicVisibilityMonitors)
                    {
                        List<string> lst = dicClass1AreaMonitorsIdentifiersLocations.Where(p => p.Value.monitorID == k.Key).Select(p => p.Key).ToList();
                        for (int i = 0; i < lst.Count(); i++)
                        {
                            if (!dicVisibilityForecastedValue.ContainsKey(lst[i])) continue;
                            foreach (KeyValuePair<string, Dictionary<string, NewImproveMonitors>> kYear in k.Value.dicNewIMPROVE)
                            {
                                #region  remove to GetForecastedVisibilityDataAttribute(), commented by sclong,2017-03-5,

                                /*
                                dicVisibilityForecastedValue[lst[i]].dicForecastedVisibilityValues.Add(kYear.Key, new ForecastedVisibilityDataAttribute()
                                {
                                    baseBest = Math.Round(kYear.Value.Where(p => p.Value.group == 10).Select(p => p.Value.baseDV).Average(), CommonClass.Visibility_calculation_decimal_point),
                                    baseWorst = Math.Round(kYear.Value.Where(p => p.Value.group == 90).Select(p => p.Value.baseDV).Average(), CommonClass.Visibility_calculation_decimal_point),
                                    dvBest = Math.Round(kYear.Value.Where(p => p.Value.group == 10).Select(p => p.Value.futureDV).Average(), CommonClass.Visibility_calculation_decimal_point),
                                    dvWorst = Math.Round(kYear.Value.Where(p => p.Value.group == 90).Select(p => p.Value.futureDV).Average(), CommonClass.Visibility_calculation_decimal_point),
                                    //commented by sclong，2017-02-14， re-calculate the deciview values (dv_best, dv_worst, base_best, base_worst) to the decimal point=2                            
                                    //baseBest = kYear.Value.Where(p => p.Value.group == 10).Select(p => p.Value.baseDV).Average(),
                                    //baseWorst = kYear.Value.Where(p => p.Value.group == 90).Select(p => p.Value.baseDV).Average(),
                                    //dvBest = kYear.Value.Where(p => p.Value.group == 10).Select(p => p.Value.futureDV).Average(),
                                    //dvWorst = kYear.Value.Where(p => p.Value.group == 90).Select(p => p.Value.futureDV).Average(),                                 
                                });
                                 */
                                #endregion remove to GetForecastedVisibilityDataAttribute(), commented by sclong,2017-03-5,

                                ForecastedVisibilityDataAttribute forecastedItem = GetForecastedVisibilityDataAttribute(kYear.Value);
                                dicVisibilityForecastedValue[lst[i]].dicForecastedVisibilityValues.Add(kYear.Key, forecastedItem);
                            }
                        }
                    }
                    #endregion
                    dicVisibilityForecastedValue = dicVisibilityForecastedValue.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                    //SaveAllDesignVluesForecatedVisibility(CommonClass.CurrentBaseScenario, dicVisibilityForecastedValue);
                    ////所有年份的均值
                    //SaveForecastedVisibility(CommonClass.CurrentBaseScenario, dicVisibilityForecastedValue);

                    bool isOutputOldFormat = System.Configuration.ConfigurationManager.AppSettings["VisibilityOldFormat"] == "T";
                    if (isOutputOldFormat)
                    {
                        SaveAllDesignVluesWithOldVariables(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);
                        SaveForecastedVisibilityWithOldVariables(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);
                    }
                    else
                    {
                        SaveAllDesignVluesWithNewFormat(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);
                        SaveForecastedVisibilityWithNewFormat(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);
                        //所有版本都需要根据isCreateForecastIMPROVEData进行是否输出Forecast IMPROVE Daily Data
                        if (visibilityAnalysisConfiguration.dataInputV.isCreateForecastIMPROVEData)
                        {
                            SaveForecastIMPROVEDailyData(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);
                        }
                    }
                    #region commented by sclong, betaVersion需要引入新 the new “create forecast IMPROVE visibility file”，因此不再输出旧格式
                    /*
                    //betaVersion需要隐藏新变量输出。
                    if (CommonClass.BetaVersion)
                    {
                        SaveAllDesignVluesWithOldVariables(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);
                        SaveForecastedVisibilityWithOldVariables(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);
                    }
                    else
                    {
                        SaveAllDesignVluesWithNewFormat(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);
                        SaveForecastedVisibilityWithNewFormat(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue) if (visibilityAnalysisConfiguration.dataInputV.isCreateForecastIMPROVEData)
                        {
                            SaveForecastIMPROVEDailyData(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);
                        }
                    }*/
                    #endregion

                    dicVisibilityForecastedValue.Clear();
                    GC.Collect();

                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish generating RRFs and computing forecast: " + CommonClass.TotalTime + " s.");
                    CommonClass.CurrentLog = "Finish generating RRFs and computing forecast: " + CommonClass.TotalTime + " s.";

                    //CommonClass.CurrentBaseScenario.log.lstLog.Add("Completed visibility analysis.");
                    //CommonClass.CurrentLog = "Completed visibility analysis.";
                }

                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }

        }

        /// <summary>
        /// Recalculate future Visibility for Advance options
        /// </summary>
        /// <param name="visibilityAnalysisConfiguration"></param>
        /// <param name="dicVisibilityMonitors"></param>
        /// <returns></returns>
        private static bool ReCalculateFutureVisibility(VisibilityAnalysisConfiguration visibilityAnalysisConfiguration, Dictionary<string, VisibilityMonitor> dicVisibilityMonitors)
        {
            try
            {
                List<string> lstClassIArea = new List<string>();
                string isReadOK = "";
                //read monitor data
                #region 1.read monitor data(IMPROVE Daily Monitor data)
                _beginTime = DateTime.Now;
                isReadOK = GetIMPROVEDailyMonitorData(visibilityAnalysisConfiguration, ref dicVisibilityMonitors, ref lstClassIArea);
                if (dicVisibilityMonitors.Count <= 0 || isReadOK == "unknow")//error message when loading file
                {
                    CommonClass.CurrentLog = "Fail to read monitor data \"" + Path.GetFileName(visibilityAnalysisConfiguration.dataInputV.monitorDataFileNewAlgorithm) + "\".";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    return false;
                }
                _endTime = DateTime.Now;
                CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                CommonClass.CurrentLog = "Finish reading monitor data: " + CommonClass.TotalTime + " s.";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                #endregion 1.read monitor data(IMPROVE Daily Monitor data)

                #region 2.Read 156-Class1-coordinates-all site names_new-2017.csv, class 1 area与monitors之间的对应关系

                _beginTime = DateTime.Now;
                Dictionary<string, MonitorClass1AreaIdentifiers> dicClass1AreaMonitorsIdentifiersLocations = new Dictionary<string, MonitorClass1AreaIdentifiers>();
                GetClassIAreaIdentifiers(visibilityAnalysisConfiguration, ref dicClass1AreaMonitorsIdentifiersLocations);


                //先读取baseline/future model data中的id，经纬度用于计算gridcell
                //--------------------------baseline model data---------------------------------------
                Dictionary<string, VisibilityModelData> dicVisibilityModelData = new Dictionary<string, VisibilityModelData>();
                GetModelDataAllID(visibilityAnalysisConfiguration, ref dicVisibilityModelData);
                if (dicVisibilityModelData.Count <= 0)
                {
                    CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(visibilityAnalysisConfiguration.dataInputV.baselineModelDataFile) + "\".";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    return false;
                }
                #endregion 2.156-Class1-coordinates-all site names_new-2017.csv

                //--------------首先得到monitor属于哪个网格-------简单的方法可以判断以最近的点作为它的网格。首先可以求出第一个网格的大小，在小于一倍网格宽度和长度的最大值求最近点
                #region
                //------monitor in grid cell-----------
                Dictionary<string, string> dicMonitorInModel = new Dictionary<string, string>();
                GetGridcellForMonitors(visibilityAnalysisConfiguration, ref dicMonitorInModel, dicClass1AreaMonitorsIdentifiersLocations, dicVisibilityModelData, dicVisibilityMonitors);

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);
                SaveClass1AreaImproveMonitorsIdentifiersLocations(CommonClass.CurrentBaseScenario, dicClass1AreaMonitorsIdentifiersLocations, dicMonitorInModel);
                //----------get all the grid cell needed-------------
                Dictionary<string, VisibilityModelData> dicModelDataVisibilityUsed = new Dictionary<string, VisibilityModelData>();
                GetGridcellNeeded(visibilityAnalysisConfiguration, ref dicModelDataVisibilityUsed, dicClass1AreaMonitorsIdentifiersLocations, dicMonitorInModel, dicVisibilityMonitors, dicVisibilityModelData);

                _endTime = DateTime.Now;
                CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish computing geometry: " + CommonClass.TotalTime + " s.");
                CommonClass.CurrentLog = "Finish computing geometry: " + CommonClass.TotalTime + " s.";

                dicVisibilityModelData.Clear();
                //CommonClass.CurrentBaseScenario.log.lstLog.Add("Loading model data...");
                //CommonClass.CurrentLog = "Loading model data...";
                _beginTime = DateTime.Now;
                CommonClass.CurrentLog = "Read model data \"" + Path.GetFileName(visibilityAnalysisConfiguration.dataInputV.baselineModelDataFile) + "\".";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                //-------read baseline/future model data-------------
                isReadOK = GetModelDataNeeded(visibilityAnalysisConfiguration, ref dicModelDataVisibilityUsed);
                switch (isReadOK)//error message when loading file
                {
                    case "wrongBaseline":
                        CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(visibilityAnalysisConfiguration.dataInputV.baselineModelDataFile) + "\".";
                        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                        return false;
                    case "wrongFuture":
                        CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(visibilityAnalysisConfiguration.dataInputV.forecastModelDataFile) + "\".";
                        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                        return false;
                    case "unknow":
                        CommonClass.CurrentLog = "Fail to read the model data.";
                        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                        return false;
                }
                _endTime = DateTime.Now;
                CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                CommonClass.CurrentLog = "Finish reading model data: " + CommonClass.TotalTime + " s.";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                //-------------计算RRF---------------
                //然后根据data input 窗体中选择的using model data：3*3，1*1等得到monitors的model值
                //CommonClass.CurrentBaseScenario.log.lstLog.Add("Generating RRFs and computing forecast...");
                //CommonClass.CurrentLog = "Generating RRFs and computing forecast...";
                _beginTime = DateTime.Now;
                Dictionary<string, VisibilityModelData> dicUsedModelData = new Dictionary<string, VisibilityModelData>();
                Dictionary<string, ForecastedVisibility> dicVisibilityForecastedValue = new Dictionary<string, ForecastedVisibility>();
                Dictionary<int, List<string>> dicMonitorYears = new Dictionary<int, List<string>>();
                int startYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear);
                int endYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.endMonitorYear);
                int minYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.minYearsForValidVisibilityMonitors);
                for (int i = 0; i < (endYear - startYear + 1) - minYear + 1; i++)
                {
                    List<string> lst = new List<string>();
                    for (int j = 0; j < minYear; j++)
                    {
                        lst.Add((startYear + i + j).ToString());
                    }
                    dicMonitorYears.Add(i, lst);
                }

                foreach (KeyValuePair<string, MonitorClass1AreaIdentifiers> k in dicClass1AreaMonitorsIdentifiersLocations)
                {
                    if (k.Key.Replace("\"", "") == "EANE" || k.Key.Replace("\"", "") == "FLTO" || k.Key.Replace("\"", "") == "MABE"
                        || k.Key.Replace("\"", "") == "WEEL" || k.Key.Replace("\"", "") == "HOOV")
                    {
                        //string s = "";
                    }
                    if (!dicMonitorInModel.ContainsKey(k.Key) || !dicVisibilityMonitors[k.Value.monitorID].dicNewIMPROVE.ContainsKey(visibilityAnalysisConfiguration.filteringV.baseModelYear)) continue;
                    bool isOK = false;
                    foreach (KeyValuePair<int, List<string>> kin in dicMonitorYears)
                    {
                        if (dicVisibilityMonitors[k.Value.monitorID].dicNewIMPROVE.Where(p => kin.Value.Contains(p.Key)).Count() == minYear)
                        {
                            isOK = true;
                            break;
                        }
                    }
                    if (!isOK) continue;
                    int Col = Convert.ToInt32(dicMonitorInModel[k.Key]) / 1000;
                    int Row = Convert.ToInt32(dicMonitorInModel[k.Key]) % 1000;
                    List<string> lstSurround = new List<string>();
                    switch (visibilityAnalysisConfiguration.dataInputV.temporalAdjustmentAtMonitorGrid)
                    {
                        case "1x1":
                            lstSurround.Add(dicMonitorInModel[k.Key]);
                            break;
                        case "3x3":
                            for (int i3 = -1; i3 <= 1; i3++)
                            {
                                for (int j3 = -1; j3 <= 1; j3++)
                                {
                                    lstSurround.Add(((Col + i3) * 1000 + (Row + j3)).ToString());
                                }
                            }
                            break;
                        case "5x5":
                            for (int i5 = -2; i5 <= 2; i5++)
                            {
                                for (int j5 = -2; j5 <= 2; j5++)
                                {
                                    lstSurround.Add(((Col + i5) * 1000 + (Row + j5)).ToString());
                                }

                            }
                            break;
                        case "7x7":
                            for (int i7 = -3; i7 <= 3; i7++)
                            {
                                for (int j7 = -3; j7 <= 3; j7++)
                                {
                                    lstSurround.Add(((Col + i7) * 1000 + (Row + j7)).ToString());
                                }
                            }
                            break;
                    }
                    var query = dicModelDataVisibilityUsed.Where(p => lstSurround.Contains(p.Key));
                    int iQueryCount = query.Count();
                    //暂时计算rrf时全部求mean。
                    if (iQueryCount > 0)
                    {
                        List<double> lstVisibilityTemp = new List<double>();
                        //---save used grid cell------
                        if (!dicUsedModelData.ContainsKey(dicMonitorInModel[k.Key]))
                        {
                            dicUsedModelData.Add(dicMonitorInModel[k.Key], new VisibilityModelData()
                            {
                                id = dicMonitorInModel[k.Key],
                                type = dicModelDataVisibilityUsed[dicMonitorInModel[k.Key]].type,
                                gridcellLat = dicModelDataVisibilityUsed[dicMonitorInModel[k.Key]].gridcellLat,
                                gridcellLong = dicModelDataVisibilityUsed[dicMonitorInModel[k.Key]].gridcellLong,
                                dicBaselineModel = new Dictionary<string, ModelDataVisibility>(),
                                dicFutureModel = new Dictionary<string, ModelDataVisibility>(),
                            });
                        }
                        Dictionary<string, string> dicDays = new Dictionary<string, string>();
                        foreach (KeyValuePair<string, NewImproveMonitors> kDays in dicVisibilityMonitors[k.Value.monitorID].dicNewIMPROVE[visibilityAnalysisConfiguration.filteringV.baseModelYear])
                        {
                            dicDays.Add(kDays.Key, Convert.ToInt32(kDays.Value.group) == 90 ? "worst" : "best");
                        }

                        Dictionary<string, ModelDataVisibility> dicVmBaseline = new Dictionary<string, ModelDataVisibility>();
                        Dictionary<string, ModelDataVisibility> dicVmFuture = new Dictionary<string, ModelDataVisibility>();
                        Dictionary<string, ModelDataVisibility> dicVmBaselineBest = new Dictionary<string, ModelDataVisibility>();
                        Dictionary<string, ModelDataVisibility> dicVmBaselineWorst = new Dictionary<string, ModelDataVisibility>();
                        Dictionary<string, ModelDataVisibility> dicVmFutureBest = new Dictionary<string, ModelDataVisibility>();
                        Dictionary<string, ModelDataVisibility> dicVmFutureWorst = new Dictionary<string, ModelDataVisibility>();

                        #region
                        for (int i = 0; i < iQueryCount; i++)
                        {
                            KeyValuePair<string, VisibilityModelData> kin = query.ToArray()[i];
                            foreach (KeyValuePair<string, ModelDataVisibility> kBase in kin.Value.dicBaselineModel)
                            {
                                if (!dicDays.ContainsKey(kBase.Key)) continue;
                                if (query.ToArray()[i].Key == dicMonitorInModel[k.Key] && !dicUsedModelData[dicMonitorInModel[k.Key]].dicBaselineModel.ContainsKey(kBase.Key))
                                {
                                    dicUsedModelData[dicMonitorInModel[k.Key]].dicBaselineModel.Add(kBase.Key, new ModelDataVisibility()
                                    {
                                        crustal = kBase.Value.crustal,
                                        so4 = kBase.Value.so4,
                                        ec = kBase.Value.ec,
                                        no3 = kBase.Value.no3,
                                        oc = kBase.Value.oc,
                                        cm = kBase.Value.cm,
                                        visibilityRank = dicDays[kBase.Key],
                                    });
                                }
                                if (dicVmBaseline.ContainsKey(kBase.Key))
                                {
                                    dicVmBaseline[kBase.Key].crustal += kBase.Value.crustal;
                                    dicVmBaseline[kBase.Key].so4 += kBase.Value.so4;
                                    dicVmBaseline[kBase.Key].ec += kBase.Value.ec;
                                    dicVmBaseline[kBase.Key].no3 += kBase.Value.no3;
                                    dicVmBaseline[kBase.Key].oc += kBase.Value.oc;
                                    dicVmBaseline[kBase.Key].cm += kBase.Value.cm;
                                    dicVmBaseline[kBase.Key].visibilityRank = dicDays[kBase.Key];
                                }
                                else
                                {
                                    dicVmBaseline.Add(kBase.Key, new ModelDataVisibility()
                                    {
                                        crustal = kBase.Value.crustal,
                                        so4 = kBase.Value.so4,
                                        ec = kBase.Value.ec,
                                        no3 = kBase.Value.no3,
                                        oc = kBase.Value.oc,
                                        cm = kBase.Value.cm,
                                        visibilityRank = dicDays[kBase.Key],
                                    });
                                }
                            }

                            foreach (KeyValuePair<string, ModelDataVisibility> kFuture in kin.Value.dicFutureModel)
                            {
                                if (!dicDays.ContainsKey(kFuture.Key)) continue;
                                if (query.ToArray()[i].Key == dicMonitorInModel[k.Key] && !dicUsedModelData[dicMonitorInModel[k.Key]].dicFutureModel.ContainsKey(kFuture.Key))
                                {
                                    dicUsedModelData[dicMonitorInModel[k.Key]].dicFutureModel.Add(kFuture.Key, new ModelDataVisibility()
                                    {
                                        crustal = kFuture.Value.crustal,
                                        so4 = kFuture.Value.so4,
                                        ec = kFuture.Value.ec,
                                        no3 = kFuture.Value.no3,
                                        oc = kFuture.Value.oc,
                                        cm = kFuture.Value.cm,
                                        visibilityRank = dicDays[kFuture.Key],
                                    });
                                }
                                if (dicVmFuture.ContainsKey(kFuture.Key))
                                {
                                    dicVmFuture[kFuture.Key].crustal += kFuture.Value.crustal;
                                    dicVmFuture[kFuture.Key].so4 += kFuture.Value.so4;
                                    dicVmFuture[kFuture.Key].ec += kFuture.Value.ec;
                                    dicVmFuture[kFuture.Key].no3 += kFuture.Value.no3;
                                    dicVmFuture[kFuture.Key].oc += kFuture.Value.oc;
                                    dicVmFuture[kFuture.Key].cm += kFuture.Value.cm;
                                    dicVmFuture[kFuture.Key].visibilityRank = dicDays[kFuture.Key];
                                }
                                else
                                {
                                    dicVmFuture.Add(kFuture.Key, new ModelDataVisibility()
                                    {
                                        crustal = kFuture.Value.crustal,
                                        so4 = kFuture.Value.so4,
                                        ec = kFuture.Value.ec,
                                        no3 = kFuture.Value.no3,
                                        oc = kFuture.Value.oc,
                                        cm = kFuture.Value.cm,
                                        visibilityRank = dicDays[kFuture.Key],
                                    });
                                }
                            }
                        }
                        #endregion
                        //求3x3网格均值
                        #region
                        foreach (KeyValuePair<string, ModelDataVisibility> kBase in dicVmBaseline)
                        {
                            if (!dicDays.ContainsKey(kBase.Key)) continue;
                            kBase.Value.crustal = kBase.Value.crustal / iQueryCount;
                            kBase.Value.so4 = kBase.Value.so4 / iQueryCount;
                            kBase.Value.ec = kBase.Value.ec / iQueryCount;
                            kBase.Value.no3 = kBase.Value.no3 / iQueryCount;
                            kBase.Value.oc = kBase.Value.oc / iQueryCount;
                            kBase.Value.cm = kBase.Value.cm / iQueryCount;
                        }

                        foreach (KeyValuePair<string, ModelDataVisibility> kFuture in dicVmFuture)
                        {
                            if (!dicDays.ContainsKey(kFuture.Key)) continue;
                            kFuture.Value.crustal = kFuture.Value.crustal / iQueryCount;
                            kFuture.Value.so4 = kFuture.Value.so4 / iQueryCount;
                            kFuture.Value.ec = kFuture.Value.ec / iQueryCount;
                            kFuture.Value.no3 = kFuture.Value.no3 / iQueryCount;
                            kFuture.Value.oc = kFuture.Value.oc / iQueryCount;
                            kFuture.Value.cm = kFuture.Value.cm / iQueryCount;
                        }

                        //---------------根据best和worst对model求日均值，然后计算RRF----------
                        dicVmBaselineBest.Add(k.Key, new ModelDataVisibility()
                        {
                            crustal = dicVmBaseline.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.crustal).Average(),
                            so4 = dicVmBaseline.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.so4).Average(),
                            ec = dicVmBaseline.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.ec).Average(),
                            no3 = dicVmBaseline.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.no3).Average(),
                            oc = dicVmBaseline.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.oc).Average(),
                            cm = dicVmBaseline.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.cm).Average(),
                            visibilityRank = "best",
                        });

                        dicVmBaselineWorst.Add(k.Key, new ModelDataVisibility()
                        {
                            crustal = dicVmBaseline.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.crustal).Average(),
                            so4 = dicVmBaseline.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.so4).Average(),
                            ec = dicVmBaseline.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.ec).Average(),
                            no3 = dicVmBaseline.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.no3).Average(),
                            oc = dicVmBaseline.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.oc).Average(),
                            cm = dicVmBaseline.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.cm).Average(),
                            visibilityRank = "worst",
                        });

                        dicVmFutureBest.Add(k.Key, new ModelDataVisibility()
                        {
                            crustal = dicVmFuture.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.crustal).Average(),
                            so4 = dicVmFuture.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.so4).Average(),
                            ec = dicVmFuture.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.ec).Average(),
                            no3 = dicVmFuture.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.no3).Average(),
                            oc = dicVmFuture.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.oc).Average(),
                            cm = dicVmFuture.Where(p => p.Value.visibilityRank == "best" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.cm).Average(),
                            visibilityRank = "best",
                        });

                        dicVmFutureWorst.Add(k.Key, new ModelDataVisibility()
                        {
                            crustal = dicVmFuture.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.crustal).Average(),
                            so4 = dicVmFuture.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.so4).Average(),
                            ec = dicVmFuture.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.ec).Average(),
                            no3 = dicVmFuture.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.no3).Average(),
                            oc = dicVmFuture.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.oc).Average(),
                            cm = dicVmFuture.Where(p => p.Value.visibilityRank == "worst" && dicDays.ContainsKey(p.Key)).Select(p => p.Value.cm).Average(),
                            visibilityRank = "worst",
                        });

                        //------------判断是否满足最小值要求------------------
                        foreach (KeyValuePair<string, ModelDataVisibility> item in dicVmBaselineBest)
                        {
                            if (item.Value.crustal < CommonClass.RrfLimit) item.Value.crustal = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.so4 < CommonClass.RrfLimit) item.Value.so4 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.ec < CommonClass.RrfLimit) item.Value.ec = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.no3 < CommonClass.RrfLimit) item.Value.no3 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.oc < CommonClass.RrfLimit) item.Value.oc = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.cm < CommonClass.RrfLimit) item.Value.cm = Convert.ToSingle(CommonClass.RrfLimit);
                        }

                        foreach (KeyValuePair<string, ModelDataVisibility> item in dicVmBaselineWorst)
                        {
                            if (item.Value.crustal < CommonClass.RrfLimit) item.Value.crustal = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.so4 < CommonClass.RrfLimit) item.Value.so4 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.ec < CommonClass.RrfLimit) item.Value.ec = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.no3 < CommonClass.RrfLimit) item.Value.no3 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.oc < CommonClass.RrfLimit) item.Value.oc = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.cm < CommonClass.RrfLimit) item.Value.cm = Convert.ToSingle(CommonClass.RrfLimit);
                        }

                        foreach (KeyValuePair<string, ModelDataVisibility> item in dicVmFutureBest)
                        {
                            if (item.Value.crustal < CommonClass.RrfLimit) item.Value.crustal = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.so4 < CommonClass.RrfLimit) item.Value.so4 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.ec < CommonClass.RrfLimit) item.Value.ec = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.no3 < CommonClass.RrfLimit) item.Value.no3 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.oc < CommonClass.RrfLimit) item.Value.oc = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.cm < CommonClass.RrfLimit) item.Value.cm = Convert.ToSingle(CommonClass.RrfLimit);
                        }

                        foreach (KeyValuePair<string, ModelDataVisibility> item in dicVmFutureWorst)
                        {
                            if (item.Value.crustal < CommonClass.RrfLimit) item.Value.crustal = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.so4 < CommonClass.RrfLimit) item.Value.so4 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.ec < CommonClass.RrfLimit) item.Value.ec = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.no3 < CommonClass.RrfLimit) item.Value.no3 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.oc < CommonClass.RrfLimit) item.Value.oc = Convert.ToSingle(CommonClass.RrfLimit);
                            if (item.Value.cm < CommonClass.RrfLimit) item.Value.cm = Convert.ToSingle(CommonClass.RrfLimit);
                        }

                        #endregion
                        dicVisibilityForecastedValue.Add(k.Value.id, new ForecastedVisibility()
                        {
                            id = k.Value.id,
                            type = k.Value.type,
                            lat = k.Value.classIlat,
                            longitude = k.Value.classIlong,
                            monitorID = k.Value.monitorID,
                            monitorLat = k.Value.monitorLat,
                            monitorLongitude = k.Value.monitorLong,
                            gridcell = dicMonitorInModel[k.Key],
                            gridcellLat = dicModelDataVisibilityUsed[dicMonitorInModel[k.Key]].gridcellLat,
                            gridcellLong = dicModelDataVisibilityUsed[dicMonitorInModel[k.Key]].gridcellLong,
                            rrfbCrustal = dicVmFutureBest[k.Key].crustal / dicVmBaselineBest[k.Key].crustal,
                            rrfbSO4 = dicVmFutureBest[k.Key].so4 / dicVmBaselineBest[k.Key].so4,
                            rrfbEC = dicVmFutureBest[k.Key].ec / dicVmBaselineBest[k.Key].ec,
                            rrfbNO3 = dicVmFutureBest[k.Key].no3 / dicVmBaselineBest[k.Key].no3,
                            rrfbOC = dicVmFutureBest[k.Key].oc / dicVmBaselineBest[k.Key].oc,
                            rrfbCM = dicVmFutureBest[k.Key].cm / dicVmBaselineBest[k.Key].cm,
                            rrfwCrustal = dicVmFutureWorst[k.Key].crustal / dicVmBaselineWorst[k.Key].crustal,
                            rrfwSO4 = dicVmFutureWorst[k.Key].so4 / dicVmBaselineWorst[k.Key].so4,
                            rrfwEC = dicVmFutureWorst[k.Key].ec / dicVmBaselineWorst[k.Key].ec,
                            rrfwNO3 = dicVmFutureWorst[k.Key].no3 / dicVmBaselineWorst[k.Key].no3,
                            rrfwOC = dicVmFutureWorst[k.Key].oc / dicVmBaselineWorst[k.Key].oc,
                            rrfwCM = dicVmFutureWorst[k.Key].cm / dicVmBaselineWorst[k.Key].cm,
                            dicForecastedVisibilityValues = new Dictionary<string, ForecastedVisibilityDataAttribute>(),
                        });
                    }
                }
                #endregion

                //生成used model data--baseline/future
                SaveUsedModelDataReference(CommonClass.CurrentBaseScenario, dicUsedModelData, visibilityAnalysisConfiguration.filteringV.baseModelYear);
                dicUsedModelData.Clear();
                GC.Collect();

                //----------先确定其他年份中的best & worst days，然后根据RRF计算future concentration values
                #region
                foreach (KeyValuePair<string, VisibilityMonitor> k in dicVisibilityMonitors)
                {
                    List<string> lst = dicClass1AreaMonitorsIdentifiersLocations.Where(p => p.Value.monitorID == k.Key).Select(p => p.Key).ToList();
                    for (int i = 0; i < lst.Count(); i++)
                    {
                        if (!dicVisibilityForecastedValue.ContainsKey(lst[i])) continue;
                        foreach (KeyValuePair<string, Dictionary<string, NewImproveMonitors>> kYear in k.Value.dicNewIMPROVE)
                        {
                            foreach (KeyValuePair<string, NewImproveMonitors> kDay in kYear.Value)
                            {
                                //base dv
                                kDay.Value.baseBext = kDay.Value.ssRayleigh + kDay.Value.e_amm_so4
                                      + kDay.Value.e_amm_no3 + kDay.Value.e_omc
                                      + kDay.Value.e_ec + kDay.Value.e_crustal
                                      + kDay.Value.e_cm + kDay.Value.e_sea_salt;
                                kDay.Value.tbext = kDay.Value.baseBext;
                                kDay.Value.baseDV = 10 * Math.Log(kDay.Value.baseBext / 10);

                                if (kDay.Value.group == 10)
                                {
                                    kDay.Value.future_e_amm_so4 = dicVisibilityForecastedValue[lst[i]].rrfbSO4 * kDay.Value.e_amm_so4;
                                    kDay.Value.future_e_amm_no3 = dicVisibilityForecastedValue[lst[i]].rrfbNO3 * kDay.Value.e_amm_no3;
                                    kDay.Value.future_e_omc = dicVisibilityForecastedValue[lst[i]].rrfbOC * kDay.Value.e_omc;
                                    kDay.Value.future_e_crustal = dicVisibilityForecastedValue[lst[i]].rrfbCrustal * kDay.Value.e_crustal;
                                    kDay.Value.future_e_ec = dicVisibilityForecastedValue[lst[i]].rrfbEC * kDay.Value.e_ec;
                                    kDay.Value.future_e_cm = dicVisibilityForecastedValue[lst[i]].rrfbCM * kDay.Value.e_cm;
                                    kDay.Value.future_e_sea_salt = kDay.Value.e_sea_salt;
                                }
                                else//(kDay.Value.group == 90)
                                {
                                    kDay.Value.future_e_amm_so4 = dicVisibilityForecastedValue[lst[i]].rrfwSO4 * kDay.Value.e_amm_so4;
                                    kDay.Value.future_e_amm_no3 = dicVisibilityForecastedValue[lst[i]].rrfwNO3 * kDay.Value.e_amm_no3;
                                    kDay.Value.future_e_omc = dicVisibilityForecastedValue[lst[i]].rrfwOC * kDay.Value.e_omc;
                                    kDay.Value.future_e_crustal = dicVisibilityForecastedValue[lst[i]].rrfwCrustal * kDay.Value.e_crustal;
                                    kDay.Value.future_e_ec = dicVisibilityForecastedValue[lst[i]].rrfwEC * kDay.Value.e_ec;
                                    kDay.Value.future_e_cm = dicVisibilityForecastedValue[lst[i]].rrfwCM * kDay.Value.e_cm;
                                    kDay.Value.future_e_sea_salt = kDay.Value.e_sea_salt;
                                }


                                kDay.Value.futureBext = kDay.Value.ssRayleigh + kDay.Value.future_e_amm_so4
                                      + kDay.Value.future_e_amm_no3 + kDay.Value.future_e_omc
                                      + kDay.Value.future_e_ec + kDay.Value.future_e_crustal
                                      + kDay.Value.future_e_cm + kDay.Value.future_e_sea_salt;
                                kDay.Value.future_tbext = kDay.Value.futureBext;
                                kDay.Value.futureDV = 10 * Math.Log(kDay.Value.futureBext / 10);
                            }
                        }
                    }

                }
                #endregion
                //计算每年的dv_best和dv_worst
                #region
                foreach (KeyValuePair<string, VisibilityMonitor> k in dicVisibilityMonitors)
                {
                    List<string> lst = dicClass1AreaMonitorsIdentifiersLocations.Where(p => p.Value.monitorID == k.Key).Select(p => p.Key).ToList();
                    for (int i = 0; i < lst.Count(); i++)
                    {
                        if (!dicVisibilityForecastedValue.ContainsKey(lst[i])) continue;
                        foreach (KeyValuePair<string, Dictionary<string, NewImproveMonitors>> kYear in k.Value.dicNewIMPROVE)
                        {
                            ForecastedVisibilityDataAttribute forecastedItem = GetForecastedVisibilityDataAttribute(kYear.Value);
                            dicVisibilityForecastedValue[lst[i]].dicForecastedVisibilityValues.Add(kYear.Key, forecastedItem);
                        }
                    }
                }
                #endregion
                dicVisibilityForecastedValue = dicVisibilityForecastedValue.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);

                SaveAllDesignVluesForAdvanceOption(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);
                SaveForecastedVisibilityForAdvanceOption(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);

                //SaveAllDesignVluesWithNewFormat(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);
                //SaveForecastedVisibilityWithNewFormat(CommonClass.CurrentBaseScenario, dicVisibilityMonitors, dicVisibilityForecastedValue);


                dicVisibilityForecastedValue.Clear();
                GC.Collect();

                _endTime = DateTime.Now;
                CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish generating RRFs and computing forecast: " + CommonClass.TotalTime + " s.");
                CommonClass.CurrentLog = "Finish generating RRFs and computing forecast: " + CommonClass.TotalTime + " s.";
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }

        }


        /// <summary>
        /// get base and future year best and worst dv value ;
        /// by sclong
        /// 2017-03-05
        /// </summary>
        /// <param name="kYearValue"></param>
        /// <returns></returns>
        private static ForecastedVisibilityDataAttribute GetForecastedVisibilityDataAttribute(Dictionary<string, NewImproveMonitors> kYearValue)
        {
            ForecastedVisibilityDataAttribute forecastedItem = null;
            try
            {
                forecastedItem = new ForecastedVisibilityDataAttribute()
                                   {
                                       //baseBest = Math.Round(kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.baseDV).Average(), CommonClass.Visibility_calculation_decimal_point),
                                       //baseWorst = Math.Round(kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.baseDV).Average(), CommonClass.Visibility_calculation_decimal_point),
                                       //dvBest = Math.Round(kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureDV).Average(), CommonClass.Visibility_calculation_decimal_point),
                                       //dvWorst = Math.Round(kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureDV).Average(), CommonClass.Visibility_calculation_decimal_point),
                                       baseBest = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.baseDV).Average(),
                                       baseWorst = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.baseDV).Average(),
                                       dvBest = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureDV).Average(),
                                       dvWorst = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureDV).Average(),
                                       AmmNO3 = new SpeciesDV()
                                       {
                                           Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.ammNO3).Average(),
                                           Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futurAmmNO3).Average(),
                                           Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.ammNO3).Average(),
                                           Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futurAmmNO3).Average(),

                                           E_Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.e_amm_no3).Average(),
                                           E_Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_amm_no3).Average(),
                                           E_Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.e_amm_no3).Average(),
                                           E_Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_amm_no3).Average()
                                       },
                                       AmmSO4 = new SpeciesDV()
                                       {
                                           Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.ammSO4).Average(),
                                           Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureAmmSO4).Average(),
                                           Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.ammSO4).Average(),
                                           Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureAmmSO4).Average(),

                                           E_Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.e_amm_so4).Average(),
                                           E_Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_amm_so4).Average(),
                                           E_Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.e_amm_so4).Average(),
                                           E_Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_amm_so4).Average()
                                       },
                                       OMC = new SpeciesDV()
                                      {
                                          Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.omc).Average(),
                                          Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureOMC).Average(),
                                          Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.omc).Average(),
                                          Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureOMC).Average(),

                                          E_Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.e_omc).Average(),
                                          E_Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_omc).Average(),
                                          E_Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.e_omc).Average(),
                                          E_Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_omc).Average()
                                      },
                                       EC = new SpeciesDV()
                                       {
                                           Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.ec).Average(),
                                           Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureEC).Average(),
                                           Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.ec).Average(),
                                           Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureEC).Average(),

                                           E_Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.e_ec).Average(),
                                           E_Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_ec).Average(),
                                           E_Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.e_ec).Average(),
                                           E_Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_ec).Average()
                                       },
                                       Crustal = new SpeciesDV()
                                       {
                                           Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.crustal).Average(),
                                           Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureCrustal).Average(),
                                           Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.crustal).Average(),
                                           Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureCrustal).Average(),

                                           E_Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.e_crustal).Average(),
                                           E_Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_crustal).Average(),
                                           E_Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.e_crustal).Average(),
                                           E_Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_crustal).Average()
                                       },
                                       CM = new SpeciesDV()
                                       {
                                           Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.cm).Average(),
                                           Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureCm).Average(),
                                           Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.cm).Average(),
                                           Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureCm).Average(),

                                           E_Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.e_cm).Average(),
                                           E_Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_cm).Average(),
                                           E_Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.e_cm).Average(),
                                           E_Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_cm).Average()
                                       },
                                       SeaSalt = new SpeciesDV()
                                       {
                                           Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.seaSalt).Average(),
                                           Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.seaSalt).Average(),
                                           Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.seaSalt).Average(),
                                           Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.seaSalt).Average(),

                                           E_Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.e_sea_salt).Average(),
                                           E_Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.e_sea_salt).Average(),
                                           E_Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.e_sea_salt).Average(),
                                           E_Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.e_sea_salt).Average()
                                       },
                                       LargeAmmNO3 = new SpeciesDV()
                                       {
                                           Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.largeAmmNO3).Average(),
                                           Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureLargeAmmNO3).Average(),
                                           Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.largeAmmNO3).Average(),
                                           Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureLargeAmmNO3).Average(),

                                           E_Best_b = -9,//-9,表示不存在
                                           E_Best_f = -9,
                                           E_Worst_b = -9,
                                           E_Worst_f = -9
                                       },
                                       SmallAmmNO3 = new SpeciesDV()
                                       {
                                           Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.smallAmmNO3).Average(),
                                           Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureSmallAmmNO3).Average(),
                                           Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.ammNO3).Average(),
                                           Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureSmallAmmNO3).Average(),

                                           E_Best_b = -9,
                                           E_Best_f = -9,
                                           E_Worst_b = -9,
                                           E_Worst_f = -9
                                       },
                                       LargeAmmSO4 = new SpeciesDV()
                                        {
                                            Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.largeAmmSO4).Average(),
                                            Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureLargeAmmSO4).Average(),
                                            Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.largeAmmSO4).Average(),
                                            Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureLargeAmmSO4).Average(),

                                            E_Best_b = -9,//-9,表示不存在
                                            E_Best_f = -9,
                                            E_Worst_b = -9,
                                            E_Worst_f = -9
                                        },
                                       SmallAmmSO4 = new SpeciesDV()
                                       {
                                           Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.smallAmmSO4).Average(),
                                           Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureSmallAmmSO4).Average(),
                                           Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.smallAmmSO4).Average(),
                                           Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureSmallAmmSO4).Average(),
                                           E_Best_b = -9,
                                           E_Best_f = -9,
                                           E_Worst_b = -9,
                                           E_Worst_f = -9
                                       },
                                       LargeOMC = new SpeciesDV()
                                       {
                                           Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.largeOMC).Average(),
                                           Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureLargeOMC).Average(),
                                           Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.largeOMC).Average(),
                                           Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureLargeOMC).Average(),

                                           E_Best_b = -9,//-9,表示不存在
                                           E_Best_f = -9,
                                           E_Worst_b = -9,
                                           E_Worst_f = -9
                                       },
                                       SmallOMC = new SpeciesDV()
                                       {
                                           Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.smallOMC).Average(),
                                           Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureSmallOMC).Average(),
                                           Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.smallOMC).Average(),
                                           Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureSmallOMC).Average(),
                                           E_Best_b = -9,
                                           E_Best_f = -9,
                                           E_Worst_b = -9,
                                           E_Worst_f = -9
                                       },
                                       TBext = new SpeciesDV()
                                       {
                                           Best_b = -9,
                                           Best_f = -9,
                                           Worst_b = -9,
                                           Worst_f = -9,
                                           E_Best_b = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.tbext).Average(),
                                           E_Best_f = kYearValue.Where(p => p.Value.group == 10).Select(p => p.Value.futureBext).Average(),
                                           E_Worst_b = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.tbext).Average(),
                                           E_Worst_f = kYearValue.Where(p => p.Value.group == 90).Select(p => p.Value.futureBext).Average()
                                       }
                                   };

                return forecastedItem;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return forecastedItem;
            }
        }

        #region get input files
        public static string GetMonitorDataForNewIMPORVEAlgorithm(VisibilityAnalysisConfiguration visibilityAnalysisConfiguration, ref Dictionary<string, VisibilityMonitor> dicVisibilityMonitors, ref List<string> lstClassIArea)
        {
            try
            {
                //string errorInfo = "";
                #region
                //记录各字段的索引值
                int iID = -1, iType = -1, iLat = -1, iLong = -1, iDate = -1, iFRH = -1, iFSRH = -1, iFLRH = -1, iFSSRH = -1, iSS_RAYLEIGH = -1, iSEA_SALT = -1, iPM25 = -1, iCRUSTAL = -1, iAMM_NO3 = -1, iOMC = -1, iEC = -1,
                    iCM = -1, iAMM_SO4 = -1, iLARGE_OMC = -1, iSMALL_OMC = -1, iLARGE_AMM_SO4 = -1, iSMALL_AMM_SO4 = -1, iLARGE_AMM_NO3 = -1, iSMALL_AMM_NO3 = -1, iGOOD_YEAR = -1, iGROUP = -1, iCOMPLETE_QUARTER = -1, //iSF = -1, iSO4F = -1,
                    iDV = -1;
                int iE_AMM_SO4 = -1, iE_AMM_NO3 = -1, iE_OMC = -1, iE_EC = -1, iE_CRUSTAL = -1, iE_CM = -1, iE_SEA_SALT = -1, iTBEXT = -1;//add by sclong,2017-02-26
                FileStream fs = new FileStream(visibilityAnalysisConfiguration.dataInputV.monitorDataFileNewAlgorithm, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                {
                    string strLine = csv.ReadLine();
                    string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                    int i = 0;
                    while (i < strLineArray.Length)
                    {
                        string s = strLineArray[i];
                        switch (s.Trim().ToLower().Replace("\"", ""))
                        {
                            case "_id":
                                iID = i;
                                break;
                            case "_type":
                                iType = i;
                                break;
                            case "lat":
                                iLat = i;
                                break;
                            case "long":
                                iLong = i;
                                break;
                            case "date":
                                iDate = i;
                                break;
                            case "frh":
                                iFRH = i;
                                break;
                            case "fsrh":
                                iFSRH = i;
                                break;
                            case "flrh":
                                iFLRH = i;
                                break;
                            case "fssrh":
                                iFSSRH = i;
                                break;
                            case "ss_rayleigh":
                                iSS_RAYLEIGH = i;
                                break;
                            case "sea_salt":
                                iSEA_SALT = i;
                                break;
                            case "pm25":
                                iPM25 = i;
                                break;
                            case "crustal":
                                iCRUSTAL = i;
                                break;
                            case "amm_no3":
                                iAMM_NO3 = i;
                                break;
                            case "omc":
                                iOMC = i;
                                break;
                            case "ec":
                                iEC = i;
                                break;
                            case "cm":
                                iCM = i;
                                break;
                            case "amm_so4":
                                iAMM_SO4 = i;
                                break;
                            case "large_omc":
                                iLARGE_OMC = i;
                                break;
                            case "small_omc":
                                iSMALL_OMC = i;
                                break;
                            case "large_amm_so4":
                                iLARGE_AMM_SO4 = i;
                                break;
                            case "small_amm_so4":
                                iSMALL_AMM_SO4 = i;
                                break;
                            case "large_amm_no3":
                                iLARGE_AMM_NO3 = i;
                                break;
                            case "small_amm_no3":
                                iSMALL_AMM_NO3 = i;
                                break;
                            case "e_amm_so4":
                                iE_AMM_SO4 = i;
                                break;
                            case "e_amm_no3":
                                iE_AMM_NO3 = i;
                                break;
                            case "e_omc":
                                iE_OMC = i;
                                break;
                            case "e_ec":
                                iE_EC = i;
                                break;
                            case "e_crustal":
                                iE_CRUSTAL = i;
                                break;
                            case "e_cm":
                                iE_CM = i;
                                break;
                            case "e_sea_salt":
                                iE_SEA_SALT = i;
                                break;
                            case "tbext":
                                iTBEXT = i;
                                break;
                            case "dv":
                                iDV = i;
                                break;
                            case "good_year":
                                iGOOD_YEAR = i;
                                break;
                            case "group":
                                iGROUP = i;
                                break;
                            case "complete_quarter":
                                iCOMPLETE_QUARTER = i;
                                break;
                        }
                        i++;
                    }
                    dicVisibilityMonitors = new Dictionary<string, VisibilityMonitor>();
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        //try
                        //{
                        strLineArray = strLine.Split(new char[] { ',' });
                        if (strLineArray[iID].ToString().Replace("\"", "") == "BRET1")
                        {
                        }
                        if (Convert.ToInt32(strLineArray[iDate].Substring(0, 4).Replace("\"", "")) >= Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear)
                            && Convert.ToInt32(strLineArray[iDate].Substring(0, 4).Replace("\"", "")) <= Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.endMonitorYear))
                        {
                            if (!lstClassIArea.Contains(strLineArray[iID].ToString().Replace("\"", ""))) lstClassIArea.Add(strLineArray[iID].ToString().Replace("\"", ""));
                            if (Convert.ToInt32(strLineArray[iGOOD_YEAR]) == 1 && (Convert.ToInt32(strLineArray[iGROUP]) == 10 || Convert.ToInt32(strLineArray[iGROUP]) == 90)
                                && Convert.ToInt32(strLineArray[iCOMPLETE_QUARTER]) == 1 && Convert.ToDouble(strLineArray[iDV]) >= -2)
                            {
                                if (dicVisibilityMonitors.ContainsKey(strLineArray[iID].ToString().Replace("\"", "")))
                                {
                                    if (!dicVisibilityMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicNewIMPROVE.ContainsKey(strLineArray[iDate].Substring(0, 4).Replace("\"", "")))
                                    {
                                        Dictionary<string, NewImproveMonitors> dic = new Dictionary<string, NewImproveMonitors>();
                                        dic.Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new NewImproveMonitors()
                                        {
                                            frh = Convert.ToDouble(strLineArray[iFRH]),
                                            fsrh = Convert.ToDouble(strLineArray[iFSRH]),
                                            flrh = Convert.ToDouble(strLineArray[iFLRH]),
                                            fssrh = Convert.ToDouble(strLineArray[iFSSRH]),
                                            ssRayleigh = Convert.ToInt32(strLineArray[iSS_RAYLEIGH]),
                                            seaSalt = Convert.ToDouble(strLineArray[iSEA_SALT]),
                                            pm25 = Convert.ToDouble(strLineArray[iPM25]),
                                            crustal = Convert.ToDouble(strLineArray[iCRUSTAL]),
                                            ammNO3 = Convert.ToDouble(strLineArray[iAMM_NO3]),
                                            omc = Convert.ToDouble(strLineArray[iOMC]),
                                            ec = Convert.ToDouble(strLineArray[iEC]),
                                            cm = Convert.ToDouble(strLineArray[iCM]),
                                            ammSO4 = Convert.ToDouble(strLineArray[iAMM_SO4]),
                                            largeOMC = Convert.ToDouble(strLineArray[iLARGE_OMC]),
                                            smallOMC = Convert.ToDouble(strLineArray[iSMALL_OMC]),
                                            largeAmmSO4 = Convert.ToDouble(strLineArray[iLARGE_AMM_SO4]),
                                            smallAmmSO4 = Convert.ToDouble(strLineArray[iSMALL_AMM_SO4]),
                                            largeAmmNO3 = Convert.ToDouble(strLineArray[iLARGE_AMM_NO3]),
                                            smallAmmNO3 = Convert.ToDouble(strLineArray[iSMALL_AMM_NO3]),

                                            e_amm_so4 = Convert.ToDouble(strLineArray[iE_AMM_SO4]),
                                            e_amm_no3 = Convert.ToDouble(strLineArray[iE_AMM_NO3]),
                                            e_omc = Convert.ToDouble(strLineArray[iE_OMC]),
                                            e_ec = Convert.ToDouble(strLineArray[iE_EC]),
                                            e_crustal = Convert.ToDouble(strLineArray[iE_CRUSTAL]),
                                            e_cm = Convert.ToDouble(strLineArray[iE_CM]),
                                            e_sea_salt = Convert.ToDouble(strLineArray[iE_SEA_SALT]),
                                            tbext = Convert.ToDouble(strLineArray[iTBEXT]),

                                            //baseDV = Convert.ToDouble(strLineArray[iDV]),
                                            goodYear = Convert.ToInt32(strLineArray[iGOOD_YEAR]),
                                            group = Convert.ToInt32(strLineArray[iGROUP]),
                                            completeQuarter = Convert.ToInt32(strLineArray[iCOMPLETE_QUARTER]),
                                            //sf = Convert.ToDouble(strLineArray[iSF]),
                                            //so4F = Convert.ToDouble(strLineArray[iSO4F]),
                                        });
                                        dicVisibilityMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicNewIMPROVE.Add(strLineArray[iDate].ToString().Substring(0, 4).Replace("\"", ""), dic);
                                    }
                                    else
                                    {
                                        dicVisibilityMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicNewIMPROVE[strLineArray[iDate].ToString().Substring(0, 4).Replace("\"", "")].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new NewImproveMonitors()
                                        {
                                            //date = strLineArray[iDate].ToString(),
                                            frh = Convert.ToDouble(strLineArray[iFRH]),
                                            fsrh = Convert.ToDouble(strLineArray[iFSRH]),
                                            flrh = Convert.ToDouble(strLineArray[iFLRH]),
                                            fssrh = Convert.ToDouble(strLineArray[iFSSRH]),
                                            ssRayleigh = Convert.ToInt32(strLineArray[iSS_RAYLEIGH]),
                                            seaSalt = Convert.ToDouble(strLineArray[iSEA_SALT]),
                                            pm25 = Convert.ToDouble(strLineArray[iPM25]),
                                            crustal = Convert.ToDouble(strLineArray[iCRUSTAL]),
                                            ammNO3 = Convert.ToDouble(strLineArray[iAMM_NO3]),
                                            omc = Convert.ToDouble(strLineArray[iOMC]),
                                            ec = Convert.ToDouble(strLineArray[iEC]),
                                            cm = Convert.ToDouble(strLineArray[iCM]),
                                            ammSO4 = Convert.ToDouble(strLineArray[iAMM_SO4]),
                                            largeOMC = Convert.ToDouble(strLineArray[iLARGE_OMC]),
                                            smallOMC = Convert.ToDouble(strLineArray[iSMALL_OMC]),
                                            largeAmmSO4 = Convert.ToDouble(strLineArray[iLARGE_AMM_SO4]),
                                            smallAmmSO4 = Convert.ToDouble(strLineArray[iSMALL_AMM_SO4]),
                                            largeAmmNO3 = Convert.ToDouble(strLineArray[iLARGE_AMM_NO3]),
                                            smallAmmNO3 = Convert.ToDouble(strLineArray[iSMALL_AMM_NO3]),

                                            e_amm_so4 = Convert.ToDouble(strLineArray[iE_AMM_SO4]),
                                            e_amm_no3 = Convert.ToDouble(strLineArray[iE_AMM_NO3]),
                                            e_omc = Convert.ToDouble(strLineArray[iE_OMC]),
                                            e_ec = Convert.ToDouble(strLineArray[iE_EC]),
                                            e_crustal = Convert.ToDouble(strLineArray[iE_CRUSTAL]),
                                            e_cm = Convert.ToDouble(strLineArray[iE_CM]),
                                            e_sea_salt = Convert.ToDouble(strLineArray[iE_SEA_SALT]),
                                            tbext = Convert.ToDouble(strLineArray[iTBEXT]),

                                            //dv = Convert.ToDouble(strLineArray[iDV]),
                                            goodYear = Convert.ToInt32(strLineArray[iGOOD_YEAR]),
                                            group = Convert.ToInt32(strLineArray[iGROUP]),
                                            completeQuarter = Convert.ToInt32(strLineArray[iCOMPLETE_QUARTER]),
                                            //sf = Convert.ToDouble(strLineArray[iSF]),
                                            //so4F = Convert.ToDouble(strLineArray[iSO4F]),
                                        });
                                    }
                                }
                                else
                                {
                                    dicVisibilityMonitors.Add(strLineArray[iID].ToString().Replace("\"", ""), new VisibilityMonitor()
                                    {
                                        id = strLineArray[iID].ToString().Replace("\"", ""),
                                        type = strLineArray[iType].ToString().Replace("\"", ""),
                                        lat = Convert.ToDouble(strLineArray[iLat]),
                                        longitude = Convert.ToDouble(strLineArray[iLong]),
                                        dicNewIMPROVE = new Dictionary<string, Dictionary<string, NewImproveMonitors>>(),
                                    });
                                    Dictionary<string, NewImproveMonitors> dic = new Dictionary<string, NewImproveMonitors>();
                                    dic.Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new NewImproveMonitors()
                                    {
                                        //date = strLineArray[iDate].ToString(),
                                        frh = Convert.ToDouble(strLineArray[iFRH]),
                                        fsrh = Convert.ToDouble(strLineArray[iFSRH]),
                                        flrh = Convert.ToDouble(strLineArray[iFLRH]),
                                        fssrh = Convert.ToDouble(strLineArray[iFSSRH]),
                                        ssRayleigh = Convert.ToInt32(strLineArray[iSS_RAYLEIGH]),
                                        seaSalt = Convert.ToDouble(strLineArray[iSEA_SALT]),
                                        pm25 = Convert.ToDouble(strLineArray[iPM25]),
                                        crustal = Convert.ToDouble(strLineArray[iCRUSTAL]),
                                        ammNO3 = Convert.ToDouble(strLineArray[iAMM_NO3]),
                                        omc = Convert.ToDouble(strLineArray[iOMC]),
                                        ec = Convert.ToDouble(strLineArray[iEC]),
                                        cm = Convert.ToDouble(strLineArray[iCM]),
                                        ammSO4 = Convert.ToDouble(strLineArray[iAMM_SO4]),
                                        largeOMC = Convert.ToDouble(strLineArray[iLARGE_OMC]),
                                        smallOMC = Convert.ToDouble(strLineArray[iSMALL_OMC]),
                                        largeAmmSO4 = Convert.ToDouble(strLineArray[iLARGE_AMM_SO4]),
                                        smallAmmSO4 = Convert.ToDouble(strLineArray[iSMALL_AMM_SO4]),
                                        largeAmmNO3 = Convert.ToDouble(strLineArray[iLARGE_AMM_NO3]),
                                        smallAmmNO3 = Convert.ToDouble(strLineArray[iSMALL_AMM_NO3]),

                                        e_amm_so4 = Convert.ToDouble(strLineArray[iE_AMM_SO4]),
                                        e_amm_no3 = Convert.ToDouble(strLineArray[iE_AMM_NO3]),
                                        e_omc = Convert.ToDouble(strLineArray[iE_OMC]),
                                        e_ec = Convert.ToDouble(strLineArray[iE_EC]),
                                        e_crustal = Convert.ToDouble(strLineArray[iE_CRUSTAL]),
                                        e_cm = Convert.ToDouble(strLineArray[iE_CM]),
                                        e_sea_salt = Convert.ToDouble(strLineArray[iE_SEA_SALT]),
                                        tbext = Convert.ToDouble(strLineArray[iTBEXT]),

                                        //dv = Convert.ToDouble(strLineArray[iDV]),
                                        goodYear = Convert.ToInt32(strLineArray[iGOOD_YEAR]),
                                        group = Convert.ToInt32(strLineArray[iGROUP]),
                                        completeQuarter = Convert.ToInt32(strLineArray[iCOMPLETE_QUARTER]),
                                        //sf = Convert.ToDouble(strLineArray[iSF]),
                                        //so4F = Convert.ToDouble(strLineArray[iSO4F]),
                                    });
                                    dicVisibilityMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicNewIMPROVE.Add(strLineArray[iDate].ToString().Substring(0, 4).Replace("\"", ""), dic);
                                }
                            }
                        }
                        //}
                        //catch
                        //{
                        //    errorInfo = "errorRow";
                        //}
                    }
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                }
                #endregion
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }
        }
        public static string GetIMPROVEDailyMonitorData(VisibilityAnalysisConfiguration visibilityAnalysisConfiguration, ref Dictionary<string, VisibilityMonitor> dicVisibilityMonitors, ref List<string> lstClassIArea)
        {
            try
            {
                //string errorInfo = "";
                #region
                //记录各字段的索引值
                int iID = -1, iType = -1, iLat = -1, iLong = -1, iGridcellLat = -1, iGridcellLong = -1, iDate = -1, iSS_RAYLEIGH = -1, iGOOD_YEAR = -1, iGROUP = -1;
                int iE_AMM_SO4 = -1, iE_AMM_NO3 = -1, iE_OMC = -1, iE_EC = -1, iE_CRUSTAL = -1, iE_CM = -1, iE_SEA_SALT = -1;//add by sclong,2017-02-26
                FileStream fs = new FileStream(visibilityAnalysisConfiguration.dataInputV.forecastIMPROVEDataFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                {
                    string strLine = csv.ReadLine();
                    string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                    int i = 0;
                    while (i < strLineArray.Length)
                    {
                        string s = strLineArray[i];
                        switch (s.Trim().ToLower().Replace("\"", ""))
                        {
                            case "_id":
                            case "site_id":
                                iID = i;
                                break;
                            case "_type":
                            case "type":
                                iType = i;
                                break;
                            case "lat":
                            case "monitor_lat":
                                iLat = i;
                                break;
                            case "long":
                            case "monitor_long":
                                iLong = i;
                                break;
                            case "gridcell_lat":
                                iGridcellLat = i;
                                break;
                            case "gridcell_long":
                                iGridcellLong = i;
                                break;
                            case "date":
                                iDate = i;
                                break;
                            case "ss_rayleigh":
                                iSS_RAYLEIGH = i;
                                break;
                            case "e_amm_so4":
                            case "e_amm_so4_f":
                                iE_AMM_SO4 = i;
                                break;
                            case "e_amm_no3":
                            case "e_amm_no3_f":
                                iE_AMM_NO3 = i;
                                break;
                            case "e_omc":
                            case "e_omc_f":
                                iE_OMC = i;
                                break;
                            case "e_ec":
                            case "e_ec_f":
                                iE_EC = i;
                                break;
                            case "e_crustal":
                            case "e_crustal_f":
                                iE_CRUSTAL = i;
                                break;
                            case "e_cm":
                            case "e_cm_f":
                                iE_CM = i;
                                break;
                            case "e_sea_salt":
                            case "e_sea_salt_f":
                                iE_SEA_SALT = i;
                                break;
                            case "good_year":
                                iGOOD_YEAR = i;
                                break;
                            case "group":
                                iGROUP = i;
                                break;
                        }
                        i++;
                    }
                    dicVisibilityMonitors = new Dictionary<string, VisibilityMonitor>();
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        strLineArray = strLine.Split(new char[] { ',' });
                        if (Convert.ToInt32(strLineArray[iDate].Substring(0, 4).Replace("\"", "")) >= Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear)
                            && Convert.ToInt32(strLineArray[iDate].Substring(0, 4).Replace("\"", "")) <= Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.endMonitorYear))
                        {
                            if (!lstClassIArea.Contains(strLineArray[iID].ToString().Replace("\"", ""))) lstClassIArea.Add(strLineArray[iID].ToString().Replace("\"", ""));
                            if (Convert.ToInt32(strLineArray[iGOOD_YEAR]) == 1 && (Convert.ToInt32(strLineArray[iGROUP]) == 10 || Convert.ToInt32(strLineArray[iGROUP]) == 90))
                            {
                                if (dicVisibilityMonitors.ContainsKey(strLineArray[iID].ToString().Replace("\"", "")))
                                {
                                    if (!dicVisibilityMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicNewIMPROVE.ContainsKey(strLineArray[iDate].Substring(0, 4).Replace("\"", "")))
                                    {
                                        Dictionary<string, NewImproveMonitors> dic = new Dictionary<string, NewImproveMonitors>();
                                        dic.Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new NewImproveMonitors()
                                        {
                                            ssRayleigh = Convert.ToInt32(strLineArray[iSS_RAYLEIGH]),
                                            e_amm_so4 = Convert.ToDouble(strLineArray[iE_AMM_SO4]),
                                            e_amm_no3 = Convert.ToDouble(strLineArray[iE_AMM_NO3]),
                                            e_omc = Convert.ToDouble(strLineArray[iE_OMC]),
                                            e_ec = Convert.ToDouble(strLineArray[iE_EC]),
                                            e_crustal = Convert.ToDouble(strLineArray[iE_CRUSTAL]),
                                            e_cm = Convert.ToDouble(strLineArray[iE_CM]),
                                            e_sea_salt = Convert.ToDouble(strLineArray[iE_SEA_SALT]),
                                            goodYear = Convert.ToInt32(strLineArray[iGOOD_YEAR]),
                                            group = Convert.ToInt32(strLineArray[iGROUP]),

                                        });
                                        dicVisibilityMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicNewIMPROVE.Add(strLineArray[iDate].ToString().Substring(0, 4).Replace("\"", ""), dic);
                                    }
                                    else
                                    {
                                        dicVisibilityMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicNewIMPROVE[strLineArray[iDate].ToString().Substring(0, 4).Replace("\"", "")].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new NewImproveMonitors()
                                        {
                                            ssRayleigh = Convert.ToInt32(strLineArray[iSS_RAYLEIGH]),
                                            e_amm_so4 = Convert.ToDouble(strLineArray[iE_AMM_SO4]),
                                            e_amm_no3 = Convert.ToDouble(strLineArray[iE_AMM_NO3]),
                                            e_omc = Convert.ToDouble(strLineArray[iE_OMC]),
                                            e_ec = Convert.ToDouble(strLineArray[iE_EC]),
                                            e_crustal = Convert.ToDouble(strLineArray[iE_CRUSTAL]),
                                            e_cm = Convert.ToDouble(strLineArray[iE_CM]),
                                            e_sea_salt = Convert.ToDouble(strLineArray[iE_SEA_SALT]),
                                            goodYear = Convert.ToInt32(strLineArray[iGOOD_YEAR]),
                                            group = Convert.ToInt32(strLineArray[iGROUP]),
                                        });
                                    }
                                }
                                else
                                {
                                    dicVisibilityMonitors.Add(strLineArray[iID].ToString().Replace("\"", ""), new VisibilityMonitor()
                                    {
                                        id = strLineArray[iID].ToString().Replace("\"", ""),
                                        type = strLineArray[iType].ToString().Replace("\"", ""),
                                        lat = Convert.ToDouble(strLineArray[iLat]),
                                        longitude = Convert.ToDouble(strLineArray[iLong]),
                                        dicNewIMPROVE = new Dictionary<string, Dictionary<string, NewImproveMonitors>>(),
                                    });
                                    Dictionary<string, NewImproveMonitors> dic = new Dictionary<string, NewImproveMonitors>();
                                    dic.Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new NewImproveMonitors()
                                    {
                                        ssRayleigh = Convert.ToInt32(strLineArray[iSS_RAYLEIGH]),
                                        e_amm_so4 = Convert.ToDouble(strLineArray[iE_AMM_SO4]),
                                        e_amm_no3 = Convert.ToDouble(strLineArray[iE_AMM_NO3]),
                                        e_omc = Convert.ToDouble(strLineArray[iE_OMC]),
                                        e_ec = Convert.ToDouble(strLineArray[iE_EC]),
                                        e_crustal = Convert.ToDouble(strLineArray[iE_CRUSTAL]),
                                        e_cm = Convert.ToDouble(strLineArray[iE_CM]),
                                        e_sea_salt = Convert.ToDouble(strLineArray[iE_SEA_SALT]),
                                        goodYear = Convert.ToInt32(strLineArray[iGOOD_YEAR]),
                                        group = Convert.ToInt32(strLineArray[iGROUP]),
                                    });
                                    dicVisibilityMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicNewIMPROVE.Add(strLineArray[iDate].ToString().Substring(0, 4).Replace("\"", ""), dic);
                                }
                            }
                        }
                        //}
                        //catch
                        //{
                        //    errorInfo = "errorRow";
                        //}
                    }
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                }
                #endregion
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }
        }
        public static bool GetMonitorDataForOldIMPORVEAlgorithm(VisibilityAnalysisConfiguration visibilityAnalysisConfiguration)
        {
            try
            {

                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetModelDataAllID(VisibilityAnalysisConfiguration visibilityAnalysisConfiguration, ref Dictionary<string, VisibilityModelData> dicVisibilityModelData)
        {
            try
            {
                int iID = -1, iLat = -1, iLong = -1;
                FileStream fs = new FileStream(visibilityAnalysisConfiguration.dataInputV.baselineModelDataFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                {
                    string strLine = csv.ReadLine();
                    string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                    int i = 0;
                    while (i < strLineArray.Length)
                    {
                        string s = strLineArray[i];
                        switch (s.Trim().ToLower().Replace("\"", ""))
                        {
                            case "_id":
                                iID = i;
                                break;
                            case "lat":
                                iLat = i;
                                break;
                            case "long":
                                iLong = i;
                                break;
                        }
                        i++;
                    }
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        strLineArray = strLine.Split(new char[] { ',' });
                        if (!dicVisibilityModelData.ContainsKey(strLineArray[iID].ToString().Trim().Replace("\"", "")))
                        {
                            dicVisibilityModelData.Add(strLineArray[iID].ToString().Trim().Replace("\"", ""), new VisibilityModelData()
                            {
                                id = strLineArray[iID].ToString().Trim().Replace("\"", ""),
                                gridcellLat = Convert.ToDouble(strLineArray[iLat]),
                                gridcellLong = Convert.ToDouble(strLineArray[iLong]),
                            });
                        }
                    }
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetClassIAreaIdentifiers(VisibilityAnalysisConfiguration visibilityAnalysisConfiguration, ref Dictionary<string, MonitorClass1AreaIdentifiers> dicClass1AreaMonitorsIdentifiersLocations)
        {
            try
            {
                int iID = -1, iLat = -1, iLong = -1, iMonitorID = -1, iMonitorLat = -1, iMonitorLong = -1, iClass1Name = -1, iStateID = -1;
                FileStream fs = new FileStream(Application.StartupPath + @"\Data\SampleData\156-Class1-coordinates-all site names_new-2019.csv", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                {
                    string strLine = csv.ReadLine();
                    string[] strLineArray = strLine.Split(new char[] { ',' });
                    int i = 0;
                    while (i < strLineArray.Length)
                    {
                        string s = strLineArray[i];
                        switch (s.Trim().ToLower().Replace("\"", ""))
                        {
                            case "_id":
                                iID = i;
                                break;
                            case "_state_id":
                                iStateID = i;
                                break;
                            case "lat":
                                iLat = i;
                                break;
                            case "long":
                                iLong = i;
                                break;
                            case "_monitor_id":
                                iMonitorID = i;
                                break;
                            case "monlat":
                                iMonitorLat = i;
                                break;
                            case "monlong":
                                iMonitorLong = i;
                                break;
                            case "_class_i_name":
                                iClass1Name = i;
                                break;
                        }
                        i++;
                    }
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        strLineArray = strLine.Split(new char[] { ',' });
                        dicClass1AreaMonitorsIdentifiersLocations.Add(strLineArray[iID].ToString().Trim().Replace("\"", ""), new MonitorClass1AreaIdentifiers()
                        {
                            id = strLineArray[iID].ToString().Trim().Replace("\"", ""),
                            classIState = strLineArray[iStateID].ToString().Replace("\"", ""),
                            classIlat = Convert.ToDouble(strLineArray[iLat]),
                            classIlong = Convert.ToDouble(strLineArray[iLong]),
                            classIName = strLineArray[iClass1Name].ToString().Replace("\"", ""),
                            monitorID = strLineArray[iMonitorID].ToString().Replace("\"", ""),
                            monitorLat = Convert.ToDouble(strLineArray[iMonitorLat]),
                            monitorLong = Convert.ToDouble(strLineArray[iMonitorLong]),
                        });
                    }
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetGridcellForMonitors(VisibilityAnalysisConfiguration visibilityAnalysisConfiguration, ref Dictionary<string, string> dicMonitorInModel, Dictionary<string, MonitorClass1AreaIdentifiers> dicClass1AreaMonitorsIdentifiersLocations, Dictionary<string, VisibilityModelData> dicVisibilityModelData, Dictionary<string, VisibilityMonitor> dicVisibilityMonitors)
        {
            try
            {
                double dFirst = dicVisibilityModelData.First().Value.gridcellLong, dLen = 0, dLat = 0;
                int iFirst = Convert.ToInt32(dicVisibilityModelData.First().Key);

                //算模型域中单个网格的长度和宽度，先刷选出与测点的经度和维度相差小于2个网格长度和宽度的所有网格点。即先刷选出以测点为中心的9宫格。
                /*
                 *  ____________
                 * |   |   |   |
                 * _____________
                 * |   | * |   |
                 * _____________
                 * |   |   |   |
                 *  ___________
                 * 
                 */
                if (dicVisibilityModelData.ContainsKey((((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()))
                {

                    dLen = Math.Abs(dicVisibilityModelData[(((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()].gridcellLong -
                        dicVisibilityModelData.First().Value.gridcellLong
                        );
                    dLat = Math.Abs(dicVisibilityModelData[(((iFirst / 1000)) * 1000 + iFirst % 1000 + 1).ToString()].gridcellLat -
                        dicVisibilityModelData.First().Value.gridcellLat
                        );
                    dLen *= 2; dLat *= 2;

                }
                if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                {
                    //---------计算两个网格之内；然后属于哪个的网格, 当monitor与gridcell之间的距离小于25km时监测点将参与计算
                    foreach (KeyValuePair<string, VisibilityMonitor> k in dicVisibilityMonitors)
                    {
                        try
                        {
                            var query = dicVisibilityModelData.Where(p => Math.Abs(p.Value.gridcellLong - k.Value.longitude) < dLen && Math.Abs(p.Value.gridcellLat - k.Value.lat) < dLat).ToList();
                            string sModelIDTemp = "";
                            if (query.Count() > 0)//说明以测点为中心，小于2网格长度有存在模型网格
                            {
                                sModelIDTemp = query.OrderBy(p => CommonClass.getDistanceFrom2Point(p.Value.gridcellLong, p.Value.gridcellLat, k.Value.longitude, k.Value.lat)).First().Key;//对刷选出来的网格与测点进行算距离，并按距离升序排序，并取最近的网格点作为该测点所在网格索引。
                                List<MonitorClass1AreaIdentifiers> lst = dicClass1AreaMonitorsIdentifiersLocations.Where(p => p.Value.monitorID == k.Key).Select(p => p.Value).ToList();

                                for (int i = 0; i < lst.Count(); i++)
                                {
                                    //Console.WriteLine(k.Key);
                                    dicMonitorInModel.Add(lst[i].id, sModelIDTemp);
                                }
                            }
                            else//不存在
                            {

                            }
                        }
                        catch
                        {
                        }
                    }
                }
                else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                {
                    foreach (KeyValuePair<string, MonitorClass1AreaIdentifiers> k in dicClass1AreaMonitorsIdentifiersLocations)
                    {
                        try
                        {
                            var query = dicVisibilityModelData.Where(p => Math.Abs(p.Value.gridcellLong - k.Value.classIlong) < dLen && Math.Abs(p.Value.gridcellLat - k.Value.classIlat) < dLat).ToList();
                            string sModelIDTemp = "";
                            if (query.Count() > 0)
                            {
                                sModelIDTemp = query.OrderBy(p => CommonClass.getDistanceFrom2Point(p.Value.gridcellLong, p.Value.gridcellLat, k.Value.classIlong, k.Value.classIlat)).First().Key;
                                dicMonitorInModel.Add(k.Key, sModelIDTemp);
                            }
                            else
                            {

                            }
                        }
                        catch
                        {
                        }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetGridcellNeeded(VisibilityAnalysisConfiguration visibilityAnalysisConfiguration, ref Dictionary<string, VisibilityModelData> dicModelDataVisibilityUsed, Dictionary<string, MonitorClass1AreaIdentifiers> dicClass1AreaMonitorsIdentifiersLocations, Dictionary<string, string> dicMonitorInModel, Dictionary<string, VisibilityMonitor> dicVisibilityMonitors, Dictionary<string, VisibilityModelData> dicVisibilityModelData)
        {
            try
            {
                foreach (KeyValuePair<string, MonitorClass1AreaIdentifiers> k in dicClass1AreaMonitorsIdentifiersLocations)
                {
                    if (!dicVisibilityMonitors.ContainsKey(k.Value.monitorID))
                    {
                        continue;
                    }
                    if (!dicMonitorInModel.ContainsKey(k.Key) || !dicVisibilityMonitors[k.Value.monitorID].dicNewIMPROVE.ContainsKey(visibilityAnalysisConfiguration.filteringV.baseModelYear)) continue;
                    int Col = Convert.ToInt32(dicMonitorInModel[k.Key]) / 1000;
                    int Row = Convert.ToInt32(dicMonitorInModel[k.Key]) % 1000;
                    List<string> lstSurround = new List<string>();
                    switch (visibilityAnalysisConfiguration.dataInputV.temporalAdjustmentAtMonitorGrid)
                    {
                        case "1x1":
                            lstSurround.Add(dicMonitorInModel[k.Key]);
                            break;
                        case "3x3":
                            for (int i3 = -1; i3 <= 1; i3++)
                            {
                                for (int j3 = -1; j3 <= 1; j3++)
                                {
                                    lstSurround.Add(((Col + i3) * 1000 + (Row + j3)).ToString());
                                }
                            }
                            break;
                        case "5x5":
                            for (int i5 = -2; i5 <= 2; i5++)
                            {
                                for (int j5 = -2; j5 <= 2; j5++)
                                {
                                    lstSurround.Add(((Col + i5) * 1000 + (Row + j5)).ToString());
                                }

                            }
                            break;
                        case "7x7":
                            for (int i7 = -3; i7 <= 3; i7++)
                            {
                                for (int j7 = -3; j7 <= 3; j7++)
                                {
                                    lstSurround.Add(((Col + i7) * 1000 + (Row + j7)).ToString());
                                }
                            }
                            break;
                    }

                    var query = dicVisibilityModelData.Where(p => lstSurround.Contains(p.Key));
                    int iQueryCount = query.Count();
                    //暂时计算rrf时全部求mean。
                    if (iQueryCount > 0)
                    {
                        foreach (KeyValuePair<string, VisibilityModelData> item in query)
                        {
                            if (!dicModelDataVisibilityUsed.ContainsKey(item.Key))
                            {
                                dicModelDataVisibilityUsed.Add(item.Key, new VisibilityModelData()
                                {
                                    id = item.Key,
                                    gridcellLat = item.Value.gridcellLat,
                                    gridcellLong = item.Value.gridcellLong,
                                    dicBaselineModel = new Dictionary<string, ModelDataVisibility>(),
                                    dicFutureModel = new Dictionary<string, ModelDataVisibility>(),
                                });
                                foreach (KeyValuePair<string, NewImproveMonitors> kDays in dicVisibilityMonitors[k.Value.monitorID].dicNewIMPROVE[visibilityAnalysisConfiguration.filteringV.baseModelYear])
                                {
                                    dicModelDataVisibilityUsed[item.Key].dicBaselineModel.Add(kDays.Key, new ModelDataVisibility());
                                    dicModelDataVisibilityUsed[item.Key].dicFutureModel.Add(kDays.Key, new ModelDataVisibility());
                                }
                            }
                            else
                            {
                                foreach (KeyValuePair<string, NewImproveMonitors> kDays in dicVisibilityMonitors[k.Value.monitorID].dicNewIMPROVE[visibilityAnalysisConfiguration.filteringV.baseModelYear])
                                {
                                    if (dicModelDataVisibilityUsed[item.Key].dicBaselineModel.ContainsKey(kDays.Key)) continue;
                                    dicModelDataVisibilityUsed[item.Key].dicBaselineModel.Add(kDays.Key, new ModelDataVisibility());
                                    dicModelDataVisibilityUsed[item.Key].dicFutureModel.Add(kDays.Key, new ModelDataVisibility());
                                }
                            }
                        }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static string GetModelDataNeeded(VisibilityAnalysisConfiguration visibilityAnalysisConfiguration, ref Dictionary<string, VisibilityModelData> dicModelDataVisibilityUsed)
        {
            try
            {
                //--------------------------baseline model data---------------------------------------
                int iID = -1, iType = -1, iDate = -1, iCRUSTAL = -1, iEC = -1, iCM = -1, iPM25 = -1, iNH4 = -1, iSO4 = -1, iNO3 = -1, iOC = -1;
                FileStream fs = new FileStream(visibilityAnalysisConfiguration.dataInputV.baselineModelDataFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                try
                {
                    using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                    {
                        string strLine = csv.ReadLine();
                        string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                        int i = 0;
                        while (i < strLineArray.Length)
                        {
                            string s = strLineArray[i];
                            switch (s.Trim().ToLower().Replace("\"", ""))
                            {
                                case "_id":
                                    iID = i;
                                    break;
                                case "_type":
                                    iType = i;
                                    break;
                                case "date":
                                    iDate = i;
                                    break;
                                case "crustal":
                                    iCRUSTAL = i;
                                    break;
                                case "nh4":
                                    iNH4 = i;
                                    break;
                                case "so4":
                                    iSO4 = i;
                                    break;
                                case "ec":
                                    iEC = i;
                                    break;
                                case "no3":
                                    iNO3 = i;
                                    break;
                                case "oc":
                                    iOC = i;
                                    break;
                                case "pm25":
                                    iPM25 = i;
                                    break;
                                case "cm":
                                    iCM = i;
                                    break;
                            }
                            i++;
                        }
                        while (strLine != null)
                        {
                            strLine = csv.ReadLine();
                            if (strLine == null) break;
                            strLineArray = strLine.Split(new char[] { ',' });
                            if (!dicModelDataVisibilityUsed.ContainsKey(strLineArray[iID].ToString().Trim().Replace("\"", ""))) continue;
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].type = strLineArray[iType].ToString().Replace("\"", "");
                            if (!dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaselineModel.ContainsKey(strLineArray[iDate].Substring(4).Replace("\"", ""))) continue;
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaselineModel[strLineArray[iDate].Substring(4).Replace("\"", "")].crustal = Convert.ToSingle(strLineArray[iCRUSTAL]);
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaselineModel[strLineArray[iDate].Substring(4).Replace("\"", "")].so4 = Convert.ToSingle(strLineArray[iSO4]);
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaselineModel[strLineArray[iDate].Substring(4).Replace("\"", "")].ec = Convert.ToSingle(strLineArray[iEC]);
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaselineModel[strLineArray[iDate].Substring(4).Replace("\"", "")].no3 = Convert.ToSingle(strLineArray[iNO3]);
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaselineModel[strLineArray[iDate].Substring(4).Replace("\"", "")].oc = Convert.ToSingle(strLineArray[iOC]);
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaselineModel[strLineArray[iDate].Substring(4).Replace("\"", "")].cm = Convert.ToSingle(strLineArray[iCM]);
                        }
                        csv.Dispose(); fs.Dispose();
                        GC.Collect();
                    }
                }
                catch
                {
                    return "wrongBaseline";
                }

                _endTime = DateTime.Now;
                CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                CommonClass.CurrentLog = "Finish reading model data: " + CommonClass.TotalTime + " s.";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                _beginTime = DateTime.Now;
                CommonClass.CurrentLog = "Read model data \"" + Path.GetFileName(visibilityAnalysisConfiguration.dataInputV.forecastModelDataFile) + "\".";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                //----------------future model data----------------
                iID = -1; iDate = -1; iCRUSTAL = -1; iEC = -1; iCM = -1; iPM25 = -1; iNH4 = -1; iSO4 = -1; iNO3 = -1; iOC = -1;

                fs = new FileStream(visibilityAnalysisConfiguration.dataInputV.forecastModelDataFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                try
                {
                    using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                    {
                        string strLine = csv.ReadLine();
                        string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                        int i = 0;
                        while (i < strLineArray.Length)
                        {
                            string s = strLineArray[i];
                            switch (s.Trim().ToLower().Replace("\"", ""))
                            {
                                case "_id":
                                    iID = i;
                                    break;
                                case "date":
                                    iDate = i;
                                    break;
                                case "crustal":
                                    iCRUSTAL = i;
                                    break;
                                case "nh4":
                                    iNH4 = i;
                                    break;
                                case "so4":
                                    iSO4 = i;
                                    break;
                                case "ec":
                                    iEC = i;
                                    break;
                                case "no3":
                                    iNO3 = i;
                                    break;
                                case "oc":
                                    iOC = i;
                                    break;
                                case "pm25":
                                    iPM25 = i;
                                    break;
                                case "cm":
                                    iCM = i;
                                    break;
                            }
                            i++;
                        }
                        while (strLine != null)
                        {
                            strLine = csv.ReadLine();
                            if (strLine == null) break;
                            strLineArray = strLine.Split(new char[] { ',' });
                            if (!dicModelDataVisibilityUsed.ContainsKey(strLineArray[iID].ToString().Trim().Replace("\"", ""))) continue;
                            if (!dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureModel.ContainsKey(strLineArray[iDate].Substring(4).Replace("\"", ""))) continue;
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureModel[strLineArray[iDate].Substring(4).Replace("\"", "")].crustal = Convert.ToSingle(strLineArray[iCRUSTAL]);
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureModel[strLineArray[iDate].Substring(4).Replace("\"", "")].so4 = Convert.ToSingle(strLineArray[iSO4]);
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureModel[strLineArray[iDate].Substring(4).Replace("\"", "")].ec = Convert.ToSingle(strLineArray[iEC]);
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureModel[strLineArray[iDate].Substring(4).Replace("\"", "")].no3 = Convert.ToSingle(strLineArray[iNO3]);
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureModel[strLineArray[iDate].Substring(4).Replace("\"", "")].oc = Convert.ToSingle(strLineArray[iOC]);
                            dicModelDataVisibilityUsed[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureModel[strLineArray[iDate].Substring(4).Replace("\"", "")].cm = Convert.ToSingle(strLineArray[iCM]);
                        }
                        csv.Dispose(); fs.Dispose();
                        GC.Collect();
                    }
                }
                catch
                {
                    return "wrongFuture";
                }
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }
        }

        #endregion

        private static double round(double d, int s)
        {
            try
            {

                if (d == 0)
                    return d;
                return Math.Round(d, s - (int)Math.Floor(Math.Log10(Math.Abs(d))));
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return Math.Round(d, s);
            }
        }

        #region Get New Output Format DataTable Columns Methods

        /// <summary>
        /// 获取新数据格式列名
        /// new output format with additional variables 
        /// (RH-2017-test-new data - Forecasted Visibility Data-NEW FIELDS-2.xlsx & RH-2017-test-new data - Forecasted Visibility - all design values NEW FIELDS-2.xlsx)
        /// add by sclong
        /// 2017-02-26
        /// </summary>
        /// <param name="visibilityAnalysisConfiguration"></param>
        /// <returns></returns>
        private static DataTable GetNewOutputFormatDataTableColumns(VisibilityAnalysisConfiguration visibilityAnalysisConfiguration)
        {
            DataTable dt = null;
            try
            {
                dt = new DataTable();
                #region Add Columns

                dt.Columns.Add("site_id");
                dt.Columns.Add("type");
                dt.Columns.Add("date");
                //The "156-Class1-coordinates-all site names.csv" file
                if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                {
                    dt.Columns.Add("monitor_gridcell");
                    dt.Columns.Add("gridcell_lat");
                    dt.Columns.Add("gridcell_long");
                    dt.Columns.Add("monitor_lat");
                    dt.Columns.Add("monitor_long");
                }
                else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                {
                    dt.Columns.Add("class_i_gridcell");
                    dt.Columns.Add("gridcell_lat");
                    dt.Columns.Add("gridcell_long");
                    dt.Columns.Add("class_i_lat");
                    dt.Columns.Add("class_i_long");
                }
                //Base and future year deciview values, calculated from the total extinction values. Base year is from the IMPROVE data. Future year is from the internally calculated future year extinction values.
                dt.Columns.Add("dv_best_b");
                dt.Columns.Add("dv_best_f");
                dt.Columns.Add("dv_worst_b");
                dt.Columns.Add("dv_worst_f");

                #region betaversion需要隐藏下列字段
                bool isOutputOldFormat = System.Configuration.ConfigurationManager.AppSettings["VisibilityOldFormat"] == "T";
                if (!isOutputOldFormat)
                //if (!CommonClass.BetaVersion)
                {
                    //Measured IMPROVE mass data from the "ClassIareas_NEWIMPROVEALG_2000to2012_2013sep12.csv" file (or newer data file)
                    dt.Columns.Add("amm_so4_g10_b");
                    dt.Columns.Add("s_amm_so4_g10_b");
                    dt.Columns.Add("l_amm_so4_g10_b");
                    dt.Columns.Add("amm_no3_g10_b");
                    dt.Columns.Add("s_amm_no3_g10_b");
                    dt.Columns.Add("l_amm_no3_g10_b");
                    dt.Columns.Add("omc_g10_b");
                    dt.Columns.Add("s_omc_g10_b");
                    dt.Columns.Add("l_omc_g10_b");
                    dt.Columns.Add("ec_g10_b");
                    dt.Columns.Add("crustal_g10_b");
                    dt.Columns.Add("cm_g10_b");
                    dt.Columns.Add("sea_salt_g10_b");
                    dt.Columns.Add("amm_so4_g90_b");
                    dt.Columns.Add("s_amm_so4_g90_b");
                    dt.Columns.Add("l_amm_so4_g90_b");
                    dt.Columns.Add("amm_no3_g90_b");
                    dt.Columns.Add("s_amm_no3_g90_b");
                    dt.Columns.Add("l_amm_no3_g90_b");
                    dt.Columns.Add("omc_g90_b");
                    dt.Columns.Add("s_omc_g90_b");
                    dt.Columns.Add("l_omc_g90_b");
                    dt.Columns.Add("ec_g90_b");
                    dt.Columns.Add("crustal_g90_b");
                    dt.Columns.Add("cm_g90_b");
                    dt.Columns.Add("sea_salt_g90_b");

                    //Measured IMPROVE extinction data from the "ClassIareas_NEWIMPROVEALG_2000to2012_2013sep12.csv" file (or newer data file)
                    dt.Columns.Add("ss_Rayleigh");
                    dt.Columns.Add("E_amm_so4_g10_b");
                    dt.Columns.Add("E_amm_no3_g10_b");
                    dt.Columns.Add("E_omc_g10_b");
                    dt.Columns.Add("E_ec_g10_b");
                    dt.Columns.Add("E_crustal_g10_b");
                    dt.Columns.Add("E_cm_g10_b");
                    dt.Columns.Add("E_sea_salt_g10_b");
                    dt.Columns.Add("tbext_g10_b");//Base year total extinction (Mm-1) 20% clearest days
                    dt.Columns.Add("E_amm_so4_g90_b");//Base year measured ammonium sulfate extinction (Mm-1) 20% most impaired days
                    dt.Columns.Add("E_amm_no3_g90_b");//Base year measured ammonium nitrate extinction (Mm-1) 20% most impaired days
                    dt.Columns.Add("E_omc_g90_b");
                    dt.Columns.Add("E_ec_g90_b");
                    dt.Columns.Add("E_crustal_g90_b");
                    dt.Columns.Add("E_cm_g90_b");
                    dt.Columns.Add("E_sea_salt_g90_b");
                    dt.Columns.Add("tbext_g90_b");//Base year total extinction (Mm-1) 20% most impaired days

                    //Future mass concentrations, calculated by multiplying the base year measured mass by the relevant RRF. Calculated internally within SMAT.
                    dt.Columns.Add("amm_so4_g10_f");
                    dt.Columns.Add("s_amm_so4_g10_f");
                    dt.Columns.Add("l_amm_so4_g10_f");
                    dt.Columns.Add("amm_no3_g10_f");
                    dt.Columns.Add("s_amm_no3_g10_f");
                    dt.Columns.Add("l_amm_no3_g10_f");
                    dt.Columns.Add("omc_g10_f");
                    dt.Columns.Add("s_omc_g10_f");
                    dt.Columns.Add("l_omc_g10_f");
                    dt.Columns.Add("ec_g10_f");
                    dt.Columns.Add("crustal_g10_f");
                    dt.Columns.Add("cm_g10_f");
                    dt.Columns.Add("sea_salt_g10_f");
                    dt.Columns.Add("amm_so4_g90_f");
                    dt.Columns.Add("s_amm_so4_g90_f");
                    dt.Columns.Add("l_amm_so4_g90_f");
                    dt.Columns.Add("amm_no3_g90_f");
                    dt.Columns.Add("s_amm_no3_g90_f");
                    dt.Columns.Add("l_amm_no3_g90_f");
                    dt.Columns.Add("omc_g90_f");
                    dt.Columns.Add("s_omc_g90_f");
                    dt.Columns.Add("l_omc_g90_f");
                    dt.Columns.Add("ec_g90_f");
                    dt.Columns.Add("crustal_g90_f");
                    dt.Columns.Add("cm_g90_f");
                    dt.Columns.Add("sea_salt_g90_f");

                    //Future year extinction values, calculated from the future year mass concentrations, using the IMPROVE formula. Calculated internally within SMAT.
                    dt.Columns.Add("E_amm_so4_g10_f");//Future year ammonium sulfate extinction (Mm-1) 20% clearest days
                    dt.Columns.Add("E_amm_no3_g10_f");//Future year ammonium nitrate extinction (Mm-1) 20% clearest days
                    dt.Columns.Add("E_omc_g10_f");
                    dt.Columns.Add("E_ec_g10_f");
                    dt.Columns.Add("E_crustal_g10_f");
                    dt.Columns.Add("E_cm_g10_f");
                    dt.Columns.Add("E_sea_salt_g10_f");
                    dt.Columns.Add("tbext_g10_f");

                    dt.Columns.Add("E_amm_so4_g90_f");
                    dt.Columns.Add("E_amm_no3_g90_f");
                    dt.Columns.Add("E_omc_g90_f");
                    dt.Columns.Add("E_ec_g90_f");
                    dt.Columns.Add("E_crustal_g90_f");
                    dt.Columns.Add("E_cm_g90_f");
                    dt.Columns.Add("E_sea_salt_g90_f");
                    dt.Columns.Add("tbext_g90_f");
                    //*/
                }
                #endregion

                //Relative response factors (RRF) calculated from the base and future year model data files. Calculated internally within SMAT.
                dt.Columns.Add("rrf_g10_crustal");
                dt.Columns.Add("rrf_g10_no3");
                dt.Columns.Add("rrf_g10_oc");
                dt.Columns.Add("rrf_g10_ec");
                dt.Columns.Add("rrf_g10_cm");
                dt.Columns.Add("rrf_g10_so4");
                dt.Columns.Add("rrf_g90_crustal");
                dt.Columns.Add("rrf_g90_no3");
                dt.Columns.Add("rrf_g90_oc");
                dt.Columns.Add("rrf_g90_ec");
                dt.Columns.Add("rrf_g90_cm");
                dt.Columns.Add("rrf_g90_so4");
                #endregion Add Columns
                return dt;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return null;
            }
        }


        /// <summary>
        /// 获取新数据格式列名
        /// new output format with additional variables 
        /// (RH-2017-test-new data - Forecasted Visibility Data-NEW FIELDS-2.xlsx & RH-2017-test-new data - Forecasted Visibility - all design values NEW FIELDS-2.xlsx)
        /// add by sclong
        /// 2017-02-26
        /// </summary>
        /// <param name="visibilityAnalysisConfiguration"></param>
        /// <returns></returns>
        private static DataTable GetNewOutputFormatDataTableColumnsForAdvanceOption(VisibilityAnalysisConfiguration visibilityAnalysisConfiguration)
        {
            DataTable dt = null;
            try
            {
                dt = new DataTable();
                #region Add Columns

                dt.Columns.Add("site_id");
                dt.Columns.Add("type");
                dt.Columns.Add("date");
                //The "156-Class1-coordinates-all site names.csv" file
                if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                {
                    dt.Columns.Add("monitor_gridcell");
                    dt.Columns.Add("gridcell_lat");
                    dt.Columns.Add("gridcell_long");
                    dt.Columns.Add("monitor_lat");
                    dt.Columns.Add("monitor_long");
                }
                else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                {
                    dt.Columns.Add("class_i_gridcell");
                    dt.Columns.Add("gridcell_lat");
                    dt.Columns.Add("gridcell_long");
                    dt.Columns.Add("class_i_lat");
                    dt.Columns.Add("class_i_long");
                }
                //Base and future year deciview values, calculated from the total extinction values. Base year is from the IMPROVE data. Future year is from the internally calculated future year extinction values.
                dt.Columns.Add("dv_best_b");
                dt.Columns.Add("dv_best_f");
                dt.Columns.Add("dv_worst_b");
                dt.Columns.Add("dv_worst_f");

                //Measured IMPROVE extinction data from the "ClassIareas_NEWIMPROVEALG_2000to2012_2013sep12.csv" file (or newer data file)
                dt.Columns.Add("ss_Rayleigh");
                dt.Columns.Add("E_amm_so4_g10_b");
                dt.Columns.Add("E_amm_no3_g10_b");
                dt.Columns.Add("E_omc_g10_b");
                dt.Columns.Add("E_ec_g10_b");
                dt.Columns.Add("E_crustal_g10_b");
                dt.Columns.Add("E_cm_g10_b");
                dt.Columns.Add("E_sea_salt_g10_b");
                dt.Columns.Add("tbext_g10_b");//Base year total extinction (Mm-1) 20% clearest days
                dt.Columns.Add("E_amm_so4_g90_b");//Base year measured ammonium sulfate extinction (Mm-1) 20% most impaired days
                dt.Columns.Add("E_amm_no3_g90_b");//Base year measured ammonium nitrate extinction (Mm-1) 20% most impaired days
                dt.Columns.Add("E_omc_g90_b");
                dt.Columns.Add("E_ec_g90_b");
                dt.Columns.Add("E_crustal_g90_b");
                dt.Columns.Add("E_cm_g90_b");
                dt.Columns.Add("E_sea_salt_g90_b");
                dt.Columns.Add("tbext_g90_b");//Base year total extinction (Mm-1) 20% most impaired days


                //Future year extinction values, calculated from the future year mass concentrations, using the IMPROVE formula. Calculated internally within SMAT.
                dt.Columns.Add("E_amm_so4_g10_f");//Future year ammonium sulfate extinction (Mm-1) 20% clearest days
                dt.Columns.Add("E_amm_no3_g10_f");//Future year ammonium nitrate extinction (Mm-1) 20% clearest days
                dt.Columns.Add("E_omc_g10_f");
                dt.Columns.Add("E_ec_g10_f");
                dt.Columns.Add("E_crustal_g10_f");
                dt.Columns.Add("E_cm_g10_f");
                dt.Columns.Add("E_sea_salt_g10_f");
                dt.Columns.Add("tbext_g10_f");

                dt.Columns.Add("E_amm_so4_g90_f");
                dt.Columns.Add("E_amm_no3_g90_f");
                dt.Columns.Add("E_omc_g90_f");
                dt.Columns.Add("E_ec_g90_f");
                dt.Columns.Add("E_crustal_g90_f");
                dt.Columns.Add("E_cm_g90_f");
                dt.Columns.Add("E_sea_salt_g90_f");
                dt.Columns.Add("tbext_g90_f");

                //Relative response factors (RRF) calculated from the base and future year model data files. Calculated internally within SMAT.
                dt.Columns.Add("rrf_g10_crustal");
                dt.Columns.Add("rrf_g10_no3");
                dt.Columns.Add("rrf_g10_oc");
                dt.Columns.Add("rrf_g10_ec");
                dt.Columns.Add("rrf_g10_cm");
                dt.Columns.Add("rrf_g10_so4");
                dt.Columns.Add("rrf_g90_crustal");
                dt.Columns.Add("rrf_g90_no3");
                dt.Columns.Add("rrf_g90_oc");
                dt.Columns.Add("rrf_g90_ec");
                dt.Columns.Add("rrf_g90_cm");
                dt.Columns.Add("rrf_g90_so4");
                #endregion Add Columns
                return dt;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return null;
            }
        }

        #endregion Get New Output Format DataTable Columns Methods

        #region Save Forecasted Visibility File Methods

        public static bool SaveForecastedVisibility(BaseScenario baseScenario, Dictionary<string, ForecastedVisibility> dicForecasedValues)
        {
            if (!(baseScenario.configuration is VisibilityAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                VisibilityAnalysisConfiguration visibilityAnalysisConfiguration = baseScenario.configuration as VisibilityAnalysisConfiguration;
                DataTable dt = new DataTable();
                dt.Columns.Add("_id");
                dt.Columns.Add("_type");
                dt.Columns.Add("date");
                dt.Columns.Add("dv_best");
                dt.Columns.Add("dv_worst");
                dt.Columns.Add("base_best");
                dt.Columns.Add("base_worst");
                dt.Columns.Add("rrf_b_crustal");
                dt.Columns.Add("rrf_b_no3");
                dt.Columns.Add("rrf_b_oc");
                dt.Columns.Add("rrf_b_ec");
                dt.Columns.Add("rrf_b_cm");
                dt.Columns.Add("rrf_b_so4");
                dt.Columns.Add("rrf_w_crustal");
                dt.Columns.Add("rrf_w_no3");
                dt.Columns.Add("rrf_w_oc");
                dt.Columns.Add("rrf_w_ec");
                dt.Columns.Add("rrf_w_cm");
                dt.Columns.Add("rrf_w_so4");
                if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                {
                    dt.Columns.Add("monitor_gridcell");
                    dt.Columns.Add("gridcell_lat");
                    dt.Columns.Add("gridcell_long");
                    dt.Columns.Add("monitor_lat");
                    dt.Columns.Add("monitor_long");
                }
                else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                {
                    //class i area
                    dt.Columns.Add("class_i_gridcell");
                    dt.Columns.Add("gridcell_lat");
                    dt.Columns.Add("gridcell_long");
                    dt.Columns.Add("class_i_lat");
                    dt.Columns.Add("class_i_long");
                }

                foreach (KeyValuePair<string, ForecastedVisibility> k in dicForecasedValues)
                {
                    DataRow dr = dt.NewRow();
                    dr[0] = k.Value.id;
                    dr[1] = k.Value.type;
                    dr[2] = visibilityAnalysisConfiguration.filteringV.baseModelYear;
                    dr[3] = Math.Round(k.Value.dicForecastedVisibilityValues.Select(p => p.Value.dvBest).Average(), 2);
                    dr[4] = Math.Round(k.Value.dicForecastedVisibilityValues.Select(p => p.Value.dvWorst).Average(), 2);
                    dr[5] = Math.Round(k.Value.dicForecastedVisibilityValues.Select(p => p.Value.baseBest).Average(), 2);
                    dr[6] = Math.Round(k.Value.dicForecastedVisibilityValues.Select(p => p.Value.baseWorst).Average(), 2);


                    dr[7] = Math.Round(k.Value.rrfbCrustal, 4);
                    dr[8] = Math.Round(k.Value.rrfbNO3, 4);
                    dr[9] = Math.Round(k.Value.rrfbOC, 4);
                    dr[10] = Math.Round(k.Value.rrfbEC, 4);
                    dr[11] = Math.Round(k.Value.rrfbCM, 4);
                    dr[12] = Math.Round(k.Value.rrfbSO4, 4);
                    dr[13] = Math.Round(k.Value.rrfwCrustal, 4);
                    dr[14] = Math.Round(k.Value.rrfwNO3, 4);
                    dr[15] = Math.Round(k.Value.rrfwOC, 4);
                    dr[16] = Math.Round(k.Value.rrfwEC, 4);
                    dr[17] = Math.Round(k.Value.rrfwCM, 4);
                    dr[18] = Math.Round(k.Value.rrfwSO4, 4);
                    dr[19] = k.Value.gridcell;
                    dr[20] = Math.Round(k.Value.gridcellLat, 6);
                    dr[21] = Math.Round(k.Value.gridcellLong, 6);
                    if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                    {
                        dr[22] = Math.Round(k.Value.monitorLat, 6);
                        dr[23] = Math.Round(k.Value.monitorLongitude, 6);
                    }
                    else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                    {
                        dr[22] = Math.Round(k.Value.lat, 6);
                        dr[23] = Math.Round(k.Value.longitude, 6);
                    }

                    dt.Rows.Add(dr);
                }

                //------------修正OutPutFileName----------------
                string strFile = "";
                if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                {
                    strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecasted Visibility Data.csv";
                }
                else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                {
                    strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecasted Visibility Data for Class I Area.csv";
                }
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Year");
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                baseScenario.lstOutput.Add(baseOutput);
                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }

        }

        /// <summary>
        /// 输出新格式的 Forecasted Visibility Data
        /// </summary>
        /// <param name="baseScenario"></param>
        /// <param name="dicForecasedValues"></param>
        /// <returns></returns>
        public static bool SaveForecastedVisibilityWithNewFormat(BaseScenario baseScenario, Dictionary<string, VisibilityMonitor> dicVisibilityMonitors, Dictionary<string, ForecastedVisibility> dicForecasedValues)
        {
            if (!(baseScenario.configuration is VisibilityAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                VisibilityAnalysisConfiguration visibilityAnalysisConfiguration = baseScenario.configuration as VisibilityAnalysisConfiguration;

                DataTable dt = GetNewOutputFormatDataTableColumns(visibilityAnalysisConfiguration);// new DataTable();  

                foreach (KeyValuePair<string, ForecastedVisibility> k in dicForecasedValues)//遍历测点
                {
                    VisibilityMonitor visibilityMonitorItem = dicVisibilityMonitors[k.Value.monitorID];
                    //ForecastedVisibilityDataAttribute forecastedYearItem = k.Value.dicForecastedVisibilityValues[visibilityAnalysisConfiguration.filteringV.baseModelYear];

                    Dictionary<string, ForecastedVisibilityDataAttribute> dicForecastedVisibilityValues = k.Value.dicForecastedVisibilityValues;

                    DataRow dr = dt.NewRow();
                    #region fill row data

                    dr[0] = k.Value.id;
                    dr[1] = k.Value.type;
                    dr[2] = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.baseModelYear);
                    dr[3] = k.Value.gridcell;
                    dr[4] = Math.Round(k.Value.gridcellLat, 6);
                    dr[5] = Math.Round(k.Value.gridcellLong, 6);
                    if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                    {
                        dr[6] = Math.Round(k.Value.monitorLat, 6);
                        dr[7] = Math.Round(k.Value.monitorLongitude, 6);
                    }
                    else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                    {
                        dr[6] = Math.Round(k.Value.lat, 6);
                        dr[7] = Math.Round(k.Value.longitude, 6);
                    }

                    //dr[8] = CommonClass.ToFixed(dicForecastedVisibilityValues.Select(p => p.Value.baseBest).Average(), CommonClass.Visibility_calculation_decimal_point);
                    //dr[9] = CommonClass.ToFixed(dicForecastedVisibilityValues.Select(p => p.Value.dvBest).Average(), CommonClass.Visibility_calculation_decimal_point);
                    //dr[10] = CommonClass.ToFixed(dicForecastedVisibilityValues.Select(p => p.Value.baseWorst).Average(), CommonClass.Visibility_calculation_decimal_point);
                    //dr[11] = CommonClass.ToFixed(dicForecastedVisibilityValues.Select(p => p.Value.dvWorst).Average(), CommonClass.Visibility_calculation_decimal_point);
                    dr[8] = Math.Round(dicForecastedVisibilityValues.Select(p => p.Value.baseBest).Average(), CommonClass.Visibility_calculation_decimal_point);//结果输出需要四舍五入，而不是截取
                    dr[9] = Math.Round(dicForecastedVisibilityValues.Select(p => p.Value.dvBest).Average(), CommonClass.Visibility_calculation_decimal_point);
                    dr[10] = Math.Round(dicForecastedVisibilityValues.Select(p => p.Value.baseWorst).Average(), CommonClass.Visibility_calculation_decimal_point);
                    dr[11] = Math.Round(dicForecastedVisibilityValues.Select(p => p.Value.dvWorst).Average(), CommonClass.Visibility_calculation_decimal_point);

                    //Dictionary<string, NewImproveMonitors> YearMonitorItem = visibilityMonitorItem.dicNewIMPROVE[visibilityAnalysisConfiguration.filteringV.baseModelYear];


                    //Base year measured species mass (ug/m3) 20% clearest days
                    dr[12] = dicForecastedVisibilityValues.Select(p => p.Value.AmmSO4.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.ammSO4).Average();
                    dr[13] = dicForecastedVisibilityValues.Select(p => p.Value.SmallAmmSO4.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.smallAmmSO4).Average();
                    dr[14] = dicForecastedVisibilityValues.Select(p => p.Value.LargeAmmSO4.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.largeAmmSO4).Average();
                    dr[15] = dicForecastedVisibilityValues.Select(p => p.Value.AmmNO3.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.ammNO3).Average();
                    dr[16] = dicForecastedVisibilityValues.Select(p => p.Value.SmallAmmNO3.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.smallAmmNO3).Average();
                    dr[17] = dicForecastedVisibilityValues.Select(p => p.Value.LargeAmmNO3.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.largeAmmNO3).Average();
                    dr[18] = dicForecastedVisibilityValues.Select(p => p.Value.OMC.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.omc).Average();
                    dr[19] = dicForecastedVisibilityValues.Select(p => p.Value.SmallOMC.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.smallOMC).Average();
                    dr[20] = dicForecastedVisibilityValues.Select(p => p.Value.LargeOMC.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.largeOMC).Average();
                    dr[21] = dicForecastedVisibilityValues.Select(p => p.Value.EC.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.ec).Average();
                    dr[22] = dicForecastedVisibilityValues.Select(p => p.Value.Crustal.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.crustal).Average();
                    dr[23] = dicForecastedVisibilityValues.Select(p => p.Value.CM.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.cm).Average();
                    dr[24] = dicForecastedVisibilityValues.Select(p => p.Value.SeaSalt.Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.seaSalt).Average();
                    //Base year measured species mass (ug/m3) 20% most impaired days
                    dr[25] = dicForecastedVisibilityValues.Select(p => p.Value.AmmSO4.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.ammSO4).Average();
                    dr[26] = dicForecastedVisibilityValues.Select(p => p.Value.SmallAmmSO4.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.smallAmmSO4).Average();
                    dr[27] = dicForecastedVisibilityValues.Select(p => p.Value.LargeAmmSO4.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.largeAmmSO4).Average();
                    dr[28] = dicForecastedVisibilityValues.Select(p => p.Value.AmmNO3.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.ammNO3).Average();
                    dr[29] = dicForecastedVisibilityValues.Select(p => p.Value.SmallAmmNO3.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.smallAmmNO3).Average();
                    dr[30] = dicForecastedVisibilityValues.Select(p => p.Value.LargeAmmNO3.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.largeAmmNO3).Average();
                    dr[31] = dicForecastedVisibilityValues.Select(p => p.Value.OMC.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.omc).Average();
                    dr[32] = dicForecastedVisibilityValues.Select(p => p.Value.SmallOMC.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.smallOMC).Average();
                    dr[33] = dicForecastedVisibilityValues.Select(p => p.Value.LargeOMC.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.largeOMC).Average();
                    dr[34] = dicForecastedVisibilityValues.Select(p => p.Value.EC.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.ec).Average();
                    dr[35] = dicForecastedVisibilityValues.Select(p => p.Value.Crustal.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.crustal).Average();
                    dr[36] = dicForecastedVisibilityValues.Select(p => p.Value.CM.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.cm).Average();
                    dr[37] = dicForecastedVisibilityValues.Select(p => p.Value.SeaSalt.Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.seaSalt).Average();

                    //Measured IMPROVE extinction data 
                    dr[38] = visibilityMonitorItem.dicNewIMPROVE[visibilityAnalysisConfiguration.filteringV.baseModelYear].First().Value.ssRayleigh;//特定地点的瑞利散射，指定地点后这个值就固定了，所以取第一个即可。
                    dr[39] = dicForecastedVisibilityValues.Select(p => p.Value.AmmSO4.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_amm_so4).Average();//E_amm_so4_g10_b
                    dr[40] = dicForecastedVisibilityValues.Select(p => p.Value.AmmNO3.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_amm_no3).Average(); ;//E_amm_no3_g10_b
                    dr[41] = dicForecastedVisibilityValues.Select(p => p.Value.OMC.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_omc).Average(); ;//E_omc_g10_b
                    dr[42] = dicForecastedVisibilityValues.Select(p => p.Value.EC.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_ec).Average(); ;//E_ec_g10_b
                    dr[43] = dicForecastedVisibilityValues.Select(p => p.Value.Crustal.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_crustal).Average(); ;//E_crustal_g10_b
                    dr[44] = dicForecastedVisibilityValues.Select(p => p.Value.CM.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_cm).Average(); ;//E_cm_g10_b
                    dr[45] = dicForecastedVisibilityValues.Select(p => p.Value.SeaSalt.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_sea_salt).Average(); ;//E_sea_salt_g10_b
                    dr[46] = dicForecastedVisibilityValues.Select(p => p.Value.TBext.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.baseBext).Average(); ;//tbext_g10_b，//Base year total extinction (Mm-1) 20% clearest days

                    dr[47] = dicForecastedVisibilityValues.Select(p => p.Value.AmmSO4.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_amm_so4).Average();//E_amm_so4_g90_b
                    dr[48] = dicForecastedVisibilityValues.Select(p => p.Value.AmmNO3.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_amm_no3).Average();//E_amm_no3_g90_b
                    dr[49] = dicForecastedVisibilityValues.Select(p => p.Value.OMC.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_omc).Average();//E_omc_g90_b
                    dr[50] = dicForecastedVisibilityValues.Select(p => p.Value.EC.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_ec).Average();//E_ec_g90_b
                    dr[51] = dicForecastedVisibilityValues.Select(p => p.Value.Crustal.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_crustal).Average();//E_crustal_g90_b
                    dr[52] = dicForecastedVisibilityValues.Select(p => p.Value.CM.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_cm).Average(); //E_cm_g90_b
                    dr[53] = dicForecastedVisibilityValues.Select(p => p.Value.SeaSalt.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_sea_salt).Average(); //E_sea_salt_g90_b
                    dr[54] = dicForecastedVisibilityValues.Select(p => p.Value.TBext.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.baseBext).Average();//tbext_g90_b，Base year total extinction (Mm-1) 20% most impaired days

                    //Future mass concentrations, calculated by multiplying the base year measured mass by the relevant RRF. Calculated internally within SMAT.
                    dr[55] = dicForecastedVisibilityValues.Select(p => p.Value.AmmSO4.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureAmmSO4).Average(); //amm_so4_g10_f
                    dr[56] = dicForecastedVisibilityValues.Select(p => p.Value.SmallAmmSO4.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureSmallAmmSO4).Average();
                    dr[57] = dicForecastedVisibilityValues.Select(p => p.Value.LargeAmmSO4.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureLargeAmmSO4).Average();
                    dr[58] = dicForecastedVisibilityValues.Select(p => p.Value.AmmNO3.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futurAmmNO3).Average(); ;
                    dr[59] = dicForecastedVisibilityValues.Select(p => p.Value.SmallAmmNO3.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureSmallAmmNO3).Average(); ;
                    dr[60] = dicForecastedVisibilityValues.Select(p => p.Value.LargeAmmNO3.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureLargeAmmNO3).Average();
                    dr[61] = dicForecastedVisibilityValues.Select(p => p.Value.OMC.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureOMC).Average(); ;
                    dr[62] = dicForecastedVisibilityValues.Select(p => p.Value.SmallOMC.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureSmallOMC).Average();
                    dr[63] = dicForecastedVisibilityValues.Select(p => p.Value.LargeOMC.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureLargeOMC).Average();
                    dr[64] = dicForecastedVisibilityValues.Select(p => p.Value.EC.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureEC).Average();
                    dr[65] = dicForecastedVisibilityValues.Select(p => p.Value.Crustal.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureCrustal).Average();
                    dr[66] = dicForecastedVisibilityValues.Select(p => p.Value.CM.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureCm).Average();
                    dr[67] = dicForecastedVisibilityValues.Select(p => p.Value.SeaSalt.Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.seaSalt).Average();

                    dr[68] = dicForecastedVisibilityValues.Select(p => p.Value.AmmSO4.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureAmmSO4).Average(); //amm_so4_g90_f
                    dr[69] = dicForecastedVisibilityValues.Select(p => p.Value.SmallAmmSO4.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureSmallAmmSO4).Average();
                    dr[70] = dicForecastedVisibilityValues.Select(p => p.Value.LargeAmmSO4.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureLargeAmmSO4).Average();
                    dr[71] = dicForecastedVisibilityValues.Select(p => p.Value.AmmNO3.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futurAmmNO3).Average(); ;
                    dr[72] = dicForecastedVisibilityValues.Select(p => p.Value.SmallAmmNO3.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureSmallAmmNO3).Average(); ;
                    dr[73] = dicForecastedVisibilityValues.Select(p => p.Value.LargeAmmNO3.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureLargeAmmNO3).Average();
                    dr[74] = dicForecastedVisibilityValues.Select(p => p.Value.OMC.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureOMC).Average(); ;
                    dr[75] = dicForecastedVisibilityValues.Select(p => p.Value.SmallOMC.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureSmallOMC).Average();
                    dr[76] = dicForecastedVisibilityValues.Select(p => p.Value.LargeOMC.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureLargeOMC).Average();
                    dr[77] = dicForecastedVisibilityValues.Select(p => p.Value.EC.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureEC).Average();
                    dr[78] = dicForecastedVisibilityValues.Select(p => p.Value.Crustal.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureCrustal).Average();
                    dr[79] = dicForecastedVisibilityValues.Select(p => p.Value.CM.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureCm).Average();
                    dr[80] = dicForecastedVisibilityValues.Select(p => p.Value.SeaSalt.Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.seaSalt).Average();

                    dr[81] = dicForecastedVisibilityValues.Select(p => p.Value.AmmSO4.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_amm_so4).Average();//E_amm_so4_g10_f
                    dr[82] = dicForecastedVisibilityValues.Select(p => p.Value.AmmNO3.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_amm_no3).Average();//E_amm_no3_g10_f
                    dr[83] = dicForecastedVisibilityValues.Select(p => p.Value.OMC.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_omc).Average();//E_omc_g10_f
                    dr[84] = dicForecastedVisibilityValues.Select(p => p.Value.EC.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_ec).Average();//E_ec_g10_f
                    dr[85] = dicForecastedVisibilityValues.Select(p => p.Value.Crustal.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_crustal).Average();//E_crustal_g10_f
                    dr[86] = dicForecastedVisibilityValues.Select(p => p.Value.CM.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_cm).Average();//E_cm_g10_f
                    dr[87] = dicForecastedVisibilityValues.Select(p => p.Value.SeaSalt.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_sea_salt).Average();//E_sea_salt_g10_f
                    dr[88] = dicForecastedVisibilityValues.Select(p => p.Value.TBext.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureBext).Average(); ;//tbext_g10_f，//Base year total extinction (Mm-1) 20% clearest days

                    dr[89] = dicForecastedVisibilityValues.Select(p => p.Value.AmmSO4.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_amm_so4).Average();//E_amm_so4_g90_f
                    dr[90] = dicForecastedVisibilityValues.Select(p => p.Value.AmmNO3.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_amm_no3).Average();//E_amm_no3_g90_f
                    dr[91] = dicForecastedVisibilityValues.Select(p => p.Value.OMC.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_omc).Average();//E_omc_g90_f
                    dr[92] = dicForecastedVisibilityValues.Select(p => p.Value.EC.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_ec).Average();//E_ec_g90_f
                    dr[93] = dicForecastedVisibilityValues.Select(p => p.Value.Crustal.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_crustal).Average();//E_crustal_g90_f
                    dr[94] = dicForecastedVisibilityValues.Select(p => p.Value.CM.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_cm).Average();//E_cm_g90_f
                    dr[95] = dicForecastedVisibilityValues.Select(p => p.Value.SeaSalt.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_sea_salt).Average();//E_sea_salt_g90_f
                    dr[96] = dicForecastedVisibilityValues.Select(p => p.Value.TBext.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureBext).Average();//tbext_g90_f，Base year total extinction (Mm-1) 20% most impaired days

                    //Relative response factors (RRF) calculated from the base and future year model data files. Calculated internally within SMAT.
                    dr[97] = k.Value.rrfbCrustal;
                    dr[98] = k.Value.rrfbNO3;
                    dr[99] = k.Value.rrfbOC;
                    dr[100] = k.Value.rrfbEC;
                    dr[101] = k.Value.rrfbCM;
                    dr[102] = k.Value.rrfbSO4;
                    dr[103] = k.Value.rrfwCrustal;
                    dr[104] = k.Value.rrfwNO3;
                    dr[105] = k.Value.rrfwOC;
                    dr[106] = k.Value.rrfwEC;
                    dr[107] = k.Value.rrfwCM;
                    dr[108] = k.Value.rrfwSO4;
                    #endregion fill row data
                    dt.Rows.Add(dr);

                }

                //------------修正OutPutFileName----------------
                string strFile = "";
                if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                {
                    strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecasted Visibility Data.csv";
                }
                else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                {
                    strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecasted Visibility Data for Class I Area.csv";
                }
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Year");
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                baseScenario.lstOutput.Add(baseOutput);
                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }

        }

        /// <summary>
        /// 输出新格式的 Forecasted Visibility Data for advance option
        /// </summary>
        /// <param name="baseScenario"></param>
        /// <param name="dicForecasedValues"></param>
        /// <returns></returns>
        public static bool SaveForecastedVisibilityForAdvanceOption(BaseScenario baseScenario, Dictionary<string, VisibilityMonitor> dicVisibilityMonitors, Dictionary<string, ForecastedVisibility> dicForecasedValues)
        {
            if (!(baseScenario.configuration is VisibilityAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                VisibilityAnalysisConfiguration visibilityAnalysisConfiguration = baseScenario.configuration as VisibilityAnalysisConfiguration;

                DataTable dt = GetNewOutputFormatDataTableColumnsForAdvanceOption(visibilityAnalysisConfiguration);// new DataTable();  

                foreach (KeyValuePair<string, ForecastedVisibility> k in dicForecasedValues)//遍历测点
                {
                    VisibilityMonitor visibilityMonitorItem = dicVisibilityMonitors[k.Value.monitorID];
                    //ForecastedVisibilityDataAttribute forecastedYearItem = k.Value.dicForecastedVisibilityValues[visibilityAnalysisConfiguration.filteringV.baseModelYear];

                    Dictionary<string, ForecastedVisibilityDataAttribute> dicForecastedVisibilityValues = k.Value.dicForecastedVisibilityValues;

                    DataRow dr = dt.NewRow();
                    #region fill row data

                    dr[0] = k.Value.id;
                    dr[1] = k.Value.type;
                    dr[2] = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.baseModelYear);
                    dr[3] = k.Value.gridcell;
                    dr[4] = Math.Round(k.Value.gridcellLat, 6);
                    dr[5] = Math.Round(k.Value.gridcellLong, 6);
                    if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                    {
                        dr[6] = Math.Round(k.Value.monitorLat, 6);
                        dr[7] = Math.Round(k.Value.monitorLongitude, 6);
                    }
                    else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                    {
                        dr[6] = Math.Round(k.Value.lat, 6);
                        dr[7] = Math.Round(k.Value.longitude, 6);
                    }

                    //dr[8] = CommonClass.ToFixed(dicForecastedVisibilityValues.Select(p => p.Value.baseBest).Average(), CommonClass.Visibility_calculation_decimal_point);
                    //dr[9] = CommonClass.ToFixed(dicForecastedVisibilityValues.Select(p => p.Value.dvBest).Average(), CommonClass.Visibility_calculation_decimal_point);
                    //dr[10] = CommonClass.ToFixed(dicForecastedVisibilityValues.Select(p => p.Value.baseWorst).Average(), CommonClass.Visibility_calculation_decimal_point);
                    //dr[11] = CommonClass.ToFixed(dicForecastedVisibilityValues.Select(p => p.Value.dvWorst).Average(), CommonClass.Visibility_calculation_decimal_point);
                    //Visibility 需要四舍五入，而不是截取
                    dr[8] = Math.Round(dicForecastedVisibilityValues.Select(p => p.Value.baseBest).Average(), CommonClass.Visibility_calculation_decimal_point);
                    dr[9] = Math.Round(dicForecastedVisibilityValues.Select(p => p.Value.dvBest).Average(), CommonClass.Visibility_calculation_decimal_point);
                    dr[10] = Math.Round(dicForecastedVisibilityValues.Select(p => p.Value.baseWorst).Average(), CommonClass.Visibility_calculation_decimal_point);
                    dr[11] = Math.Round(dicForecastedVisibilityValues.Select(p => p.Value.dvWorst).Average(), CommonClass.Visibility_calculation_decimal_point);

                    //Measured IMPROVE extinction data 
                    dr[12] = visibilityMonitorItem.dicNewIMPROVE[visibilityAnalysisConfiguration.filteringV.baseModelYear].First().Value.ssRayleigh;//特定地点的瑞利散射，指定地点后这个值就固定了，所以取第一个即可。
                    dr[13] = dicForecastedVisibilityValues.Select(p => p.Value.AmmSO4.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_amm_so4).Average();//E_amm_so4_g10_b
                    dr[14] = dicForecastedVisibilityValues.Select(p => p.Value.AmmNO3.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_amm_no3).Average(); ;//E_amm_no3_g10_b
                    dr[15] = dicForecastedVisibilityValues.Select(p => p.Value.OMC.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_omc).Average(); ;//E_omc_g10_b
                    dr[16] = dicForecastedVisibilityValues.Select(p => p.Value.EC.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_ec).Average(); ;//E_ec_g10_b
                    dr[17] = dicForecastedVisibilityValues.Select(p => p.Value.Crustal.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_crustal).Average(); ;//E_crustal_g10_b
                    dr[18] = dicForecastedVisibilityValues.Select(p => p.Value.CM.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_cm).Average(); ;//E_cm_g10_b
                    dr[19] = dicForecastedVisibilityValues.Select(p => p.Value.SeaSalt.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_sea_salt).Average(); ;//E_sea_salt_g10_b
                    dr[20] = dicForecastedVisibilityValues.Select(p => p.Value.TBext.E_Best_b).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.baseBext).Average(); ;//tbext_g10_b，//Base year total extinction (Mm-1) 20% clearest days

                    dr[21] = dicForecastedVisibilityValues.Select(p => p.Value.AmmSO4.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_amm_so4).Average();//E_amm_so4_g90_b
                    dr[22] = dicForecastedVisibilityValues.Select(p => p.Value.AmmNO3.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_amm_no3).Average();//E_amm_no3_g90_b
                    dr[23] = dicForecastedVisibilityValues.Select(p => p.Value.OMC.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_omc).Average();//E_omc_g90_b
                    dr[24] = dicForecastedVisibilityValues.Select(p => p.Value.EC.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_ec).Average();//E_ec_g90_b
                    dr[25] = dicForecastedVisibilityValues.Select(p => p.Value.Crustal.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_crustal).Average();//E_crustal_g90_b
                    dr[26] = dicForecastedVisibilityValues.Select(p => p.Value.CM.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_cm).Average(); //E_cm_g90_b
                    dr[27] = dicForecastedVisibilityValues.Select(p => p.Value.SeaSalt.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_sea_salt).Average(); //E_sea_salt_g90_b
                    dr[28] = dicForecastedVisibilityValues.Select(p => p.Value.TBext.E_Worst_b).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.baseBext).Average();//tbext_g90_b，Base year total extinction (Mm-1) 20% most impaired days

                    dr[29] = dicForecastedVisibilityValues.Select(p => p.Value.AmmSO4.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_amm_so4).Average();//E_amm_so4_g10_f
                    dr[30] = dicForecastedVisibilityValues.Select(p => p.Value.AmmNO3.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_amm_no3).Average();//E_amm_no3_g10_f
                    dr[31] = dicForecastedVisibilityValues.Select(p => p.Value.OMC.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_omc).Average();//E_omc_g10_f
                    dr[32] = dicForecastedVisibilityValues.Select(p => p.Value.EC.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_ec).Average();//E_ec_g10_f
                    dr[33] = dicForecastedVisibilityValues.Select(p => p.Value.Crustal.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_crustal).Average();//E_crustal_g10_f
                    dr[34] = dicForecastedVisibilityValues.Select(p => p.Value.CM.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_cm).Average();//E_cm_g10_f
                    dr[35] = dicForecastedVisibilityValues.Select(p => p.Value.SeaSalt.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_sea_salt).Average();//E_sea_salt_g10_f
                    dr[36] = dicForecastedVisibilityValues.Select(p => p.Value.TBext.E_Best_f).Average();// YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureBext).Average(); ;//tbext_g10_f，//Base year total extinction (Mm-1) 20% clearest days

                    dr[37] = dicForecastedVisibilityValues.Select(p => p.Value.AmmSO4.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_amm_so4).Average();//E_amm_so4_g90_f
                    dr[38] = dicForecastedVisibilityValues.Select(p => p.Value.AmmNO3.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_amm_no3).Average();//E_amm_no3_g90_f
                    dr[39] = dicForecastedVisibilityValues.Select(p => p.Value.OMC.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_omc).Average();//E_omc_g90_f
                    dr[40] = dicForecastedVisibilityValues.Select(p => p.Value.EC.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_ec).Average();//E_ec_g90_f
                    dr[41] = dicForecastedVisibilityValues.Select(p => p.Value.Crustal.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_crustal).Average();//E_crustal_g90_f
                    dr[42] = dicForecastedVisibilityValues.Select(p => p.Value.CM.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_cm).Average();//E_cm_g90_f
                    dr[43] = dicForecastedVisibilityValues.Select(p => p.Value.SeaSalt.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_sea_salt).Average();//E_sea_salt_g90_f
                    dr[44] = dicForecastedVisibilityValues.Select(p => p.Value.TBext.E_Worst_f).Average();// YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureBext).Average();//tbext_g90_f，Base year total extinction (Mm-1) 20% most impaired days

                    //Relative response factors (RRF) calculated from the base and future year model data files. Calculated internally within SMAT.
                    dr[45] = k.Value.rrfbCrustal;
                    dr[46] = k.Value.rrfbNO3;
                    dr[47] = k.Value.rrfbOC;
                    dr[48] = k.Value.rrfbEC;
                    dr[49] = k.Value.rrfbCM;
                    dr[50] = k.Value.rrfbSO4;
                    dr[51] = k.Value.rrfwCrustal;
                    dr[52] = k.Value.rrfwNO3;
                    dr[53] = k.Value.rrfwOC;
                    dr[54] = k.Value.rrfwEC;
                    dr[55] = k.Value.rrfwCM;
                    dr[56] = k.Value.rrfwSO4;
                    #endregion fill row data
                    dt.Rows.Add(dr);

                }

                //------------修正OutPutFileName----------------
                string strFile = "";
                if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                {
                    strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecasted Visibility Data.csv";
                }
                else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                {
                    strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecasted Visibility Data for Class I Area.csv";
                }
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Year");
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                baseScenario.lstOutput.Add(baseOutput);
                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }

        }
        /// <summary>
        /// 输出新格式的 Forecasted Visibility Data
        /// </summary>
        /// <param name="baseScenario"></param>
        /// <param name="dicForecasedValues"></param>
        /// <returns></returns>
        public static bool SaveForecastedVisibilityWithOldVariables(BaseScenario baseScenario, Dictionary<string, VisibilityMonitor> dicVisibilityMonitors, Dictionary<string, ForecastedVisibility> dicForecasedValues)
        {
            if (!(baseScenario.configuration is VisibilityAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                VisibilityAnalysisConfiguration visibilityAnalysisConfiguration = baseScenario.configuration as VisibilityAnalysisConfiguration;

                DataTable dt = GetNewOutputFormatDataTableColumns(visibilityAnalysisConfiguration);// new DataTable();  

                foreach (KeyValuePair<string, ForecastedVisibility> k in dicForecasedValues)//遍历测点
                {
                    VisibilityMonitor visibilityMonitorItem = dicVisibilityMonitors[k.Value.monitorID];
                    Dictionary<string, ForecastedVisibilityDataAttribute> dicForecastedVisibilityValues = k.Value.dicForecastedVisibilityValues;

                    DataRow dr = dt.NewRow();
                    #region fill row data

                    dr[0] = k.Value.id;
                    dr[1] = k.Value.type;
                    dr[2] = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.baseModelYear);
                    dr[3] = k.Value.gridcell;
                    dr[4] = Math.Round(k.Value.gridcellLat, 6);
                    dr[5] = Math.Round(k.Value.gridcellLong, 6);
                    if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                    {
                        dr[6] = Math.Round(k.Value.monitorLat, 6);
                        dr[7] = Math.Round(k.Value.monitorLongitude, 6);
                    }
                    else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                    {
                        dr[6] = Math.Round(k.Value.lat, 6);
                        dr[7] = Math.Round(k.Value.longitude, 6);
                    }


                    //dr[8] = CommonClass.ToFixed(dicForecastedVisibilityValues.Select(p => p.Value.baseBest).Average(), CommonClass.Visibility_calculation_decimal_point);
                    //dr[9] = CommonClass.ToFixed(dicForecastedVisibilityValues.Select(p => p.Value.dvBest).Average(), CommonClass.Visibility_calculation_decimal_point);
                    //dr[10] = CommonClass.ToFixed(dicForecastedVisibilityValues.Select(p => p.Value.baseWorst).Average(), CommonClass.Visibility_calculation_decimal_point);
                    //dr[11] = CommonClass.ToFixed(dicForecastedVisibilityValues.Select(p => p.Value.dvWorst).Average(), CommonClass.Visibility_calculation_decimal_point);

                    dr[8] = Math.Round(dicForecastedVisibilityValues.Select(p => p.Value.baseBest).Average(), CommonClass.Visibility_calculation_decimal_point);//结果输出需要四舍五入，而不是截取
                    dr[9] = Math.Round(dicForecastedVisibilityValues.Select(p => p.Value.dvBest).Average(), CommonClass.Visibility_calculation_decimal_point);
                    dr[10] = Math.Round(dicForecastedVisibilityValues.Select(p => p.Value.baseWorst).Average(), CommonClass.Visibility_calculation_decimal_point);
                    dr[11] = Math.Round(dicForecastedVisibilityValues.Select(p => p.Value.dvWorst).Average(), CommonClass.Visibility_calculation_decimal_point);

                    //Relative response factors (RRF) calculated from the base and future year model data files. Calculated internally within SMAT.
                    dr[12] = k.Value.rrfbCrustal;
                    dr[13] = k.Value.rrfbNO3;
                    dr[14] = k.Value.rrfbOC;
                    dr[15] = k.Value.rrfbEC;
                    dr[16] = k.Value.rrfbCM;
                    dr[17] = k.Value.rrfbSO4;
                    dr[18] = k.Value.rrfwCrustal;
                    dr[19] = k.Value.rrfwNO3;
                    dr[20] = k.Value.rrfwOC;
                    dr[21] = k.Value.rrfwEC;
                    dr[22] = k.Value.rrfwCM;
                    dr[23] = k.Value.rrfwSO4;
                    #endregion fill row data
                    dt.Rows.Add(dr);

                }

                //------------修正OutPutFileName----------------
                string strFile = "";
                if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                {
                    strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecasted Visibility Data.csv";
                }
                else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                {
                    strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecasted Visibility Data for Class I Area.csv";
                }
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Year");
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                baseScenario.lstOutput.Add(baseOutput);
                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }

        }
        #endregion Save Forecasted Visibility File Methods

        #region  Save All Design Vlues Files Methods

        public static bool SaveAllDesignVluesForecatedVisibility(BaseScenario baseScenario, Dictionary<string, ForecastedVisibility> dicForecastedValues)
        {
            if (!(baseScenario.configuration is VisibilityAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                VisibilityAnalysisConfiguration visibilityAnalysisConfiguration = baseScenario.configuration as VisibilityAnalysisConfiguration;
                DataTable dt = new DataTable();
                #region Add columns

                dt.Columns.Add("_id");
                dt.Columns.Add("_type");
                dt.Columns.Add("date");
                dt.Columns.Add("dv_best");
                dt.Columns.Add("dv_worst");
                dt.Columns.Add("base_best");
                dt.Columns.Add("base_worst");
                if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                {
                    dt.Columns.Add("monitor_gridcell");
                    dt.Columns.Add("gridcell_lat");
                    dt.Columns.Add("gridcell_long");
                    dt.Columns.Add("monitor_lat");
                    dt.Columns.Add("monitor_long");
                }
                else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                {
                    dt.Columns.Add("class_i_gridcell");
                    dt.Columns.Add("gridcell_lat");
                    dt.Columns.Add("gridcell_long");
                    dt.Columns.Add("class_i_lat");
                    dt.Columns.Add("class_i_long");
                }
                #endregion  Add columns

                foreach (KeyValuePair<string, ForecastedVisibility> k in dicForecastedValues)
                {
                    for (int i = 0; i < Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.endMonitorYear) - Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear) + 1; i++)
                    {
                        DataRow dr = dt.NewRow();
                        #region Fill row data

                        dr[0] = k.Value.id;
                        dr[1] = k.Value.type;
                        dr[2] = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear) + i;
                        if (k.Value.dicForecastedVisibilityValues.ContainsKey(Convert.ToString(Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear) + i)))
                        {
                            dr[3] = CommonClass.ToFixed(k.Value.dicForecastedVisibilityValues[Convert.ToString(Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear) + i)].dvBest, 4);
                            dr[4] = CommonClass.ToFixed(k.Value.dicForecastedVisibilityValues[Convert.ToString(Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear) + i)].dvWorst, 4);
                            dr[5] = CommonClass.ToFixed(k.Value.dicForecastedVisibilityValues[Convert.ToString(Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear) + i)].baseBest, 4);
                            dr[6] = CommonClass.ToFixed(k.Value.dicForecastedVisibilityValues[Convert.ToString(Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear) + i)].baseWorst, 4);
                            //dr[3] = CommonClass.ToFixed(k.Value.dicForecastedVisibilityValues[Convert.ToString(Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear) + i)].dvBest, 2);
                            //dr[4] = CommonClass.ToFixed(k.Value.dicForecastedVisibilityValues[Convert.ToString(Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear) + i)].dvWorst, 2);
                            //dr[5] = CommonClass.ToFixed(k.Value.dicForecastedVisibilityValues[Convert.ToString(Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear) + i)].baseBest, 2);
                            //dr[6] = CommonClass.ToFixed(k.Value.dicForecastedVisibilityValues[Convert.ToString(Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear) + i)].baseWorst, 2);
                        }
                        else
                        {
                            dr[3] = -9;
                            dr[4] = -9;
                            dr[5] = -9;
                            dr[6] = -9;
                        }
                        dr[7] = k.Value.gridcell;
                        dr[8] = Math.Round(k.Value.gridcellLat, 6);
                        dr[9] = Math.Round(k.Value.gridcellLong, 6);
                        if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                        {
                            dr[10] = Math.Round(k.Value.monitorLat, 6);
                            dr[11] = Math.Round(k.Value.monitorLongitude, 6);
                        }
                        else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                        {
                            dr[10] = Math.Round(k.Value.lat, 6);
                            dr[11] = Math.Round(k.Value.longitude, 6);
                        }
                        #endregion Fill row data
                        dt.Rows.Add(dr);
                    }
                }

                //------------修正OutPutFileName----------------
                string strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecasted Visibility - all design values.csv";
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Year");
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                #region Move the last output file: “Forecasted future visibility – All Design Values”(use Capital for first letter consistently) to 2nd output file under “Forecasted future visibility”, add by sclong, 2017-02-14
                //baseScenario.lstOutput.Add(baseOutput);
                baseScenario.lstOutput.Insert(0, baseOutput);// to 2nd output file 
                #endregion

                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        /// <summary>
        /// Create the file of All Design Vlues With New Format 
        /// </summary>
        /// <param name="baseScenario"></param>
        /// <param name="dicForecastedValues"></param>
        /// <returns></returns>
        public static bool SaveAllDesignVluesWithOldVariables(BaseScenario baseScenario, Dictionary<string, VisibilityMonitor> dicVisibilityMonitors, Dictionary<string, ForecastedVisibility> dicForecastedValues)
        {
            if (!(baseScenario.configuration is VisibilityAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                VisibilityAnalysisConfiguration visibilityAnalysisConfiguration = baseScenario.configuration as VisibilityAnalysisConfiguration;

                DataTable dt = GetNewOutputFormatDataTableColumns(visibilityAnalysisConfiguration);
                int startYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear);
                int endYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.endMonitorYear);
                foreach (KeyValuePair<string, ForecastedVisibility> k in dicForecastedValues)//遍历测点
                {
                    VisibilityMonitor visibilityMonitorItem = dicVisibilityMonitors[k.Value.monitorID];
                    for (int i = 0; i < endYear - startYear + 1; i++)
                    {
                        string currentYear = (startYear + i).ToString();
                        DataRow dr = dt.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.type;
                        dr[2] = currentYear;
                        dr[3] = k.Value.gridcell;
                        dr[4] = Math.Round(k.Value.gridcellLat, 6);
                        dr[5] = Math.Round(k.Value.gridcellLong, 6);
                        if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                        {
                            dr[6] = Math.Round(k.Value.monitorLat, 6);
                            dr[7] = Math.Round(k.Value.monitorLongitude, 6);
                        }
                        else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                        {
                            dr[6] = Math.Round(k.Value.lat, 6);
                            dr[7] = Math.Round(k.Value.longitude, 6);
                        }
                        if (!k.Value.dicForecastedVisibilityValues.ContainsKey(currentYear))
                        {
                            #region 不存在该年数据，所以赋值为-9；

                            dr[8] = -9;
                            dr[9] = -9;
                            dr[10] = -9;
                            dr[11] = -9;

                            #endregion 不存在该年数据，所以赋值为-9；
                        }
                        else
                        {
                            ForecastedVisibilityDataAttribute forecastedYearItem = k.Value.dicForecastedVisibilityValues[currentYear];
                            //dr[8] = CommonClass.ToFixed(forecastedYearItem.baseBest, CommonClass.Visibility_calculation_decimal_point);
                            //dr[9] = CommonClass.ToFixed(forecastedYearItem.dvBest, CommonClass.Visibility_calculation_decimal_point);
                            //dr[10] = CommonClass.ToFixed(forecastedYearItem.baseWorst, CommonClass.Visibility_calculation_decimal_point);
                            //dr[11] = CommonClass.ToFixed(forecastedYearItem.dvWorst, CommonClass.Visibility_calculation_decimal_point);
                            dr[8] = Math.Round(forecastedYearItem.baseBest, CommonClass.Visibility_calculation_decimal_point);//Visibility 结果输出需要四舍五入，而不是截取
                            dr[9] = Math.Round(forecastedYearItem.dvBest, CommonClass.Visibility_calculation_decimal_point);
                            dr[10] = Math.Round(forecastedYearItem.baseWorst, CommonClass.Visibility_calculation_decimal_point);
                            dr[11] = Math.Round(forecastedYearItem.dvWorst, CommonClass.Visibility_calculation_decimal_point);
                        }//else
                        //Relative response factors (RRF) calculated from the base and future year model data files. Calculated internally within SMAT.

                        dr[12] = k.Value.rrfbCrustal;
                        dr[13] = k.Value.rrfbNO3;
                        dr[14] = k.Value.rrfbOC;
                        dr[15] = k.Value.rrfbEC;
                        dr[16] = k.Value.rrfbCM;
                        dr[17] = k.Value.rrfbSO4;
                        dr[18] = k.Value.rrfwCrustal;
                        dr[19] = k.Value.rrfwNO3;
                        dr[20] = k.Value.rrfwOC;
                        dr[21] = k.Value.rrfwEC;
                        dr[22] = k.Value.rrfwCM;
                        dr[23] = k.Value.rrfwSO4;

                        dt.Rows.Add(dr);

                    }//遍历年份， for (int i = 0; i < endYear - startYear + 1; i++)                  
                }//遍历测点

                //------------修正OutPutFileName----------------
                string strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecasted Visibility - all design values.csv";
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Year");
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                #region Move the last output file: “Forecasted future visibility – All Design Values”(use Capital for first letter consistently) to 2nd output file under “Forecasted future visibility”, add by sclong, 2017-02-14
                //baseScenario.lstOutput.Add(baseOutput);
                baseScenario.lstOutput.Insert(0, baseOutput);// to 2nd output file 
                #endregion

                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        /// <summary>
        /// Create the file of All Design Vlues With New Format 
        /// </summary>
        /// <param name="baseScenario"></param>
        /// <param name="dicForecastedValues"></param>
        /// <returns></returns>
        public static bool SaveAllDesignVluesWithNewFormat(BaseScenario baseScenario, Dictionary<string, VisibilityMonitor> dicVisibilityMonitors, Dictionary<string, ForecastedVisibility> dicForecastedValues)
        {
            if (!(baseScenario.configuration is VisibilityAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                VisibilityAnalysisConfiguration visibilityAnalysisConfiguration = baseScenario.configuration as VisibilityAnalysisConfiguration;

                DataTable dt = GetNewOutputFormatDataTableColumns(visibilityAnalysisConfiguration);
                int startYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear);
                int endYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.endMonitorYear);
                foreach (KeyValuePair<string, ForecastedVisibility> k in dicForecastedValues)//遍历测点
                {
                    VisibilityMonitor visibilityMonitorItem = dicVisibilityMonitors[k.Value.monitorID];
                    for (int i = 0; i < endYear - startYear + 1; i++)
                    {
                        string currentYear = (startYear + i).ToString();
                        DataRow dr = dt.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.type;
                        dr[2] = currentYear;
                        dr[3] = k.Value.gridcell;
                        dr[4] = Math.Round(k.Value.gridcellLat, 6);
                        dr[5] = Math.Round(k.Value.gridcellLong, 6);
                        if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                        {
                            dr[6] = Math.Round(k.Value.monitorLat, 6);
                            dr[7] = Math.Round(k.Value.monitorLongitude, 6);
                        }
                        else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                        {
                            dr[6] = Math.Round(k.Value.lat, 6);
                            dr[7] = Math.Round(k.Value.longitude, 6);
                        }
                        if (!k.Value.dicForecastedVisibilityValues.ContainsKey(currentYear))
                        {
                            #region 不存在该年数据，所以赋值为-9；

                            dr[8] = -9;
                            dr[9] = -9;
                            dr[10] = -9;
                            dr[11] = -9;

                            //Base year measured species mass (ug/m3) 20% clearest days
                            dr[12] = -9;
                            dr[13] = -9;
                            dr[14] = -9;
                            dr[15] = -9;
                            dr[16] = -9;
                            dr[17] = -9;
                            dr[18] = -9;
                            dr[19] = -9;
                            dr[20] = -9;
                            dr[21] = -9;
                            dr[22] = -9;
                            dr[23] = -9;
                            dr[24] = -9;
                            //Base year measured species mass (ug/m3) 20% most impaired days
                            dr[25] = -9;
                            dr[26] = -9;
                            dr[27] = -9;
                            dr[28] = -9;
                            dr[29] = -9;
                            dr[30] = -9;
                            dr[31] = -9;
                            dr[32] = -9;
                            dr[33] = -9;
                            dr[34] = -9;
                            dr[35] = -9;
                            dr[36] = -9;
                            dr[37] = -9;

                            //Measured IMPROVE extinction data 
                            dr[38] = -9;//特定地点的瑞利散射，指定地点后这个值就固定了，所以取第一个即可。
                            dr[39] = -9;//E_amm_so4_g10_b
                            dr[40] = -9; ;//E_amm_no3_g10_b
                            dr[41] = -9; ;//E_omc_g10_b
                            dr[42] = -9; ;//E_ec_g10_b
                            dr[43] = -9; ;//E_crustal_g10_b
                            dr[44] = -9; ;//E_cm_g10_b
                            dr[45] = -9; ;//E_sea_salt_g10_b
                            dr[46] = -9; ;//tbext_g10_b，//Base year total extinction (Mm-1) 20% clearest days

                            dr[47] = -9;//E_amm_so4_g90_b
                            dr[48] = -9;//E_amm_no3_g90_b
                            dr[49] = -9;//E_omc_g90_b
                            dr[50] = -9;//E_ec_g90_b
                            dr[51] = -9;//E_crustal_g90_b
                            dr[52] = -9; //E_cm_g90_b
                            dr[53] = -9; //E_sea_salt_g90_b
                            dr[54] = -9;//tbext_g90_b，Base year total extinction (Mm-1) 20% most impaired days

                            //Future mass concentrations, calculated by multiplying the base year measured mass by the relevant RRF. Calculated internally within SMAT.
                            dr[55] = -9; //amm_so4_g10_f
                            dr[56] = -9;
                            dr[57] = -9;
                            dr[58] = -9; ;
                            dr[59] = -9; ;
                            dr[60] = -9;
                            dr[61] = -9; ;
                            dr[62] = -9;
                            dr[63] = -9;
                            dr[64] = -9;
                            dr[65] = -9;
                            dr[66] = -9;
                            dr[67] = -9;

                            dr[68] = -9; //amm_so4_g90_f
                            dr[69] = -9;
                            dr[70] = -9;
                            dr[71] = -9; ;
                            dr[72] = -9; ;
                            dr[73] = -9;
                            dr[74] = -9; ;
                            dr[75] = -9;
                            dr[76] = -9;
                            dr[77] = -9;
                            dr[78] = -9;
                            dr[79] = -9;
                            dr[80] = -9;

                            dr[81] = -9;//E_amm_so4_g10_f
                            dr[82] = -9;//E_amm_no3_g10_f
                            dr[83] = -9;//E_omc_g10_f
                            dr[84] = -9;//E_ec_g10_f
                            dr[85] = -9;//E_crustal_g10_f
                            dr[86] = -9;//E_cm_g10_f
                            dr[87] = -9;//E_sea_salt_g10_f
                            dr[88] = -9; ;//tbext_g10_f，//Base year total extinction (Mm-1) 20% clearest days

                            dr[89] = -9;//E_amm_so4_g90_f
                            dr[90] = -9;//E_amm_no3_g90_f
                            dr[91] = -9;//E_omc_g90_f
                            dr[92] = -9;//E_ec_g90_f
                            dr[93] = -9;//E_crustal_g90_f
                            dr[94] = -9;//E_cm_g90_f
                            dr[95] = -9;//E_sea_salt_g90_f
                            dr[96] = -9;//tbext_g90_f，Base 

                            #endregion 不存在该年数据，所以赋值为-9；
                        }
                        else
                        {
                            ForecastedVisibilityDataAttribute forecastedYearItem = k.Value.dicForecastedVisibilityValues[currentYear];

                            //dr[8] = CommonClass.ToFixed(forecastedYearItem.baseBest, CommonClass.Visibility_calculation_decimal_point);
                            //dr[9] = CommonClass.ToFixed(forecastedYearItem.dvBest, CommonClass.Visibility_calculation_decimal_point);
                            //dr[10] = CommonClass.ToFixed(forecastedYearItem.baseWorst, CommonClass.Visibility_calculation_decimal_point);
                            //dr[11] = CommonClass.ToFixed(forecastedYearItem.dvWorst, CommonClass.Visibility_calculation_decimal_point);

                            dr[8] = Math.Round(forecastedYearItem.baseBest, CommonClass.Visibility_calculation_decimal_point);//Visibility 结果输出需要四舍五入，而不是截取
                            dr[9] = Math.Round(forecastedYearItem.dvBest, CommonClass.Visibility_calculation_decimal_point);
                            dr[10] = Math.Round(forecastedYearItem.baseWorst, CommonClass.Visibility_calculation_decimal_point);
                            dr[11] = Math.Round(forecastedYearItem.dvWorst, CommonClass.Visibility_calculation_decimal_point);

                            Dictionary<string, NewImproveMonitors> YearMonitorItem = visibilityMonitorItem.dicNewIMPROVE[currentYear];
                            //Base year measured species mass (ug/m3) 20% clearest days
                            dr[12] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.ammSO4).Average();
                            dr[13] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.smallAmmSO4).Average();
                            dr[14] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.largeAmmSO4).Average();
                            dr[15] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.ammNO3).Average();
                            dr[16] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.smallAmmNO3).Average();
                            dr[17] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.largeAmmNO3).Average();
                            dr[18] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.omc).Average();
                            dr[19] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.smallOMC).Average();
                            dr[20] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.largeOMC).Average();
                            dr[21] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.ec).Average();
                            dr[22] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.crustal).Average();
                            dr[23] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.cm).Average();
                            dr[24] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.seaSalt).Average();
                            //Base year measured species mass (ug/m3) 20% most impaired days
                            dr[25] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.ammSO4).Average();
                            dr[26] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.smallAmmSO4).Average();
                            dr[27] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.largeAmmSO4).Average();
                            dr[28] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.ammNO3).Average();
                            dr[29] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.smallAmmNO3).Average();
                            dr[30] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.largeAmmNO3).Average();
                            dr[31] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.omc).Average();
                            dr[32] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.smallOMC).Average();
                            dr[33] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.largeOMC).Average();
                            dr[34] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.ec).Average();
                            dr[35] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.crustal).Average();
                            dr[36] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.cm).Average();
                            dr[37] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.seaSalt).Average();

                            //Measured IMPROVE extinction data 
                            dr[38] = YearMonitorItem.First().Value.ssRayleigh;//特定地点的瑞利散射，指定地点后这个值就固定了，所以取第一个即可。
                            dr[39] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_amm_so4).Average();//E_amm_so4_g10_b
                            dr[40] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_amm_no3).Average(); ;//E_amm_no3_g10_b
                            dr[41] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_omc).Average(); ;//E_omc_g10_b
                            dr[42] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_ec).Average(); ;//E_ec_g10_b
                            dr[43] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_crustal).Average(); ;//E_crustal_g10_b
                            dr[44] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_cm).Average(); ;//E_cm_g10_b
                            dr[45] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_sea_salt).Average(); ;//E_sea_salt_g10_b
                            dr[46] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.baseBext).Average(); ;//tbext_g10_b，//Base year total extinction (Mm-1) 20% clearest days

                            dr[47] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_amm_so4).Average();//E_amm_so4_g90_b
                            dr[48] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_amm_no3).Average();//E_amm_no3_g90_b
                            dr[49] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_omc).Average();//E_omc_g90_b
                            dr[50] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_ec).Average();//E_ec_g90_b
                            dr[51] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_crustal).Average();//E_crustal_g90_b
                            dr[52] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_cm).Average(); //E_cm_g90_b
                            dr[53] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_sea_salt).Average(); //E_sea_salt_g90_b
                            dr[54] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.baseBext).Average();//tbext_g90_b，Base year total extinction (Mm-1) 20% most impaired days

                            //Future mass concentrations, calculated by multiplying the base year measured mass by the relevant RRF. Calculated internally within SMAT.
                            dr[55] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureAmmSO4).Average(); //amm_so4_g10_f
                            dr[56] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureSmallAmmSO4).Average();
                            dr[57] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureLargeAmmSO4).Average();
                            dr[58] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futurAmmNO3).Average(); ;
                            dr[59] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureSmallAmmNO3).Average(); ;
                            dr[60] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureLargeAmmNO3).Average();
                            dr[61] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureOMC).Average(); ;
                            dr[62] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureSmallOMC).Average();
                            dr[63] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureLargeOMC).Average();
                            dr[64] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureEC).Average();
                            dr[65] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureCrustal).Average();
                            dr[66] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureCm).Average();
                            dr[67] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.seaSalt).Average();

                            dr[68] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureAmmSO4).Average(); //amm_so4_g90_f
                            dr[69] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureSmallAmmSO4).Average();
                            dr[70] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureLargeAmmSO4).Average();
                            dr[71] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futurAmmNO3).Average(); ;
                            dr[72] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureSmallAmmNO3).Average(); ;
                            dr[73] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureLargeAmmNO3).Average();
                            dr[74] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureOMC).Average(); ;
                            dr[75] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureSmallOMC).Average();
                            dr[76] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureLargeOMC).Average();
                            dr[77] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureEC).Average();
                            dr[78] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureCrustal).Average();
                            dr[79] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureCm).Average();
                            dr[80] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.seaSalt).Average();

                            dr[81] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_amm_so4).Average();//E_amm_so4_g10_f
                            dr[82] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_amm_no3).Average();//E_amm_no3_g10_f
                            dr[83] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_omc).Average();//E_omc_g10_f
                            dr[84] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_ec).Average();//E_ec_g10_f
                            dr[85] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_crustal).Average();//E_crustal_g10_f
                            dr[86] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_cm).Average();//E_cm_g10_f
                            dr[87] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_sea_salt).Average();//E_sea_salt_g10_f
                            dr[88] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureBext).Average(); ;//tbext_g10_f，//Base year total extinction (Mm-1) 20% clearest days

                            dr[89] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_amm_so4).Average();//E_amm_so4_g90_f
                            dr[90] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_amm_no3).Average();//E_amm_no3_g90_f
                            dr[91] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_omc).Average();//E_omc_g90_f
                            dr[92] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_ec).Average();//E_ec_g90_f
                            dr[93] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_crustal).Average();//E_crustal_g90_f
                            dr[94] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_cm).Average();//E_cm_g90_f
                            dr[95] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_sea_salt).Average();//E_sea_salt_g90_f
                            dr[96] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureBext).Average();//tbext_g90_f，Base year total extinction (Mm-1) 20% most impaired days

                        }//else
                        //Relative response factors (RRF) calculated from the base and future year model data files. Calculated internally within SMAT.

                        dr[97] = k.Value.rrfbCrustal;
                        dr[98] = k.Value.rrfbNO3;
                        dr[99] = k.Value.rrfbOC;
                        dr[100] = k.Value.rrfbEC;
                        dr[101] = k.Value.rrfbCM;
                        dr[102] = k.Value.rrfbSO4;
                        dr[103] = k.Value.rrfwCrustal;
                        dr[104] = k.Value.rrfwNO3;
                        dr[105] = k.Value.rrfwOC;
                        dr[106] = k.Value.rrfwEC;
                        dr[107] = k.Value.rrfwCM;
                        dr[108] = k.Value.rrfwSO4;

                        dt.Rows.Add(dr);

                    }//遍历年份， for (int i = 0; i < endYear - startYear + 1; i++)                  
                }//遍历测点

                //------------修正OutPutFileName----------------
                string strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecasted Visibility - all design values.csv";
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Year");
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                #region Move the last output file: “Forecasted future visibility – All Design Values”(use Capital for first letter consistently) to 2nd output file under “Forecasted future visibility”, add by sclong, 2017-02-14
                //baseScenario.lstOutput.Add(baseOutput);
                baseScenario.lstOutput.Insert(0, baseOutput);// to 2nd output file 
                #endregion

                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }


        /// <summary>
        /// Create the file of All Design Vlues for the choice of AdvanceOption
        /// </summary>
        /// <param name="baseScenario"></param>
        /// <param name="dicForecastedValues"></param>
        /// <returns></returns>
        public static bool SaveAllDesignVluesForAdvanceOption(BaseScenario baseScenario, Dictionary<string, VisibilityMonitor> dicVisibilityMonitors, Dictionary<string, ForecastedVisibility> dicForecastedValues)
        {
            if (!(baseScenario.configuration is VisibilityAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                VisibilityAnalysisConfiguration visibilityAnalysisConfiguration = baseScenario.configuration as VisibilityAnalysisConfiguration;

                DataTable dt = GetNewOutputFormatDataTableColumnsForAdvanceOption(visibilityAnalysisConfiguration);
                int startYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear);
                int endYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.endMonitorYear);
                foreach (KeyValuePair<string, ForecastedVisibility> k in dicForecastedValues)//遍历测点
                {
                    VisibilityMonitor visibilityMonitorItem = dicVisibilityMonitors[k.Value.monitorID];
                    for (int i = 0; i < endYear - startYear + 1; i++)
                    {
                        string currentYear = (startYear + i).ToString();
                        DataRow dr = dt.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.type;
                        dr[2] = currentYear;
                        dr[3] = k.Value.gridcell;
                        dr[4] = Math.Round(k.Value.gridcellLat, 6);
                        dr[5] = Math.Round(k.Value.gridcellLong, 6);
                        if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor)
                        {
                            dr[6] = Math.Round(k.Value.monitorLat, 6);
                            dr[7] = Math.Round(k.Value.monitorLongitude, 6);
                        }
                        else if (visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid)
                        {
                            dr[6] = Math.Round(k.Value.lat, 6);
                            dr[7] = Math.Round(k.Value.longitude, 6);
                        }
                        if (!k.Value.dicForecastedVisibilityValues.ContainsKey(currentYear))
                        {
                            #region 不存在该年数据，所以赋值为-9；

                            dr[8] = -9;
                            dr[9] = -9;
                            dr[10] = -9;
                            dr[11] = -9;

                            //Measured IMPROVE extinction data 
                            dr[12] = -9;//特定地点的瑞利散射，指定地点后这个值就固定了，所以取第一个即可。
                            dr[13] = -9;//E_amm_so4_g10_b
                            dr[14] = -9; ;//E_amm_no3_g10_b
                            dr[15] = -9; ;//E_omc_g10_b
                            dr[16] = -9; ;//E_ec_g10_b
                            dr[17] = -9; ;//E_crustal_g10_b
                            dr[18] = -9; ;//E_cm_g10_b
                            dr[19] = -9; ;//E_sea_salt_g10_b
                            dr[20] = -9; ;//tbext_g10_b，//Base year total extinction (Mm-1) 20% clearest days

                            dr[21] = -9;//E_amm_so4_g90_b
                            dr[22] = -9;//E_amm_no3_g90_b
                            dr[23] = -9;//E_omc_g90_b
                            dr[24] = -9;//E_ec_g90_b
                            dr[25] = -9;//E_crustal_g90_b
                            dr[26] = -9; //E_cm_g90_b
                            dr[27] = -9; //E_sea_salt_g90_b
                            dr[28] = -9;//tbext_g90_b，Base year total extinction (Mm-1) 20% most impaired days

                            dr[29] = -9;//E_amm_so4_g10_f
                            dr[30] = -9;//E_amm_no3_g10_f
                            dr[31] = -9;//E_omc_g10_f
                            dr[32] = -9;//E_ec_g10_f
                            dr[33] = -9;//E_crustal_g10_f
                            dr[34] = -9;//E_cm_g10_f
                            dr[35] = -9;//E_sea_salt_g10_f
                            dr[36] = -9; ;//tbext_g10_f，//Base year total extinction (Mm-1) 20% clearest days

                            dr[37] = -9;//E_amm_so4_g90_f
                            dr[38] = -9;//E_amm_no3_g90_f
                            dr[39] = -9;//E_omc_g90_f
                            dr[40] = -9;//E_ec_g90_f
                            dr[41] = -9;//E_crustal_g90_f
                            dr[42] = -9;//E_cm_g90_f
                            dr[43] = -9;//E_sea_salt_g90_f
                            dr[44] = -9;//tbext_g90_f，Base 

                            #endregion 不存在该年数据，所以赋值为-9；
                        }
                        else
                        {
                            ForecastedVisibilityDataAttribute forecastedYearItem = k.Value.dicForecastedVisibilityValues[currentYear];

                            //dr[8] = CommonClass.ToFixed(forecastedYearItem.baseBest, CommonClass.Visibility_calculation_decimal_point);
                            //dr[9] = CommonClass.ToFixed(forecastedYearItem.dvBest, CommonClass.Visibility_calculation_decimal_point);
                            //dr[10] = CommonClass.ToFixed(forecastedYearItem.baseWorst, CommonClass.Visibility_calculation_decimal_point);
                            //dr[11] = CommonClass.ToFixed(forecastedYearItem.dvWorst, CommonClass.Visibility_calculation_decimal_point);
                            //Visibility，需要四舍五入，而不是截取
                            dr[8] = Math.Round(forecastedYearItem.baseBest, CommonClass.Visibility_calculation_decimal_point);
                            dr[9] = Math.Round(forecastedYearItem.dvBest, CommonClass.Visibility_calculation_decimal_point);
                            dr[10] = Math.Round(forecastedYearItem.baseWorst, CommonClass.Visibility_calculation_decimal_point);
                            dr[11] = Math.Round(forecastedYearItem.dvWorst, CommonClass.Visibility_calculation_decimal_point);
                            Dictionary<string, NewImproveMonitors> YearMonitorItem = visibilityMonitorItem.dicNewIMPROVE[currentYear];

                            //Measured IMPROVE extinction data 
                            dr[12] = YearMonitorItem.First().Value.ssRayleigh;//特定地点的瑞利散射，指定地点后这个值就固定了，所以取第一个即可。
                            dr[13] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_amm_so4).Average();//E_amm_so4_g10_b
                            dr[14] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_amm_no3).Average(); ;//E_amm_no3_g10_b
                            dr[15] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_omc).Average(); ;//E_omc_g10_b
                            dr[16] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_ec).Average(); ;//E_ec_g10_b
                            dr[17] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_crustal).Average(); ;//E_crustal_g10_b
                            dr[18] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_cm).Average(); ;//E_cm_g10_b
                            dr[19] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.e_sea_salt).Average(); ;//E_sea_salt_g10_b
                            dr[20] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.baseBext).Average(); ;//tbext_g10_b，//Base year total extinction (Mm-1) 20% clearest days

                            dr[21] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_amm_so4).Average();//E_amm_so4_g90_b
                            dr[22] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_amm_no3).Average();//E_amm_no3_g90_b
                            dr[23] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_omc).Average();//E_omc_g90_b
                            dr[24] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_ec).Average();//E_ec_g90_b
                            dr[25] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_crustal).Average();//E_crustal_g90_b
                            dr[26] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_cm).Average(); //E_cm_g90_b
                            dr[27] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.e_sea_salt).Average(); //E_sea_salt_g90_b
                            dr[28] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.baseBext).Average();//tbext_g90_b，Base year total extinction (Mm-1) 20% most impaired days


                            dr[29] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_amm_so4).Average();//E_amm_so4_g10_f
                            dr[30] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_amm_no3).Average();//E_amm_no3_g10_f
                            dr[31] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_omc).Average();//E_omc_g10_f
                            dr[32] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_ec).Average();//E_ec_g10_f
                            dr[33] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_crustal).Average();//E_crustal_g10_f
                            dr[34] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_cm).Average();//E_cm_g10_f
                            dr[35] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.future_e_sea_salt).Average();//E_sea_salt_g10_f
                            dr[36] = YearMonitorItem.Where(p => p.Value.group == 10).Select(p => p.Value.futureBext).Average(); ;//tbext_g10_f，//Base year total extinction (Mm-1) 20% clearest days

                            dr[37] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_amm_so4).Average();//E_amm_so4_g90_f
                            dr[38] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_amm_no3).Average();//E_amm_no3_g90_f
                            dr[39] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_omc).Average();//E_omc_g90_f
                            dr[40] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_ec).Average();//E_ec_g90_f
                            dr[41] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_crustal).Average();//E_crustal_g90_f
                            dr[42] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_cm).Average();//E_cm_g90_f
                            dr[43] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.future_e_sea_salt).Average();//E_sea_salt_g90_f
                            dr[44] = YearMonitorItem.Where(p => p.Value.group == 90).Select(p => p.Value.futureBext).Average();//tbext_g90_f，Base year total extinction (Mm-1) 20% most impaired days

                        }//else
                        //Relative response factors (RRF) calculated from the base and future year model data files. Calculated internally within SMAT.

                        dr[45] = k.Value.rrfbCrustal;
                        dr[46] = k.Value.rrfbNO3;
                        dr[47] = k.Value.rrfbOC;
                        dr[48] = k.Value.rrfbEC;
                        dr[49] = k.Value.rrfbCM;
                        dr[50] = k.Value.rrfbSO4;
                        dr[51] = k.Value.rrfwCrustal;
                        dr[52] = k.Value.rrfwNO3;
                        dr[53] = k.Value.rrfwOC;
                        dr[54] = k.Value.rrfwEC;
                        dr[55] = k.Value.rrfwCM;
                        dr[56] = k.Value.rrfwSO4;

                        dt.Rows.Add(dr);

                    }//遍历年份， for (int i = 0; i < endYear - startYear + 1; i++)                  
                }//遍历测点

                //------------修正OutPutFileName----------------
                string strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecasted Visibility - all design values.csv";
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Year");
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                #region Move the last output file: “Forecasted future visibility – All Design Values”(use Capital for first letter consistently) to 2nd output file under “Forecasted future visibility”, add by sclong, 2017-02-14
                //baseScenario.lstOutput.Add(baseOutput);
                baseScenario.lstOutput.Insert(0, baseOutput);// to 2nd output file 
                #endregion

                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        #endregion Save All Design Vlues Files Methods

        public static bool SaveUsedModelDataReference(BaseScenario baseScenario, Dictionary<string, VisibilityModelData> dicUsedModel, string baseModelYear)
        {
            if (!(baseScenario.configuration is VisibilityAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                dicUsedModel = dicUsedModel.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                VisibilityAnalysisConfiguration visibilityAnalysisConfiguration = baseScenario.configuration as VisibilityAnalysisConfiguration;
                DataTable dtUsedModelBaseline = new DataTable();
                DataTable dtUsedModelFuture = new DataTable();
                DataTable dtUsedModelDelta = new DataTable();//added by Yangwenwei 20131220
                DataRow drDelta = null;
                DataRow dr = null;
                dtUsedModelBaseline.Columns.Add("_id");
                dtUsedModelBaseline.Columns.Add("_type");
                dtUsedModelBaseline.Columns.Add("gridcell_lat");
                dtUsedModelBaseline.Columns.Add("gridcell_long");
                dtUsedModelBaseline.Columns.Add("date");
                dtUsedModelBaseline.Columns.Add("crustal");
                dtUsedModelBaseline.Columns.Add("so4");
                dtUsedModelBaseline.Columns.Add("ec");
                dtUsedModelBaseline.Columns.Add("no3");
                dtUsedModelBaseline.Columns.Add("oc");
                dtUsedModelBaseline.Columns.Add("cm");
                dtUsedModelBaseline.Columns.Add("_visibility_rank");

                dtUsedModelFuture.Columns.Add("_id");
                dtUsedModelFuture.Columns.Add("_type");
                dtUsedModelFuture.Columns.Add("gridcell_lat");
                dtUsedModelFuture.Columns.Add("gridcell_long");
                dtUsedModelFuture.Columns.Add("date");
                dtUsedModelFuture.Columns.Add("crustal");
                dtUsedModelFuture.Columns.Add("so4");
                dtUsedModelFuture.Columns.Add("ec");
                dtUsedModelFuture.Columns.Add("no3");
                dtUsedModelFuture.Columns.Add("oc");
                dtUsedModelFuture.Columns.Add("cm");
                dtUsedModelFuture.Columns.Add("_visibility_rank");

                //added by Yangwenwei 20131220
                dtUsedModelDelta.Columns.Add("_id");
                dtUsedModelDelta.Columns.Add("_type");
                dtUsedModelDelta.Columns.Add("gridcell_lat");
                dtUsedModelDelta.Columns.Add("gridcell_long");
                dtUsedModelDelta.Columns.Add("date");
                dtUsedModelDelta.Columns.Add("DeltaC(crustal)");
                dtUsedModelDelta.Columns.Add("DeltaC(so4)");
                dtUsedModelDelta.Columns.Add("DeltaC(ec)");
                dtUsedModelDelta.Columns.Add("DeltaC(no3)");
                dtUsedModelDelta.Columns.Add("DeltaC(oc)");
                dtUsedModelDelta.Columns.Add("DeltaC(cm)");//end

                foreach (KeyValuePair<string, VisibilityModelData> k in dicUsedModel)
                {
                    foreach (KeyValuePair<string, ModelDataVisibility> kBase in k.Value.dicBaselineModel)
                    {
                        dr = dtUsedModelBaseline.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.type;
                        dr[2] = Math.Round(k.Value.gridcellLat, 6);
                        dr[3] = Math.Round(k.Value.gridcellLong, 6);
                        dr[4] = baseModelYear + kBase.Key;
                        dr[5] = round(kBase.Value.crustal, 4);
                        dr[6] = round(kBase.Value.so4, 4);
                        dr[7] = round(kBase.Value.ec, 4);
                        dr[8] = round(kBase.Value.no3, 4);
                        dr[9] = round(kBase.Value.oc, 4);
                        dr[10] = round(kBase.Value.cm, 4);
                        dr[11] = kBase.Value.visibilityRank;
                        dtUsedModelBaseline.Rows.Add(dr);

                    }

                    foreach (KeyValuePair<string, ModelDataVisibility> kFuture in k.Value.dicFutureModel)
                    {
                        dr = dtUsedModelFuture.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.type;
                        dr[2] = Math.Round(k.Value.gridcellLat, 6);
                        dr[3] = Math.Round(k.Value.gridcellLong, 6);
                        dr[4] = baseModelYear + kFuture.Key;
                        dr[5] = round(kFuture.Value.crustal, 4);
                        dr[6] = round(kFuture.Value.so4, 4);
                        dr[7] = round(kFuture.Value.ec, 4);
                        dr[8] = round(kFuture.Value.no3, 4);
                        dr[9] = round(kFuture.Value.oc, 4);
                        dr[10] = round(kFuture.Value.cm, 4);
                        dr[11] = kFuture.Value.visibilityRank;
                        dtUsedModelFuture.Rows.Add(dr);

                        //added by Yangwenwei 20131220
                        drDelta = dtUsedModelDelta.NewRow();
                        drDelta[0] = k.Value.id;
                        drDelta[1] = k.Value.type;
                        drDelta[2] = Math.Round(k.Value.gridcellLat, 6);
                        drDelta[3] = Math.Round(k.Value.gridcellLong, 6);
                        drDelta[4] = baseModelYear + kFuture.Key;
                        drDelta[5] = round(k.Value.dicBaselineModel[kFuture.Key].crustal - kFuture.Value.crustal, 4);
                        drDelta[6] = round(k.Value.dicBaselineModel[kFuture.Key].so4 - kFuture.Value.so4, 4);
                        drDelta[7] = round(k.Value.dicBaselineModel[kFuture.Key].ec - kFuture.Value.ec, 4);
                        drDelta[8] = round(k.Value.dicBaselineModel[kFuture.Key].no3 - kFuture.Value.no3, 4);
                        drDelta[9] = round(k.Value.dicBaselineModel[kFuture.Key].oc - kFuture.Value.oc, 4);
                        drDelta[10] = round(k.Value.dicBaselineModel[kFuture.Key].cm - kFuture.Value.cm, 4);
                        dtUsedModelDelta.Rows.Add(drDelta);//end

                    }
                }

                //------------修正OutPutFileName----------------
                string strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Used Model Reference Cells - Base Data.csv";
                CommonClass.SaveCSV(dtUsedModelBaseline, _resultFilePath + @"\" + strFile, "Day");
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                baseScenario.lstOutput.Add(baseOutput);
                dtUsedModelBaseline.Dispose();
                GC.Collect();

                strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Used Model Reference Cells - Future Data.csv";
                CommonClass.SaveCSV(dtUsedModelFuture, _resultFilePath + @"\" + strFile, "Day");
                baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                baseScenario.lstOutput.Add(baseOutput);
                dtUsedModelFuture.Dispose();
                GC.Collect();

                //added by Yangwenwei 20131220
                strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Used Model Reference Cells - Delta Data.csv";
                CommonClass.SaveCSV(dtUsedModelDelta, _resultFilePath + @"\" + strFile, "Day");
                baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                baseScenario.lstOutput.Add(baseOutput);
                dtUsedModelDelta.Dispose();
                GC.Collect();//end
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        /// <summary>
        /// create a new output file, named“Forecast IMPROVE Daily Data.csv”, by sclong,2017-02-14
        /// </summary>
        /// <param name="baseScenario"></param>
        /// <param name="dicVisibilityMonitors"></param>
        /// <param name="dicForecasedValues"></param>
        /// <returns></returns>
        public static bool SaveForecastIMPROVEDailyData(BaseScenario baseScenario, Dictionary<string, VisibilityMonitor> dicVisibilityMonitors, Dictionary<string, ForecastedVisibility> dicForecasedValues)
        {

            if (!(baseScenario.configuration is VisibilityAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                VisibilityAnalysisConfiguration visibilityAnalysisConfiguration = baseScenario.configuration as VisibilityAnalysisConfiguration;
                DataTable dt = new DataTable();
                //below columns from the "156-Class1-coordinates-all site names.csv" file
                dt.Columns.Add("site_id");
                dt.Columns.Add("type");
                dt.Columns.Add("date");
                dt.Columns.Add("monitor_gridcell");
                dt.Columns.Add("gridcell_lat");
                dt.Columns.Add("gridcell_long");
                dt.Columns.Add("monitor_lat");
                dt.Columns.Add("monitor_long");

                //Date, Group, and monthly f(RH) values from IMPROVE data file "ClassIareas_NEWIMPROVEALG_2000to2012_2013sep12.csv" file (or newer data file)
                //dt.Columns.Add("FRH");
                //dt.Columns.Add("FSRH");
                //dt.Columns.Add("FLRH");
                //dt.Columns.Add("FSSRH");

                dt.Columns.Add("Group");
                dt.Columns.Add("Good_Year");
                dt.Columns.Add("ss_Rayleigh");

                //Future mass concentrations, calculated by multiplying the base year measured mass by the relevant RRF. Calculated internally within SMAT.
                dt.Columns.Add("E_amm_so4_f");
                dt.Columns.Add("E_amm_no3_f");
                dt.Columns.Add("E_omc_f");
                dt.Columns.Add("E_ec_f");
                dt.Columns.Add("E_crustal_f");
                dt.Columns.Add("E_cm_f");
                dt.Columns.Add("E_sea_salt_f");

                int endYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.endMonitorYear);
                int startYear = Convert.ToInt32(visibilityAnalysisConfiguration.filteringV.startMonitorYear);
                foreach (KeyValuePair<string, VisibilityMonitor> k in dicVisibilityMonitors)
                {
                    var result = dicForecasedValues.Where(p => p.Value.monitorID.Contains(k.Key));
                    if (result.Count() <= 0)
                    {
                        continue;
                    }
                    ForecastedVisibility forecastedVisibilityItem = result.ToList().First().Value;

                    VisibilityMonitor visibilityMonitorItem = k.Value;
                    foreach (KeyValuePair<string, Dictionary<string, NewImproveMonitors>> yearDayItem in visibilityMonitorItem.dicNewIMPROVE)
                    {
                        foreach (KeyValuePair<string, NewImproveMonitors> dayItem in yearDayItem.Value)
                        {
                            DataRow dr = dt.NewRow();

                            //ForecastedVisibility forecastedVisibilityItem = dicForecasedValues[k.Key.Replace("1", "")];
                            dr[0] = visibilityMonitorItem.id;
                            dr[1] = k.Value.type;
                            dr[2] = yearDayItem.Key + dayItem.Key;//date
                            dr[3] = forecastedVisibilityItem.gridcell;// forecastedVisibilityItem.gridcell;//monitor_gridcell
                            dr[4] = forecastedVisibilityItem.gridcellLat;//gridcell_lat
                            dr[5] = forecastedVisibilityItem.gridcellLong;//gridcell_long
                            dr[6] = forecastedVisibilityItem.monitorLat;// k.Value.lat;//monitor_lat
                            dr[7] = forecastedVisibilityItem.monitorLongitude;//monitor_long

                            dr[8] = dayItem.Value.group;//Group
                            dr[9] = dayItem.Value.goodYear;//Good_Year
                            dr[10] = dayItem.Value.ssRayleigh;//ss_Rayleigh
                            dr[11] = dayItem.Value.future_e_amm_so4;//E_amm_so4_f
                            dr[12] = dayItem.Value.future_e_amm_no3;//E_amm_no3_f
                            dr[13] = dayItem.Value.future_e_omc;//E_omc_f
                            dr[14] = dayItem.Value.future_e_ec;//E_ec_f
                            dr[15] = dayItem.Value.future_e_crustal;//E_crustal_f
                            dr[16] = dayItem.Value.future_e_cm;//E_cm_f
                            dr[17] = dayItem.Value.future_e_sea_salt;//E_sea_salt_f
                            //dr[18] = 
                            //dr[19] =
                            //dr[20] = 
                            dt.Rows.Add(dr);
                        }
                    }
                }

                //foreach (KeyValuePair<string, ForecastedVisibility> k in dicForecasedValues)//遍历测点
                //{

                //    VisibilityMonitor visibilityMonitorItem = dicVisibilityMonitors[k.Value.monitorID];

                //    foreach (KeyValuePair<string, Dictionary<string, NewImproveMonitors>> yearDayItem in visibilityMonitorItem.dicNewIMPROVE)
                //    {
                //        foreach (KeyValuePair<string, NewImproveMonitors> dayItem in yearDayItem.Value)
                //        {
                //            DataRow dr = dt.NewRow();

                //            //ForecastedVisibility forecastedVisibilityItem = dicForecasedValues[k.Key.Replace("1", "")];
                //            dr[0] = visibilityMonitorItem.id;
                //            dr[1] = k.Value.type;
                //            dr[2] = yearDayItem.Key + dayItem.Key;//date
                //            dr[3] = k.Value.gridcell;// forecastedVisibilityItem.gridcell;//monitor_gridcell
                //            dr[4] =  k.Value.gridcellLat;//gridcell_lat
                //            dr[5] = k.Value.gridcellLong;//gridcell_long
                //            dr[6] = k.Value.monitorLat;// k.Value.lat;//monitor_lat
                //            dr[7] = k.Value.monitorLongitude;//monitor_long

                //            dr[8] = dayItem.Value.group;//Group
                //            dr[9] = dayItem.Value.goodYear;//Good_Year
                //            dr[10] = dayItem.Value.ssRayleigh;//ss_Rayleigh
                //            dr[11] = dayItem.Value.future_e_amm_so4;//E_amm_so4_f
                //            dr[12] = dayItem.Value.future_e_amm_no3;//E_amm_no3_f
                //            dr[13] = dayItem.Value.future_e_omc;//E_omc_f
                //            dr[14] = dayItem.Value.future_e_ec;//E_ec_f
                //            dr[15] = dayItem.Value.future_e_crustal;//E_crustal_f
                //            dr[16] = dayItem.Value.future_e_cm;//E_cm_f
                //            dr[17] = dayItem.Value.future_e_sea_salt;//E_sea_salt_f
                //            //dr[18] = 
                //            //dr[19] =
                //            //dr[20] = 
                //            dt.Rows.Add(dr);
                //        }
                //    }
                //}
                //------------修正OutPutFileName----------------
                string strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Forecast IMPROVE Daily Data.csv";
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Day");
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                baseScenario.lstOutput.Add(baseOutput);
                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool SaveClass1AreaImproveMonitorsIdentifiersLocations(BaseScenario baseScenario, Dictionary<string, MonitorClass1AreaIdentifiers> dicMonitorsClassI, Dictionary<string, string> dicMonitorGridcell)
        {
            if (!(baseScenario.configuration is VisibilityAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                VisibilityAnalysisConfiguration visibilityAnalysisConfiguration = baseScenario.configuration as VisibilityAnalysisConfiguration;
                DataTable dt = new DataTable();
                dt.Columns.Add("_id");
                dt.Columns.Add("_type");
                dt.Columns.Add("_class_i_name");
                dt.Columns.Add("_class_i_state");
                dt.Columns.Add("class_i_lat");
                dt.Columns.Add("class_i_long");
                dt.Columns.Add("class_i_gridcell");
                dt.Columns.Add("date");
                dt.Columns.Add("_monitor_id");
                dt.Columns.Add("monitor_lat");
                dt.Columns.Add("monitor_long");
                dt.Columns.Add("monitor_gridcell");

                foreach (KeyValuePair<string, MonitorClass1AreaIdentifiers> k in dicMonitorsClassI)
                {
                    DataRow dr = dt.NewRow();
                    dr[0] = k.Value.id;
                    dr[1] = "";
                    dr[2] = k.Value.classIName;
                    dr[3] = k.Value.classIState;
                    dr[4] = k.Value.classIlat;
                    dr[5] = k.Value.classIlong;
                    dr[6] = visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellatClassIAreaCentroid ? (dicMonitorGridcell.ContainsKey(k.Key) ? dicMonitorGridcell[k.Key] : Convert.ToString(-8)) : Convert.ToString(-8);
                    dr[7] = visibilityAnalysisConfiguration.filteringV.startMonitorYear + "0101";
                    dr[8] = k.Value.monitorID;
                    dr[9] = k.Value.monitorLat;
                    dr[10] = k.Value.monitorLong;
                    dr[11] = visibilityAnalysisConfiguration.chooseDesiredOutputV.choiceUseModelGridCellAtMonitor ? (dicMonitorGridcell.ContainsKey(k.Key) ? dicMonitorGridcell[k.Key] : Convert.ToString(-8)) : Convert.ToString(-8);
                    dt.Rows.Add(dr);
                }

                //------------修正OutPutFileName----------------
                string strFile = visibilityAnalysisConfiguration.chooseDesiredOutputV.scenarioName + " - Class 1 Area and IMPROVE Monitors Identifiers and Locations.csv";
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Day");
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                    baseOutput.outputSize = 0;
                baseScenario.lstOutput.Add(baseOutput);
                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
    }
}
