using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using DotSpatial.Projections;

namespace SMAT_CE
{
    class AnnualPMCommonClassChina
    {
        public static DateTime _beginTime;//记录开始时间
        public static DateTime _endTime;//记录结束时间
        public static string baseYear = "";//base model year
        public static string controlYear = "";//future model year

        public static string _resultFilePath = "";

        public static bool AnnualPMAnalysis(BaseScenario baseScenario, SMAT_CE mats)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
            {
                return false;
            }
            try
            {
                _beginTime = DateTime.Now;
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                #region generate folder when save files
                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);
                #endregion

                #region model data--baseline/future
                Dictionary<string, PmModelDataOutput> dicQuarterlyModelDataPM = new Dictionary<string, PmModelDataOutput>();
                string baseModelYear = "", futureModelYear = "";
                string isOK = "";

                CommonClass.CurrentLog = "Read model data \"" + Path.GetFileName(annualPMAnalysisConfiguration.modelDataInputChina.BaselineModelDataFile) + "\".";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                if (annualPMAnalysisConfiguration.modelDataInputChina.doQuarterlyAverageDataInput)
                {
                    isOK = GetModelDataQuarterly(annualPMAnalysisConfiguration, ref dicQuarterlyModelDataPM, ref baseModelYear, ref futureModelYear);
                    switch (isOK)//error message when loading file
                    {
                        case "wrongBaseline":
                            CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(annualPMAnalysisConfiguration.modelDataInputChina.BaselineModelDataFile) + "\".";
                            CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                            return false;
                        case "wrongFuture":
                            CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(annualPMAnalysisConfiguration.modelDataInputChina.ControlModelDataFile) + "\".";
                            CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                            return false;
                        case "unknow":
                            CommonClass.CurrentLog = "Fail to read model data.";
                            CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                            return false;
                    }
                    SaveQuarterlyModelDataCopyDirectly(CommonClass.CurrentBaseScenario, dicQuarterlyModelDataPM);
                }
                else if (annualPMAnalysisConfiguration.modelDataInputChina.doDailyAverageDataInput)
                {
                    //isOK = GetModelDataDaily(annualPMAnalysisConfiguration, ref dicQuarterlyModelDataPM, ref baseModelYear, ref futureModelYear);
                    //switch (isOK)//error message when loading file
                    //{
                    //    case "wrongBaseline":
                    //        CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(annualPMAnalysisConfiguration.modelDataInputChina.BaselineModelDataFile) + "\".";
                    //        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    //        return false;
                    //    case "wrongFuture":
                    //        CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(annualPMAnalysisConfiguration.modelDataInputChina.ControlModelDataFile) + "\".";
                    //        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    //        return false;
                    //    case "unknow":
                    //        CommonClass.CurrentLog = "Fail to read model data.";
                    //        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    //        return false;
                    //}
                    //SaveModelDataQuarterly(CommonClass.CurrentBaseScenario, dicQuarterlyModelDataPM, baseModelYear, futureModelYear);
                }
                else if (annualPMAnalysisConfiguration.modelDataInputChina.doInputFromCMAQ)
                {
                    //GetModelDataFromCMAQ(annualPMAnalysisConfiguration);

                }
                SaveAnnualModelData(CommonClass.CurrentBaseScenario, dicQuarterlyModelDataPM, baseModelYear, futureModelYear);
                _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);

                //change project - write in dictionary (lat,long to lambert) - for draw map
                DataTable dt = new DataTable();
                dt.Columns.Add("id");
                dt.Columns.Add("lat");
                dt.Columns.Add("long");
                foreach (KeyValuePair<string, PmModelDataOutput> keyvalue in dicQuarterlyModelDataPM)
                {
                    DataRow dr = dt.NewRow();
                    dr[0] = keyvalue.Key;
                    dr[1] = keyvalue.Value.lat;
                    dr[2] = keyvalue.Value.longitude;
                    dt.Rows.Add(dr);
                }

                mats.changeProject(dt, CommonClass.CurrentAnalysis == enumAnalysis.AnnualPMOther ? "Other" : "China");
                //这里要改
                ProjectionInfo prj = new ProjectionInfo();
                if (CommonClass.CurrentAnalysis != enumAnalysis.AnnualPMOther)
                {
                    if (mats.mainMap.Layers.Count > 0 && mats.mainMap.Layers[mats.mainMap.Layers.Count - 1].LegendText == "China_prov_WGS84_LCC")
                        prj = mats.mainMap.Layers[mats.mainMap.Layers.Count - 1].Projection;
                    else
                    {
                        mats.mainMap.Layers.Add(System.Windows.Forms.Application.StartupPath + @"\Data\ShapeFiles\China_prov_WGS84_LCC.shp");
                        prj = mats.mainMap.Layers[mats.mainMap.Layers.Count - 1].Projection;
                        mats.mainMap.Layers.RemoveAt(mats.mainMap.Layers.Count - 1);
                    }
                }

                prj = mats.mainMap.Projection;

                //--------------修正dicQuarterlyModelDataPM的坐标系！-------------------
                #region
                double[] dConvertArrayModel = null;
                List<double> lstConvertArrayModel = new List<double>();
                List<string> lstKeyModel = dicQuarterlyModelDataPM.Keys.ToList();
                for (int iLstKey = 0; iLstKey < dicQuarterlyModelDataPM.Keys.Count; iLstKey++)
                {
                    lstConvertArrayModel.Add(dicQuarterlyModelDataPM[lstKeyModel[iLstKey]].longitude);
                    lstConvertArrayModel.Add(dicQuarterlyModelDataPM[lstKeyModel[iLstKey]].lat);
                }
                dConvertArrayModel = lstConvertArrayModel.ToArray();
                DotSpatial.Projections.Reproject.ReprojectPoints(dConvertArrayModel, null, DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984,
                   prj, 0, dConvertArrayModel.Length / 2);
                for (int iLstKey = 0; iLstKey < dicQuarterlyModelDataPM.Keys.Count; iLstKey++)
                {
                    dicQuarterlyModelDataPM[lstKeyModel[iLstKey]].longitudeLamber = dConvertArrayModel[2 * iLstKey] / 100.00;
                    dicQuarterlyModelDataPM[lstKeyModel[iLstKey]].latitudeLamber = dConvertArrayModel[2 * iLstKey + 1] / 100.00;
                }
                #endregion
                #endregion

                _beginTime = DateTime.Now;
                CommonClass.CurrentLog = "Read PM monitor data \"" + Path.GetFileName(annualPMAnalysisConfiguration.monitorDataInputChina.MonitorDataInputFile) + "\".";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                Dictionary<string, PMMonitorChina> dicPMMonitors = new Dictionary<string, PMMonitorChina>();
                isOK = GetPMMonitors(annualPMAnalysisConfiguration, ref dicPMMonitors);
                if (dicPMMonitors.Count <= 0 || isOK == "unknow")//error message when loading file
                {
                    CommonClass.CurrentLog = "Fail to read PM monitor data \"" + Path.GetFileName(annualPMAnalysisConfiguration.monitorDataInputChina.MonitorDataInputFile) + "\".";
                    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 PM monitor data: " + CommonClass.TotalTime + " s.";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                #region PM Monitor quarterly average
                foreach (KeyValuePair<string, PMMonitorChina> k in dicPMMonitors)
                {
                    k.Value.dicMonitorPMAvg = new Dictionary<string, float>();
                    foreach (KeyValuePair<string, Dictionary<string, float>> kQ in k.Value.dicMonitorPM)
                    {
                        double pm = 0;
                        if (kQ.Value.Count > 0)
                        {
                            pm = kQ.Value.Select(q => q.Value).ToList().Average();
                            k.Value.dicMonitorPMAvg.Add(kQ.Key, Convert.ToSingle(Math.Round(pm, CommonClass.Pm_defaultformat)));
                        }

                    }
                }
                #endregion

                #region modify monitor projection
                double[] dConvertArrayMonitor = null;
                List<string> lstKey = dicPMMonitors.Keys.ToList();
                List<double> lstConvertArrayUnofficial = new List<double>();
                for (int iLstKey = 0; iLstKey < dicPMMonitors.Keys.Count; iLstKey++)
                {
                    lstConvertArrayUnofficial.Add(dicPMMonitors[lstKey[iLstKey]].longitude);
                    lstConvertArrayUnofficial.Add(dicPMMonitors[lstKey[iLstKey]].latitude);
                }
                dConvertArrayMonitor = lstConvertArrayUnofficial.ToArray();
                DotSpatial.Projections.Reproject.ReprojectPoints(dConvertArrayMonitor, null, DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984,
                   prj, 0, dConvertArrayMonitor.Length / 2);
                for (int iLstKey = 0; iLstKey < dicPMMonitors.Keys.Count; iLstKey++)
                {
                    dicPMMonitors[lstKey[iLstKey]].longitudeLamber = dConvertArrayMonitor[2 * iLstKey] / 100.00;
                    dicPMMonitors[lstKey[iLstKey]].latitudeLamber = dConvertArrayMonitor[2 * iLstKey + 1] / 100.00;
                }
                #endregion

                #region monitor in model grid cell
                Dictionary<string, string> dicMonitorInModel = new Dictionary<string, string>();
                GetGridCellMonitors(ref dicMonitorInModel, dicQuarterlyModelDataPM, dicPMMonitors);
                #endregion


                if (annualPMAnalysisConfiguration.pm25SpeciesOptionChina.PM25SpeciesFractionDataAvailable)
                {
                    #region with species
                    _beginTime = DateTime.Now;
                    CommonClass.CurrentLog = "Read species monitor data \"" + Path.GetFileName(annualPMAnalysisConfiguration.pm25SpeciesOptionChina.SpeciesMonitorDataFile) + "\".";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                    Dictionary<string, PMMonitorChina> dicSpeciesMonitors = new Dictionary<string, PMMonitorChina>();
                    isOK = GetSpeciesMonitors(annualPMAnalysisConfiguration, dicSpeciesMonitors);
                    if (dicSpeciesMonitors.Count <= 0 || isOK == "unknow")//error message when loading file
                    {
                        CommonClass.CurrentLog = "Fail to read species monitor data \"" + Path.GetFileName(annualPMAnalysisConfiguration.pm25SpeciesOptionChina.SpeciesMonitorDataFile) + "\".";
                        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                        return false;
                    }

                    #region Species Monitor quarterly average
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicSpeciesMonitors)
                    {
                        k.Value.dicSpeciesAvg = new Dictionary<string, SpeciesMonitorChina>();
                        foreach (KeyValuePair<string, Dictionary<string, SpeciesMonitorChina>> kQ in k.Value.dicSpecies)
                        {
                            SpeciesMonitorChina smc = new SpeciesMonitorChina();
                            if (kQ.Value.Count > 0)
                            {
                                smc.bSO4 = kQ.Value.Select(q => q.Value.bSO4).ToList().Average();
                                smc.bNO3 = kQ.Value.Select(q => q.Value.bNO3).ToList().Average();
                                smc.bNH4 = kQ.Value.Select(q => q.Value.bNH4).ToList().Average();
                                smc.bOC = kQ.Value.Select(q => q.Value.bOC).ToList().Average();
                                smc.bEC = kQ.Value.Select(q => q.Value.bEC).ToList().Average();
                                smc.bCrustal = kQ.Value.Select(q => q.Value.bCrustal).ToList().Average();
                                smc.bH2O = kQ.Value.Select(q => q.Value.bH2O).ToList().Average();
                                smc.bOther = kQ.Value.Select(q => q.Value.bOther).ToList().Average();
                                k.Value.dicSpeciesAvg.Add(kQ.Key, smc);
                            }
                        }
                    }
                    #endregion

                    #region modify dicSpeciesMonitors projection
                    double[] dConvertArray = null;
                    List<string> lstKeySpeciesMonitors = dicSpeciesMonitors.Keys.ToList();
                    List<double> lstConvertArray = new List<double>();
                    for (int iLstKey = 0; iLstKey < dicSpeciesMonitors.Keys.Count; iLstKey++)
                    {
                        lstConvertArray.Add(dicSpeciesMonitors[lstKeySpeciesMonitors[iLstKey]].longitude);
                        lstConvertArray.Add(dicSpeciesMonitors[lstKeySpeciesMonitors[iLstKey]].latitude);
                    }
                    dConvertArray = lstConvertArray.ToArray();
                    DotSpatial.Projections.Reproject.ReprojectPoints(dConvertArray, null, DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984,
                       prj, 0, dConvertArray.Length / 2);
                    for (int iLstKey = 0; iLstKey < dicSpeciesMonitors.Keys.Count; iLstKey++)
                    {
                        dicSpeciesMonitors[lstKeySpeciesMonitors[iLstKey]].longitudeLamber = dConvertArray[2 * iLstKey] / 100.00;
                        dicSpeciesMonitors[lstKeySpeciesMonitors[iLstKey]].latitudeLamber = dConvertArray[2 * iLstKey + 1] / 100.00;
                    }
                    #endregion

                    #region species fraction point
                    Dictionary<string, PMMonitorChina> dicSpeciesLongLat = new Dictionary<string, PMMonitorChina>();
                    //根据unofficial pm25得到其周围的speciated monitors,根据species fractions calculation窗体中选择的interpolation method，最终计算species fractions=species values/FRM-blank_mass
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicSpeciesMonitors)
                    {
                        if (!dicSpeciesLongLat.ContainsKey(k.Value.longitudeLamber + "," + k.Value.latitudeLamber))
                            dicSpeciesLongLat.Add(k.Value.longitudeLamber + "," + k.Value.latitudeLamber, k.Value);
                    }

                    Dictionary<string, PMMonitorChina> dicSpeciesFractions = new Dictionary<string, PMMonitorChina>();
                    Dictionary<string, PMMonitorChina> dicPmMonitorsLatLong = new Dictionary<string, PMMonitorChina>();
                    Dictionary<string, PMMonitorChina> dicSpecFracSpatial = new Dictionary<string, PMMonitorChina>();

                    foreach (KeyValuePair<string, PMMonitorChina> kPM in dicPMMonitors)
                    {
                        Dictionary<string, Dictionary<string, float>> dicNeighborDistance = new Dictionary<string, Dictionary<string, float>>();
                        foreach (KeyValuePair<string, float> kQ in kPM.Value.dicMonitorPMAvg)
                        {
                            //----------不同的季度分别进行VNA----------
                            List<double> fsInterSpecies = new List<double>();
                            fsInterSpecies.Add(kPM.Value.longitudeLamber);
                            fsInterSpecies.Add(kPM.Value.latitudeLamber);

                            bool isSame = false;
                            List<double> fsOutSpecies = new List<double>();
                            //----判断是否一模一样，如果一样就不需要计算---
                            if (dicSpeciesLongLat.ContainsKey(kPM.Value.longitudeLamber + "," + kPM.Value.latitudeLamber)
                                && dicSpeciesLongLat[kPM.Value.longitudeLamber + "," + kPM.Value.latitudeLamber].dicSpeciesAvg.ContainsKey(kQ.Key))
                                isSame = true;
                            if (!isSame)
                            {
                                //-------简化VNA算法：求指定半径内的监测点做VNA,一开始是以5个经纬度来算，一直达到10个为止
                                Dictionary<string, double> dicDistanceMonitorSpecies = new Dictionary<string, double>();
                                foreach (KeyValuePair<string, PMMonitorChina> kin in dicSpeciesMonitors)
                                {
                                    if (!kin.Value.dicSpeciesAvg.ContainsKey(kQ.Key)) continue;
                                    //if (kin.Value.dicSpecies.Count == 0) continue;
                                    dicDistanceMonitorSpecies.Add(kin.Key, (kPM.Value.longitude - kin.Value.longitude) * (kPM.Value.longitude - kin.Value.longitude) + (kPM.Value.latitude - kin.Value.latitude) * (kPM.Value.latitude - kin.Value.latitude));
                                }
                                var query = dicDistanceMonitorSpecies.Where(p => p.Value < 49).ToList();
                                int iDistanceForQuery = 1;
                                while (query.Count < 20 && query.Count < dicDistanceMonitorSpecies.Count)
                                {
                                    query = dicDistanceMonitorSpecies.Where(p => p.Value < 49 + iDistanceForQuery).ToList();
                                    iDistanceForQuery++;
                                }
                                foreach (KeyValuePair<string, double> item in query)
                                {
                                    fsInterSpecies.Add(dicSpeciesMonitors[item.Key].longitudeLamber);
                                    fsInterSpecies.Add(dicSpeciesMonitors[item.Key].latitudeLamber);
                                }
                                //-----------end VNA-------------
                                CommonClass.VoronoiPoints(fsInterSpecies.ToArray(), ref fsOutSpecies);
                            }
                            else
                            {
                                fsOutSpecies.Add(kPM.Value.longitudeLamber);
                                fsOutSpecies.Add(kPM.Value.latitudeLamber);
                            }

                            //---------根据得到的neighbor进行计算--------------
                            Dictionary<string, float> fsOutString = new Dictionary<string, float>();
                            for (int ifsout = 0; ifsout < fsOutSpecies.Count; ifsout++)
                            {
                                if (ifsout % 2 == 1)
                                {
                                    float distance = CommonClass.getDistanceFrom2Point(dicSpeciesLongLat[fsOutSpecies[ifsout - 1] + "," + fsOutSpecies[ifsout]].longitude, dicSpeciesLongLat[fsOutSpecies[ifsout - 1] + "," + fsOutSpecies[ifsout]].latitude, kPM.Value.longitude, kPM.Value.latitude);
                                    fsOutString.Add(dicSpeciesLongLat[fsOutSpecies[ifsout - 1] + "," + fsOutSpecies[ifsout]].id + "," + dicSpeciesLongLat[fsOutSpecies[ifsout - 1] + "," + fsOutSpecies[ifsout]].gridcell, distance);
                                }
                            }
                            if (fsOutString.Count == 0) continue;
                            double vnaCrustal = 0, vnaEC = 0, vnaNH4 = 0, vnaSO4 = 0, vnaOC = 0, vnaOther = 0, vnaH2O = 0, vnaNO3 = 0;
                            AnnualVNA(ref dicNeighborDistance, kQ.Key, "so4", "Inverse Distance Squared Weights", 9000000000, ref vnaSO4, fsOutString, dicSpeciesMonitors);
                            AnnualVNA(ref dicNeighborDistance, kQ.Key, "no3", "Inverse Distance Squared Weights", 9000000000, ref vnaNO3, fsOutString, dicSpeciesMonitors);
                            AnnualVNA(ref dicNeighborDistance, kQ.Key, "oc", "Inverse Distance Squared Weights", 9000000000, ref vnaOC, fsOutString, dicSpeciesMonitors);
                            AnnualVNA(ref dicNeighborDistance, kQ.Key, "ec", "Inverse Distance Squared Weights", 9000000000, ref vnaEC, fsOutString, dicSpeciesMonitors);
                            AnnualVNA(ref dicNeighborDistance, kQ.Key, "crustal", "Inverse Distance Squared Weights", 9000000000, ref vnaCrustal, fsOutString, dicSpeciesMonitors);
                            AnnualVNA(ref dicNeighborDistance, kQ.Key, "nh4", "Inverse Distance Squared Weights", 9000000000, ref vnaNH4, fsOutString, dicSpeciesMonitors);
                            AnnualVNA(ref dicNeighborDistance, kQ.Key, "h2o", "Inverse Distance Squared Weights", 9000000000, ref vnaH2O, fsOutString, dicSpeciesMonitors);
                            AnnualVNA(ref dicNeighborDistance, kQ.Key, "other", "Inverse Distance Squared Weights", 9000000000, ref vnaOther, fsOutString, dicSpeciesMonitors);

                            //-----------先保存插值得到的各个species concentration------------
                            SpecFracPMChina sfAnnual = new SpecFracPMChina();
                            GetSpeciesFractionValuesPointEstimates(annualPMAnalysisConfiguration, ref sfAnnual, vnaCrustal, vnaEC, vnaNH4, vnaSO4, vnaOC, vnaNO3, vnaOther, vnaH2O, kQ.Value);

                            if (dicSpeciesFractions.ContainsKey(kPM.Key))
                            {
                                dicSpeciesFractions[kPM.Key].dicSpeciesFraction.Add(kQ.Key, sfAnnual);
                            }
                            else
                            {
                                dicSpeciesFractions.Add(kPM.Key, new PMMonitorChina()
                                {
                                    id = kPM.Value.id,
                                    type = kPM.Value.type,
                                    gridcell = dicMonitorInModel[kPM.Key],
                                    locationName = kPM.Value.locationName,
                                    stationName = kPM.Value.stationName,
                                    latitude = kPM.Value.latitude,
                                    longitude = kPM.Value.longitude,
                                    dicSpeciesFraction = new Dictionary<string, SpecFracPMChina>(),
                                });
                                dicSpeciesFractions[kPM.Key].dicSpeciesFraction.Add(kQ.Key, sfAnnual);
                            }
                        }
                    }
                    dicSpeciesLongLat.Clear();
                    dicMonitorInModel.Clear();
                    GC.Collect();
                    #endregion
                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish interpolating monitor sites: " + CommonClass.TotalTime + " s.");
                    CommonClass.CurrentLog = "Finish interpolating monitor sites: " + CommonClass.TotalTime + " s.";
                    _beginTime = DateTime.Now;

                    #region species fraction spatial field
                    if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM || annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM|| annualPMAnalysisConfiguration.monitorDataInputChina.doNS)
                    {
                        #region monitor in model grid cell
                        Dictionary<string, string> dicMonitorInModelSpecies = new Dictionary<string, string>();
                        GetGridCellSpeciatedMonitors(ref dicMonitorInModelSpecies, dicQuarterlyModelDataPM, dicSpeciesMonitors);
                        dicMonitorInModelSpecies.Clear();// dicMonitorInModelSpecies may be useful
                        #endregion

                        #region species values Longitude and Latitude
                        dicSpeciesLongLat = new Dictionary<string, PMMonitorChina>();
                        foreach (KeyValuePair<string, PMMonitorChina> k in dicSpeciesMonitors)
                        {
                            if (!dicSpeciesLongLat.ContainsKey(k.Value.longitudeLamber + "," + k.Value.latitudeLamber))
                            {
                                dicSpeciesLongLat.Add(k.Value.longitudeLamber + "," + k.Value.latitudeLamber, k.Value);
                            }
                        }
                        #endregion

                        #region monitor pm Longitude & Latitude
                        foreach (KeyValuePair<string, PMMonitorChina> k in dicPMMonitors)
                        {
                            if (!dicPmMonitorsLatLong.ContainsKey(k.Value.longitudeLamber + "," + k.Value.latitudeLamber))
                            {
                                dicPmMonitorsLatLong.Add(k.Value.longitudeLamber + "," + k.Value.latitudeLamber, k.Value);
                            }
                        }
                        #endregion
                        GC.Collect();
                        //获取species和pm的neighbors及相关的数据参数
                        #region
                        List<string> lstGradAdjId = new List<string>();
                        Dictionary<string, Dictionary<string, float>> dicNeighborDistance = new Dictionary<string, Dictionary<string, float>>();

                        foreach (KeyValuePair<string, PmModelDataOutput> k in dicQuarterlyModelDataPM)
                        {
                            dicNeighborDistance = new Dictionary<string, Dictionary<string, float>>();
                            #region
                            foreach (KeyValuePair<string, ModelDataSpecies> kQ in k.Value.dicBaselineModel)
                            {
                                #region pm && species
                                #region species values
                                List<double> fsInterSpecies = new List<double>();
                                fsInterSpecies.Add(k.Value.longitudeLamber);
                                fsInterSpecies.Add(k.Value.latitudeLamber);
                                bool isSame = false;

                                //简化VNA算法：求半径范围内的监测点做VNA，一开始以5个经纬度来算一直达到10个为止
                                Dictionary<string, double> dicDistanceMonitorSpecies = new Dictionary<string, double>();
                                foreach (KeyValuePair<string, PMMonitorChina> kSpecies in dicSpeciesMonitors)
                                {
                                    if (!kSpecies.Value.dicSpecies.ContainsKey(kQ.Key)) continue;
                                    //----------改成extent----
                                    double dLongAbs = Math.Abs(kSpecies.Value.longitude - k.Value.longitude);
                                    double dLatAbs = Math.Abs(kSpecies.Value.latitude - k.Value.lat);
                                    if (dLongAbs > dLatAbs)
                                    {
                                        dicDistanceMonitorSpecies.Add(kSpecies.Key, dLongAbs);
                                    }
                                    else
                                    {
                                        dicDistanceMonitorSpecies.Add(kSpecies.Key, dLatAbs);
                                    }
                                }
                                List<KeyValuePair<string, double>> query = new List<KeyValuePair<string, double>>();

                                query = dicDistanceMonitorSpecies.ToList();

                                foreach (KeyValuePair<string, double> kSpecies in query)
                                {
                                    fsInterSpecies.Add(dicSpeciesMonitors[kSpecies.Key].longitudeLamber);
                                    fsInterSpecies.Add(dicSpeciesMonitors[kSpecies.Key].latitudeLamber);
                                    if (k.Value.longitudeLamber == dicSpeciesMonitors[kSpecies.Key].longitudeLamber
                                       && k.Value.latitudeLamber == dicSpeciesMonitors[kSpecies.Key].latitudeLamber)
                                    {
                                        isSame = true;
                                        break;
                                    }
                                }
                                //------------end VNA 简化算法
                                List<double> fsoutSpecies = new List<double>();
                                if (!isSame)
                                {
                                    CommonClass.VoronoiPoints(fsInterSpecies.ToArray(), ref fsoutSpecies);
                                }
                                else
                                {
                                    fsoutSpecies.Add(k.Value.longitudeLamber);
                                    fsoutSpecies.Add(k.Value.latitudeLamber);
                                }
                                if (fsoutSpecies.Count == 0) continue;
                                //----------------根据得到的邻居计算数值----------------
                                Dictionary<string, float> fsoutStringSpecies = new Dictionary<string, float>();
                                for (int ifsoutSpecies = 0; ifsoutSpecies < fsoutSpecies.Count; ifsoutSpecies++)
                                {
                                    if (ifsoutSpecies % 2 == 1)
                                    {
                                        float distance = CommonClass.getDistanceFrom2Point(dicSpeciesLongLat[fsoutSpecies[ifsoutSpecies - 1] + "," + fsoutSpecies[ifsoutSpecies]].longitude, dicSpeciesLongLat[fsoutSpecies[ifsoutSpecies - 1] + "," + fsoutSpecies[ifsoutSpecies]].latitude, k.Value.longitude, k.Value.lat);
                                        fsoutStringSpecies.Add(dicSpeciesLongLat[fsoutSpecies[ifsoutSpecies - 1] + "," + fsoutSpecies[ifsoutSpecies]].id + "," + dicSpeciesLongLat[fsoutSpecies[ifsoutSpecies - 1] + "," + fsoutSpecies[ifsoutSpecies]].gridcell, distance);
                                    }
                                }
                                #endregion

                                #region pm values
                                List<double> fsInterPM = new List<double>();
                                fsInterPM.Add(k.Value.longitudeLamber);
                                fsInterPM.Add(k.Value.latitudeLamber);
                                //简化VNA算法：求半径范围内的监测点做VNA，一开始以5个经纬度来算一直达到10个为止
                                Dictionary<string, double> dicDistanceMonitorPM = new Dictionary<string, double>();
                                foreach (KeyValuePair<string, PMMonitorChina> kPM in dicPMMonitors)
                                {
                                    if (!kPM.Value.dicMonitorPMAvg.ContainsKey(kQ.Key)) continue;
                                    double dLongAbs = Math.Abs(kPM.Value.longitude - k.Value.longitude);
                                    double dLatAbs = Math.Abs(kPM.Value.latitude - k.Value.lat);
                                    if (dLongAbs > dLatAbs)
                                    {
                                        dicDistanceMonitorPM.Add(kPM.Key, dLongAbs);
                                    }
                                    else
                                    {
                                        dicDistanceMonitorPM.Add(kPM.Key, dLatAbs);
                                    }
                                }
                                query = dicDistanceMonitorPM.ToList();
                                isSame = false;
                                foreach (KeyValuePair<string, double> kPM in query)
                                {
                                    fsInterPM.Add(dicPMMonitors[kPM.Key].longitudeLamber);
                                    fsInterPM.Add(dicPMMonitors[kPM.Key].latitudeLamber);
                                    if (k.Value.longitudeLamber == dicPMMonitors[kPM.Key].longitudeLamber
                                        && k.Value.latitudeLamber == dicPMMonitors[kPM.Key].latitudeLamber)
                                    {
                                        isSame = true;
                                        break;
                                    }
                                }
                                //------------end VNA 简化算法
                                List<double> fsoutPM = new List<double>();
                                if (!isSame)
                                {
                                    CommonClass.VoronoiPoints(fsInterPM.ToArray(), ref fsoutPM);
                                }
                                else
                                {
                                    fsInterPM.Add(k.Value.longitudeLamber);
                                    fsInterPM.Add(k.Value.latitudeLamber);
                                }
                                if (fsoutPM.Count == 0) continue;
                                //----------------根据得到的邻居计算数值----------------
                                Dictionary<string, float> fsoutStringPM = new Dictionary<string, float>();
                                //List<NeighborFile> lstPMNeighbors = new List<NeighborFile>();
                                for (int ifsoutPM = 0; ifsoutPM < fsoutPM.Count; ifsoutPM++)
                                {
                                    if (ifsoutPM % 2 == 1)
                                    {
                                        float distance = CommonClass.getDistanceFrom2Point(k.Value.longitude, k.Value.lat, dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].longitude, dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].latitude);
                                        fsoutStringPM.Add(dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].id + "," + dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].gridcell, distance);
                                    }
                                }
                                #endregion
                                #endregion
                                if (fsoutStringSpecies.Count == 0 || fsoutStringPM.Count == 0) continue;
                                Dictionary<string, Dictionary<string, ModelDataSpecies>> dicGradAdjValues = new Dictionary<string, Dictionary<string, ModelDataSpecies>>();
                                GetGradAdjValues(ref dicGradAdjValues, fsoutStringSpecies, fsoutStringPM, k.Value.dicBaselineModel, dicQuarterlyModelDataPM);
                                double vnaCrustal = 0, vnaEC = 0, vnaNH4 = 0, vnaSO4 = 0, vnaOC = 0, vnaOther = 0, vnaPBW = 0, vnaNO3 = 0,
                                    gvnaCrustal = 0, gvnaEC = 0, gvnaNH4 = 0, gvnaSO4 = 0, gvnaOC = 0, gvnaOther = 0, gvnaPBW = 0, gvnaNO3 = 0,
                                    vnaPM = 0, gvnaPM = 0, nsSO4 = 0, nsNO3 = 0, nsOC = 0, nsEC = 0, nsCrustal = 0, nsNH4 = 0, nsPBW = 0, nsOther = 0, nsPM = 0;
                                //--------根据用户选择计算vna和evna----------------
                                #region
                                if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM && annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM)
                                {
                                    AnnualVNAEVNA(ref dicNeighborDistance, kQ.Key, "so4", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref vnaSO4, ref gvnaSO4, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNAEVNA(ref dicNeighborDistance, kQ.Key, "no3", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref vnaNO3, ref gvnaNO3, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNAEVNA(ref dicNeighborDistance, kQ.Key, "oc", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref vnaOC, ref gvnaOC, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNAEVNA(ref dicNeighborDistance, kQ.Key, "ec", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref vnaEC, ref gvnaEC, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNAEVNA(ref dicNeighborDistance, kQ.Key, "crustal", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref vnaCrustal, ref gvnaCrustal, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNAEVNA(ref dicNeighborDistance, kQ.Key, "nh4", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref vnaNH4, ref gvnaNH4, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNAEVNA(ref dicNeighborDistance, kQ.Key, "h2o", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref vnaPBW, ref gvnaPBW, fsoutStringSpecies,dicSpeciesMonitors);
                                    AnnualVNAEVNA(ref dicNeighborDistance, kQ.Key, "other", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref vnaOther, ref gvnaOther, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNAEVNA(ref dicNeighborDistance, kQ.Key, "pm25", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref vnaPM, ref gvnaPM, fsoutStringPM, dicPMMonitors);
                                }
                                else if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM)
                                {
                                    AnnualVNA(ref dicNeighborDistance, kQ.Key, "so4", "Inverse Distance Squared Weights", 9000000000, ref vnaSO4, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNA(ref dicNeighborDistance, kQ.Key, "no3", "Inverse Distance Squared Weights", 9000000000, ref vnaNO3, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNA(ref dicNeighborDistance, kQ.Key, "oc", "Inverse Distance Squared Weights", 9000000000, ref vnaOC, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNA(ref dicNeighborDistance, kQ.Key, "ec", "Inverse Distance Squared Weights", 9000000000, ref vnaEC, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNA(ref dicNeighborDistance, kQ.Key, "crustal", "Inverse Distance Squared Weights", 9000000000, ref vnaCrustal, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNA(ref dicNeighborDistance, kQ.Key, "nh4", "Inverse Distance Squared Weights", 9000000000, ref vnaNH4, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNA(ref dicNeighborDistance, kQ.Key, "h2o", "Inverse Distance Squared Weights", 9000000000, ref vnaPBW, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNA(ref dicNeighborDistance, kQ.Key, "other", "Inverse Distance Squared Weights", 9000000000, ref vnaOther, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualVNA(ref dicNeighborDistance, kQ.Key, "pm25", "Inverse Distance Squared Weights", 9000000000, ref vnaPM, fsoutStringPM, dicPMMonitors);
                                }
                                else if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM)
                                {
                                    AnnualEVNA(ref dicNeighborDistance, kQ.Key, "so4", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref gvnaSO4, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualEVNA(ref dicNeighborDistance, kQ.Key, "no3", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref gvnaNO3, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualEVNA(ref dicNeighborDistance, kQ.Key, "oc", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref gvnaOC, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualEVNA(ref dicNeighborDistance, kQ.Key, "ec", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref gvnaEC, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualEVNA(ref dicNeighborDistance, kQ.Key, "crustal", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref gvnaCrustal, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualEVNA(ref dicNeighborDistance, kQ.Key, "nh4", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref gvnaNH4, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualEVNA(ref dicNeighborDistance, kQ.Key, "h2o", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref gvnaPBW, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualEVNA(ref dicNeighborDistance, kQ.Key, "other", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref gvnaOther, fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualEVNA(ref dicNeighborDistance, kQ.Key, "pm25", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref gvnaPM, fsoutStringPM, dicPMMonitors);
                                }

                                if (annualPMAnalysisConfiguration.monitorDataInputChina.doNS)
                                {
                                    AnnualNearestSite(ref dicNeighborDistance, kQ.Key, "so4", 9000000000, ref nsSO4,
                                   fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualNearestSite(ref dicNeighborDistance, kQ.Key, "no3", 9000000000, ref nsNO3,
                                        fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualNearestSite(ref dicNeighborDistance, kQ.Key, "oc", 9000000000, ref nsOC,
                                        fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualNearestSite(ref dicNeighborDistance, kQ.Key, "ec", 9000000000, ref nsEC,
                                        fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualNearestSite(ref dicNeighborDistance, kQ.Key, "crustal", 9000000000, ref nsCrustal,
                                        fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualNearestSite(ref dicNeighborDistance, kQ.Key, "nh4", 9000000000, ref nsNH4,
                                        fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualNearestSite(ref dicNeighborDistance, kQ.Key, "h2o", 9000000000, ref nsPBW,
                                        fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualNearestSite(ref dicNeighborDistance, kQ.Key, "other", 9000000000, ref nsOther,
                                        fsoutStringSpecies, dicSpeciesMonitors);
                                    AnnualNearestSite(ref dicNeighborDistance, kQ.Key, "pm25", 9000000000, ref nsPM,
                                        fsoutStringPM, dicPMMonitors);
                                }

                                #endregion
                                //------保存vna和evna插值结果
                                #region
                                SpecFracPMChina sfAnnualSpatialGradAdj = new SpecFracPMChina();
                                SpecFracPMChina sfAnnualSpatial = new SpecFracPMChina();
                                GetSpeciesFractionValuesVNAEVNA(annualPMAnalysisConfiguration, ref sfAnnualSpatial, vnaCrustal, vnaEC, vnaNH4, vnaSO4, vnaOC, vnaOther, vnaPBW, vnaNO3, vnaPM);
                                #region species fractions
                                if (dicSpecFracSpatial.ContainsKey(k.Key))
                                {
                                    dicSpecFracSpatial[k.Key].dicSpecFracSpatial.Add(kQ.Key, sfAnnualSpatial);
                                }
                                else
                                {
                                    dicSpecFracSpatial.Add(k.Key, new PMMonitorChina()
                                    {
                                        id = k.Value.id,
                                        latitude = k.Value.lat,
                                        longitude = k.Value.longitude,
                                        dicSpecFracSpatial = new Dictionary<string, SpecFracPMChina>(),
                                    });
                                    dicSpecFracSpatial[k.Key].dicSpecFracSpatial.Add(kQ.Key, sfAnnualSpatial);
                                }
                                #endregion
                                #region
                                GetSpeciesFractionValuesVNAEVNA(annualPMAnalysisConfiguration, ref sfAnnualSpatialGradAdj, gvnaCrustal, gvnaEC, gvnaNH4, gvnaSO4, gvnaOC, gvnaOther, gvnaPBW, gvnaNO3, gvnaPM);
                                #region species fractions
                                if (dicSpecFracSpatial.ContainsKey(k.Key))
                                {
                                    if (dicSpecFracSpatial[k.Key].dicSpecFracSpatialGradAdj == null)
                                        dicSpecFracSpatial[k.Key].dicSpecFracSpatialGradAdj = new Dictionary<string, SpecFracPMChina>();
                                    dicSpecFracSpatial[k.Key].dicSpecFracSpatialGradAdj.Add(kQ.Key, sfAnnualSpatialGradAdj);
                                }
                                else
                                {
                                    dicSpecFracSpatial.Add(k.Key, new PMMonitorChina()
                                    {
                                        id = k.Value.id,
                                        latitude = k.Value.lat,
                                        longitude = k.Value.longitude,
                                        dicSpecFracSpatialGradAdj = new Dictionary<string, SpecFracPMChina>(),
                                    });
                                    dicSpecFracSpatial[k.Key].dicSpecFracSpatialGradAdj.Add(kQ.Key, sfAnnualSpatialGradAdj);
                                }
                                #endregion
                                GetSpeciesFractionValuesVNAEVNA(annualPMAnalysisConfiguration, ref sfAnnualSpatial, nsCrustal, nsEC, nsNH4, nsSO4, nsOC, nsOther, nsPBW, nsNO3, nsPM);
                                #region species fractions
                                if (dicSpecFracSpatial.ContainsKey(k.Key))
                                {
                                    if (dicSpecFracSpatial[k.Key].dicSpecFracSpatial_NS == null)
                                        dicSpecFracSpatial[k.Key].dicSpecFracSpatial_NS =
                                            new Dictionary<string, SpecFracPMChina>();
                                    dicSpecFracSpatial[k.Key].dicSpecFracSpatial_NS.Add(kQ.Key, sfAnnualSpatial);
                                }
                                else
                                {
                                    dicSpecFracSpatial.Add(k.Key, new PMMonitorChina()
                                    {
                                        id = k.Value.id,
                                        latitude = k.Value.lat,
                                        longitude = k.Value.longitude,
                                        dicSpecFracSpatial_NS = new Dictionary<string, SpecFracPMChina>()
                                    });
                                    dicSpecFracSpatial[k.Key].dicSpecFracSpatial_NS.Add(kQ.Key, sfAnnualSpatial);
                                }
                                #endregion
                                #endregion
                                #endregion
                                //dicGradAdjValues.Clear();
                                fsoutStringPM.Clear();
                                fsoutStringSpecies.Clear();
                            }
                            #endregion
                        }
                        #endregion

                        dicSpeciesLongLat.Clear();
                        GC.Collect();
                        dicSpeciesMonitors.Clear();
                        GC.Collect();
                        dicPmMonitorsLatLong.Clear();
                        GC.Collect();

                        _endTime = DateTime.Now;
                        CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                        CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish interpolating SI,FRM data to grid. " + CommonClass.TotalTime + " s.");
                        CommonClass.CurrentLog = "Finish interpolating SI,FRM data to grid. " + CommonClass.TotalTime + " s.";
                    }
                    #endregion

                    #region get baseline species value
                    Dictionary<string, PMMonitorChina> dicQuarterlyPMPoint = new Dictionary<string, PMMonitorChina>();
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicSpeciesFractions)
                    {
                        dicQuarterlyPMPoint.Add(k.Key, new PMMonitorChina()
                        {
                            id = k.Key,
                            type = string.IsNullOrEmpty(k.Value.type) ? dicPMMonitors[k.Key].type : k.Value.type,
                            locationName = k.Value.locationName,
                            stationName = k.Value.stationName,
                            latitude = k.Value.latitude,
                            longitude = k.Value.longitude,
                            gridcell = string.IsNullOrEmpty(k.Value.gridcell) ? dicMonitorInModel[k.Key] : k.Value.gridcell,
                            dicQuarterlyPoint = new Dictionary<string, PMPointChina>(),
                        });
                        double nonBlankMass = 0;
                        foreach (KeyValuePair<string, SpecFracPMChina> kin in k.Value.dicSpeciesFraction)
                        {
                            nonBlankMass = dicPMMonitors[k.Key].dicMonitorPMAvg[kin.Key] - 0;
                            dicQuarterlyPMPoint[k.Key].dicQuarterlyPoint.Add(kin.Key, new PMPointChina()
                            {
                                bPMDV = dicPMMonitors[k.Key].dicMonitorPMAvg[kin.Key],
                                bSO4 = nonBlankMass * kin.Value.fSO4,
                                bNO3 = nonBlankMass * kin.Value.fNO3,
                                bOC = nonBlankMass * kin.Value.fOC,
                                bEC = nonBlankMass * kin.Value.fEC,
                                bWater = nonBlankMass * kin.Value.fWater,
                                bNH4 = nonBlankMass * kin.Value.fNH4,
                                bCrustal = nonBlankMass * kin.Value.fCrustal,
                                bOther = nonBlankMass * kin.Value.fOther
                            });
                        }
                    }
                    dicSpeciesFractions.Clear();
                    GC.Collect();
                    #endregion

                    _beginTime = DateTime.Now;
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicQuarterlyPMPoint)
                    {
                        int Col = Convert.ToInt32(k.Value.gridcell) / 1000;
                        int Row = Convert.ToInt32(k.Value.gridcell) % 1000;
                        List<string> lstArrond = new List<string>();

                        PMPointChina pmPoint = new PMPointChina();

                        //-------首先根据gridtype获取周围的网格数
                        #region
                        switch (annualPMAnalysisConfiguration.modelDataInputChina.temporalAdjustmentAtMonitorGridPoint)//"3x3"
                        {
                            case "1x1":
                                lstArrond.Add(dicQuarterlyModelDataPM[k.Value.gridcell].id);
                                break;
                            case "3x3":
                                for (int m3 = -1; m3 <= 1; m3++)
                                {
                                    for (int n3 = -1; n3 <= 1; n3++)
                                    {
                                        lstArrond.Add(((Col + m3) * 1000 + (Row + n3)).ToString());
                                    }
                                }
                                break;
                            case "5x5":
                                for (int m5 = -2; m5 <= 2; m5++)
                                {
                                    for (int j5 = -2; j5 <= 2; j5++)
                                    {
                                        lstArrond.Add(((Col + m5) * 1000 + (Row + j5)).ToString());
                                    }
                                }
                                break;
                            case "7x7":
                                for (int m7 = -3; m7 <= 3; m7++)
                                {
                                    for (int j7 = -3; j7 <= 3; j7++)
                                    {
                                        lstArrond.Add(((Col + m7) * 1000 + (Row + j7)).ToString());
                                    }
                                }
                                break;
                            default://默认3x3
                                for (int m3 = -1; m3 <= 1; m3++)
                                {
                                    for (int n3 = -1; n3 <= 1; n3++)
                                    {
                                        lstArrond.Add(((Col + m3) * 1000 + (Row + n3)).ToString());
                                    }
                                }
                                break;
                        }
                        #endregion

                        //然后求所有网格的baseline和control的均值,得到rrf，然后求future values
                        #region
                        var query = dicQuarterlyModelDataPM.Where(p => lstArrond.Contains(p.Key)).ToList();
                        if (query.Count() > 0)
                        {
                            int iQueryCount = query.Count();
                            Dictionary<string, ModelDataSpecies> dicAmBaseline = new Dictionary<string, ModelDataSpecies>();
                            Dictionary<string, ModelDataSpecies> dicAmFuture = new Dictionary<string, ModelDataSpecies>();

                            for (int i = 0; i < iQueryCount; i++)
                            {
                                KeyValuePair<string, PmModelDataOutput> kin = query.ToArray()[i];
                                foreach (KeyValuePair<string, ModelDataSpecies> kBase in kin.Value.dicBaselineModel)
                                {
                                    if (dicAmBaseline.ContainsKey(kBase.Key))
                                    {
                                        dicAmBaseline[kBase.Key].crustal += kBase.Value.crustal;
                                        dicAmBaseline[kBase.Key].nh4 += kBase.Value.nh4;
                                        dicAmBaseline[kBase.Key].so4 += kBase.Value.so4;
                                        dicAmBaseline[kBase.Key].ec += kBase.Value.ec;
                                        dicAmBaseline[kBase.Key].no3 += kBase.Value.no3;
                                        dicAmBaseline[kBase.Key].oc += kBase.Value.oc;
                                        dicAmBaseline[kBase.Key].pm25 += kBase.Value.pm25;
                                        //dicAmBaseline[kBase.Key].cm += kBase.Value.cm;
                                        dicAmBaseline[kBase.Key].salt += kBase.Value.salt;
                                    }
                                    else
                                    {
                                        dicAmBaseline.Add(kBase.Key, new ModelDataSpecies()
                                        {
                                            crustal = kBase.Value.crustal,
                                            nh4 = kBase.Value.nh4,
                                            so4 = kBase.Value.so4,
                                            ec = kBase.Value.ec,
                                            no3 = kBase.Value.no3,
                                            oc = kBase.Value.oc,
                                            pm25 = kBase.Value.pm25,
                                            cm = kBase.Value.cm,
                                            salt = kBase.Value.salt,
                                        });
                                    }
                                }
                                foreach (KeyValuePair<string, ModelDataSpecies> kFuture in kin.Value.dicFutureModel)
                                {
                                    if (dicAmFuture.ContainsKey(kFuture.Key))
                                    {
                                        dicAmFuture[kFuture.Key].crustal += kFuture.Value.crustal;
                                        dicAmFuture[kFuture.Key].nh4 += kFuture.Value.nh4;
                                        dicAmFuture[kFuture.Key].so4 += kFuture.Value.so4;
                                        dicAmFuture[kFuture.Key].ec += kFuture.Value.ec;
                                        dicAmFuture[kFuture.Key].no3 += kFuture.Value.no3;
                                        dicAmFuture[kFuture.Key].oc += kFuture.Value.oc;
                                        dicAmFuture[kFuture.Key].pm25 += kFuture.Value.pm25;
                                        dicAmFuture[kFuture.Key].salt += kFuture.Value.salt;
                                    }
                                    else
                                    {
                                        dicAmFuture.Add(kFuture.Key, new ModelDataSpecies()
                                        {
                                            crustal = kFuture.Value.crustal,
                                            nh4 = kFuture.Value.nh4,
                                            so4 = kFuture.Value.so4,
                                            ec = kFuture.Value.ec,
                                            no3 = kFuture.Value.no3,
                                            oc = kFuture.Value.oc,
                                            pm25 = kFuture.Value.pm25,
                                            salt = kFuture.Value.salt,
                                        });
                                    }
                                }
                            }
                            //-----------RRF limitation----------------
                            foreach (KeyValuePair<string, ModelDataSpecies> kBase in dicAmBaseline)
                            {//CRUSTAL_b NH4_b SO4_b EC_b NO3_b OC_b salt_b PM25_b
                                if (kBase.Value.crustal < CommonClass.RrfLimit) kBase.Value.crustal = Convert.ToSingle(CommonClass.RrfLimit);
                                if (kBase.Value.ec < CommonClass.RrfLimit) kBase.Value.ec = Convert.ToSingle(CommonClass.RrfLimit);
                                if (kBase.Value.no3 < CommonClass.RrfLimit) kBase.Value.no3 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (kBase.Value.so4 < CommonClass.RrfLimit) kBase.Value.so4 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (kBase.Value.nh4 < CommonClass.RrfLimit) kBase.Value.nh4 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (kBase.Value.oc < CommonClass.RrfLimit) kBase.Value.oc = Convert.ToSingle(CommonClass.RrfLimit);
                                if (kBase.Value.pm25 < CommonClass.RrfLimit) kBase.Value.pm25 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (Double.IsNaN(kBase.Value.salt) || kBase.Value.salt < CommonClass.RrfLimit) kBase.Value.salt = Convert.ToSingle(CommonClass.RrfLimit);
                            }
                            foreach (KeyValuePair<string, ModelDataSpecies> kFuture in dicAmFuture)
                            {
                                if (kFuture.Value.crustal < CommonClass.RrfLimit) kFuture.Value.crustal = Convert.ToSingle(CommonClass.RrfLimit);
                                if (kFuture.Value.ec < CommonClass.RrfLimit) kFuture.Value.ec = Convert.ToSingle(CommonClass.RrfLimit);
                                if (kFuture.Value.no3 < CommonClass.RrfLimit) kFuture.Value.no3 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (kFuture.Value.so4 < CommonClass.RrfLimit) kFuture.Value.so4 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (kFuture.Value.nh4 < CommonClass.RrfLimit) kFuture.Value.nh4 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (kFuture.Value.oc < CommonClass.RrfLimit) kFuture.Value.oc = Convert.ToSingle(CommonClass.RrfLimit);
                                if (kFuture.Value.pm25 < CommonClass.RrfLimit) kFuture.Value.pm25 = Convert.ToSingle(CommonClass.RrfLimit);
                                if (Double.IsNaN(kFuture.Value.salt) || kFuture.Value.salt < CommonClass.RrfLimit) kFuture.Value.salt = Convert.ToSingle(CommonClass.RrfLimit);
                            }

                            foreach (KeyValuePair<string, PMPointChina> kQ in k.Value.dicQuarterlyPoint)
                            {
                                #region
                                #region rrf and species values
                                pmPoint.rrfCrustal = CommonClass.ToFixed(dicAmFuture[kQ.Key].crustal / dicAmBaseline[kQ.Key].crustal, 4);
                                pmPoint.fCrustal = kQ.Value.bCrustal * pmPoint.rrfCrustal;
                                pmPoint.rrfEC = CommonClass.ToFixed(dicAmFuture[kQ.Key].ec / dicAmBaseline[kQ.Key].ec, 4);
                                pmPoint.fEC = kQ.Value.bEC * pmPoint.rrfEC;
                                pmPoint.rrfNO3 = CommonClass.ToFixed(dicAmFuture[kQ.Key].no3 / dicAmBaseline[kQ.Key].no3, 4);
                                pmPoint.fNO3 = kQ.Value.bNO3 * pmPoint.rrfNO3;
                                pmPoint.rrfOC = CommonClass.ToFixed(dicAmFuture[kQ.Key].oc / dicAmBaseline[kQ.Key].oc, 4);
                                pmPoint.fOC = kQ.Value.bOC * pmPoint.rrfOC;
                                pmPoint.rrfSO4 = CommonClass.ToFixed(dicAmFuture[kQ.Key].so4 / dicAmBaseline[kQ.Key].so4, 4);
                                pmPoint.fSO4 = kQ.Value.bSO4 * pmPoint.rrfSO4;
                                pmPoint.rrfNH4 = CommonClass.ToFixed(dicAmFuture[kQ.Key].nh4 / dicAmBaseline[kQ.Key].nh4, 4);
                                pmPoint.fNH4 = kQ.Value.bNH4 * pmPoint.rrfNH4;
                                pmPoint.rrfWater = CommonClass.ToFixed((dicAmFuture[kQ.Key].so4 + dicAmFuture[kQ.Key].no3 + dicAmFuture[kQ.Key].nh4 + dicAmFuture[kQ.Key].oc + dicAmFuture[kQ.Key].ec) / (dicAmBaseline[kQ.Key].so4 + dicAmBaseline[kQ.Key].no3 + dicAmBaseline[kQ.Key].nh4 + dicAmBaseline[kQ.Key].oc + dicAmBaseline[kQ.Key].ec), 4);
                                pmPoint.fWater = kQ.Value.bWater * pmPoint.rrfWater;
                                pmPoint.rrfOther = CommonClass.ToFixed((dicAmFuture[kQ.Key].so4 + dicAmFuture[kQ.Key].no3 + dicAmFuture[kQ.Key].nh4 + dicAmFuture[kQ.Key].oc + dicAmFuture[kQ.Key].ec) / (dicAmBaseline[kQ.Key].so4 + dicAmBaseline[kQ.Key].no3 + dicAmBaseline[kQ.Key].nh4 + dicAmBaseline[kQ.Key].oc + dicAmBaseline[kQ.Key].ec), 4);
                                pmPoint.fOther = kQ.Value.bOther * pmPoint.rrfOther;
                                pmPoint.fPMDV = pmPoint.fCrustal + pmPoint.fEC + pmPoint.fNO3 + pmPoint.fOC + pmPoint.fSO4 + pmPoint.fNH4 + pmPoint.fWater + pmPoint.fOther + 0;
                                #endregion

                                kQ.Value.rrfCrustal = pmPoint.rrfCrustal;
                                kQ.Value.fCrustal = pmPoint.fCrustal;
                                kQ.Value.rrfEC = pmPoint.rrfEC;
                                kQ.Value.fEC = pmPoint.fEC;
                                kQ.Value.rrfNO3 = pmPoint.rrfNO3;
                                kQ.Value.fNO3 = pmPoint.fNO3;
                                kQ.Value.rrfOC = pmPoint.rrfOC;
                                kQ.Value.fOC = pmPoint.fOC;
                                kQ.Value.rrfSO4 = pmPoint.rrfSO4;
                                kQ.Value.fSO4 = pmPoint.fSO4;
                                kQ.Value.rrfNH4 = pmPoint.rrfNH4;
                                kQ.Value.fNH4 = pmPoint.fNH4;
                                kQ.Value.rrfWater = pmPoint.rrfWater;
                                kQ.Value.fWater = pmPoint.fWater;
                                kQ.Value.rrfOther = pmPoint.rrfOther;
                                kQ.Value.fOther = pmPoint.fOther;
                                kQ.Value.fPMDV = pmPoint.fPMDV;
                                #endregion

                            }
                        }
                        #endregion
                    }
                    GC.Collect();
                    SaveQuarterlyPMPoint(CommonClass.CurrentBaseScenario, dicQuarterlyPMPoint, true);

                    #region annual pm point
                    Dictionary<string, PMPointChina> dicAnnualPMPoint = new Dictionary<string, PMPointChina>();
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicQuarterlyPMPoint)
                    {
                        dicAnnualPMPoint.Add(k.Key, new PMPointChina()
                        {
                            id = k.Value.id,
                            type = k.Value.type,
                            locationName = k.Value.locationName,
                            stationName = k.Value.stationName,
                            monitorLat = k.Value.latitude,
                            monitorLong = k.Value.longitude,
                            monitorGridcell = k.Value.gridcell,
                            bPMDV = k.Value.dicQuarterlyPoint.Select(p => p.Value.bPMDV).Average(),
                            fPMDV = k.Value.dicQuarterlyPoint.Select(p => p.Value.fPMDV).Average(),
                            bCrustal = k.Value.dicQuarterlyPoint.Select(p => p.Value.bCrustal).Average(),
                            bEC = k.Value.dicQuarterlyPoint.Select(p => p.Value.bEC).Average(),
                            bNH4 = k.Value.dicQuarterlyPoint.Select(p => p.Value.bNH4).Average(),
                            bNO3 = k.Value.dicQuarterlyPoint.Select(p => p.Value.bNO3).Average(),
                            bOC = k.Value.dicQuarterlyPoint.Select(p => p.Value.bOC).Average(),
                            bSO4 = k.Value.dicQuarterlyPoint.Select(p => p.Value.bSO4).Average(),
                            bWater = k.Value.dicQuarterlyPoint.Select(p => p.Value.bWater).Average(),
                            bOther = k.Value.dicQuarterlyPoint.Select(p => p.Value.bOther).Average(),
                            fCrustal = k.Value.dicQuarterlyPoint.Select(p => p.Value.fCrustal).Average(),
                            fEC = k.Value.dicQuarterlyPoint.Select(p => p.Value.fEC).Average(),
                            fNH4 = k.Value.dicQuarterlyPoint.Select(p => p.Value.fNH4).Average(),
                            fNO3 = k.Value.dicQuarterlyPoint.Select(p => p.Value.fNO3).Average(),
                            fOC = k.Value.dicQuarterlyPoint.Select(p => p.Value.fOC).Average(),
                            fOther = k.Value.dicQuarterlyPoint.Select(p => p.Value.fOther).Average(),
                            fSO4 = k.Value.dicQuarterlyPoint.Select(p => p.Value.fSO4).Average(),
                            fWater = k.Value.dicQuarterlyPoint.Select(p => p.Value.fWater).Average(),
                        });
                        dicAnnualPMPoint[k.Key].rrfCrustal = Double.IsNaN(dicAnnualPMPoint[k.Key].fCrustal / dicAnnualPMPoint[k.Key].bCrustal) || Double.IsInfinity(dicAnnualPMPoint[k.Key].fCrustal / dicAnnualPMPoint[k.Key].bCrustal) ? -9 : dicAnnualPMPoint[k.Key].fCrustal / dicAnnualPMPoint[k.Key].bCrustal;
                        dicAnnualPMPoint[k.Key].rrfEC = Double.IsNaN(dicAnnualPMPoint[k.Key].fEC / dicAnnualPMPoint[k.Key].bEC) || Double.IsInfinity(dicAnnualPMPoint[k.Key].fEC / dicAnnualPMPoint[k.Key].bEC) ? -9 : dicAnnualPMPoint[k.Key].fEC / dicAnnualPMPoint[k.Key].bEC;
                        dicAnnualPMPoint[k.Key].rrfNH4 = Double.IsNaN(dicAnnualPMPoint[k.Key].fNH4 / dicAnnualPMPoint[k.Key].bNH4) || Double.IsInfinity(dicAnnualPMPoint[k.Key].fNH4 / dicAnnualPMPoint[k.Key].bNH4) ? -9 : dicAnnualPMPoint[k.Key].fNH4 / dicAnnualPMPoint[k.Key].bNH4;
                        dicAnnualPMPoint[k.Key].rrfNO3 = Double.IsNaN(dicAnnualPMPoint[k.Key].fNO3 / dicAnnualPMPoint[k.Key].bNO3) || Double.IsInfinity(dicAnnualPMPoint[k.Key].fNO3 / dicAnnualPMPoint[k.Key].bNO3) ? -9 : dicAnnualPMPoint[k.Key].fNO3 / dicAnnualPMPoint[k.Key].bNO3;
                        dicAnnualPMPoint[k.Key].rrfOC = Double.IsNaN(dicAnnualPMPoint[k.Key].fOC / dicAnnualPMPoint[k.Key].bOC) || Double.IsInfinity(dicAnnualPMPoint[k.Key].fOC / dicAnnualPMPoint[k.Key].bOC) ? -9 : dicAnnualPMPoint[k.Key].fOC / dicAnnualPMPoint[k.Key].bOC;
                        dicAnnualPMPoint[k.Key].rrfOther = Double.IsNaN(dicAnnualPMPoint[k.Key].fOther / dicAnnualPMPoint[k.Key].bOther) || Double.IsInfinity(dicAnnualPMPoint[k.Key].fOther / dicAnnualPMPoint[k.Key].bOther) ? -9 : dicAnnualPMPoint[k.Key].fOther / dicAnnualPMPoint[k.Key].bOther;
                        dicAnnualPMPoint[k.Key].rrfSO4 = Double.IsNaN(dicAnnualPMPoint[k.Key].fSO4 / dicAnnualPMPoint[k.Key].bSO4) || Double.IsInfinity(dicAnnualPMPoint[k.Key].fSO4 / dicAnnualPMPoint[k.Key].bSO4) ? -9 : dicAnnualPMPoint[k.Key].fSO4 / dicAnnualPMPoint[k.Key].bSO4;
                        dicAnnualPMPoint[k.Key].rrfWater = Double.IsNaN(dicAnnualPMPoint[k.Key].fWater / dicAnnualPMPoint[k.Key].bWater) || Double.IsInfinity(dicAnnualPMPoint[k.Key].fWater / dicAnnualPMPoint[k.Key].bWater) ? -9 : dicAnnualPMPoint[k.Key].fWater / dicAnnualPMPoint[k.Key].bWater;
                    }
                    dicQuarterlyPMPoint.Clear();
                    GC.Collect();
                    #endregion
                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish computing RRF: " + CommonClass.TotalTime + " s.");
                    CommonClass.CurrentLog = "Finish computing RRF: " + CommonClass.TotalTime + " s.";

                    SaveAnnualPMPoint(CommonClass.CurrentBaseScenario, dicAnnualPMPoint, true);

                    if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM || annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM || annualPMAnalysisConfiguration.monitorDataInputChina.doNS)
                    {
                        _beginTime = DateTime.Now;
                        #region Spatial Field
                        Dictionary<string, PMMonitorChina> dicQuarterlySpatialField = new Dictionary<string, PMMonitorChina>();
                        foreach (KeyValuePair<string, PMMonitorChina> k in dicSpecFracSpatial)
                        {
                            dicQuarterlySpatialField.Add(k.Key, new PMMonitorChina()
                            {
                                id = k.Key,
                                latitude = k.Value.latitude,
                                longitude = k.Value.longitude,
                            });
                            double nonBlankMass = 0;
                            #region VNA
                            if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM)
                            {
                                dicQuarterlySpatialField[k.Key].dicQuarterlySpatial = new Dictionary<string, PMSpatialChina>();
                                foreach (KeyValuePair<string, SpecFracPMChina> kQ in k.Value.dicSpecFracSpatial)
                                {
                                    nonBlankMass = kQ.Value.pm25Frac - kQ.Value.blankMass;
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial.Add(kQ.Key, new PMSpatialChina()
                                    {
                                        bPMAnnDV = Convert.ToSingle(kQ.Value.pm25Frac),
                                        bBlankMass = Convert.ToSingle(kQ.Value.blankMass),
                                        bCrustalMass = Convert.ToSingle(kQ.Value.fCrustal * nonBlankMass),
                                        bECMass = Convert.ToSingle(kQ.Value.fEC * nonBlankMass),
                                        bNH4Mass = Convert.ToSingle(kQ.Value.fNH4 * nonBlankMass),
                                        bOCMass = Convert.ToSingle(kQ.Value.fOC * nonBlankMass),
                                        bSO4Mass = Convert.ToSingle(kQ.Value.fSO4 * nonBlankMass),
                                        bNO3Mass = Convert.ToSingle(kQ.Value.fNO3 * nonBlankMass),
                                        bWaterMass = Convert.ToSingle(kQ.Value.fWater * nonBlankMass),
                                        bOtherMass = Convert.ToSingle(kQ.Value.fOther * nonBlankMass),
                                        fBlankMass = Convert.ToSingle(kQ.Value.blankMass),
                                    });
                                    //----------判断是否满足最小值要求------------------
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].crustal < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].crustal = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3 = Convert.ToSingle(CommonClass.RrfLimit);

                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].crustal < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].crustal = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 = Convert.ToSingle(CommonClass.RrfLimit);

                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfCrustal = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].crustal / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].crustal, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfEC = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfNH4 = Math.Round(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfOC = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfSO4 = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfNO3 = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfWaterMass = CommonClass.ToFixed((dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec) / (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec), 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfOther = CommonClass.ToFixed((dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec) / (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec), 4);

                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fCrustalMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfCrustal * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].bCrustalMass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fECMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfEC * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].bECMass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fOCMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfOC * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].bOCMass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fSO4Mass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfSO4 * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].bSO4Mass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fNO3Mass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfNO3 * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].bNO3Mass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fNH4Mass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfNH4 * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].bNH4Mass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fWaterMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfWaterMass * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].bWaterMass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fOtherMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].rrfOther * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].bOtherMass);

                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fPMAnnDV = dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fCrustalMass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fECMass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fOCMass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fOtherMass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fSO4Mass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fNO3Mass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fNH4Mass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fWaterMass;// + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fBlankMass;
                                }
                            }
                            #endregion

                            #region EVNA
                            if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM)
                            {
                                dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted = new Dictionary<string, PMSpatialChina>();
                                foreach (KeyValuePair<string, SpecFracPMChina> kQ in k.Value.dicSpecFracSpatialGradAdj)
                                {
                                    nonBlankMass = kQ.Value.pm25Frac - kQ.Value.blankMass;
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted.Add(kQ.Key, new PMSpatialChina()
                                    {
                                        bPMAnnDV = Convert.ToSingle(kQ.Value.pm25Frac),
                                        bBlankMass = Convert.ToSingle(kQ.Value.blankMass),
                                        bCrustalMass = Convert.ToSingle(kQ.Value.fCrustal * nonBlankMass),
                                        bECMass = Convert.ToSingle(kQ.Value.fEC * nonBlankMass),
                                        bNH4Mass = Convert.ToSingle(kQ.Value.fNH4 * nonBlankMass),
                                        bOCMass = Convert.ToSingle(kQ.Value.fOC * nonBlankMass),
                                        bSO4Mass = Convert.ToSingle(kQ.Value.fSO4 * nonBlankMass),
                                        bNO3Mass = Convert.ToSingle(kQ.Value.fNO3 * nonBlankMass),
                                        bWaterMass = Convert.ToSingle(kQ.Value.fWater * nonBlankMass),
                                        bOtherMass = Convert.ToSingle(kQ.Value.fOther * nonBlankMass),
                                        fBlankMass = Convert.ToSingle(kQ.Value.blankMass),
                                    });
                                    //------------判断是否满足最小值要求-----------
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].crustal < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].crustal = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3 = Convert.ToSingle(CommonClass.RrfLimit);

                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].crustal < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].crustal = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 = Convert.ToSingle(CommonClass.RrfLimit);

                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfCrustal = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].crustal / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].crustal, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfEC = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfNH4 = Math.Round(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfOC = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfSO4 = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfNO3 = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfWaterMass = CommonClass.ToFixed((dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec) / (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec), 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfOther = CommonClass.ToFixed((dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec) / (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec), 4);

                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fCrustalMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfCrustal * dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].bCrustalMass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fECMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfEC * dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].bECMass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fOCMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfOC * dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].bOCMass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fSO4Mass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfSO4 * dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].bSO4Mass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fNO3Mass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfNO3 * dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].bNO3Mass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fNH4Mass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfNH4 * dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].bNH4Mass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fWaterMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfWaterMass * dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].bWaterMass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fOtherMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfOther * dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].bOtherMass);

                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fPMAnnDV = dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fCrustalMass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fECMass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fOCMass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fOtherMass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fSO4Mass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fNO3Mass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fNH4Mass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fWaterMass;// +dicQuarterlySpatialField[k.Key].dicQuarterlySpatialGradientAdjusted[kQ.Key].fBlankMass;
                                }

                            }
                            #endregion

                            #region NearestSite
                            if (annualPMAnalysisConfiguration.monitorDataInputChina.doNS)
                            {
                                dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS = new Dictionary<string, PMSpatialChina>();
                                foreach (KeyValuePair<string, SpecFracPMChina> kQ in k.Value.dicSpecFracSpatial_NS)
                                {
                                    nonBlankMass = kQ.Value.pm25Frac - kQ.Value.blankMass;
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS.Add(kQ.Key, new PMSpatialChina()
                                    {
                                        bPMAnnDV = Convert.ToSingle(kQ.Value.pm25Frac),
                                        bBlankMass = Convert.ToSingle(kQ.Value.blankMass),
                                        bCrustalMass = Convert.ToSingle(kQ.Value.fCrustal * nonBlankMass),
                                        bECMass = Convert.ToSingle(kQ.Value.fEC * nonBlankMass),
                                        bNH4Mass = Convert.ToSingle(kQ.Value.fNH4 * nonBlankMass),
                                        bOCMass = Convert.ToSingle(kQ.Value.fOC * nonBlankMass),
                                        bSO4Mass = Convert.ToSingle(kQ.Value.fSO4 * nonBlankMass),
                                        bNO3Mass = Convert.ToSingle(kQ.Value.fNO3 * nonBlankMass),
                                        bWaterMass = Convert.ToSingle(kQ.Value.fWater * nonBlankMass),
                                        bOtherMass = Convert.ToSingle(kQ.Value.fOther * nonBlankMass),
                                        fBlankMass = Convert.ToSingle(kQ.Value.blankMass),
                                    });
                                    //----------判断是否满足最小值要求------------------
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].crustal < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].crustal = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3 = Convert.ToSingle(CommonClass.RrfLimit);

                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].crustal < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].crustal = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 = Convert.ToSingle(CommonClass.RrfLimit);

                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfCrustal = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].crustal / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].crustal, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfEC = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfNH4 = Math.Round(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfOC = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfSO4 = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfNO3 = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3, 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfWaterMass = CommonClass.ToFixed((dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec) / (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec), 4);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfOther = CommonClass.ToFixed((dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].so4 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].no3 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].nh4 + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].oc + dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].ec) / (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].so4 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].no3 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].nh4 + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].oc + dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].ec), 4);

                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fCrustalMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfCrustal * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].bCrustalMass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fECMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfEC * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].bECMass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fOCMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfOC * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].bOCMass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fSO4Mass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfSO4 * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].bSO4Mass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fNO3Mass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfNO3 * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].bNO3Mass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fNH4Mass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfNH4 * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].bNH4Mass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fWaterMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfWaterMass * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].bWaterMass);
                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fOtherMass = Convert.ToSingle(dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].rrfOther * dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].bOtherMass);

                                    dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fPMAnnDV = dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fCrustalMass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fECMass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fOCMass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fOtherMass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fSO4Mass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fNO3Mass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fNH4Mass + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial_NS[kQ.Key].fWaterMass;// + dicQuarterlySpatialField[k.Key].dicQuarterlySpatial[kQ.Key].fBlankMass;
                                }
                            }
                            #endregion
                        }
                        dicQuarterlyModelDataPM.Clear();
                        GC.Collect();
                        dicSpecFracSpatial.Clear();
                        GC.Collect();
                        #region save files
                        if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM)
                        {
                            SaveQuarterlySpatialField(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, true);
                            SaveAnnualPointSpatialField(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, true);
                        }
                        if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM)
                        {
                            SaveQuarterlySpatialFieldGradAdj(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, true);
                            SaveAnnualPointSpatialFieldGradAdj(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, true);
                        }
                        if (annualPMAnalysisConfiguration.monitorDataInputChina.dowVNA)
                        {
                            SaveQuarterlySpatialFieldwVNA(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, true);
                            SaveAnnualPointSpatialFieldwVNA(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, true);
                        }
                        if (annualPMAnalysisConfiguration.monitorDataInputChina.doNS)
                        {
                            SaveQuarterlySpatialFieldNearestSite(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, true);
                            SaveAnnualPointSpatialFieldNearestSite(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, true);
                        }
                        #endregion
                        dicQuarterlySpatialField.Clear();
                        GC.Collect();
                        #endregion
                        _endTime = DateTime.Now;
                        CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                        CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish interpolating Spatial Field: " + CommonClass.TotalTime + " s.");
                        CommonClass.CurrentLog = "Finish interpolating Spatial Field: " + CommonClass.TotalTime + " s.";
                    }
                    #endregion with species
                }
                else //no species
                {
                    #region no species

                    Dictionary<string, PMMonitorChina> dicPmMonitorsLatLong = new Dictionary<string, PMMonitorChina>();
                    Dictionary<string, PMMonitorChina> dicQuarterlySpatialField = new Dictionary<string, PMMonitorChina>();
                    var w = annualPMAnalysisConfiguration.monitorDataInputChina.wVNAWeight;// wVNA权重

                    #region pm2.5 spatial field
                    if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM || annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM || annualPMAnalysisConfiguration.monitorDataInputChina.doNS)
                    {
                        #region monitor pm Longitude & Latitude
                        foreach (KeyValuePair<string, PMMonitorChina> k in dicPMMonitors)
                        {
                            if (!dicPmMonitorsLatLong.ContainsKey(k.Value.longitudeLamber + "," + k.Value.latitudeLamber))
                            {
                                dicPmMonitorsLatLong.Add(k.Value.longitudeLamber + "," + k.Value.latitudeLamber, k.Value);
                            }
                        }
                        #endregion
                        GC.Collect();
                        //获取species和pm的neighbors及相关的数据参数
                        #region 获取pm的neighbors及相关的数据参数计算vna和evna插值结果
                        List<string> lstGradAdjId = new List<string>();
                        Dictionary<string, Dictionary<string, float>> dicNeighborDistance = new Dictionary<string, Dictionary<string, float>>();

                        foreach (KeyValuePair<string, PmModelDataOutput> k in dicQuarterlyModelDataPM)
                        {
                            dicNeighborDistance = new Dictionary<string, Dictionary<string, float>>();
                            #region
                            foreach (KeyValuePair<string, ModelDataSpecies> kQ in k.Value.dicBaselineModel)
                            {
                                #region pm values
                                List<double> fsInterPM = new List<double>();
                                fsInterPM.Add(k.Value.longitudeLamber);
                                fsInterPM.Add(k.Value.latitudeLamber);
                                //简化VNA算法：求半径范围内的监测点做VNA，一开始以5个经纬度来算一直达到10个为止
                                Dictionary<string, double> dicDistanceMonitorPM = new Dictionary<string, double>();
                                foreach (KeyValuePair<string, PMMonitorChina> kPM in dicPMMonitors)
                                {
                                    if (!kPM.Value.dicMonitorPMAvg.ContainsKey(kQ.Key)) continue;
                                    double dLongAbs = Math.Abs(kPM.Value.longitude - k.Value.longitude);
                                    double dLatAbs = Math.Abs(kPM.Value.latitude - k.Value.lat);
                                    if (dLongAbs > dLatAbs)
                                    {
                                        dicDistanceMonitorPM.Add(kPM.Key, dLongAbs);
                                    }
                                    else
                                    {
                                        dicDistanceMonitorPM.Add(kPM.Key, dLatAbs);
                                    }
                                }
                                var query = dicDistanceMonitorPM.ToList();
                                bool isSame = false;
                                foreach (KeyValuePair<string, double> kPM in query)
                                {
                                    fsInterPM.Add(dicPMMonitors[kPM.Key].longitudeLamber);
                                    fsInterPM.Add(dicPMMonitors[kPM.Key].latitudeLamber);
                                    if (k.Value.longitudeLamber == dicPMMonitors[kPM.Key].longitudeLamber
                                        && k.Value.latitudeLamber == dicPMMonitors[kPM.Key].latitudeLamber)
                                    {
                                        isSame = true;
                                        break;
                                    }
                                }
                                //------------end VNA 简化算法
                                List<double> fsoutPM = new List<double>();
                                if (!isSame)
                                {
                                    CommonClass.VoronoiPoints(fsInterPM.ToArray(), ref fsoutPM);
                                }
                                else
                                {
                                    fsInterPM.Add(k.Value.longitudeLamber);
                                    fsInterPM.Add(k.Value.latitudeLamber);
                                }
                                if (fsoutPM.Count == 0) continue;
                                //----------------根据得到的邻居计算数值----------------
                                Dictionary<string, float> fsoutStringPM = new Dictionary<string, float>();
                                //List<NeighborFile> lstPMNeighbors = new List<NeighborFile>();
                                for (int ifsoutPM = 0; ifsoutPM < fsoutPM.Count; ifsoutPM++)
                                {
                                    if (ifsoutPM % 2 == 1)
                                    {
                                        float distance = CommonClass.getDistanceFrom2Point(k.Value.longitude, k.Value.lat, dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].longitude, dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].latitude);
                                        fsoutStringPM.Add(dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].id + "," + dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].gridcell, distance);
                                    }
                                }
                                #endregion
                                if (fsoutStringPM.Count == 0) continue;
                                Dictionary<string, Dictionary<string, ModelDataSpecies>> dicGradAdjValues = new Dictionary<string, Dictionary<string, ModelDataSpecies>>();
                                GetGradAdjValues(ref dicGradAdjValues, new Dictionary<string, float>(), fsoutStringPM, k.Value.dicBaselineModel, dicQuarterlyModelDataPM);
                                double vnaPM = 0, gvnaPM = 0 , nsPM=0, wvnaPM = 0;
                                //--------根据用户选择计算vna和evna----------------
                                #region
                                if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM && annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM)
                                {
                                    AnnualVNAEVNA(ref dicNeighborDistance, kQ.Key, "pm25", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref vnaPM, ref gvnaPM, fsoutStringPM, dicPMMonitors);
                                }
                                else if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM)
                                {
                                    AnnualVNA(ref dicNeighborDistance, kQ.Key, "pm25", "Inverse Distance Squared Weights", 9000000000, ref vnaPM, fsoutStringPM, dicPMMonitors);
                                }
                                else if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM)
                                {
                                    AnnualEVNA(ref dicNeighborDistance, kQ.Key, "pm25", dicGradAdjValues, "Inverse Distance Squared Weights", 9000000000, ref gvnaPM, fsoutStringPM, dicPMMonitors);
                                }
                                if (annualPMAnalysisConfiguration.monitorDataInputChina.doNS)
                                {
                                    AnnualNearestSite(ref dicNeighborDistance, kQ.Key, "pm25", 9000000000, ref nsPM,
                                        fsoutStringPM, dicPMMonitors);
                                }

                                #endregion
                                //------保存vna和evna插值结果
                                #region species fractions
                                if (dicQuarterlySpatialField.ContainsKey(k.Key))
                                {
                                    dicQuarterlySpatialField[k.Key].dicpmSpatial.Add(kQ.Key, new double[8] { vnaPM, 0, gvnaPM, 0, nsPM ,0, wvnaPM , 0});
                                }
                                else
                                {
                                    dicQuarterlySpatialField.Add(k.Key, new PMMonitorChina()
                                    {
                                        id = k.Value.id,
                                        latitude = k.Value.lat,
                                        longitude = k.Value.longitude,
                                        dicpmSpatial = new Dictionary<string, double[]>()
                                    });
                                    dicQuarterlySpatialField[k.Key].dicpmSpatial.Add(kQ.Key, new double[8] { vnaPM, 0, gvnaPM, 0 , nsPM, 0, wvnaPM, 0 });
                                }
                                #endregion
                                //dicGradAdjValues.Clear();
                                fsoutStringPM.Clear();
                            }
                            #endregion
                        }
                        #endregion

                        dicPmMonitorsLatLong.Clear();
                        GC.Collect();

                        _endTime = DateTime.Now;
                        CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                        CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish interpolating SI,FRM data to grid. " + CommonClass.TotalTime + " s.");
                        CommonClass.CurrentLog = "Finish interpolating SI,FRM data to grid. " + CommonClass.TotalTime + " s.";
                    }
                    #endregion


                    foreach (KeyValuePair<string, PMMonitorChina> k in dicPMMonitors)
                    {
                        int Col = Convert.ToInt32(k.Value.gridcell) / 1000;
                        int Row = Convert.ToInt32(k.Value.gridcell) % 1000;
                        List<string> lstArrond = new List<string>();

                        //-------首先根据gridtype获取周围的网格数
                        #region
                        switch (annualPMAnalysisConfiguration.modelDataInputChina.temporalAdjustmentAtMonitorGridPoint)//"3x3"
                        {
                            case "1x1":
                                lstArrond.Add(dicQuarterlyModelDataPM[k.Value.gridcell].id);
                                break;
                            case "3x3":
                                for (int m3 = -1; m3 <= 1; m3++)
                                {
                                    for (int n3 = -1; n3 <= 1; n3++)
                                    {
                                        lstArrond.Add(((Col + m3) * 1000 + (Row + n3)).ToString());
                                    }
                                }
                                break;
                            case "5x5":
                                for (int m5 = -2; m5 <= 2; m5++)
                                {
                                    for (int j5 = -2; j5 <= 2; j5++)
                                    {
                                        lstArrond.Add(((Col + m5) * 1000 + (Row + j5)).ToString());
                                    }
                                }
                                break;
                            case "7x7":
                                for (int m7 = -3; m7 <= 3; m7++)
                                {
                                    for (int j7 = -3; j7 <= 3; j7++)
                                    {
                                        lstArrond.Add(((Col + m7) * 1000 + (Row + j7)).ToString());
                                    }
                                }
                                break;
                            default://默认3x3
                                for (int m3 = -1; m3 <= 1; m3++)
                                {
                                    for (int n3 = -1; n3 <= 1; n3++)
                                    {
                                        lstArrond.Add(((Col + m3) * 1000 + (Row + n3)).ToString());
                                    }
                                }
                                break;
                        }
                        #endregion

                        //然后求所有网格的baseline和control的均值,得到rrf，然后求future values
                        #region
                        var query = dicQuarterlyModelDataPM.Where(p => lstArrond.Contains(p.Key)).ToList();
                        if (query.Count() > 0)
                        {
                            int iQueryCount = query.Count();
                            Dictionary<string, float> dicAmBaseline = new Dictionary<string, float>();
                            Dictionary<string, float> dicAmFuture = new Dictionary<string, float>();

                            for (int i = 0; i < iQueryCount; i++)
                            {
                                KeyValuePair<string, PmModelDataOutput> kin = query.ToArray()[i];
                                foreach (KeyValuePair<string, ModelDataSpecies> kBase in kin.Value.dicBaselineModel)
                                {
                                    if (dicAmBaseline.ContainsKey(kBase.Key))
                                    {
                                        dicAmBaseline[kBase.Key] += kBase.Value.pm25;
                                    }
                                    else
                                    {
                                        dicAmBaseline.Add(kBase.Key, kBase.Value.pm25);
                                    }
                                }
                                foreach (KeyValuePair<string, ModelDataSpecies> kFuture in kin.Value.dicFutureModel)
                                {
                                    if (dicAmFuture.ContainsKey(kFuture.Key))
                                    {
                                        dicAmFuture[kFuture.Key] += kFuture.Value.pm25;
                                    }
                                    else
                                    {
                                        dicAmFuture.Add(kFuture.Key, kFuture.Value.pm25);
                                    }
                                }
                            }
                            //-----------RRF limitation----------------

                            for (int i = 0; i < dicAmBaseline.Keys.Count; i++)
                            {
                                string s = dicAmBaseline.Keys.ElementAt(i);
                                if (dicAmBaseline[s] < CommonClass.RrfLimit) dicAmBaseline[s] = Convert.ToSingle(CommonClass.RrfLimit);
                                if (dicAmFuture[s] < CommonClass.RrfLimit) dicAmFuture[s] = Convert.ToSingle(CommonClass.RrfLimit);
                            }                         

                            //foreach (string s in dicAmBaseline.Keys)
                            //{
                            //    if (dicAmBaseline[s] < CommonClass.RrfLimit) dicAmBaseline[s] = Convert.ToSingle(CommonClass.RrfLimit);
                            //}
                            //foreach (string s in dicAmFuture.Keys)
                            //{
                            //    if (dicAmFuture[s] < CommonClass.RrfLimit) dicAmFuture[s] = Convert.ToSingle(CommonClass.RrfLimit);
                            //}

                            k.Value.dicQuarterlyPoint = new Dictionary<string, PMPointChina>();
                            foreach (KeyValuePair<string, float> pm in k.Value.dicMonitorPMAvg)
                            {
                                k.Value.dicQuarterlyPoint.Add(pm.Key, new PMPointChina());
                                k.Value.dicQuarterlyPoint[pm.Key].bPMDV = pm.Value;
                                double rrf = CommonClass.ToFixed(dicAmFuture[pm.Key] / dicAmBaseline[pm.Key], 4);
                                k.Value.dicQuarterlyPoint[pm.Key].fPMDV = k.Value.dicQuarterlyPoint[pm.Key].bPMDV * rrf;
                            }
                        }
                        #endregion
                    }
                    GC.Collect();
                    SaveQuarterlyPMPoint(CommonClass.CurrentBaseScenario, dicPMMonitors, false);

                    #region annual pm point
                    Dictionary<string, PMPointChina> dicAnnualPMPoint = new Dictionary<string, PMPointChina>();
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicPMMonitors)
                    {
                        dicAnnualPMPoint.Add(k.Key, new PMPointChina()
                        {
                            id = k.Value.id,
                            type = k.Value.type,
                            locationName = k.Value.locationName,
                            stationName = k.Value.stationName,
                            monitorLat = k.Value.latitude,
                            monitorLong = k.Value.longitude,
                            monitorGridcell = k.Value.gridcell,
                            bPMDV = k.Value.dicQuarterlyPoint.Select(p => p.Value.bPMDV).Average(),
                            fPMDV = k.Value.dicQuarterlyPoint.Select(p => p.Value.fPMDV).Average(),
                        });
                    }
                    GC.Collect();
                    #endregion
                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish computing RRF: " + CommonClass.TotalTime + " s.");
                    CommonClass.CurrentLog = "Finish computing RRF: " + CommonClass.TotalTime + " s.";

                    SaveAnnualPMPoint(CommonClass.CurrentBaseScenario, dicAnnualPMPoint, false);

                    if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM || annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM || annualPMAnalysisConfiguration.monitorDataInputChina.doNS)
                    {
                        _beginTime = DateTime.Now;
                        #region Spatial Field
                        foreach (KeyValuePair<string, PMMonitorChina> k in dicQuarterlySpatialField)
                        {
                            #region VNA eVNA
                            if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM || annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM || annualPMAnalysisConfiguration.monitorDataInputChina.doNS)
                            {
                                foreach (KeyValuePair<string, double[]> kQ in k.Value.dicpmSpatial)
                                {
                                    //----------判断是否满足最小值要求------------------
                                    if (dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].pm25 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].pm25 = Convert.ToSingle(CommonClass.RrfLimit);
                                    if (dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].pm25 < CommonClass.RrfLimit) dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].pm25 = Convert.ToSingle(CommonClass.RrfLimit);
                                    double rrf = CommonClass.ToFixed(dicQuarterlyModelDataPM[k.Key].dicFutureModel[kQ.Key].pm25 / dicQuarterlyModelDataPM[k.Key].dicBaselineModel[kQ.Key].pm25, 4);
                                    kQ.Value[1] = kQ.Value[0] * rrf;
                                    kQ.Value[3] = kQ.Value[2] * rrf;
                                    kQ.Value[5] = kQ.Value[4] * rrf;
                                    kQ.Value[6] = kQ.Value[2] * w + kQ.Value[0] * (1 - w);
                                    kQ.Value[7] = kQ.Value[6] * rrf;
                                }
                            }
                            #endregion
                        }
                        dicQuarterlyModelDataPM.Clear();
                        GC.Collect();
                        #region save files
                        if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM)
                        {
                            SaveQuarterlySpatialField(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, false);
                            SaveAnnualPointSpatialField(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, false);
                        }
                        if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM)
                        {
                            SaveQuarterlySpatialFieldGradAdj(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, false);
                            SaveAnnualPointSpatialFieldGradAdj(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, false);
                        }
                        if (annualPMAnalysisConfiguration.monitorDataInputChina.dowVNA)
                        {
                            SaveQuarterlySpatialFieldwVNA(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, false);
                            SaveAnnualPointSpatialFieldwVNA(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, false);
                        }
                        if (annualPMAnalysisConfiguration.monitorDataInputChina.doNS)
                        {
                            SaveQuarterlySpatialFieldNearestSite(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, false);
                            SaveAnnualPointSpatialFieldNearestSite(CommonClass.CurrentBaseScenario, dicQuarterlySpatialField, false);
                        }
                        #endregion
                        dicQuarterlySpatialField.Clear();
                        GC.Collect();
                        #endregion
                        _endTime = DateTime.Now;
                        CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                        CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish interpolating Spatial Field: " + CommonClass.TotalTime + " s.");
                        CommonClass.CurrentLog = "Finish interpolating Spatial Field: " + CommonClass.TotalTime + " s.";
                    }
                    #endregion no species
                }


                #region output data for BenMAP

                string strFileSpatialFiled = " Annual PM25 Spatial Field.csv";
                string strFileGradSpatialField = " Grad Adj Annual PM25 Spatial Field.csv";
                string strFileGradSpatialFieldwvna = " Annual PM25 Spatial Field(wVNA).csv";
                string strFileNearestSiteSpatialFiled = " Nearest Site Annual PM25 Spatial Field.csv";
                string strPath = "";
                if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateAdjustedFRM)//EVNA 
                {
                    strPath = CommonClass.CurrentBaseScenario.lstOutput.Where(p => p.outputFilePath.Contains(strFileGradSpatialField)).First().outputFilePath;
                    OutputPMDataForBenMAP(strPath, annualPMAnalysisConfiguration.monitorDataInputChina);
                }
                if (annualPMAnalysisConfiguration.monitorDataInputChina.doInterpolateFRM)//VNA
                {
                    strPath = CommonClass.CurrentBaseScenario.lstOutput.Where(p => p.outputFilePath.Contains(strFileSpatialFiled)).First().outputFilePath;
                    OutputPMDataForBenMAP(strPath, annualPMAnalysisConfiguration.monitorDataInputChina);
                }
                if (annualPMAnalysisConfiguration.monitorDataInputChina.dowVNA)//wVNA
                {
                    strPath = CommonClass.CurrentBaseScenario.lstOutput.Where(p => p.outputFilePath.Contains(strFileGradSpatialFieldwvna)).First().outputFilePath;
                    OutputPMDataForBenMAP(strPath, annualPMAnalysisConfiguration.monitorDataInputChina);
                }
                if (annualPMAnalysisConfiguration.monitorDataInputChina.doNS)//Nearest Site
                {
                    strPath = CommonClass.CurrentBaseScenario.lstOutput.Where(p => p.outputFilePath.Contains(strFileNearestSiteSpatialFiled)).First().outputFilePath;
                    OutputPMDataForBenMAP(strPath, annualPMAnalysisConfiguration.monitorDataInputChina);
                }
                #endregion

                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 导出BenMAP格式数据
        /// add by sclong
        /// 2016-09-12
        /// </summary>
        /// <param name="strPath"></param>
        /// <param name="dic"></param>
        private static void OutputPMDataForBenMAP(string strPath, MonitorDataInputChina monitorDataInputChina)
        {
            try
            {
                string strFirstLine = "";
                bool errorOccur = false;
                DataTable dt = CommonClass.getDataSetFromCSVAndFirstLine(strPath, ref strFirstLine, ref errorOccur);
                List<string> lstStringOutputb = new List<string>();
                lstStringOutputb.Add("Column,Row,Metric,Seasonal Metric,Statistic,Values");
                List<string> lstStringOutputc = new List<string>();
                lstStringOutputc.Add("Column,Row,Metric,Seasonal Metric,Statistic,Values");
                //Dictionary<string, Dictionary<string, double>> dicOutput = new Dictionary<string, Dictionary<string, double>>();
                int iLat = 0, iLong = 0, iPM25b = 0, iPM25c = 0, iQuarter = 0, iID = 0;
                foreach (DataColumn dc in dt.Columns)
                {
                    switch (dc.ColumnName.ToLower().Trim())
                    {
                        case "gridcell_lat":
                            iLat = dt.Columns.IndexOf(dc);
                            break;
                        case "gridcell_long":
                            iLong = dt.Columns.IndexOf(dc);
                            break;
                        case "b_pm25_ann_dv_ga":
                        case "b_pm25_ann_dv_ns":
                        case "b_pm25_ann_dv_wvna":
                        case "b_pm25_ann_dv":
                            iPM25b = dt.Columns.IndexOf(dc);
                            break;
                        case "f_pm25_ann_dv_ga":
                        case "f_pm25_ann_dv_ns":
                        case "f_pm25_ann_dv_wvna":
                        case "f_pm25_ann_dv":
                            iPM25c = dt.Columns.IndexOf(dc);
                            break;
                        case "quarter":
                            iQuarter = dt.Columns.IndexOf(dc);
                            break;
                        case "_id":
                            iID = dt.Columns.IndexOf(dc);
                            break;
                    }
                }

                foreach (DataRow dr in dt.Rows)
                {
                    int id = Convert.ToInt32(dr[iID]);
                    int col = Convert.ToInt32(id / 1000);
                    int row = Convert.ToInt32(id % 1000);

                    lstStringOutputb.Add(string.Format("{0},{1},{2},{3},{4}", col + "," + row, "D24HourMean", "QuarterlyMean", "Mean", Convert.ToDouble(dr[iPM25b])));
                    lstStringOutputc.Add(string.Format("{0},{1},{2},{3},{4}", col + "," + row, "D24HourMean", "QuarterlyMean", "Mean", Convert.ToDouble(dr[iPM25c])));
                }

                if (monitorDataInputChina.doInterpolateFRM && dt.Columns[iPM25b].ColumnName.ToLower()== "b_pm25_ann_dv")
                {
                    string algorithmType = "(VNA)";
                    string strPathB = Path.GetDirectoryName(strPath) + @"\BenMAP-ready PM25 Spatial Field Base " + algorithmType + ".csv";
                    string strPathC = Path.GetDirectoryName(strPath) + @"\BenMAP-ready PM25 Spatial Field Future " + algorithmType + ".csv";
                    System.IO.StreamWriter swB = new System.IO.StreamWriter(strPathB, false);
                    foreach (string s in lstStringOutputb)
                    {
                        swB.WriteLine(s);
                    }
                    swB.Flush();

                    System.IO.StreamWriter swC = new System.IO.StreamWriter(strPathC, false);
                    foreach (string s in lstStringOutputc)
                    {
                        swC.WriteLine(s);
                    }
                    swC.Flush();
                }

                if (monitorDataInputChina.doInterpolateAdjustedFRM && dt.Columns[iPM25b].ColumnName.ToLower() == "b_pm25_ann_dv_ga")
                {
                    string algorithmType = "(eVNA)";
                    string strPathB = Path.GetDirectoryName(strPath) + @"\BenMAP-ready PM25 Spatial Field Base " + algorithmType + ".csv";
                    string strPathC = Path.GetDirectoryName(strPath) + @"\BenMAP-ready PM25 Spatial Field Future " + algorithmType + ".csv";
                    System.IO.StreamWriter swB = new System.IO.StreamWriter(strPathB, false);
                    foreach (string s in lstStringOutputb)
                    {
                        swB.WriteLine(s);
                    }
                    swB.Flush();

                    System.IO.StreamWriter swC = new System.IO.StreamWriter(strPathC, false);
                    foreach (string s in lstStringOutputc)
                    {
                        swC.WriteLine(s);
                    }
                    swC.Flush();
                }

                if (monitorDataInputChina.dowVNA && dt.Columns[iPM25b].ColumnName.ToLower() == "b_pm25_ann_dv_wvna")
                {
                    string algorithmType = "(wVNA)";
                    string strPathB = Path.GetDirectoryName(strPath) + @"\BenMAP-ready PM25 Spatial Field Base " + algorithmType + ".csv";
                    string strPathC = Path.GetDirectoryName(strPath) + @"\BenMAP-ready PM25 Spatial Field Future " + algorithmType + ".csv";
                    System.IO.StreamWriter swB = new System.IO.StreamWriter(strPathB, false);
                    foreach (string s in lstStringOutputb)
                    {
                        swB.WriteLine(s);
                    }
                    swB.Flush();

                    System.IO.StreamWriter swC = new System.IO.StreamWriter(strPathC, false);
                    foreach (string s in lstStringOutputc)
                    {
                        swC.WriteLine(s);
                    }
                    swC.Flush();
                }

                if (monitorDataInputChina.doNS && dt.Columns[iPM25b].ColumnName.ToLower() == "b_pm25_ann_dv_ns")
                {
                    string algorithmType = "(Nearest Site)";
                    string strPathB = Path.GetDirectoryName(strPath) + @"\BenMAP-ready PM25 Spatial Field Base " + algorithmType + ".csv";
                    string strPathC = Path.GetDirectoryName(strPath) + @"\BenMAP-ready PM25 Spatial Field Future " + algorithmType + ".csv";
                    System.IO.StreamWriter swB = new System.IO.StreamWriter(strPathB, false);
                    foreach (string s in lstStringOutputb)
                    {
                        swB.WriteLine(s);
                    }
                    swB.Flush();

                    System.IO.StreamWriter swC = new System.IO.StreamWriter(strPathC, false);
                    foreach (string s in lstStringOutputc)
                    {
                        swC.WriteLine(s);
                    }
                    swC.Flush();
                }
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }

        public static string GetModelDataQuarterly(AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration, ref Dictionary<string, PmModelDataOutput> dicQuarterlyModelDataPM, ref string baseModelYear, ref string futureModelYear)
        {
            try
            {
                #region quarterly baseline model data
                string dataType = "";
                bool errorOccur = false;
                DataTable dtModel = CommonClass.getDataSetFromCSVAndFirstLine(annualPMAnalysisConfiguration.modelDataInputChina.BaselineModelDataFile, ref dataType, ref errorOccur);
                if (dtModel == null)
                    return "wrongBaseline";
                int iID = -1, iType = -1, iLat = -1, iLong = -1, iDate = -1, iCrustal = -1, iNH4 = -1, iSO4 = -1, iEC = -1, iNO3 = -1, iOC = -1, iPM25 = -1, iCM = -1;
                try
                {
                    #region get index for each field
                    for (int i = 0; i < dtModel.Columns.Count; i++)
                    {
                        switch (dtModel.Columns[i].ColumnName.ToLower().Trim().Replace("\"", ""))
                        {
                            case "_id":
                                iID = i;
                                break;
                            case "_type":
                                iType = i;
                                break;
                            case "lat":
                                iLat = i;
                                break;
                            case "long":
                                iLong = i;
                                break;
                            case "quarter":
                                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;
                        }
                    }
                    #endregion
                    foreach (DataRow dr in dtModel.Rows)
                    {
                        if (baseModelYear == "") baseModelYear = dr[iDate].ToString().Replace("\"", "").Substring(0, 4);
                        string q = "";
                        switch (dr[iDate].ToString().Replace("\"", "").Substring(4))
                        {
                            case "01":
                                q = "1";
                                break;
                            case "04":
                                q = "2";
                                break;
                            case "07":
                                q = "3";
                                break;
                            case "10":
                                q = "4";
                                break;
                        }
                        if (dicQuarterlyModelDataPM.ContainsKey(dr[iID].ToString().Replace("\"", "")))
                        {
                            dicQuarterlyModelDataPM[dr[iID].ToString().Replace("\"", "")].dicBaselineModel.Add(q, new ModelDataSpecies()
                            {
                                crustal = Convert.ToSingle(dr[iCrustal].ToString()),
                                nh4 = Convert.ToSingle(dr[iNH4].ToString()),
                                so4 = Convert.ToSingle(dr[iSO4].ToString()),
                                ec = Convert.ToSingle(dr[iEC].ToString()),
                                no3 = Convert.ToSingle(dr[iNO3].ToString()),
                                oc = Convert.ToSingle(dr[iOC].ToString()),
                                pm25 = Convert.ToSingle(dr[iPM25].ToString()),
                                cm = Convert.ToSingle(dr[iCM].ToString()),
                            });
                        }
                        else
                        {
                            dicQuarterlyModelDataPM.Add(dr[iID].ToString().Replace("\"", ""), new PmModelDataOutput()
                            {
                                id = dr[iID].ToString().Replace("\"", ""),
                                type = dr[iType].ToString().Replace("\"", ""),
                                lat = Convert.ToDouble(dr[iLat].ToString()),
                                longitude = Convert.ToDouble(dr[iLong].ToString()),
                                dicBaselineModel = new Dictionary<string, ModelDataSpecies>(),
                                dicFutureModel = new Dictionary<string, ModelDataSpecies>(),
                            });
                            dicQuarterlyModelDataPM[dr[iID].ToString().Replace("\"", "")].dicBaselineModel.Add(q, new ModelDataSpecies()
                            {
                                crustal = Convert.ToSingle(dr[iCrustal].ToString()),
                                nh4 = Convert.ToSingle(dr[iNH4].ToString()),
                                so4 = Convert.ToSingle(dr[iSO4].ToString()),
                                ec = Convert.ToSingle(dr[iEC].ToString()),
                                no3 = Convert.ToSingle(dr[iNO3].ToString()),
                                oc = Convert.ToSingle(dr[iOC].ToString()),
                                pm25 = Convert.ToSingle(dr[iPM25].ToString()),
                                cm = Convert.ToSingle(dr[iCM].ToString()),
                            });
                        }
                    }
                    dtModel.Dispose();
                    GC.Collect();
                }
                catch
                {
                    return "wrongBaseline";
                }
                #endregion

                _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(annualPMAnalysisConfiguration.modelDataInputChina.ControlModelDataFile) + "\".";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                #region quarterly future model data
                errorOccur = false;
                dtModel = CommonClass.getDataSetFromCSVAndFirstLine(annualPMAnalysisConfiguration.modelDataInputChina.ControlModelDataFile, ref dataType, ref errorOccur);
                if (dtModel == null)
                    return "wrongFuture";

                //保存字段的索引
                iID = -1; iType = -1; iLat = -1; iLong = -1; iDate = -1; iCrustal = -1; iNH4 = -1; iSO4 = -1; iEC = -1; iNO3 = -1; iOC = -1; iPM25 = -1; iCM = -1;
                try
                {
                    #region get index for each field
                    for (int i = 0; i < dtModel.Columns.Count; i++)
                    {
                        switch (dtModel.Columns[i].ColumnName.ToLower().Trim().Replace("\"", ""))
                        {
                            case "_id":
                                iID = i;
                                break;
                            case "_type":
                                iType = i;
                                break;
                            case "lat":
                                iLat = i;
                                break;
                            case "long":
                                iLong = i;
                                break;
                            case "quarter":
                                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;
                        }
                    }
                    #endregion
                    foreach (DataRow dr in dtModel.Rows)
                    {
                        if (futureModelYear == "") futureModelYear = dr[iDate].ToString().Replace("\"", "").Substring(0, 4);
                        string q = "";
                        switch (dr[iDate].ToString().Replace("\"", "").Substring(4))
                        {
                            case "01":
                                q = "1";
                                break;
                            case "04":
                                q = "2";
                                break;
                            case "07":
                                q = "3";
                                break;
                            case "10":
                                q = "4";
                                break;
                        }
                        if (dicQuarterlyModelDataPM.ContainsKey(dr[iID].ToString().Replace("\"", "")))
                        {
                            dicQuarterlyModelDataPM[dr[iID].ToString().Replace("\"", "")].dicFutureModel.Add(q, new ModelDataSpecies()
                            {
                                crustal = Convert.ToSingle(dr[iCrustal].ToString()),
                                nh4 = Convert.ToSingle(dr[iNH4].ToString()),
                                so4 = Convert.ToSingle(dr[iSO4].ToString()),
                                ec = Convert.ToSingle(dr[iEC].ToString()),
                                no3 = Convert.ToSingle(dr[iNO3].ToString()),
                                oc = Convert.ToSingle(dr[iOC].ToString()),
                                pm25 = Convert.ToSingle(dr[iPM25].ToString()),
                                cm = Convert.ToSingle(dr[iCM].ToString()),
                            });
                        }
                        else
                        {
                            dicQuarterlyModelDataPM.Add(dr[iID].ToString().Replace("\"", ""), new PmModelDataOutput()
                            {
                                id = dr[iID].ToString().Replace("\"", ""),
                                type = dr[iType].ToString().Replace("\"", ""),
                                lat = Convert.ToDouble(dr[iLat].ToString()),
                                longitude = Convert.ToDouble(dr[iLong].ToString()),
                                dicBaselineModel = new Dictionary<string, ModelDataSpecies>(),
                                dicFutureModel = new Dictionary<string, ModelDataSpecies>(),
                            });
                            dicQuarterlyModelDataPM[dr[iID].ToString().Replace("\"", "")].dicFutureModel.Add(q, new ModelDataSpecies()
                            {
                                crustal = Convert.ToSingle(dr[iCrustal].ToString()),
                                nh4 = Convert.ToSingle(dr[iNH4].ToString()),
                                so4 = Convert.ToSingle(dr[iSO4].ToString()),
                                ec = Convert.ToSingle(dr[iEC].ToString()),
                                no3 = Convert.ToSingle(dr[iNO3].ToString()),
                                oc = Convert.ToSingle(dr[iOC].ToString()),
                                pm25 = Convert.ToSingle(dr[iPM25].ToString()),
                                cm = Convert.ToSingle(dr[iCM].ToString()),
                            });
                        }
                    }
                }
                catch
                {
                    return "wrongFuture";
                }
                dtModel.Dispose();
                GC.Collect();
                #endregion
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }

        }

        public static bool SaveQuarterlyModelDataCopyDirectly(BaseScenario baseScenario, Dictionary<string, PmModelDataOutput> dicModelData)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
            {
                return false;
            }
            try
            {
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                #region
                File.Copy((CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.BaselineModelDataFile, _resultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName + " Baseline Quarterly Avg Model Data.csv", true);
                FileInfo fileInfo = null;
                if (CommonClass.CurrentBaseScenario.lstOutput == null)
                    CommonClass.CurrentBaseScenario.lstOutput = new List<BaseOutput>();
                string strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Baseline Quarterly Avg Model Data.csv";
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                baseScenario.lstOutput.Add(baseOutput);

                strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Future Quarterly Avg Model Data.csv";
                baseOutput = new BaseOutput();
                File.Copy((CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.ControlModelDataFile, _resultFilePath + @"\" + strFile, true);
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                baseScenario.lstOutput.Add(baseOutput);
                #endregion

                //added by yangwenwei 
                //added by Yangwenwei 20131220
                DataTable dtDeltaModelData = new DataTable();
                //Construct the DataTable "dtDeltaModelData". added by Yangwenwei 20131219
                dtDeltaModelData.Columns.Add("_id");
                dtDeltaModelData.Columns.Add("_type");
                dtDeltaModelData.Columns.Add("lat");
                dtDeltaModelData.Columns.Add("long");
                dtDeltaModelData.Columns.Add("date");
                dtDeltaModelData.Columns.Add("DeltaC(crustal)");
                dtDeltaModelData.Columns.Add("DeltaC(nh4)");
                dtDeltaModelData.Columns.Add("DeltaC(so4)");
                dtDeltaModelData.Columns.Add("DeltaC(ec)");
                dtDeltaModelData.Columns.Add("DeltaC(no3)");
                dtDeltaModelData.Columns.Add("DeltaC(oc)");
                dtDeltaModelData.Columns.Add("DeltaC(pm25)");
                dtDeltaModelData.Columns.Add("DeltaC(cm)");

                //read data in dicQuarterlyModel and write Delta data
                dicModelData = dicModelData.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                foreach (KeyValuePair<string, PmModelDataOutput> k in dicModelData)
                {
                    foreach (KeyValuePair<string, ModelDataSpecies> kFuture in dicModelData[k.Key].dicFutureModel)
                    {
                        DataRow drDelta = dtDeltaModelData.NewRow();
                        drDelta[0] = k.Key;
                        drDelta[1] = k.Value.type;
                        drDelta[2] = k.Value.lat;
                        drDelta[3] = k.Value.longitude;
                        switch (kFuture.Key)
                        {
                            case "1":
                                drDelta[4] = "01";
                                break;
                            case "2":
                                drDelta[4] = "04";
                                break;
                            case "3":
                                drDelta[4] = "07";
                                break;
                            case "4":
                                drDelta[4] = "10";
                                break;
                        }
                        drDelta[5] = Math.Round(k.Value.dicBaselineModel[kFuture.Key].crustal - kFuture.Value.crustal, 8);
                        drDelta[6] = Math.Round(k.Value.dicBaselineModel[kFuture.Key].nh4 - kFuture.Value.nh4, 8);
                        drDelta[7] = Math.Round(k.Value.dicBaselineModel[kFuture.Key].so4 - kFuture.Value.so4, 8);
                        drDelta[8] = Math.Round(k.Value.dicBaselineModel[kFuture.Key].ec - kFuture.Value.ec, 8);
                        drDelta[9] = Math.Round(k.Value.dicBaselineModel[kFuture.Key].no3 - kFuture.Value.no3, 8);
                        drDelta[10] = Math.Round(k.Value.dicBaselineModel[kFuture.Key].oc - kFuture.Value.oc, 8);
                        drDelta[11] = Math.Round(k.Value.dicBaselineModel[kFuture.Key].pm25 - kFuture.Value.pm25, 8);
                        drDelta[12] = Math.Round(k.Value.dicBaselineModel[kFuture.Key].cm - kFuture.Value.cm, 8);
                        dtDeltaModelData.Rows.Add(drDelta);
                    }
                }

                //create Delta CSV added by Yangwenwei 20131219
                strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Delta Quarterly Avg Model Data.csv";
                baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtDeltaModelData, _resultFilePath + @"\" + strFile, "Quarter");
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                dtDeltaModelData.Dispose();//end
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static string GetPMMonitors(AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration, ref  Dictionary<string, PMMonitorChina> dicPMMonitors)
        {
            try
            {
                //string error = "";
                #region read offcial pm25
                //字段索引值
                int iID = -1, iType = -1, iLat = -1, iLong = -1, iDate = -1, iPM25 = -1;
                int iLocationName = -1, iStationName = -1;
                FileStream fs = new FileStream(annualPMAnalysisConfiguration.monitorDataInputChina.MonitorDataInputFile, 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(" ", "").Replace("\"", ""))
                        {
                            case "_id":
                                iID = i;
                                break;
                            case "_type":
                                iType = i;
                                break;
                            case "lat":
                                iLat = i;
                                break;
                            case "long":
                                iLong = i;
                                break;
                            case "quarter_dv":
                                iDate = i;
                                break;
                            case "pm25":
                                iPM25 = i;
                                break;
                            case "location_name":
                                iLocationName = i;
                                break;
                            case "station_name":
                                iStationName = i;
                                break;
                        }
                        i++;
                    }
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        //try
                        //{
                        strLineArray = strLine.Split(new char[] { ',' });
                        //首先判断是否满足start year和end year
                        if (Convert.ToInt32(strLineArray[iDate].Replace("\"", "").Substring(0, 4)) >= Convert.ToInt32(annualPMAnalysisConfiguration.monitorDataInputChina.MonitorDataStartYear)
                            && Convert.ToInt32(strLineArray[iDate].Replace("\"", "").Substring(0, 4)) <= Convert.ToInt32(annualPMAnalysisConfiguration.monitorDataInputChina.MonitorDataEndYear))
                        {
                            if (dicPMMonitors.ContainsKey(strLineArray[iID].ToString().Replace("\"", "")))
                            {
                                string quarter = "";
                                switch (strLineArray[iDate].Replace("\"", "").Substring(strLineArray[iDate].Replace("\"", "").Length - 2))
                                {
                                    case "01":
                                        quarter = "1";
                                        break;
                                    case "04":
                                        quarter = "2";
                                        break;
                                    case "07":
                                        quarter = "3";
                                        break;
                                    case "10":
                                        quarter = "4";
                                        break;
                                }
                                dicPMMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicMonitorPM[quarter].Add(strLineArray[iDate].Replace("\"", "").Substring(0, 6), Convert.ToSingle(strLineArray[iPM25]) == -9 ? float.NaN : Convert.ToSingle(strLineArray[iPM25]));
                            }
                            else
                            {
                                dicPMMonitors.Add(strLineArray[iID].ToString().Replace("\"", ""), new PMMonitorChina()
                                {
                                    id = strLineArray[iID].Replace("\"", ""),
                                    latitude = Convert.ToDouble(strLineArray[iLat]),
                                    longitude = Convert.ToDouble(strLineArray[iLong]),
                                    type = strLineArray[iType].Replace("\"", ""),
                                    locationName = strLineArray[iLocationName].Replace("\"", ""),
                                    stationName = strLineArray[iStationName].Replace("\"", ""),
                                    dicMonitorPM = new Dictionary<string, Dictionary<string, float>>(),
                                });
                                dicPMMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicMonitorPM.Add("1", new Dictionary<string, float>());
                                dicPMMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicMonitorPM.Add("2", new Dictionary<string, float>());
                                dicPMMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicMonitorPM.Add("3", new Dictionary<string, float>());
                                dicPMMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicMonitorPM.Add("4", new Dictionary<string, float>());
                                string quarter = "";
                                switch (strLineArray[iDate].Replace("\"", "").Substring(strLineArray[iDate].Replace("\"", "").Length - 2))
                                {
                                    case "01":
                                        quarter = "1";
                                        break;
                                    case "04":
                                        quarter = "2";
                                        break;
                                    case "07":
                                        quarter = "3";
                                        break;
                                    case "10":
                                        quarter = "4";
                                        break;
                                }
                                dicPMMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicMonitorPM[quarter].Add(strLineArray[iDate].Replace("\"", "").Substring(0, 6), Convert.ToSingle(strLineArray[iPM25]) == -9 ? float.NaN : Convert.ToSingle(strLineArray[iPM25]));
                            }
                        }
                        //}
                        //catch
                        //{
                        //    error = "errorRow";
                        //}
                    }
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                }
                #endregion
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }

        }

        public static string GetSpeciesMonitors(AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration, Dictionary<string, PMMonitorChina> dicSpeciesMonitors)
        {
            try
            {
                #region read species monitor data
                //字段索引值
                int iID = -1, iType = -1, iLat = -1, iLong = -1, iDate = -1, iSO4 = -1, iNO3 = -1, iNH4 = -1, iOC = -1, iEC = -1, iCrustal = -1, iH2O = -1, iOther = -1;
                int iLocationName = -1, iStationName = -1;
                //string quarter = "";
                //string error = "";
                //bool isOKinfilter = true;
                FileStream fs = new FileStream(annualPMAnalysisConfiguration.pm25SpeciesOptionChina.SpeciesMonitorDataFile, 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;
                    //----------get index for each field------------
                    #region
                    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 "quarter_dv":
                                iDate = i;
                                break;
                            case "so4":
                                iSO4 = i;
                                break;
                            case "no3":
                                iNO3 = i;
                                break;
                            case "nh4":
                                iNH4 = i;
                                break;
                            case "oc":
                                iOC = i;
                                break;
                            case "ec":
                                iEC = i;
                                break;
                            case "crustal":
                                iCrustal = i;
                                break;
                            case "h2o":
                                iH2O = i;
                                break;
                            case "other":
                                iOther = i;
                                break;
                            case "location_name":
                                iLocationName = i;
                                break;
                            case "station_name":
                                iStationName = i;
                                break;
                        }
                        i++;
                    }
                    #endregion
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        //try
                        //{
                        strLineArray = strLine.Split(new char[] { ',' });
                        //对于各种species，首先必须将其值为null，或者负数的全部设为null
                        if (Convert.ToInt32(strLineArray[iDate].Replace("\"", "").Substring(0, 4)) >= Convert.ToInt32(annualPMAnalysisConfiguration.monitorDataInputChina.MonitorDataStartYear)
                                && Convert.ToInt32(strLineArray[iDate].Replace("\"", "").Substring(0, 4)) <= Convert.ToInt32(annualPMAnalysisConfiguration.monitorDataInputChina.MonitorDataEndYear))
                        {
                            if (dicSpeciesMonitors.ContainsKey(strLineArray[iID].ToString().Replace("\"", "")))
                            {
                                string quarter = "";
                                switch (strLineArray[iDate].Replace("\"", "").Substring(strLineArray[iDate].Replace("\"", "").Length - 2))
                                {
                                    case "01":
                                        quarter = "1";
                                        break;
                                    case "04":
                                        quarter = "2";
                                        break;
                                    case "07":
                                        quarter = "3";
                                        break;
                                    case "10":
                                        quarter = "4";
                                        break;
                                }
                                dicSpeciesMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicSpecies[quarter].Add(strLineArray[iDate].Replace("\"", "").Substring(0, 6), new SpeciesMonitorChina()
                                {
                                    bCrustal = strLineArray[iCrustal] == "" && strLineArray[iCrustal].Length == 0 || Convert.ToSingle(strLineArray[iCrustal]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iCrustal]),
                                    bEC = strLineArray[iEC] == "" && strLineArray[iEC].Length == 0 || Convert.ToSingle(strLineArray[iEC]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iEC]),
                                    bOC = strLineArray[iOC] == "" && strLineArray[iOC].Length == 0 ? float.NaN : Convert.ToSingle(strLineArray[iOC]),
                                    bSO4 = strLineArray[iSO4] == "" && strLineArray[iSO4].Length == 0 || Convert.ToSingle(strLineArray[iSO4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSO4]),
                                    bNO3 = strLineArray[iNO3] == "" && strLineArray[iNO3].Length == 0 || Convert.ToSingle(strLineArray[iNO3]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3]),
                                    bNH4 = strLineArray[iNH4] == "" && strLineArray[iNH4].Length == 0 || Convert.ToSingle(strLineArray[iNH4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNH4]),
                                    bH2O = strLineArray[iH2O] == "" && strLineArray[iH2O].Length == 0 || Convert.ToSingle(strLineArray[iH2O]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iH2O]),
                                    bOther = strLineArray[iOther] == "" && strLineArray[iOther].Length == 0 || Convert.ToSingle(strLineArray[iOther]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iOther]),
                                });
                            }
                            else
                            {
                                dicSpeciesMonitors.Add(strLineArray[iID].ToString().Replace("\"", ""), new PMMonitorChina()
                                {
                                    id = strLineArray[iID].Replace("\"", ""),
                                    type = strLineArray[iType].Replace("\"", ""),
                                    latitude = Convert.ToDouble(strLineArray[iLat]),
                                    longitude = Convert.ToDouble(strLineArray[iLong]),
                                    dicSpecies = new Dictionary<string, Dictionary<string, SpeciesMonitorChina>>(),
                                });
                                dicSpeciesMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicSpecies.Add("1", new Dictionary<string, SpeciesMonitorChina>());
                                dicSpeciesMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicSpecies.Add("2", new Dictionary<string, SpeciesMonitorChina>());
                                dicSpeciesMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicSpecies.Add("3", new Dictionary<string, SpeciesMonitorChina>());
                                dicSpeciesMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicSpecies.Add("4", new Dictionary<string, SpeciesMonitorChina>());
                                string quarter = "";
                                switch (strLineArray[iDate].Replace("\"", "").Substring(strLineArray[iDate].Replace("\"", "").Length - 2))
                                {
                                    case "01":
                                        quarter = "1";
                                        break;
                                    case "04":
                                        quarter = "2";
                                        break;
                                    case "07":
                                        quarter = "3";
                                        break;
                                    case "10":
                                        quarter = "4";
                                        break;
                                }
                                dicSpeciesMonitors[strLineArray[iID].ToString().Replace("\"", "")].dicSpecies[quarter].Add(strLineArray[iDate].Replace("\"", "").Substring(0, 6), new SpeciesMonitorChina()
                                {
                                    bCrustal = strLineArray[iCrustal] == "" && strLineArray[iCrustal].Length == 0 || Convert.ToSingle(strLineArray[iCrustal]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iCrustal]),
                                    bEC = strLineArray[iEC] == "" && strLineArray[iEC].Length == 0 || Convert.ToSingle(strLineArray[iEC]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iEC]),
                                    bOC = strLineArray[iOC] == "" && strLineArray[iOC].Length == 0 ? float.NaN : Convert.ToSingle(strLineArray[iOC]),
                                    bSO4 = strLineArray[iSO4] == "" && strLineArray[iSO4].Length == 0 || Convert.ToSingle(strLineArray[iSO4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSO4]),
                                    bNO3 = strLineArray[iNO3] == "" && strLineArray[iNO3].Length == 0 || Convert.ToSingle(strLineArray[iNO3]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3]),
                                    bNH4 = strLineArray[iNH4] == "" && strLineArray[iNH4].Length == 0 || Convert.ToSingle(strLineArray[iNH4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNH4]),
                                    bH2O = strLineArray[iH2O] == "" && strLineArray[iH2O].Length == 0 || Convert.ToSingle(strLineArray[iH2O]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iH2O]),
                                    bOther = strLineArray[iOther] == "" && strLineArray[iOther].Length == 0 || Convert.ToSingle(strLineArray[iOther]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iOther]),
                                });
                            }

                        }
                        //}
                        //catch
                        //{
                        //    error = "errorRow";
                        //}
                    }
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                }
                #endregion
                //if (!isOKinfilter)
                //    return "errorRow";
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }

        }

        public static bool AnnualVNA(ref Dictionary<string, Dictionary<string, float>> dicNeighborDistance, string quarter, string pollutantName, string interpolationMethod, double distanceInterpolation, ref double dVNA, Dictionary<string, float> fsoutStringSpecies, Dictionary<string, PMMonitorChina> dicSpeciesMonitors)
        {
            try
            {
                double distanceSpecies = 0, distanceSumSpecies = 0, vnaSum = 0;
                int n = 0;
                Dictionary<string, float> dic = new Dictionary<string, float>();
                switch (interpolationMethod)
                {
                    case "Equal Weighting of Monitors":
                        #region
                        //foreach (KeyValuePair<string, float> s in fsoutStringSpecies)
                        //{
                        //    string id = s.Key.Substring(0, s.Key.IndexOf(","));
                        //    if (s.Value > distanceInterpolation) continue;
                        //    try
                        //    {
                        //        //------------10个------------
                        //        #region
                        //        if (pollutantName == "so4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bSO4Mass))) continue;
                        //        if (pollutantName == "no3r" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bNO3rMass))) continue;
                        //        if (pollutantName == "ocb" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bOCBMass))) continue;
                        //        if (pollutantName == "ec" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bECMass))) continue;
                        //        if (pollutantName == "crustal" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bCrustalMass))) continue;
                        //        if (pollutantName == "salt" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bSaltMass))) continue;
                        //        if (pollutantName == "no3" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bNO3Mass))) continue;
                        //        if (pollutantName == "NH4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bNH4Mass))) continue;
                        //        if (pollutantName == "DON" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bDON))) continue;
                        //        if (pollutantName == "pm25" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicUnofficialPM.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicUnofficialPM[quarter]))) continue;
                        //        #endregion
                        //        if (dicNeighborDistance.ContainsKey(pollutantName + "," + quarter))
                        //        {
                        //            dicNeighborDistance[pollutantName + "," + quarter].Add(s.Key, s.Value);
                        //        }
                        //        else
                        //        {
                        //            dic.Add(s.Key, s.Value);
                        //            dicNeighborDistance.Add(pollutantName + "," + quarter, dic);
                        //        }
                        //        n++;
                        //        switch (pollutantName)
                        //        {
                        //            //---------10个-------
                        //            #region
                        //            case "so4":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bSO4Mass;
                        //                break;
                        //            case "no3r":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bNO3rMass;
                        //                break;
                        //            case "ocb":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bOCBMass;
                        //                break;
                        //            case "ec":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bECMass;
                        //                break;
                        //            case "crustal":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bCrustalMass;
                        //                break;
                        //            case "salt":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bSaltMass;
                        //                break;
                        //            case "no3":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bNO3Mass;
                        //                break;
                        //            case "NH4":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bNH4Mass;
                        //                break;
                        //            case "DON":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bDON;
                        //                break;
                        //            case "pm25":
                        //                vnaSum += dicSpeciesMonitors[id].dicUnofficialPM[quarter];
                        //                break;
                        //            #endregion
                        //        }
                        //    }
                        //    catch { }
                        //}
                        //try
                        //{
                        //    dVNA = Math.Round(Double.IsNaN(vnaSum / n) ? 0 : vnaSum / n, CommonClass.Species_calc_precision);
                        //}
                        //catch { }
                        #endregion
                        break;
                    case "Inverse Distance Weights":
                        #region
                        //foreach (KeyValuePair<string, float> s in fsoutStringSpecies)
                        //{
                        //    string id = s.Key.Substring(0, s.Key.IndexOf(","));
                        //    if (s.Value > distanceInterpolation) continue;
                        //    try
                        //    {
                        //        //------------10个------------
                        //        #region
                        //        if (pollutantName == "so4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bSO4Mass))) continue;
                        //        if (pollutantName == "no3r" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bNO3rMass))) continue;
                        //        if (pollutantName == "ocb" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bOCBMass))) continue;
                        //        if (pollutantName == "ec" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bECMass))) continue;
                        //        if (pollutantName == "crustal" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bCrustalMass))) continue;
                        //        if (pollutantName == "salt" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bSaltMass))) continue;
                        //        if (pollutantName == "no3" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bNO3Mass))) continue;
                        //        if (pollutantName == "NH4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bNH4Mass))) continue;
                        //        if (pollutantName == "DON" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bDON))) continue;
                        //        if (pollutantName == "pm25" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicUnofficialPM.ContainsKey(quarter) || float.IsNaN(dicSpeciesMonitors[id].dicUnofficialPM[quarter]))) continue;
                        //        #endregion
                        //        if (dicNeighborDistance.ContainsKey(pollutantName + "," + quarter))
                        //        {
                        //            dicNeighborDistance[pollutantName + "," + quarter].Add(s.Key, s.Value);
                        //        }
                        //        else
                        //        {
                        //            dic.Add(s.Key, s.Value);
                        //            dicNeighborDistance.Add(pollutantName + "," + quarter, dic);
                        //        }
                        //        distanceSpecies = s.Value == 0 ? 1 : Convert.ToSingle(1.0000 / s.Value);
                        //        distanceSumSpecies += distanceSpecies;
                        //        switch (pollutantName)
                        //        {
                        //            //---------10个
                        //            #region
                        //            case "so4":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bSO4Mass * distanceSpecies;
                        //                break;
                        //            case "no3r":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bNO3rMass * distanceSpecies;
                        //                break;
                        //            case "ocb":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bOCBMass * distanceSpecies;
                        //                break;
                        //            case "ec":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bECMass * distanceSpecies;
                        //                break;
                        //            case "crustal":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bCrustalMass * distanceSpecies;
                        //                break;
                        //            case "salt":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bSaltMass * distanceSpecies;
                        //                break;
                        //            case "no3":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bNO3Mass * distanceSpecies;
                        //                break;
                        //            case "NH4":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bNH4Mass * distanceSpecies;
                        //                break;
                        //            case "DON":
                        //                vnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bDON * distanceSpecies;
                        //                break;
                        //            case "pm25":
                        //                vnaSum += dicSpeciesMonitors[id].dicUnofficialPM[quarter] * distanceSpecies;
                        //                break;
                        //            #endregion
                        //        }
                        //    }
                        //    catch { }
                        //}
                        //try
                        //{
                        //    dVNA = Math.Round(Double.IsNaN(vnaSum / distanceSumSpecies) ? 0 : vnaSum / distanceSumSpecies, CommonClass.Species_calc_precision);
                        //}
                        //catch { }
                        #endregion
                        break;
                    case "Inverse Distance Squared Weights":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringSpecies)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                //------------10个------------
                                #region
                                if (pollutantName == "so4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bSO4))) continue;
                                if (pollutantName == "no3" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNO3))) continue;
                                if (pollutantName == "oc" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOC))) continue;
                                if (pollutantName == "ec" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bEC))) continue;
                                if (pollutantName == "crustal" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bCrustal))) continue;
                                if (pollutantName == "nh4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNH4))) continue;
                                if (pollutantName == "h2o" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bH2O))) continue;
                                if (pollutantName == "other" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOther))) continue;
                                if (pollutantName == "pm25" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicMonitorPMAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicMonitorPMAvg[quarter]))) continue;
                                #endregion
                                if (dicNeighborDistance.ContainsKey(pollutantName + "," + quarter))
                                {
                                    dicNeighborDistance[pollutantName + "," + quarter].Add(s.Key, s.Value);
                                }
                                else
                                {
                                    dic.Add(s.Key, s.Value);
                                    dicNeighborDistance.Add(pollutantName + "," + quarter, dic);
                                }
                                distanceSpecies = s.Value == 0 ? 1 : Convert.ToSingle(1.0000 / Math.Pow(s.Value, 2));
                                distanceSumSpecies += distanceSpecies;
                                switch (pollutantName)
                                {
                                    //---------10个
                                    #region
                                    case "so4":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bSO4 * distanceSpecies;
                                        break;
                                    case "no3":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNO3 * distanceSpecies;
                                        break;
                                    case "oc":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOC * distanceSpecies;
                                        break;
                                    case "ec":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bEC * distanceSpecies;
                                        break;
                                    case "crustal":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bCrustal * distanceSpecies;
                                        break;
                                    case "nh4":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNH4 * distanceSpecies;
                                        break;
                                    case "h2o":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bH2O * distanceSpecies;
                                        break;
                                    case "other":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOther * distanceSpecies;
                                        break;
                                    case "pm25":
                                        vnaSum += dicSpeciesMonitors[id].dicMonitorPMAvg[quarter] * distanceSpecies;
                                        break;
                                    #endregion
                                }
                            }
                            catch
                            {
                            }
                        }
                        try
                        {
                            double d = Double.IsNaN(vnaSum / distanceSumSpecies) ? 0 : vnaSum / distanceSumSpecies;
                            dVNA = Math.Round(Double.IsNaN(vnaSum / distanceSumSpecies) ? 0 : vnaSum / distanceSumSpecies, CommonClass.Species_calc_precision);
                        }
                        catch { }
                        #endregion
                        break;
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool AnnualEVNA(ref Dictionary<string, Dictionary<string, float>> dicNeighborDistance, string quarter, string pollutantName, Dictionary<string, Dictionary<string, ModelDataSpecies>> dicGradAdjValues, string interpolationMethod, double distanceInterpolation, ref double dEVNA, Dictionary<string, float> fsoutStringSpecies, Dictionary<string, PMMonitorChina> dicSpeciesMonitors)
        {
            try
            {
                double distanceSpecies = 0, distanceSumSpecies = 0, gvnaSum = 0;
                int n = 0;
                Dictionary<string, float> dic = new Dictionary<string, float>();
                switch (interpolationMethod)
                {
                    case "Equal Weighting of Monitors":
                        #region
                        //foreach (KeyValuePair<string, float> s in fsoutStringSpecies)
                        //{
                        //    string id = s.Key.Substring(0, s.Key.IndexOf(","));
                        //    if (s.Value > distanceInterpolation) continue;
                        //    try
                        //    {
                        //        //------------10个------------
                        //        #region
                        //        if (pollutantName == "so4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bSO4Mass))) continue;
                        //        if (pollutantName == "no3r" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bNO3rMass))) continue;
                        //        if (pollutantName == "ocb" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bOCBMass))) continue;
                        //        if (pollutantName == "ec" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bECMass))) continue;
                        //        if (pollutantName == "crustal" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bCrustalMass))) continue;
                        //        if (pollutantName == "salt" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bSaltMass))) continue;
                        //        if (pollutantName == "no3" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bNO3Mass))) continue;
                        //        if (pollutantName == "NH4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bNH4Mass))) continue;
                        //        if (pollutantName == "DON" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bDON))) continue;
                        //        if (pollutantName == "pm25" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicUnofficialPM.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicUnofficialPM[quarter]))) continue;
                        //        #endregion
                        //        if (dicNeighborDistance.ContainsKey(pollutantName + "," + quarter))
                        //        {
                        //            dicNeighborDistance[pollutantName + "," + quarter].Add(s.Key, s.Value);
                        //        }
                        //        else
                        //        {
                        //            dic.Add(s.Key, s.Value);
                        //            dicNeighborDistance.Add(pollutantName + "," + quarter, dic);
                        //        }
                        //        n++;
                        //        switch (pollutantName)
                        //        {
                        //            //---------10个-------
                        //            #region
                        //            case "so4":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bSO4Mass * dicGradAdjValues[s.Key][quarter].so4;
                        //                break;
                        //            case "no3r":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bNO3rMass * dicGradAdjValues[s.Key][quarter].no3;
                        //                break;
                        //            case "ocb":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bOCBMass * dicGradAdjValues[s.Key][quarter].oc;
                        //                break;
                        //            case "ec":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bECMass * dicGradAdjValues[s.Key][quarter].ec;
                        //                break;
                        //            case "crustal":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bCrustalMass * dicGradAdjValues[s.Key][quarter].crustal;
                        //                break;
                        //            case "salt":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bSaltMass * dicGradAdjValues[s.Key][quarter].salt;
                        //                break;
                        //            case "no3":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bNO3Mass * dicGradAdjValues[s.Key][quarter].no3;
                        //                break;
                        //            case "NH4":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bNH4Mass * dicGradAdjValues[s.Key][quarter].nh4;
                        //                break;
                        //            case "DON":
                        //                gvnaSum = dicSpeciesMonitors[id].dicSpecies[quarter].bDON;
                        //                break;
                        //            case "pm25":
                        //                gvnaSum += dicSpeciesMonitors[id].dicUnofficialPM[quarter] * dicGradAdjValues[s.Key][quarter].pm25;
                        //                break;
                        //            #endregion
                        //        }
                        //    }
                        //    catch { }
                        //}
                        //try
                        //{
                        //    dEVNA = Math.Round(Double.IsNaN(gvnaSum / n) ? 0 : gvnaSum / n, CommonClass.Species_calc_precision);
                        //}
                        //catch
                        //{
                        //}
                        #endregion
                        break;
                    case "Inverse Distance Weights":
                        #region
                        //foreach (KeyValuePair<string, float> s in fsoutStringSpecies)
                        //{
                        //    string id = s.Key.Substring(0, s.Key.IndexOf(","));
                        //    if (s.Value > distanceInterpolation) continue;
                        //    try
                        //    {
                        //        //------------10个------------
                        //        #region
                        //        if (pollutantName == "so4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bSO4Mass))) continue;
                        //        if (pollutantName == "no3r" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bNO3rMass))) continue;
                        //        if (pollutantName == "ocb" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bOCBMass))) continue;
                        //        if (pollutantName == "ec" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bECMass))) continue;
                        //        if (pollutantName == "crustal" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bCrustalMass))) continue;
                        //        if (pollutantName == "salt" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bSaltMass))) continue;
                        //        if (pollutantName == "no3" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bNO3Mass))) continue;
                        //        if (pollutantName == "NH4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bNH4Mass))) continue;
                        //        if (pollutantName == "DON" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpecies.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpecies[quarter].bDON))) continue;
                        //        if (pollutantName == "pm25" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicUnofficialPM.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicUnofficialPM[quarter]))) continue;
                        //        #endregion
                        //        if (dicNeighborDistance.ContainsKey(pollutantName + "," + quarter))
                        //        {
                        //            dicNeighborDistance[pollutantName + "," + quarter].Add(s.Key, s.Value);
                        //        }
                        //        else
                        //        {
                        //            dic.Add(s.Key, s.Value);
                        //            dicNeighborDistance.Add(pollutantName + "," + quarter, dic);
                        //        }
                        //        distanceSpecies = s.Value == 0 ? 1 : 1.0000 / s.Value;
                        //        distanceSumSpecies += distanceSpecies;
                        //        switch (pollutantName)
                        //        {
                        //            //---------10个
                        //            #region
                        //            case "so4":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bSO4Mass * distanceSpecies * dicGradAdjValues[s.Key][quarter].so4;
                        //                break;
                        //            case "no3r":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bNO3rMass * distanceSpecies * dicGradAdjValues[s.Key][quarter].no3;
                        //                break;
                        //            case "ocb":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bOCBMass * distanceSpecies * dicGradAdjValues[s.Key][quarter].oc;
                        //                break;
                        //            case "ec":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bECMass * distanceSpecies * dicGradAdjValues[s.Key][quarter].ec;
                        //                break;
                        //            case "crustal":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bCrustalMass * distanceSpecies * dicGradAdjValues[s.Key][quarter].crustal;
                        //                break;
                        //            case "salt":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bSaltMass * distanceSpecies * dicGradAdjValues[s.Key][quarter].salt;
                        //                break;
                        //            case "no3":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bNO3Mass * distanceSpecies * dicGradAdjValues[s.Key][quarter].no3;
                        //                break;
                        //            case "NH4":
                        //                gvnaSum += dicSpeciesMonitors[id].dicSpecies[quarter].bNH4Mass * distanceSpecies * dicGradAdjValues[s.Key][quarter].nh4;
                        //                break;
                        //            case "DON":
                        //                gvnaSum = dicSpeciesMonitors[id].dicSpecies[quarter].bDON * distanceSpecies;
                        //                break;
                        //            case "pm25":
                        //                gvnaSum += dicSpeciesMonitors[id].dicUnofficialPM[quarter] * distanceSpecies * dicGradAdjValues[s.Key][quarter].pm25;
                        //                break;
                        //            #endregion
                        //        }
                        //    }
                        //    catch { }
                        //}
                        //try
                        //{
                        //    dEVNA = Math.Round(Double.IsNaN(gvnaSum / distanceSumSpecies) ? 0 : Convert.ToSingle(gvnaSum / distanceSumSpecies), CommonClass.Species_calc_precision);
                        //}
                        //catch { }
                        #endregion
                        break;
                    case "Inverse Distance Squared Weights":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringSpecies)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                //------------10个------------
                                #region
                                if (pollutantName == "so4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bSO4))) continue;
                                if (pollutantName == "no3" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNO3))) continue;
                                if (pollutantName == "oc" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOC))) continue;
                                if (pollutantName == "ec" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bEC))) continue;
                                if (pollutantName == "crustal" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bCrustal))) continue;
                                if (pollutantName == "nh4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNH4))) continue;
                                if (pollutantName == "h2o" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bH2O))) continue;
                                if (pollutantName == "other" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOther))) continue;
                                if (pollutantName == "pm25" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicMonitorPMAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicMonitorPMAvg[quarter]))) continue;
                                #endregion
                                if (dicNeighborDistance.ContainsKey(pollutantName + "," + quarter))
                                {
                                    dicNeighborDistance[pollutantName + "," + quarter].Add(s.Key, s.Value);
                                }
                                else
                                {
                                    dic.Add(s.Key, s.Value);
                                    dicNeighborDistance.Add(pollutantName + "," + quarter, dic);
                                }
                                distanceSpecies = s.Value == 0 ? 1 : 1.0000 / Math.Pow(s.Value, 2);
                                distanceSumSpecies += distanceSpecies;
                                switch (pollutantName)
                                {
                                    //---------10个
                                    #region
                                    case "so4":
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bSO4 * distanceSpecies * dicGradAdjValues[s.Key][quarter].so4;
                                        break;
                                    case "no3":
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNO3 * distanceSpecies * dicGradAdjValues[s.Key][quarter].no3;
                                        break;
                                    case "oc":
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOC * distanceSpecies * dicGradAdjValues[s.Key][quarter].oc;
                                        break;
                                    case "ec":
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bEC * distanceSpecies * dicGradAdjValues[s.Key][quarter].ec;
                                        break;
                                    case "crustal":
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bCrustal * distanceSpecies * dicGradAdjValues[s.Key][quarter].crustal;
                                        break;
                                    case "nh4":
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNH4 * distanceSpecies * dicGradAdjValues[s.Key][quarter].no3;
                                        break;
                                    case "h2o":
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bH2O * distanceSpecies;
                                        break;
                                    case "other":
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOther * distanceSpecies;
                                        break;
                                    case "pm25":
                                        gvnaSum += dicSpeciesMonitors[id].dicMonitorPMAvg[quarter] * distanceSpecies * dicGradAdjValues[s.Key][quarter].pm25;
                                        break;
                                    #endregion
                                }
                            }
                            catch
                            {
                            }
                        }
                        try
                        {
                            dEVNA = Math.Round(Double.IsNaN(gvnaSum / distanceSumSpecies) ? 0 : Convert.ToSingle(gvnaSum / distanceSumSpecies), CommonClass.Species_calc_precision);
                        }
                        catch { }
                        #endregion
                        break;
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool AnnualVNAEVNA(ref Dictionary<string, Dictionary<string, float>> dicNeighborDistance, string quarter, string pollutantName, Dictionary<string, Dictionary<string, ModelDataSpecies>> dicGradAdjValues, string interpolationMethod, double distanceInterpolation, ref double dVNA, ref double dEVNA, Dictionary<string, float> fsoutStringSpecies, Dictionary<string, PMMonitorChina> dicSpeciesMonitors)
        {
            try
            {
                double distanceSpecies = 0, distanceSumSpecies = 0, vnaSum = 0, gvnaSum = 0;
                int n = 0;
                Dictionary<string, float> dic = new Dictionary<string, float>();
                switch (interpolationMethod)
                {
                    case "Equal Weighting of Monitors":

                        break;
                    case "Inverse Distance Weights":

                        break;
                    case "Inverse Distance Squared Weights":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringSpecies)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                //------------10个------------
                                #region
                                if (pollutantName == "so4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bSO4))) continue;
                                if (pollutantName == "no3" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNO3))) continue;
                                if (pollutantName == "oc" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOC))) continue;
                                if (pollutantName == "ec" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bEC))) continue;
                                if (pollutantName == "crustal" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bCrustal))) continue;
                                if (pollutantName == "nh4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNH4))) continue;
                                if (pollutantName == "h2o" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bH2O))) continue;
                                if (pollutantName == "other" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOther))) continue;
                                if (pollutantName == "pm25" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicMonitorPMAvg.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicMonitorPMAvg[quarter]))) continue;
                                #endregion
                                if (dicNeighborDistance.ContainsKey(pollutantName + "," + quarter))
                                {
                                    dicNeighborDistance[pollutantName + "," + quarter].Add(s.Key, s.Value);
                                }
                                else
                                {
                                    dic.Add(s.Key, s.Value);
                                    dicNeighborDistance.Add(pollutantName + "," + quarter, dic);
                                }
                                distanceSpecies = s.Value == 0 ? 1 : 1.0000 / Math.Pow(s.Value, 2);
                                distanceSumSpecies += distanceSpecies;
                                switch (pollutantName)
                                {
                                    //---------10个
                                    #region
                                    case "so4":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bSO4 * distanceSpecies;
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bSO4 * distanceSpecies * dicGradAdjValues[s.Key][quarter].so4;
                                        break;
                                    case "no3":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNO3 * distanceSpecies;
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNO3 * distanceSpecies * dicGradAdjValues[s.Key][quarter].no3;
                                        break;
                                    case "oc":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOC * distanceSpecies;
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOC * distanceSpecies * dicGradAdjValues[s.Key][quarter].oc;
                                        break;
                                    case "ec":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bEC * distanceSpecies;
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bEC * distanceSpecies * dicGradAdjValues[s.Key][quarter].ec;
                                        break;
                                    case "crustal":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bCrustal * distanceSpecies;
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bCrustal * distanceSpecies * dicGradAdjValues[s.Key][quarter].crustal;
                                        break;
                                    case "nh4":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNH4 * distanceSpecies;
                                        gvnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNH4 * distanceSpecies * dicGradAdjValues[s.Key][quarter].no3;
                                        break;
                                    case "h2o":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bH2O * distanceSpecies;
                                        gvnaSum = vnaSum;
                                        break;
                                    case "other":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOther * distanceSpecies;
                                        gvnaSum = vnaSum;
                                        break;
                                    case "pm25":
                                        vnaSum += dicSpeciesMonitors[id].dicMonitorPMAvg[quarter] * distanceSpecies;
                                        gvnaSum += dicSpeciesMonitors[id].dicMonitorPMAvg[quarter] * distanceSpecies * dicGradAdjValues[s.Key][quarter].pm25;
                                        break;
                                    #endregion
                                }
                            }
                            catch
                            {
                            }
                        }
                        try
                        {
                            dVNA = Math.Round(Double.IsNaN(vnaSum / distanceSumSpecies) ? 0 : vnaSum / distanceSumSpecies, CommonClass.Species_calc_precision);
                            dEVNA = Math.Round(Double.IsNaN(gvnaSum / distanceSumSpecies) ? 0 : gvnaSum / distanceSumSpecies, CommonClass.Species_calc_precision);
                        }
                        catch { }
                        #endregion
                        break;
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        #region Nearest Site
        public static bool AnnualNearestSite(
            ref Dictionary<string, Dictionary<string, float>> dicNeighborDistance,
            string quarter,
            string pollutantName,
            double distanceInterpolation,
            ref double dNearestSite,
            Dictionary<string, float> fsoutStringSpecies,
            Dictionary<string, PMMonitorChina> dicSpeciesMonitors)
        {
            try
            {
                var dic = new Dictionary<string, float>();
                var id = string.Empty;
                foreach (var s in fsoutStringSpecies)
                {
                    id = s.Key.Substring(0, s.Key.IndexOf(",", StringComparison.Ordinal));
                    if (s.Value > distanceInterpolation) continue;
                    //------------10个------------

                    #region

                    if (pollutantName == "so4" &&
                        (!dicSpeciesMonitors.ContainsKey(id) ||
                         !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) ||
                         double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bSO4))) continue;
                    if (pollutantName == "no3" &&
                        (!dicSpeciesMonitors.ContainsKey(id) ||
                         !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) ||
                         double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNO3))) continue;
                    if (pollutantName == "oc" &&
                        (!dicSpeciesMonitors.ContainsKey(id) ||
                         !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) ||
                         double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOC))) continue;
                    if (pollutantName == "ec" &&
                        (!dicSpeciesMonitors.ContainsKey(id) ||
                         !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) ||
                         double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bEC))) continue;
                    if (pollutantName == "crustal" &&
                        (!dicSpeciesMonitors.ContainsKey(id) ||
                         !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) ||
                         double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bCrustal))) continue;
                    if (pollutantName == "nh4" &&
                        (!dicSpeciesMonitors.ContainsKey(id) ||
                         !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) ||
                         double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNH4))) continue;
                    if (pollutantName == "h2o" &&
                        (!dicSpeciesMonitors.ContainsKey(id) ||
                         !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) ||
                         double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bH2O))) continue;
                    if (pollutantName == "other" &&
                        (!dicSpeciesMonitors.ContainsKey(id) ||
                         !dicSpeciesMonitors[id].dicSpeciesAvg.ContainsKey(quarter) ||
                         double.IsNaN(dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOther))) continue;
                    if (pollutantName == "pm25" &&
                        (!dicSpeciesMonitors.ContainsKey(id) ||
                         !dicSpeciesMonitors[id].dicMonitorPMAvg.ContainsKey(quarter) ||
                         double.IsNaN(dicSpeciesMonitors[id].dicMonitorPMAvg[quarter]))) continue;
                    #endregion

                    if (dicNeighborDistance.ContainsKey(pollutantName + "," + quarter))
                    {
                        if (!dicNeighborDistance[pollutantName + "," + quarter].ContainsKey(s.Key))
                        {
                            dicNeighborDistance[pollutantName + "," + quarter].Add(s.Key, s.Value);
                        }
                    }
                    else
                    {
                        dic.Add(s.Key, s.Value);
                        dicNeighborDistance.Add(pollutantName + "," + quarter, dic);
                    }
                } // foreach

                // 找到周围距离最近的点
                var minItem = fsoutStringSpecies.OrderBy(t => t.Value).FirstOrDefault();
                if (minItem.Equals(default(KeyValuePair<string, double>)))
                {
                    dNearestSite = 0d;
                    return false;
                }
                var minKey = minItem.Key;
                id = minKey.Substring(0, minKey.IndexOf(",", StringComparison.Ordinal));
                switch (pollutantName)
                {
                    //---------10个

                    #region

                    case "so4":
                        dNearestSite = dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bSO4;
                        break;
                    case "no3":
                        dNearestSite = dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNO3;
                        break;
                    case "oc":
                        dNearestSite = dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOC;
                        break;
                    case "ec":
                        dNearestSite = dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bEC;
                        break;
                    case "crustal":
                        dNearestSite = dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bCrustal;
                        break;
                    case "nh4":
                        dNearestSite = dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bNH4;
                        break;
                    case "h2o":
                        dNearestSite = dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bH2O;
                        break;
                    case "other":
                        dNearestSite = dicSpeciesMonitors[id].dicSpeciesAvg[quarter].bOther;
                        break;
                    case "pm25":
                        dNearestSite = dicSpeciesMonitors[id].dicMonitorPMAvg[quarter];
                        break;

                        #endregion
                }
                dNearestSite = Math.Round(double.IsNaN(dNearestSite) ? 0d : dNearestSite, CommonClass.Species_calc_precision);
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex); 
            }
            dNearestSite = 0d;
            return false;
        }
        #endregion

        public static bool GetSpeciesFractionValuesVNAEVNA(AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration, ref SpecFracPMChina sfAnnualPM, double vnaCrustal, double vnaEC, double vnaNH4, double vnaSO4, double vnaOC, double vnaOther, double vnaPBW, double vnaNO3, double vnaPM)
        {
            try
            {
                sfAnnualPM = new SpecFracPMChina
                {
                    iSO4 = vnaSO4,
                    iOC = vnaOC,
                    iEC = vnaEC,
                    iCrustal = vnaCrustal,
                    iNH4 = vnaNH4,
                    iNO3 = vnaNO3,
                    iOther = vnaOther,
                    iWater = vnaPBW
                };
                //------------adjustment ocmmb--------------
                #region
                double oc_floor = 0, nonBlankMass = 0, oc_max = 0, oc_ceiling = 0, oc = 0, checkOC = 0, change = 0;
                //当vna得出的pm为0时，直接将所有species之和对其赋值
                vnaPM = vnaPM == 0 ? (vnaCrustal + vnaSO4 + vnaNO3 + vnaNH4 + vnaPBW + vnaOther + vnaEC + vnaOC) : vnaPM;
                nonBlankMass = vnaPM - 0;
                oc = nonBlankMass - (vnaCrustal + vnaSO4 + vnaNO3 + vnaNH4 + vnaPBW + vnaOther + vnaEC);
                oc_floor = 1 * vnaOC;
                oc_max = Math.Max(oc, oc_floor);
                oc_ceiling = 0.8 * nonBlankMass;
                vnaOC = Math.Round(Math.Min(oc_max, oc_ceiling), CommonClass.Species_calc_precision);
                //--------当各species的和大于或小于NonBlankMass时调整OCMmb-------------SO4 + NO3r + NH4r + PBW + crustal + EC + OCMmb_calc + salt
                checkOC = nonBlankMass - (vnaCrustal + vnaSO4 + vnaNO3 + vnaNH4 + vnaPBW + vnaOther + vnaEC + vnaOC);
                change = Double.IsNaN(checkOC / (vnaCrustal + vnaSO4 + vnaNO3 + vnaNH4 + vnaPBW + vnaOther + vnaEC)) || Double.IsInfinity(checkOC / (vnaCrustal + vnaSO4 + vnaNO3 + vnaNH4 + vnaPBW + vnaOther + vnaEC)) ? 0 : checkOC / (vnaCrustal + vnaSO4 + vnaNO3 + vnaNH4 + vnaPBW + vnaOther + vnaEC);
                vnaCrustal = Math.Round((1 + change) * vnaCrustal, CommonClass.Species_calc_precision);
                vnaEC = Math.Round((1 + change) * vnaEC, CommonClass.Species_calc_precision);
                vnaNH4 = Math.Round((1 + change) * vnaNH4, CommonClass.Species_calc_precision);
                vnaNO3 = Math.Round((1 + change) * vnaNO3, CommonClass.Species_calc_precision);
                vnaSO4 = Math.Round((1 + change) * vnaSO4, CommonClass.Species_calc_precision);
                vnaOther = Math.Round((1 + change) * vnaOther, CommonClass.Species_calc_precision);
                vnaPBW = Math.Round((1 + change) * vnaPBW, CommonClass.Species_calc_precision);
                #endregion
                #region species fractions
                float nonBlankMassPM = Convert.ToSingle(vnaSO4 + vnaOther + vnaNO3 + vnaNH4 + vnaOC + vnaPBW + vnaCrustal + vnaEC);
                sfAnnualPM.pm25Frac = Math.Round(nonBlankMassPM, CommonClass.Pm_defaultformat);
                sfAnnualPM.fCrustal = Math.Round(vnaCrustal / nonBlankMassPM, CommonClass.Species_fraction_precision);
                sfAnnualPM.fEC = Math.Round(vnaEC / nonBlankMassPM, CommonClass.Species_fraction_precision);
                sfAnnualPM.fNH4 = Math.Round(vnaNH4 / nonBlankMassPM, CommonClass.Species_fraction_precision);
                sfAnnualPM.fOC = Math.Round(vnaOC / nonBlankMassPM, CommonClass.Species_fraction_precision);
                sfAnnualPM.fNO3 = Math.Round(vnaNO3 / nonBlankMassPM, CommonClass.Species_fraction_precision);
                sfAnnualPM.fWater = Math.Round(vnaPBW / nonBlankMassPM, CommonClass.Species_fraction_precision);
                sfAnnualPM.fOther = Math.Round(vnaOther / nonBlankMassPM, CommonClass.Species_fraction_precision);
                sfAnnualPM.fSO4 = Math.Round(vnaSO4 / nonBlankMassPM, CommonClass.Species_fraction_precision);
                //sfAnnualPM.blankMass = Math.Round(Convert.ToDouble(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass), CommonClass.Species_calc_precision);
                #endregion
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetSpeciesFractionValuesPointEstimates(AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration, ref SpecFracPMChina sfAnnualPM, double vnaCrustal, double vnaEC, double vnaNH4, double vnaSO4, double vnaOC, double vnaNO3, double vnaOther, double vnaH2O, double pmValue)
        {
            try
            {
                sfAnnualPM = new SpecFracPMChina()
                {
                    iCrustal = vnaCrustal,
                    iNH4 = vnaNH4,
                    iEC = vnaEC,
                    iNO3 = vnaNO3,
                    iSO4 = vnaSO4,
                    iOC = vnaOC,
                    iWater = vnaH2O,
                    iOther = vnaOther,
                    pm25Frac = pmValue,
                };
                //-----利用调整之后的值计算spec frac-----------
                double nonBlankMass = 0;
                nonBlankMass = vnaCrustal + vnaEC + vnaNH4 + vnaSO4 + vnaOC + vnaNO3 + vnaOther + vnaH2O - 0;
                sfAnnualPM.fCrustal = Math.Round(vnaCrustal / nonBlankMass, CommonClass.Species_fraction_precision);
                sfAnnualPM.fNH4 = Math.Round(vnaNH4 / nonBlankMass, CommonClass.Species_fraction_precision);
                sfAnnualPM.fEC = Math.Round(vnaEC / nonBlankMass, CommonClass.Species_fraction_precision);
                sfAnnualPM.fNO3 = Math.Round(vnaNO3 / nonBlankMass, CommonClass.Species_fraction_precision);
                sfAnnualPM.fSO4 = Math.Round(vnaSO4 / nonBlankMass, CommonClass.Species_fraction_precision);
                sfAnnualPM.fOther = Math.Round(vnaOther / nonBlankMass, CommonClass.Species_fraction_precision);
                sfAnnualPM.fOC = Math.Round(vnaOC / nonBlankMass, CommonClass.Species_fraction_precision);
                sfAnnualPM.fWater = Math.Round(vnaH2O / nonBlankMass, CommonClass.Species_fraction_precision);
                //sfAnnualPM.blankMass = Math.Round(Convert.ToDouble(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass), CommonClass.Species_calc_precision);
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetGridCellMonitors(ref Dictionary<string, string> dicMonitorInModel, Dictionary<string, PmModelDataOutput> dicQuarterlyModelDataPM, Dictionary<string, PMMonitorChina> dicPMMonitor)
        {
            try
            {
                //得到species monitor属于哪个网格--------简单的方法可以判断以最近的点作为它的网格。首先可以求出第一个网格的大小，在小于一倍网格宽度和长度的最大值求最近点
                double dFirst = dicQuarterlyModelDataPM.First().Value.longitude, dLon = 0, dLat = 0;
                int iFirst = Convert.ToInt32(dicQuarterlyModelDataPM.First().Key);
                if (dicQuarterlyModelDataPM.ContainsKey((((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()))
                {
                    dLon = Math.Abs(dicQuarterlyModelDataPM[(((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()].longitude -
                            dicQuarterlyModelDataPM.First().Value.longitude
                            );
                    dLat = Math.Abs(dicQuarterlyModelDataPM[(((iFirst / 1000)) * 1000 + iFirst % 1000 + 1).ToString()].lat -
                        dicQuarterlyModelDataPM.First().Value.lat
                        );
                    dLon *= 2; dLat *= 2;
                }

                //---------计算两个网格之内；然后属于哪个的网格，根据距离判断属于哪个网格
                foreach (KeyValuePair<string, PMMonitorChina> k in dicPMMonitor)
                {
                    try
                    {
                        var query = dicQuarterlyModelDataPM.Where(p => Math.Abs(p.Value.longitude - k.Value.longitude) < dLon && Math.Abs(p.Value.lat - k.Value.latitude) < dLat).ToList();
                        string sModelIDTemp = "";
                        if (query.Count() > 0)
                        {
                            DotSpatial.Topology.Coordinate coor = new DotSpatial.Topology.Coordinate(k.Value.longitude, k.Value.latitude);
                            sModelIDTemp = query.OrderBy(p => CommonClass.getDistanceFrom2Point(p.Value.longitude, p.Value.lat, k.Value.longitude, k.Value.latitude)).First().Key;
                        }
                        else
                        {
                            sModelIDTemp = dicQuarterlyModelDataPM.OrderBy(p => CommonClass.getDistanceFrom2Point(p.Value.longitude, p.Value.lat, k.Value.longitude, k.Value.latitude)).First().Key;
                        }
                        k.Value.gridcell = sModelIDTemp;
                        dicMonitorInModel.Add(k.Key, sModelIDTemp);
                    }
                    catch
                    {
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetGridCellSpeciatedMonitors(ref Dictionary<string, string> dicMonitorInModelSpecies, Dictionary<string, PmModelDataOutput> dicQuarterlyModelDataPM, Dictionary<string, PMMonitorChina> dicSpeciesMonitors)
        {
            try
            {
                //得到species monitor属于哪个网格--------简单的方法可以判断以最近的点作为它的网格。首先可以求出第一个网格的大小，在小于一倍网格宽度和长度的最大值求最近点
                double dFirst = dicQuarterlyModelDataPM.First().Value.longitude, dLon = 0, dLat = 0;
                int iFirst = Convert.ToInt32(dicQuarterlyModelDataPM.First().Key);
                if (dicQuarterlyModelDataPM.ContainsKey((((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()))
                {
                    dLon = Math.Abs(dicQuarterlyModelDataPM[(((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()].longitude -
                            dicQuarterlyModelDataPM.First().Value.longitude
                            );
                    dLat = Math.Abs(dicQuarterlyModelDataPM[(((iFirst / 1000)) * 1000 + iFirst % 1000 + 1).ToString()].lat -
                        dicQuarterlyModelDataPM.First().Value.lat
                        );
                    dLon *= 2; dLat *= 2;
                }

                //---------计算两个网格之内；然后属于哪个的网格，根据距离判断属于哪个网格
                foreach (KeyValuePair<string, PMMonitorChina> k in dicSpeciesMonitors)
                {
                    try
                    {
                        var query = dicQuarterlyModelDataPM.Where(p => Math.Abs(p.Value.longitude - k.Value.longitude) < dLon && Math.Abs(p.Value.lat - k.Value.latitude) < dLat).ToList();
                        string sModelIDTemp = "";
                        if (query.Count() > 0)
                        {
                            DotSpatial.Topology.Coordinate coor = new DotSpatial.Topology.Coordinate(k.Value.longitude, k.Value.latitude);
                            sModelIDTemp = query.OrderBy(p => CommonClass.getDistanceFrom2Point(p.Value.longitude, p.Value.lat, k.Value.longitude, k.Value.latitude)).First().Key;
                        }
                        else
                        {
                            sModelIDTemp = dicQuarterlyModelDataPM.OrderBy(p => CommonClass.getDistanceFrom2Point(p.Value.longitude, p.Value.lat, k.Value.longitude, k.Value.latitude)).First().Key;
                        }
                        k.Value.gridcell = sModelIDTemp;
                        dicMonitorInModelSpecies.Add(k.Key, sModelIDTemp);
                    }
                    catch
                    {
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool SaveAnnualPMPoint(BaseScenario baseScenario, Dictionary<string, PMPointChina> dicAnnualPoint, bool useSpecies)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
                return false;
            try
            {
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                DataTable dt = new DataTable();
                dt.Columns.Add("_id");
                dt.Columns.Add("_type");
                dt.Columns.Add("LOCATION_NAME");
                dt.Columns.Add("STATION_NAME");
                dt.Columns.Add("monitor_lat");
                dt.Columns.Add("monitor_long");
                dt.Columns.Add("monitor_gridcell");
                dt.Columns.Add("b_pm25_ann_DV");
                dt.Columns.Add("f_pm25_ann_DV");
                if (useSpecies)
                {
                    //dt.Columns.Add("b_blank_mass");
                    dt.Columns.Add("b_crustal_mass");
                    dt.Columns.Add("b_EC_mass");
                    dt.Columns.Add("b_NH4_mass");
                    dt.Columns.Add("b_OC_mass");
                    dt.Columns.Add("b_SO4_mass");
                    dt.Columns.Add("b_NO3_mass");
                    dt.Columns.Add("b_water_mass");
                    dt.Columns.Add("b_other_mass");
                    //dt.Columns.Add("b_salt_mass");
                    //dt.Columns.Add("f_blank_mass");
                    dt.Columns.Add("f_crustal_mass");
                    dt.Columns.Add("f_EC_mass");
                    dt.Columns.Add("f_NH4_mass");
                    dt.Columns.Add("f_OC_mass");
                    dt.Columns.Add("f_SO4_mass");
                    dt.Columns.Add("f_NO3_mass");
                    dt.Columns.Add("f_water_mass");
                    dt.Columns.Add("f_other_mass");
                    //dt.Columns.Add("f_salt_mass");
                    dt.Columns.Add("rrf_crustal");
                    dt.Columns.Add("rrf_ec");
                    dt.Columns.Add("rrf_nh4");
                    dt.Columns.Add("rrf_oc");
                    dt.Columns.Add("rrf_so4");
                    dt.Columns.Add("rrf_no3");
                    dt.Columns.Add("rrf_water");
                    dt.Columns.Add("rrf_other");
                }
                //dicAnnualPoint = dicAnnualPoint.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                foreach (KeyValuePair<string, PMPointChina> k in dicAnnualPoint)
                {
                    DataRow dr = dt.NewRow();
                    dr[0] = k.Value.id;
                    dr[1] = k.Value.type;
                    dr[2] = k.Value.locationName;
                    dr[3] = k.Value.stationName;
                    dr[4] = Math.Round(k.Value.monitorLat, 6);
                    dr[5] = Math.Round(k.Value.monitorLong, 6);
                    dr[6] = k.Value.monitorGridcell;
                    dr[7] = CommonClass.ToFixed(k.Value.bPMDV, 2);
                    dr[8] = CommonClass.ToFixed(k.Value.fPMDV, 2);
                    if (useSpecies)
                    {
                        //dr[9] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                        dr[9] = Math.Round(k.Value.bCrustal, CommonClass.Species_calc_precision);
                        dr[10] = Math.Round(k.Value.bEC, CommonClass.Species_calc_precision);
                        dr[11] = Math.Round(k.Value.bNH4, CommonClass.Species_calc_precision);
                        dr[12] = Math.Round(k.Value.bOC, CommonClass.Species_calc_precision);
                        dr[13] = Math.Round(k.Value.bSO4, CommonClass.Species_calc_precision);
                        dr[14] = Math.Round(k.Value.bNO3, CommonClass.Species_calc_precision);
                        dr[15] = Math.Round(k.Value.bWater, CommonClass.Species_calc_precision);
                        dr[16] = Math.Round(k.Value.bOther, CommonClass.Species_calc_precision);
                        //dr[18] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                        dr[17] = Math.Round(k.Value.fCrustal, CommonClass.Species_calc_precision);
                        dr[18] = Math.Round(k.Value.fEC, CommonClass.Species_calc_precision);
                        dr[19] = Math.Round(k.Value.fNH4, CommonClass.Species_calc_precision);
                        dr[20] = Math.Round(k.Value.fOC, CommonClass.Species_calc_precision);
                        dr[21] = Math.Round(k.Value.fSO4, CommonClass.Species_calc_precision);
                        dr[22] = Math.Round(k.Value.fNO3, CommonClass.Species_calc_precision);
                        dr[23] = Math.Round(k.Value.fWater, CommonClass.Species_calc_precision);
                        dr[24] = Math.Round(k.Value.fOther, CommonClass.Species_calc_precision);
                        dr[25] = Double.IsNaN(k.Value.rrfCrustal) ? -9 : Math.Round(k.Value.rrfCrustal, 4);
                        dr[26] = Double.IsNaN(k.Value.rrfEC) ? -9 : Math.Round(k.Value.rrfEC, 4);
                        dr[27] = Double.IsNaN(k.Value.rrfNH4) ? -9 : Math.Round(k.Value.rrfNH4, 4);
                        dr[28] = Double.IsNaN(k.Value.rrfOC) ? -9 : Math.Round(k.Value.rrfOC, 4);
                        dr[29] = Double.IsNaN(k.Value.rrfSO4) ? -9 : Math.Round(k.Value.rrfSO4, 4);
                        dr[30] = Double.IsNaN(k.Value.rrfNO3) ? -9 : Math.Round(k.Value.rrfNO3, 4);
                        dr[31] = Double.IsNaN(k.Value.rrfWater) ? -9 : Math.Round(k.Value.rrfWater, 4);
                        dr[32] = Double.IsNaN(k.Value.rrfOther) ? -9 : Math.Round(k.Value.rrfOther, 4);
                    }
                    dt.Rows.Add(dr);
                }
                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);

                //修正文件名称
                string strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Annual PM25 Point.csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Year");
                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.Insert(0, baseOutput);
                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool SaveQuarterlyPMPoint(BaseScenario baseScenario, Dictionary<string, PMMonitorChina> dicQuarterlyPM, bool useSpecies)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
                return false;
            try
            {
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                DataTable dt = new DataTable();
                dt.Columns.Add("_id");
                dt.Columns.Add("_type");
                dt.Columns.Add("LOCATION_NAME");
                dt.Columns.Add("STATION_NAME");
                dt.Columns.Add("monitor_lat");
                dt.Columns.Add("monitor_long");
                dt.Columns.Add("monitor_gridcell");
                dt.Columns.Add("quarter");
                dt.Columns.Add("b_pm25_ann_q_DV");
                dt.Columns.Add("f_pm25_ann_q_DV");
                //dt.Columns.Add("b_blank_mass_q");
                if (useSpecies)
                {
                    dt.Columns.Add("b_crustal_mass_q");
                    dt.Columns.Add("b_EC_mass_q");
                    dt.Columns.Add("b_NH4_mass_q");
                    dt.Columns.Add("b_OC_mass_q");
                    dt.Columns.Add("b_SO4_mass_q");
                    dt.Columns.Add("b_NO3_mass_q");
                    dt.Columns.Add("b_water_mass_q");
                    dt.Columns.Add("b_other_mass_q");
                    //dt.Columns.Add("f_blank_mass_q");
                    dt.Columns.Add("f_crustal_mass_q");
                    dt.Columns.Add("f_EC_mass_q");
                    dt.Columns.Add("f_NH4_mass_q");
                    dt.Columns.Add("f_OC_mass_q");
                    dt.Columns.Add("f_SO4_mass_q");
                    dt.Columns.Add("f_NO3_mass_q");
                    dt.Columns.Add("f_water_mass_q");
                    dt.Columns.Add("f_other_mass_q");
                    dt.Columns.Add("rrf_crustal_q");
                    dt.Columns.Add("rrf_ec_q");
                    dt.Columns.Add("rrf_nh4_q");
                    dt.Columns.Add("rrf_oc_q");
                    dt.Columns.Add("rrf_so4_q");
                    dt.Columns.Add("rrf_no3_q");
                    dt.Columns.Add("rrf_water_q");
                    dt.Columns.Add("rrf_other_q");
                }
                Dictionary<string, string> dicQuarter = new Dictionary<string, string>();
                dicQuarter.Add("1", "1");
                dicQuarter.Add("2", "4");
                dicQuarter.Add("3", "7");
                dicQuarter.Add("4", "10");
                //dicQuarterlyPM = dicQuarterlyPM.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                foreach (KeyValuePair<string, PMMonitorChina> k in dicQuarterlyPM)
                {
                    foreach (KeyValuePair<string, PMPointChina> kin in k.Value.dicQuarterlyPoint)
                    {
                        DataRow dr = dt.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.type;
                        dr[2] = k.Value.locationName;
                        dr[3] = k.Value.stationName;
                        dr[4] = Math.Round(k.Value.latitude, 6);
                        dr[5] = Math.Round(k.Value.longitude, 6);
                        dr[6] = k.Value.gridcell;
                        dr[7] = dicQuarter[kin.Key];
                        dr[8] = Math.Round(kin.Value.bPMDV, CommonClass.Pm_defaultformat);
                        dr[9] = Math.Round(kin.Value.fPMDV, CommonClass.Pm_defaultformat);
                        if (useSpecies)
                        {
                            //dr[10] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankinMass, CommonClass.Species_calc_precision);
                            dr[10] = Math.Round(kin.Value.bCrustal, CommonClass.Species_calc_precision);
                            dr[11] = Math.Round(kin.Value.bEC, CommonClass.Species_calc_precision);
                            dr[12] = Math.Round(kin.Value.bNH4, CommonClass.Species_calc_precision);
                            dr[13] = Math.Round(kin.Value.bOC, CommonClass.Species_calc_precision);
                            dr[14] = Math.Round(kin.Value.bSO4, CommonClass.Species_calc_precision);
                            dr[15] = Math.Round(kin.Value.bNO3, CommonClass.Species_calc_precision);
                            dr[16] = Math.Round(kin.Value.bWater, CommonClass.Species_calc_precision);
                            dr[17] = Math.Round(kin.Value.bOther, CommonClass.Species_calc_precision);
                            //dr[19] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankinMass, CommonClass.Species_calc_precision);
                            dr[18] = Math.Round(kin.Value.fCrustal, CommonClass.Species_calc_precision);
                            dr[19] = Math.Round(kin.Value.fEC, CommonClass.Species_calc_precision);
                            dr[20] = Math.Round(kin.Value.fNH4, CommonClass.Species_calc_precision);
                            dr[21] = Math.Round(kin.Value.fOC, CommonClass.Species_calc_precision);
                            dr[22] = Math.Round(kin.Value.fSO4, CommonClass.Species_calc_precision);
                            dr[23] = Math.Round(kin.Value.fNO3, CommonClass.Species_calc_precision);
                            dr[24] = Math.Round(kin.Value.fWater, CommonClass.Species_calc_precision);
                            dr[25] = Math.Round(kin.Value.fOther, CommonClass.Species_calc_precision);
                            dr[26] = Double.IsNaN(kin.Value.rrfCrustal) ? -9 : Math.Round(kin.Value.rrfCrustal, 4);
                            dr[27] = Double.IsNaN(kin.Value.rrfEC) ? -9 : Math.Round(kin.Value.rrfEC, 4);
                            dr[28] = Double.IsNaN(kin.Value.rrfNH4) ? -9 : Math.Round(kin.Value.rrfNH4, 4);
                            dr[29] = Double.IsNaN(kin.Value.rrfOC) ? -9 : Math.Round(kin.Value.rrfOC, 4);
                            dr[30] = Double.IsNaN(kin.Value.rrfSO4) ? -9 : Math.Round(kin.Value.rrfSO4, 4);
                            dr[31] = Double.IsNaN(kin.Value.rrfNO3) ? -9 : Math.Round(kin.Value.rrfNO3, 4);
                            dr[32] = Double.IsNaN(kin.Value.rrfWater) ? -9 : Math.Round(kin.Value.rrfWater, 4);
                            dr[33] = Double.IsNaN(kin.Value.rrfOther) ? -9 : Math.Round(kin.Value.rrfOther, 4);
                        }
                        dt.Rows.Add(dr);
                    }
                }

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);

                //修正文件名称
                string strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Quarterly PM25 Point.csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Quarter");
                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.Insert(3, baseOutput);
                dt.Dispose();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool SaveAnnualModelData(BaseScenario baseScenario, Dictionary<string, PmModelDataOutput> dicModelData, string baseModelYear, string futureModelYear)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
            {
                return false;
            }
            try
            {
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                DataTable dtBaseline = new DataTable();
                DataTable dtFuture = new DataTable();
                DataTable dtDelta = new DataTable();
                DataRow dr = null;
                dtBaseline.Columns.Add("_id");
                dtBaseline.Columns.Add("_type");
                dtBaseline.Columns.Add("lat");
                dtBaseline.Columns.Add("long");
                dtBaseline.Columns.Add("date");
                dtBaseline.Columns.Add("crustal");
                dtBaseline.Columns.Add("nh4");
                dtBaseline.Columns.Add("so4");
                dtBaseline.Columns.Add("ec");
                dtBaseline.Columns.Add("no3");
                dtBaseline.Columns.Add("oc");
                dtBaseline.Columns.Add("pm25");
                dtBaseline.Columns.Add("cm");

                dtFuture.Columns.Add("_id");
                dtFuture.Columns.Add("_type");
                dtFuture.Columns.Add("lat");
                dtFuture.Columns.Add("long");
                dtFuture.Columns.Add("date");
                dtFuture.Columns.Add("crustal");
                dtFuture.Columns.Add("nh4");
                dtFuture.Columns.Add("so4");
                dtFuture.Columns.Add("ec");
                dtFuture.Columns.Add("no3");
                dtFuture.Columns.Add("oc");
                dtFuture.Columns.Add("pm25");
                dtFuture.Columns.Add("cm");

                dtDelta.Columns.Add("_id");
                dtDelta.Columns.Add("_type");
                dtDelta.Columns.Add("lat");
                dtDelta.Columns.Add("long");
                //dtDelta.Columns.Add("date");
                dtDelta.Columns.Add("DeltaC(crustal)");
                dtDelta.Columns.Add("DeltaC(nh4)");
                dtDelta.Columns.Add("DeltaC(so4)");
                dtDelta.Columns.Add("DeltaC(ec)");
                dtDelta.Columns.Add("DeltaC(no3)");
                dtDelta.Columns.Add("DeltaC(oc)");
                dtDelta.Columns.Add("DeltaC(pm25)");
                dtDelta.Columns.Add("DeltaC(cm)");

                dicModelData = dicModelData.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                foreach (KeyValuePair<string, PmModelDataOutput> k in dicModelData)
                {
                    dr = dtBaseline.NewRow();
                    dr[0] = k.Value.id;
                    dr[1] = k.Value.type;
                    dr[2] = k.Value.lat;
                    dr[3] = k.Value.longitude;
                    dr[4] = baseModelYear;
                    dr[5] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.crustal).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[6] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.nh4).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[7] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.so4).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[8] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.ec).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[9] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.no3).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[10] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.oc).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[11] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.pm25).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[12] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.cm).ToList().Average(), CommonClass.Species_calc_precision);
                    dtBaseline.Rows.Add(dr);

                    dr = dtFuture.NewRow();
                    dr[0] = k.Value.id;
                    dr[1] = k.Value.type;
                    dr[2] = k.Value.lat;
                    dr[3] = k.Value.longitude;
                    dr[4] = futureModelYear;
                    dr[5] = Math.Round(k.Value.dicFutureModel.Select(q => q.Value.crustal).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[6] = Math.Round(k.Value.dicFutureModel.Select(q => q.Value.nh4).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[7] = Math.Round(k.Value.dicFutureModel.Select(q => q.Value.so4).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[8] = Math.Round(k.Value.dicFutureModel.Select(q => q.Value.ec).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[9] = Math.Round(k.Value.dicFutureModel.Select(q => q.Value.no3).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[10] = Math.Round(k.Value.dicFutureModel.Select(q => q.Value.oc).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[11] = Math.Round(k.Value.dicFutureModel.Select(q => q.Value.pm25).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[12] = Math.Round(k.Value.dicFutureModel.Select(q => q.Value.cm).ToList().Average(), CommonClass.Species_calc_precision);
                    dtFuture.Rows.Add(dr);

                    dr = dtDelta.NewRow();
                    dr[0] = k.Value.id;
                    dr[1] = k.Value.type;
                    dr[2] = k.Value.lat;
                    dr[3] = k.Value.longitude;
                    //dr[4] = baseModelYear;
                    dr[4] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.crustal).ToList().Average() - k.Value.dicFutureModel.Select(q => q.Value.crustal).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[5] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.nh4).ToList().Average() - k.Value.dicFutureModel.Select(q => q.Value.nh4).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[6] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.so4).ToList().Average() - k.Value.dicFutureModel.Select(q => q.Value.so4).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[7] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.ec).ToList().Average() - k.Value.dicFutureModel.Select(q => q.Value.ec).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[8] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.no3).ToList().Average() - k.Value.dicFutureModel.Select(q => q.Value.no3).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[9] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.oc).ToList().Average() - k.Value.dicFutureModel.Select(q => q.Value.oc).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[10] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.pm25).ToList().Average() - k.Value.dicFutureModel.Select(q => q.Value.pm25).ToList().Average(), CommonClass.Species_calc_precision);
                    dr[11] = Math.Round(k.Value.dicBaselineModel.Select(q => q.Value.cm).ToList().Average() - k.Value.dicFutureModel.Select(q => q.Value.cm).ToList().Average(), CommonClass.Species_calc_precision);
                    dtDelta.Rows.Add(dr);
                }

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);
                //修正文件名称
                string strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Baseline Annual Avg Model Data.csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtBaseline, _resultFilePath + @"\" + strFile, "Annual");
                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.Insert(0, baseOutput);

                strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Future Annual Avg Model Data.csv";
                baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtFuture, _resultFilePath + @"\" + strFile, "Annual");
                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.Insert(1, baseOutput);

                strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Delta Annual Avg Model Data.csv";
                baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtDelta, _resultFilePath + @"\" + strFile, "Annual");
                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.Insert(2, baseOutput);
                dtBaseline.Dispose();
                dtFuture.Dispose();
                dtDelta.Dispose();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetGradAdjValues(ref Dictionary<string, Dictionary<string, ModelDataSpecies>> dicGradAdjValues, Dictionary<string, float> fsoutStringSpecies, Dictionary<string, float> fsoutStringPM, Dictionary<string, ModelDataSpecies> dicBaselineModel, Dictionary<string, PmModelDataOutput> dicQuarterlyModelDataPM)
        {
            try
            {
                foreach (KeyValuePair<string, float> s in fsoutStringSpecies)
                {
                    string id = s.Key.Substring(0, s.Key.IndexOf(","));
                    string gridcell = s.Key.Substring(s.Key.IndexOf(",") + 1);
                    Dictionary<string, ModelDataSpecies> dic = new Dictionary<string, ModelDataSpecies>();
                    foreach (KeyValuePair<string, ModelDataSpecies> kQin in dicBaselineModel)
                    {
                        if (dicGradAdjValues.ContainsKey(s.Key))
                        {
                            if (dicGradAdjValues[s.Key].ContainsKey(kQin.Key))
                            {
                                dicGradAdjValues[s.Key][kQin.Key].so4 = (kQin.Value.so4 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.so4) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].so4 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].so4);
                                dicGradAdjValues[s.Key][kQin.Key].no3 = (kQin.Value.no3 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.no3) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].no3 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].no3);
                                dicGradAdjValues[s.Key][kQin.Key].oc = (kQin.Value.oc < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.oc) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].oc < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].oc);
                                dicGradAdjValues[s.Key][kQin.Key].ec = (kQin.Value.ec < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.ec) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].ec < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].ec);
                                dicGradAdjValues[s.Key][kQin.Key].crustal = (kQin.Value.crustal < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.crustal) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].crustal < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].crustal);
                                dicGradAdjValues[s.Key][kQin.Key].nh4 = (kQin.Value.nh4 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.nh4) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].nh4 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].nh4);
                            }
                            else
                            {
                                dicGradAdjValues[s.Key].Add(kQin.Key, new ModelDataSpecies()
                                {
                                    so4 = (kQin.Value.so4 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.so4) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].so4 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].so4),
                                    no3 = (kQin.Value.no3 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.no3) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].no3 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].no3),
                                    oc = (kQin.Value.oc < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.oc) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].oc < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].oc),
                                    ec = (kQin.Value.ec < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.ec) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].ec < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].ec),
                                    crustal = (kQin.Value.crustal < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.crustal) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].crustal < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].crustal),
                                    nh4 = (kQin.Value.nh4 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.nh4) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].nh4 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].nh4),
                                });
                            }
                        }
                        else
                        {
                            dic.Add(kQin.Key, new ModelDataSpecies()
                            {
                                so4 = (kQin.Value.so4 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.so4) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].so4 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].so4),
                                no3 = (kQin.Value.no3 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.no3) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].no3 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].no3),
                                oc = (kQin.Value.oc < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.oc) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].oc < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].oc),
                                ec = (kQin.Value.ec < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.ec) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].ec < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].ec),
                                crustal = (kQin.Value.crustal < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.crustal) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].crustal < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].crustal),
                                nh4 = (kQin.Value.nh4 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.nh4) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].nh4 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].nh4),
                            });
                            dicGradAdjValues.Add(s.Key, dic);
                        }
                    }
                }
                foreach (KeyValuePair<string, float> s in fsoutStringPM)
                {
                    string id = s.Key.Substring(0, s.Key.IndexOf(","));
                    string gridcell = s.Key.Substring(s.Key.IndexOf(",") + 1);
                    foreach (KeyValuePair<string, ModelDataSpecies> kQin in dicBaselineModel)
                    {
                        if (dicGradAdjValues.ContainsKey(s.Key))
                        {
                            if (dicGradAdjValues[s.Key].ContainsKey(kQin.Key))
                            {
                                dicGradAdjValues[s.Key][kQin.Key].pm25 = (kQin.Value.pm25 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.pm25) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].pm25 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].pm25);
                            }
                            else
                            {
                                dicGradAdjValues[s.Key].Add(kQin.Key, new ModelDataSpecies()
                                {
                                    pm25 = (kQin.Value.pm25 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.pm25) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].pm25 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].pm25),
                                });
                            }
                        }
                        else
                        {
                            Dictionary<string, ModelDataSpecies> dic = new Dictionary<string, ModelDataSpecies>();
                            dic.Add(kQin.Key, new ModelDataSpecies()
                            {
                                pm25 = (kQin.Value.pm25 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : kQin.Value.pm25) / (dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].pm25 < CommonClass.GradLimit ? Convert.ToSingle(CommonClass.GradLimit) : dicQuarterlyModelDataPM[gridcell].dicBaselineModel[kQin.Key].pm25),
                            });
                            dicGradAdjValues.Add(s.Key, dic);
                        }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool SaveQuarterlySpatialField(BaseScenario baseScenario, Dictionary<string, PMMonitorChina> dicQuarterSpatialField, bool useSpecies)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
                return false;
            try
            {
                dicQuarterSpatialField = dicQuarterSpatialField.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                DataTable dtQuarterPMSpatial = new DataTable();
                #region
                dtQuarterPMSpatial.Columns.Add("_id");
                dtQuarterPMSpatial.Columns.Add("gridcell_lat");
                dtQuarterPMSpatial.Columns.Add("gridcell_long");
                dtQuarterPMSpatial.Columns.Add("quarter");
                dtQuarterPMSpatial.Columns.Add("b_pm25_ann_q_DV");
                dtQuarterPMSpatial.Columns.Add("f_pm25_ann_q_DV");
                //dtQuarterPMSpatial.Columns.Add("b_blank_mass_q");
                if (useSpecies)
                {
                    dtQuarterPMSpatial.Columns.Add("b_crustal_mass_q");
                    dtQuarterPMSpatial.Columns.Add("b_EC_mass_q");
                    dtQuarterPMSpatial.Columns.Add("b_NH4_mass_q");
                    dtQuarterPMSpatial.Columns.Add("b_OC_mass_q");
                    dtQuarterPMSpatial.Columns.Add("b_SO4_mass_q");
                    dtQuarterPMSpatial.Columns.Add("b_NO3_mass_q");
                    dtQuarterPMSpatial.Columns.Add("b_water_mass_q");
                    dtQuarterPMSpatial.Columns.Add("b_other_mass_q");
                    //dtQuarterPMSpatial.Columns.Add("f_blank_mass_q");
                    dtQuarterPMSpatial.Columns.Add("f_crustal_mass_q");
                    dtQuarterPMSpatial.Columns.Add("f_EC_mass_q");
                    dtQuarterPMSpatial.Columns.Add("f_NH4_mass_q");
                    dtQuarterPMSpatial.Columns.Add("f_OC_mass_q");
                    dtQuarterPMSpatial.Columns.Add("f_SO4_mass_q");
                    dtQuarterPMSpatial.Columns.Add("f_NO3_mass_q");
                    dtQuarterPMSpatial.Columns.Add("f_water_mass_q");
                    dtQuarterPMSpatial.Columns.Add("f_other_mass_q");
                    dtQuarterPMSpatial.Columns.Add("rrf_crustal_q");
                    dtQuarterPMSpatial.Columns.Add("rrf_ec_q");
                    dtQuarterPMSpatial.Columns.Add("rrf_nh4_q");
                    dtQuarterPMSpatial.Columns.Add("rrf_oc_q");
                    dtQuarterPMSpatial.Columns.Add("rrf_so4_q");
                    dtQuarterPMSpatial.Columns.Add("rrf_no3_q");
                    dtQuarterPMSpatial.Columns.Add("rrf_water_q");
                    dtQuarterPMSpatial.Columns.Add("rrf_other_q");
                }
                #endregion
                #region
                if (useSpecies)
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicQuarterSpatialField)
                    {
                        foreach (KeyValuePair<string, PMSpatialChina> kQ in k.Value.dicQuarterlySpatial)
                        {
                            DataRow dr = dtQuarterPMSpatial.NewRow();
                            dr[0] = k.Value.id;
                            dr[1] = k.Value.latitude;
                            dr[2] = k.Value.longitude;
                            dr[3] = kQ.Key;
                            dr[4] = Math.Round(kQ.Value.bPMAnnDV, CommonClass.Pm_defaultformat);
                            dr[5] = Math.Round(kQ.Value.fPMAnnDV, CommonClass.Pm_defaultformat);
                            //dr[6] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                            dr[6] = Math.Round(kQ.Value.bCrustalMass, CommonClass.Species_calc_precision);
                            dr[7] = Math.Round(kQ.Value.bECMass, CommonClass.Species_calc_precision);
                            dr[8] = Math.Round(kQ.Value.bNH4Mass, CommonClass.Species_calc_precision);
                            dr[9] = Math.Round(kQ.Value.bOCMass, CommonClass.Species_calc_precision);
                            dr[10] = Math.Round(kQ.Value.bSO4Mass, CommonClass.Species_calc_precision);
                            dr[11] = Math.Round(kQ.Value.bNO3Mass, CommonClass.Species_calc_precision);
                            dr[12] = Math.Round(kQ.Value.bWaterMass, CommonClass.Species_calc_precision);
                            dr[13] = Math.Round(kQ.Value.bOtherMass, CommonClass.Species_calc_precision);
                            //dr[15] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                            dr[14] = Math.Round(kQ.Value.fCrustalMass, CommonClass.Species_calc_precision);
                            dr[15] = Math.Round(kQ.Value.fECMass, CommonClass.Species_calc_precision);
                            dr[16] = Math.Round(kQ.Value.fNH4Mass, CommonClass.Species_calc_precision);
                            dr[17] = Math.Round(kQ.Value.fOCMass, CommonClass.Species_calc_precision);
                            dr[18] = Math.Round(kQ.Value.fSO4Mass, CommonClass.Species_calc_precision);
                            dr[19] = Math.Round(kQ.Value.fNO3Mass, CommonClass.Species_calc_precision);
                            dr[20] = Math.Round(kQ.Value.fWaterMass, CommonClass.Species_calc_precision);
                            dr[21] = Math.Round(kQ.Value.fOtherMass, CommonClass.Species_calc_precision);
                            dr[22] = Double.IsNaN(kQ.Value.rrfCrustal) ? -9 : Math.Round(kQ.Value.rrfCrustal, 8);
                            dr[23] = Double.IsNaN(kQ.Value.rrfEC) ? -9 : Math.Round(kQ.Value.rrfEC, 8);
                            dr[24] = Double.IsNaN(kQ.Value.rrfNH4) ? -9 : Math.Round(kQ.Value.rrfNH4, 8);
                            dr[25] = Double.IsNaN(kQ.Value.rrfOC) ? -9 : Math.Round(kQ.Value.rrfOC, 8);
                            dr[26] = Double.IsNaN(kQ.Value.rrfSO4) ? -9 : Math.Round(kQ.Value.rrfSO4, 8);
                            dr[27] = Double.IsNaN(kQ.Value.rrfNO3) ? -9 : Math.Round(kQ.Value.rrfNO3, 8);
                            dr[28] = Double.IsNaN(kQ.Value.rrfWaterMass) ? -9 : Math.Round(kQ.Value.rrfWaterMass, 8);
                            dr[29] = Double.IsNaN(kQ.Value.rrfOther) ? -9 : Math.Round(kQ.Value.rrfOther, 8);
                            dtQuarterPMSpatial.Rows.Add(dr);
                        }
                    }
                }
                else
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicQuarterSpatialField)
                    {
                        foreach (KeyValuePair<string, double[]> kQ in k.Value.dicpmSpatial)
                        {
                            DataRow dr = dtQuarterPMSpatial.NewRow();
                            dr[0] = k.Value.id;
                            dr[1] = k.Value.latitude;
                            dr[2] = k.Value.longitude;
                            dr[3] = kQ.Key;
                            dr[4] = Math.Round(kQ.Value[0], CommonClass.Pm_defaultformat);
                            dr[5] = Math.Round(kQ.Value[1], CommonClass.Pm_defaultformat);
                            dtQuarterPMSpatial.Rows.Add(dr);
                        }
                    }
                }
                #endregion

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);

                //修正文件名称
                string strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Quarterly PM25 Spatial Field.csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtQuarterPMSpatial, _resultFilePath + @"\" + strFile, "Quarter");
                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);
                dtQuarterPMSpatial.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool SaveQuarterlySpatialFieldGradAdj(BaseScenario baseScenario, Dictionary<string, PMMonitorChina> dicQuarterlySpatialFieldGradAdj, bool useSpecies)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
                return false;
            try
            {
                dicQuarterlySpatialFieldGradAdj = dicQuarterlySpatialFieldGradAdj.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                DataTable dtGradAdjQuarterSpatial = new DataTable();
                #region
                dtGradAdjQuarterSpatial.Columns.Add("_id");
                dtGradAdjQuarterSpatial.Columns.Add("gridcell_lat");
                dtGradAdjQuarterSpatial.Columns.Add("gridcell_long");
                dtGradAdjQuarterSpatial.Columns.Add("quarter");
                dtGradAdjQuarterSpatial.Columns.Add("b_pm25_ann_q_DV_ga");
                dtGradAdjQuarterSpatial.Columns.Add("f_pm25_ann_q_DV_ga");
                if (useSpecies)
                {
                    //dtGradAdjQuarterSpatial.Columns.Add("b_blank_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("b_crustal_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("b_EC_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("b_NH4_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("b_OC_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("b_SO4_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("b_NO3_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("b_water_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("b_other_mass_q_ga");
                    //dtGradAdjQuarterSpatial.Columns.Add("f_blank_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("f_crustal_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("f_EC_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("f_NH4_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("f_OC_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("f_SO4_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("f_NO3_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("f_water_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("f_other_mass_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("rrf_crustal_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("rrf_ec_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("rrf_nh4_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("rrf_oc_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("rrf_so4_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("rrf_no3_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("rrf_water_q_ga");
                    dtGradAdjQuarterSpatial.Columns.Add("rrf_other_q_ga");
                }
                #endregion
                #region
                if (useSpecies)
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicQuarterlySpatialFieldGradAdj)
                    {
                        foreach (KeyValuePair<string, PMSpatialChina> kQ in k.Value.dicQuarterlySpatialGradientAdjusted)
                        {
                            DataRow dr = dtGradAdjQuarterSpatial.NewRow();
                            dr[0] = k.Value.id;
                            dr[1] = k.Value.latitude;
                            dr[2] = k.Value.longitude;
                            dr[3] = kQ.Key;
                            dr[4] = Math.Round(kQ.Value.bPMAnnDV, 2);
                            dr[5] = Math.Round(kQ.Value.fPMAnnDV, 2);
                            //dr[6] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                            dr[6] = Math.Round(kQ.Value.bCrustalMass, CommonClass.Species_calc_precision);
                            dr[7] = Math.Round(kQ.Value.bECMass, CommonClass.Species_calc_precision);
                            dr[8] = Math.Round(kQ.Value.bNH4Mass, CommonClass.Species_calc_precision);
                            dr[9] = Math.Round(kQ.Value.bOCMass, CommonClass.Species_calc_precision);
                            dr[10] = Math.Round(kQ.Value.bSO4Mass, CommonClass.Species_calc_precision);
                            dr[11] = Math.Round(kQ.Value.bNO3Mass, CommonClass.Species_calc_precision);
                            dr[12] = Math.Round(kQ.Value.bWaterMass, CommonClass.Species_calc_precision);
                            dr[13] = Math.Round(kQ.Value.bOtherMass, CommonClass.Species_calc_precision);
                            //dr[15] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                            dr[14] = Math.Round(kQ.Value.fCrustalMass, CommonClass.Species_calc_precision);
                            dr[15] = Math.Round(kQ.Value.fECMass, CommonClass.Species_calc_precision);
                            dr[16] = Math.Round(kQ.Value.fNH4Mass, CommonClass.Species_calc_precision);
                            dr[17] = Math.Round(kQ.Value.fOCMass, CommonClass.Species_calc_precision);
                            dr[18] = Math.Round(kQ.Value.fSO4Mass, CommonClass.Species_calc_precision);
                            dr[19] = Math.Round(kQ.Value.fNO3Mass, CommonClass.Species_calc_precision);
                            dr[20] = Math.Round(kQ.Value.fWaterMass, CommonClass.Species_calc_precision);
                            dr[21] = Math.Round(kQ.Value.fOtherMass, CommonClass.Species_calc_precision);
                            dr[22] = Double.IsNaN(kQ.Value.rrfCrustal) ? -9 : Math.Round(kQ.Value.rrfCrustal, 8);
                            dr[23] = Double.IsNaN(kQ.Value.rrfEC) ? -9 : Math.Round(kQ.Value.rrfEC, 8);
                            dr[24] = Double.IsNaN(kQ.Value.rrfNH4) ? -9 : Math.Round(kQ.Value.rrfNH4, 8);
                            dr[25] = Double.IsNaN(kQ.Value.rrfOC) ? -9 : Math.Round(kQ.Value.rrfOC, 8);
                            dr[26] = Double.IsNaN(kQ.Value.rrfSO4) ? -9 : Math.Round(kQ.Value.rrfSO4, 8);
                            dr[27] = Double.IsNaN(kQ.Value.rrfNO3) ? -9 : Math.Round(kQ.Value.rrfNO3, 8);
                            dr[28] = Double.IsNaN(kQ.Value.rrfWaterMass) ? -9 : Math.Round(kQ.Value.rrfWaterMass, 8);
                            dr[29] = Double.IsNaN(kQ.Value.rrfOther) ? -9 : Math.Round(kQ.Value.rrfOther, 8);
                            dtGradAdjQuarterSpatial.Rows.Add(dr);
                        }
                    }
                }
                else
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicQuarterlySpatialFieldGradAdj)
                    {
                        foreach (KeyValuePair<string, double[]> kQ in k.Value.dicpmSpatial)
                        {
                            DataRow dr = dtGradAdjQuarterSpatial.NewRow();
                            dr[0] = k.Value.id;
                            dr[1] = k.Value.latitude;
                            dr[2] = k.Value.longitude;
                            dr[3] = kQ.Key;
                            dr[4] = Math.Round(kQ.Value[2], CommonClass.Pm_defaultformat);
                            dr[5] = Math.Round(kQ.Value[3], CommonClass.Pm_defaultformat);
                            dtGradAdjQuarterSpatial.Rows.Add(dr);
                        }
                    }
                }
                #endregion

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);

                //修正文件名称
                string strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Grad Adj Quarterly PM25 Spatial Field.csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtGradAdjQuarterSpatial, _resultFilePath + @"\" + strFile, "Quarter");
                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);
                dtGradAdjQuarterSpatial.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool SaveQuarterlySpatialFieldwVNA(BaseScenario baseScenario, Dictionary<string, PMMonitorChina> dicQuarterSpatialFieldwVNA, bool useSpecies)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
                return false;
            try
            {
                dicQuarterSpatialFieldwVNA = dicQuarterSpatialFieldwVNA.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                var w = annualPMAnalysisConfiguration.monitorDataInputChina.wVNAWeight;// wVNA权重
                DataTable dtQuarterPMSpatialwVNA = new DataTable();
                #region
                dtQuarterPMSpatialwVNA.Columns.Add("_id");
                dtQuarterPMSpatialwVNA.Columns.Add("gridcell_lat");
                dtQuarterPMSpatialwVNA.Columns.Add("gridcell_long");
                dtQuarterPMSpatialwVNA.Columns.Add("quarter");
                dtQuarterPMSpatialwVNA.Columns.Add("b_pm25_ann_q_DV_wvna");
                dtQuarterPMSpatialwVNA.Columns.Add("f_pm25_ann_q_DV_wvna");
                //dtQuarterPMSpatialwVNA.Columns.Add("b_blank_mass_q_wvna");
                if (useSpecies)
                {
                    dtQuarterPMSpatialwVNA.Columns.Add("b_crustal_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("b_EC_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("b_NH4_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("b_OC_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("b_SO4_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("b_NO3_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("b_water_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("b_other_mass_q_wvna");
                    //dtQuarterPMSpatialwVNA.Columns.Add("f_blank_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("f_crustal_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("f_EC_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("f_NH4_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("f_OC_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("f_SO4_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("f_NO3_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("f_water_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("f_other_mass_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("rrf_crustal_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("rrf_ec_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("rrf_nh4_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("rrf_oc_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("rrf_so4_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("rrf_no3_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("rrf_water_q_wvna");
                    dtQuarterPMSpatialwVNA.Columns.Add("rrf_other_q_wvna");
                }
                #endregion
                #region
                //wVNA = w * eVNA + (1 - w) * VNA
                if (useSpecies)
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicQuarterSpatialFieldwVNA)
                    {
                        foreach (KeyValuePair<string, PMSpatialChina> kQ in k.Value.dicQuarterlySpatial)
                        {
                            PMSpatialChina wvna = new PMSpatialChina();
                            PMSpatialChina dicQuarterlySpatial_wVNA = new PMSpatialChina();
                         
                            wvna.bPMAnnDV= (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].bPMAnnDV * w + kQ.Value.bPMAnnDV * (1 - w));
                            wvna.fPMAnnDV = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].fPMAnnDV * w + kQ.Value.fPMAnnDV * (1 - w));
                            wvna.bCrustalMass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].bCrustalMass * w + kQ.Value.bCrustalMass * (1 - w));
                            wvna.bECMass  = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].bECMass * w + kQ.Value.bECMass * (1 - w));
                            wvna.bNH4Mass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].bNH4Mass * w + kQ.Value.bNH4Mass * (1 - w));
                            wvna.bOCMass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].bOCMass * w + kQ.Value.bOCMass * (1 - w));
                            wvna.bSO4Mass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].bSO4Mass * w + kQ.Value.bSO4Mass * (1 - w));
                            wvna.bNO3Mass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].bNO3Mass * w + kQ.Value.bNO3Mass * (1 - w));
                            wvna.bWaterMass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].bWaterMass * w + kQ.Value.bWaterMass * (1 - w));
                            wvna.bOtherMass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].bOtherMass * w + kQ.Value.bOtherMass * (1 - w));

                            wvna.fCrustalMass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].fCrustalMass * w + kQ.Value.fCrustalMass * (1 - w));
                            wvna.fECMass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].fECMass * w + kQ.Value.fECMass * (1 - w));
                            wvna.fNH4Mass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].fNH4Mass * w + kQ.Value.fNH4Mass * (1 - w));
                            wvna.fOCMass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].fOCMass * w + kQ.Value.fOCMass * (1 - w));
                            wvna.fSO4Mass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].fSO4Mass * w + kQ.Value.fSO4Mass * (1 - w));
                            wvna.fNO3Mass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].fNO3Mass * w + kQ.Value.fNO3Mass * (1 - w));
                            wvna.fWaterMass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].fWaterMass * w + kQ.Value.fWaterMass * (1 - w));
                            wvna.fOtherMass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].fOtherMass * w + kQ.Value.fOtherMass * (1 - w));
                            wvna.rrfCrustal = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfCrustal * w + kQ.Value.rrfCrustal * (1 - w));
                            wvna.rrfEC = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfEC * w + kQ.Value.rrfEC * (1 - w));
                            wvna.rrfNH4 = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfNH4 * w + kQ.Value.rrfNH4 * (1 - w));
                            wvna.rrfOC = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfOC * w + kQ.Value.rrfOC * (1 - w));
                            wvna.rrfSO4 = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfSO4 * w + kQ.Value.rrfSO4 * (1 - w));
                            wvna.rrfNO3 = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfNO3 * w + kQ.Value.rrfNO3 * (1 - w));
                            wvna.rrfWaterMass = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfWaterMass * w + kQ.Value.rrfWaterMass * (1 - w));
                            wvna.rrfOther = (float)(k.Value.dicQuarterlySpatialGradientAdjusted[kQ.Key].rrfOther * w + kQ.Value.rrfOther * (1 - w));
                            if (k.Value.dicQuarterlySpatial_wVNA==null)
                            {
                                k.Value.dicQuarterlySpatial_wVNA = new Dictionary<string, PMSpatialChina>();
                                k.Value.dicQuarterlySpatial_wVNA.Add(kQ.Key, wvna);
                            }
                            else
                            {
                                k.Value.dicQuarterlySpatial_wVNA.Add(kQ.Key, wvna);
                            }
                        }
                            foreach (KeyValuePair<string, PMSpatialChina> kQ in k.Value.dicQuarterlySpatial_wVNA)
                        {
                            DataRow dr = dtQuarterPMSpatialwVNA.NewRow();
                            dr[0] = k.Value.id;
                            dr[1] = k.Value.latitude;
                            dr[2] = k.Value.longitude;
                            dr[3] = kQ.Key;
                            dr[4] = Math.Round(kQ.Value.bPMAnnDV, CommonClass.Pm_defaultformat);
                            dr[5] = Math.Round(kQ.Value.fPMAnnDV, CommonClass.Pm_defaultformat);
                            //dr[6] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                            dr[6] = Math.Round(kQ.Value.bCrustalMass, CommonClass.Species_calc_precision);
                            dr[7] = Math.Round(kQ.Value.bECMass, CommonClass.Species_calc_precision);
                            dr[8] = Math.Round(kQ.Value.bNH4Mass, CommonClass.Species_calc_precision);
                            dr[9] = Math.Round(kQ.Value.bOCMass, CommonClass.Species_calc_precision);
                            dr[10] = Math.Round(kQ.Value.bSO4Mass, CommonClass.Species_calc_precision);
                            dr[11] = Math.Round(kQ.Value.bNO3Mass, CommonClass.Species_calc_precision);
                            dr[12] = Math.Round(kQ.Value.bWaterMass, CommonClass.Species_calc_precision);
                            dr[13] = Math.Round(kQ.Value.bOtherMass, CommonClass.Species_calc_precision);
                            //dr[15] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                            dr[14] = Math.Round(kQ.Value.fCrustalMass, CommonClass.Species_calc_precision);
                            dr[15] = Math.Round(kQ.Value.fECMass, CommonClass.Species_calc_precision);
                            dr[16] = Math.Round(kQ.Value.fNH4Mass, CommonClass.Species_calc_precision);
                            dr[17] = Math.Round(kQ.Value.fOCMass, CommonClass.Species_calc_precision);
                            dr[18] = Math.Round(kQ.Value.fSO4Mass, CommonClass.Species_calc_precision);
                            dr[19] = Math.Round(kQ.Value.fNO3Mass, CommonClass.Species_calc_precision);
                            dr[20] = Math.Round(kQ.Value.fWaterMass, CommonClass.Species_calc_precision);
                            dr[21] = Math.Round(kQ.Value.fOtherMass, CommonClass.Species_calc_precision);
                            dr[22] = Double.IsNaN(kQ.Value.rrfCrustal) ? -9 : Math.Round(kQ.Value.rrfCrustal, 8);
                            dr[23] = Double.IsNaN(kQ.Value.rrfEC) ? -9 : Math.Round(kQ.Value.rrfEC, 8);
                            dr[24] = Double.IsNaN(kQ.Value.rrfNH4) ? -9 : Math.Round(kQ.Value.rrfNH4, 8);
                            dr[25] = Double.IsNaN(kQ.Value.rrfOC) ? -9 : Math.Round(kQ.Value.rrfOC, 8);
                            dr[26] = Double.IsNaN(kQ.Value.rrfSO4) ? -9 : Math.Round(kQ.Value.rrfSO4, 8);
                            dr[27] = Double.IsNaN(kQ.Value.rrfNO3) ? -9 : Math.Round(kQ.Value.rrfNO3, 8);
                            dr[28] = Double.IsNaN(kQ.Value.rrfWaterMass) ? -9 : Math.Round(kQ.Value.rrfWaterMass, 8);
                            dr[29] = Double.IsNaN(kQ.Value.rrfOther) ? -9 : Math.Round(kQ.Value.rrfOther, 8);
                            dtQuarterPMSpatialwVNA.Rows.Add(dr);
                        }
                    }
                }
                else
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicQuarterSpatialFieldwVNA)
                    {
                        foreach (KeyValuePair<string, double[]> kQ in k.Value.dicpmSpatial)
                        {
                            DataRow dr = dtQuarterPMSpatialwVNA.NewRow();
                            dr[0] = k.Value.id;
                            dr[1] = k.Value.latitude;
                            dr[2] = k.Value.longitude;
                            dr[3] = kQ.Key;
                            dr[4] = Math.Round(kQ.Value[6], CommonClass.Pm_defaultformat);
                            dr[5] = Math.Round(kQ.Value[7], CommonClass.Pm_defaultformat);
                            dtQuarterPMSpatialwVNA.Rows.Add(dr);
                        }
                    }
                }
                #endregion

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);

                //修正文件名称
                string strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Quarterly PM25 Spatial Field(wVNA).csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtQuarterPMSpatialwVNA, _resultFilePath + @"\" + strFile, "Quarter");
                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);
                dtQuarterPMSpatialwVNA.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        public static bool SaveQuarterlySpatialFieldNearestSite(BaseScenario baseScenario, Dictionary<string, PMMonitorChina> dicQuarterSpatialFieldNearestSite, bool useSpecies)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
                return false;
            try
            {
                dicQuarterSpatialFieldNearestSite = dicQuarterSpatialFieldNearestSite.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                DataTable dtNSQuarterPMSpatial = new DataTable();
                #region
                dtNSQuarterPMSpatial.Columns.Add("_id");
                dtNSQuarterPMSpatial.Columns.Add("gridcell_lat");
                dtNSQuarterPMSpatial.Columns.Add("gridcell_long");
                dtNSQuarterPMSpatial.Columns.Add("quarter");
                dtNSQuarterPMSpatial.Columns.Add("b_pm25_ann_q_DV_ns");
                dtNSQuarterPMSpatial.Columns.Add("f_pm25_ann_q_DV_ns");
                //dtNSQuarterPMSpatial.Columns.Add("b_blank_mass_q");
                if (useSpecies)
                {
                    dtNSQuarterPMSpatial.Columns.Add("b_crustal_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("b_EC_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("b_NH4_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("b_OC_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("b_SO4_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("b_NO3_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("b_water_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("b_other_mass_q_ns");
                    //dtNSQuarterPMSpatial.Columns.Add("f_blank_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("f_crustal_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("f_EC_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("f_NH4_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("f_OC_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("f_SO4_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("f_NO3_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("f_water_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("f_other_mass_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("rrf_crustal_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("rrf_ec_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("rrf_nh4_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("rrf_oc_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("rrf_so4_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("rrf_no3_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("rrf_water_q_ns");
                    dtNSQuarterPMSpatial.Columns.Add("rrf_other_q_ns");
                }
                #endregion
                #region
                if (useSpecies)
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicQuarterSpatialFieldNearestSite)
                    {
                        foreach (KeyValuePair<string, PMSpatialChina> kQ in k.Value.dicQuarterlySpatial_NS)
                        {
                            DataRow dr = dtNSQuarterPMSpatial.NewRow();
                            dr[0] = k.Value.id;
                            dr[1] = k.Value.latitude;
                            dr[2] = k.Value.longitude;
                            dr[3] = kQ.Key;
                            dr[4] = Math.Round(kQ.Value.bPMAnnDV, CommonClass.Pm_defaultformat);
                            dr[5] = Math.Round(kQ.Value.fPMAnnDV, CommonClass.Pm_defaultformat);
                            //dr[6] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                            dr[6] = Math.Round(kQ.Value.bCrustalMass, CommonClass.Species_calc_precision);
                            dr[7] = Math.Round(kQ.Value.bECMass, CommonClass.Species_calc_precision);
                            dr[8] = Math.Round(kQ.Value.bNH4Mass, CommonClass.Species_calc_precision);
                            dr[9] = Math.Round(kQ.Value.bOCMass, CommonClass.Species_calc_precision);
                            dr[10] = Math.Round(kQ.Value.bSO4Mass, CommonClass.Species_calc_precision);
                            dr[11] = Math.Round(kQ.Value.bNO3Mass, CommonClass.Species_calc_precision);
                            dr[12] = Math.Round(kQ.Value.bWaterMass, CommonClass.Species_calc_precision);
                            dr[13] = Math.Round(kQ.Value.bOtherMass, CommonClass.Species_calc_precision);
                            //dr[15] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                            dr[14] = Math.Round(kQ.Value.fCrustalMass, CommonClass.Species_calc_precision);
                            dr[15] = Math.Round(kQ.Value.fECMass, CommonClass.Species_calc_precision);
                            dr[16] = Math.Round(kQ.Value.fNH4Mass, CommonClass.Species_calc_precision);
                            dr[17] = Math.Round(kQ.Value.fOCMass, CommonClass.Species_calc_precision);
                            dr[18] = Math.Round(kQ.Value.fSO4Mass, CommonClass.Species_calc_precision);
                            dr[19] = Math.Round(kQ.Value.fNO3Mass, CommonClass.Species_calc_precision);
                            dr[20] = Math.Round(kQ.Value.fWaterMass, CommonClass.Species_calc_precision);
                            dr[21] = Math.Round(kQ.Value.fOtherMass, CommonClass.Species_calc_precision);
                            dr[22] = Double.IsNaN(kQ.Value.rrfCrustal) ? -9 : Math.Round(kQ.Value.rrfCrustal, 8);
                            dr[23] = Double.IsNaN(kQ.Value.rrfEC) ? -9 : Math.Round(kQ.Value.rrfEC, 8);
                            dr[24] = Double.IsNaN(kQ.Value.rrfNH4) ? -9 : Math.Round(kQ.Value.rrfNH4, 8);
                            dr[25] = Double.IsNaN(kQ.Value.rrfOC) ? -9 : Math.Round(kQ.Value.rrfOC, 8);
                            dr[26] = Double.IsNaN(kQ.Value.rrfSO4) ? -9 : Math.Round(kQ.Value.rrfSO4, 8);
                            dr[27] = Double.IsNaN(kQ.Value.rrfNO3) ? -9 : Math.Round(kQ.Value.rrfNO3, 8);
                            dr[28] = Double.IsNaN(kQ.Value.rrfWaterMass) ? -9 : Math.Round(kQ.Value.rrfWaterMass, 8);
                            dr[29] = Double.IsNaN(kQ.Value.rrfOther) ? -9 : Math.Round(kQ.Value.rrfOther, 8);
                            dtNSQuarterPMSpatial.Rows.Add(dr);
                        }
                    }
                }
                else
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicQuarterSpatialFieldNearestSite)
                    {
                        foreach (KeyValuePair<string, double[]> kQ in k.Value.dicpmSpatial)
                        {
                            DataRow dr = dtNSQuarterPMSpatial.NewRow();
                            dr[0] = k.Value.id;
                            dr[1] = k.Value.latitude;
                            dr[2] = k.Value.longitude;
                            dr[3] = kQ.Key;
                            dr[4] = Math.Round(kQ.Value[4], CommonClass.Pm_defaultformat);
                            dr[5] = Math.Round(kQ.Value[5], CommonClass.Pm_defaultformat);
                            dtNSQuarterPMSpatial.Rows.Add(dr);
                        }
                    }
                }
                #endregion

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);

                //修正文件名称
                string strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Nearest Site Quarterly PM25 Spatial Field.csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtNSQuarterPMSpatial, _resultFilePath + @"\" + strFile, "Quarter");
                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);
                dtNSQuarterPMSpatial.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool SaveAnnualPointSpatialField(BaseScenario baseScenario, Dictionary<string, PMMonitorChina> dicSpatialField, bool useSpecies)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
                return false;
            try
            {
                dicSpatialField = dicSpatialField.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                DataTable dtAnnualPMSpatial = new DataTable();
                #region
                dtAnnualPMSpatial.Columns.Add("_id");
                dtAnnualPMSpatial.Columns.Add("gridcell_lat");
                dtAnnualPMSpatial.Columns.Add("gridcell_long");
                dtAnnualPMSpatial.Columns.Add("b_pm25_ann_DV");
                dtAnnualPMSpatial.Columns.Add("f_pm25_ann_DV");
                //dtAnnualPMSpatial.Columns.Add("b_blank_mass");
                if (useSpecies)
                {
                    dtAnnualPMSpatial.Columns.Add("b_crustal_mass");
                    dtAnnualPMSpatial.Columns.Add("b_EC_mass");
                    dtAnnualPMSpatial.Columns.Add("b_NH4_mass");
                    dtAnnualPMSpatial.Columns.Add("b_OC_mass");
                    dtAnnualPMSpatial.Columns.Add("b_SO4_mass");
                    dtAnnualPMSpatial.Columns.Add("b_NO3_mass");
                    dtAnnualPMSpatial.Columns.Add("b_water_mass");
                    dtAnnualPMSpatial.Columns.Add("b_other_mass");
                    //dtAnnualPMSpatial.Columns.Add("f_blank_mass");
                    dtAnnualPMSpatial.Columns.Add("f_crustal_mass");
                    dtAnnualPMSpatial.Columns.Add("f_EC_mass");
                    dtAnnualPMSpatial.Columns.Add("f_NH4_mass");
                    dtAnnualPMSpatial.Columns.Add("f_OC_mass");
                    dtAnnualPMSpatial.Columns.Add("f_SO4_mass");
                    dtAnnualPMSpatial.Columns.Add("f_NO3_mass");
                    dtAnnualPMSpatial.Columns.Add("f_water_mass");
                    dtAnnualPMSpatial.Columns.Add("f_other_mass");
                    dtAnnualPMSpatial.Columns.Add("rrf_crustal");
                    dtAnnualPMSpatial.Columns.Add("rrf_ec");
                    dtAnnualPMSpatial.Columns.Add("rrf_nh4");
                    dtAnnualPMSpatial.Columns.Add("rrf_oc");
                    dtAnnualPMSpatial.Columns.Add("rrf_so4");
                    dtAnnualPMSpatial.Columns.Add("rrf_no3");
                    dtAnnualPMSpatial.Columns.Add("rrf_water");
                    dtAnnualPMSpatial.Columns.Add("rrf_other");
                }
                #endregion
                #region
                if (useSpecies)
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicSpatialField)
                    {
                        DataRow dr = dtAnnualPMSpatial.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.latitude;
                        dr[2] = k.Value.longitude;
                        dr[3] = CommonClass.ToFixed(k.Value.dicQuarterlySpatial.Select(p => p.Value.bPMAnnDV).Average(), 2);
                        dr[4] = CommonClass.ToFixed(k.Value.dicQuarterlySpatial.Select(p => p.Value.fPMAnnDV).Average(), 2);
                        //dr[5] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                        dr[5] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.bCrustalMass).Average(), CommonClass.Species_calc_precision);
                        dr[6] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.bECMass).Average(), CommonClass.Species_calc_precision);
                        dr[7] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.bNH4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[8] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.bOCMass).Average(), CommonClass.Species_calc_precision);
                        dr[9] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.bSO4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[10] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.bNO3Mass).Average(), CommonClass.Species_calc_precision);
                        dr[11] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.bWaterMass).Average(), CommonClass.Species_calc_precision);
                        dr[12] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.bOtherMass).Average(), CommonClass.Species_calc_precision);
                        //dr[14] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                        dr[13] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fCrustalMass).Average(), CommonClass.Species_calc_precision);
                        dr[14] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fECMass).Average(), CommonClass.Species_calc_precision);
                        dr[15] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fNH4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[16] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fOCMass).Average(), CommonClass.Species_calc_precision);
                        dr[17] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fSO4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[18] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fNO3Mass).Average(), CommonClass.Species_calc_precision);
                        dr[19] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fWaterMass).Average(), CommonClass.Species_calc_precision);
                        dr[20] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fOtherMass).Average(), CommonClass.Species_calc_precision);
                        dr[21] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fCrustalMass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bCrustalMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fCrustalMass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bCrustalMass).Average(), 4);
                        dr[22] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fECMass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bECMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fECMass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bECMass).Average(), 4);
                        dr[23] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fNH4Mass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bNH4Mass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fNH4Mass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bNH4Mass).Average(), 4);
                        dr[24] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fOCMass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bOCMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fOCMass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bOCMass).Average(), 4);
                        dr[25] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fSO4Mass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bSO4Mass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fSO4Mass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bSO4Mass).Average(), 4);
                        //dr[28] = Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fNO3Mass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bNO3rMass).Average(), 4);
                        dr[26] = Double.IsNaN(k.Value.dicQuarterlySpatial.Select(p => p.Value.bNO3Mass).Average() == 0 ? 0 : Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fNO3Mass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bNO3Mass).Average(), 4)) ? -9 : k.Value.dicQuarterlySpatial.Select(p => p.Value.bNO3Mass).Average() == 0 ? -9 : Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fNO3Mass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bNO3Mass).Average(), 4);
                        dr[27] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fWaterMass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bWaterMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fWaterMass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bWaterMass).Average(), 4);
                        dr[28] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fOtherMass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bOtherMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial.Select(p => p.Value.fOtherMass).Average() / k.Value.dicQuarterlySpatial.Select(p => p.Value.bOtherMass).Average(), 4);
                        dtAnnualPMSpatial.Rows.Add(dr);
                    }
                }
                else
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicSpatialField)
                    {
                        DataRow dr = dtAnnualPMSpatial.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.latitude;
                        dr[2] = k.Value.longitude;
                        dr[3] = CommonClass.ToFixed(k.Value.dicpmSpatial.Select(p => p.Value[0]).ToList().Average(), 2);
                        dr[4] = CommonClass.ToFixed(k.Value.dicpmSpatial.Select(p => p.Value[1]).ToList().Average(), 2);
                        dtAnnualPMSpatial.Rows.Add(dr);
                    }
                }
                #endregion

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);

                //修正文件名称
                string strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Annual PM25 Spatial Field.csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtAnnualPMSpatial, _resultFilePath + @"\" + strFile, "Year");
                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);
                dtAnnualPMSpatial.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool SaveAnnualPointSpatialFieldGradAdj(BaseScenario baseScenario, Dictionary<string, PMMonitorChina> dicSpatialFieldGradAdj, bool useSpecies)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
                return false;
            try
            {
                dicSpatialFieldGradAdj = dicSpatialFieldGradAdj.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                DataTable dtGradAdjAnnualSpatial = new DataTable();
                #region
                dtGradAdjAnnualSpatial.Columns.Add("_id");
                dtGradAdjAnnualSpatial.Columns.Add("gridcell_lat");
                dtGradAdjAnnualSpatial.Columns.Add("gridcell_long");
                dtGradAdjAnnualSpatial.Columns.Add("b_pm25_ann_DV_ga");
                dtGradAdjAnnualSpatial.Columns.Add("f_pm25_ann_DV_ga");
                //dtGradAdjAnnualSpatial.Columns.Add("b_blank_mass_ga");
                if (useSpecies)
                {
                    dtGradAdjAnnualSpatial.Columns.Add("b_crustal_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("b_EC_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("b_NH4_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("b_OC_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("b_SO4_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("b_NO3_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("b_water_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("b_other_mass_ga");
                    //dtGradAdjAnnualSpatial.Columns.Add("f_blank_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("f_crustal_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("f_EC_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("f_NH4_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("f_OC_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("f_SO4_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("f_NO3_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("f_water_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("f_other_mass_ga");
                    dtGradAdjAnnualSpatial.Columns.Add("rrf_crustal");
                    dtGradAdjAnnualSpatial.Columns.Add("rrf_ec");
                    dtGradAdjAnnualSpatial.Columns.Add("rrf_nh4");
                    dtGradAdjAnnualSpatial.Columns.Add("rrf_oc");
                    dtGradAdjAnnualSpatial.Columns.Add("rrf_so4");
                    dtGradAdjAnnualSpatial.Columns.Add("rrf_no3");
                    dtGradAdjAnnualSpatial.Columns.Add("rrf_water");
                    dtGradAdjAnnualSpatial.Columns.Add("rrf_other");
                }
                #endregion
                #region
                if (useSpecies)
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicSpatialFieldGradAdj)
                    {
                        DataRow dr = dtGradAdjAnnualSpatial.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.latitude;
                        dr[2] = k.Value.longitude;
                        dr[3] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bPMAnnDV).Average(), 2);
                        dr[4] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fPMAnnDV).Average(), 2);
                        //dr[5] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                        dr[5] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bCrustalMass).Average(), CommonClass.Species_calc_precision);
                        dr[6] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bECMass).Average(), CommonClass.Species_calc_precision);
                        dr[7] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bNH4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[8] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bOCMass).Average(), CommonClass.Species_calc_precision);
                        dr[9] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bSO4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[10] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bNO3Mass).Average(), CommonClass.Species_calc_precision);
                        dr[11] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bWaterMass).Average(), CommonClass.Species_calc_precision);
                        dr[12] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bOtherMass).Average(), CommonClass.Species_calc_precision);
                        //dr[14] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                        dr[13] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fCrustalMass).Average(), CommonClass.Species_calc_precision);
                        dr[14] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fECMass).Average(), CommonClass.Species_calc_precision);
                        dr[15] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fNH4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[16] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fOCMass).Average(), CommonClass.Species_calc_precision);
                        dr[17] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fSO4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[18] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fNO3Mass).Average(), CommonClass.Species_calc_precision);
                        dr[19] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fWaterMass).Average(), CommonClass.Species_calc_precision);
                        dr[20] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fOtherMass).Average(), CommonClass.Species_calc_precision);
                        dr[21] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fCrustalMass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bCrustalMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fCrustalMass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bCrustalMass).Average(), 4);
                        dr[22] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fECMass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bECMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fECMass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bECMass).Average(), 4);
                        dr[23] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fNH4Mass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bNH4Mass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fNH4Mass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bNH4Mass).Average(), 4);
                        dr[24] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fOCMass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bOCMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fOCMass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bOCMass).Average(), 4);
                        dr[25] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fSO4Mass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bSO4Mass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fSO4Mass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bSO4Mass).Average(), 4);
                        //dr[28] = Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fNO3Mass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bNO3rMass).Average(), 4);
                        dr[26] = k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bNO3Mass).Average() == 0 ? -9 : Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fNO3Mass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bNO3Mass).Average(), 4);
                        dr[27] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fWaterMass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bWaterMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fWaterMass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bWaterMass).Average(), 4);
                        dr[28] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fOtherMass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bOtherMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.fOtherMass).Average() / k.Value.dicQuarterlySpatialGradientAdjusted.Select(p => p.Value.bOtherMass).Average(), 4);
                        dtGradAdjAnnualSpatial.Rows.Add(dr);
                    }
                }
                else
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicSpatialFieldGradAdj)
                    {
                        DataRow dr = dtGradAdjAnnualSpatial.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.latitude;
                        dr[2] = k.Value.longitude;
                        dr[3] = CommonClass.ToFixed(k.Value.dicpmSpatial.Select(p => p.Value[2]).ToList().Average(), 2);
                        dr[4] = CommonClass.ToFixed(k.Value.dicpmSpatial.Select(p => p.Value[3]).ToList().Average(), 2);
                        dtGradAdjAnnualSpatial.Rows.Add(dr);
                    }
                }
                #endregion

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);
                //修正文件名称
                string strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Grad Adj Annual PM25 Spatial Field.csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtGradAdjAnnualSpatial, _resultFilePath + @"\" + strFile, "Year");
                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);
                dtGradAdjAnnualSpatial.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool SaveAnnualPointSpatialFieldwVNA(BaseScenario baseScenario, Dictionary<string, PMMonitorChina> dicSpatialFieldwVNA, bool useSpecies)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
                return false;
            try
            {
                dicSpatialFieldwVNA = dicSpatialFieldwVNA.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                DataTable dtAnnualPMSpatialwVNA = new DataTable();
                #region
                dtAnnualPMSpatialwVNA.Columns.Add("_id");
                dtAnnualPMSpatialwVNA.Columns.Add("gridcell_lat");
                dtAnnualPMSpatialwVNA.Columns.Add("gridcell_long");
                dtAnnualPMSpatialwVNA.Columns.Add("b_pm25_ann_DV_wvna");
                dtAnnualPMSpatialwVNA.Columns.Add("f_pm25_ann_DV_wvna");
                //dtAnnualPMSpatialwVNA.Columns.Add("b_blank_mass_wvna");
                if (useSpecies)
                {
                    dtAnnualPMSpatialwVNA.Columns.Add("b_crustal_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("b_EC_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("b_NH4_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("b_OC_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("b_SO4_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("b_NO3_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("b_water_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("b_other_mass_wvna");
                    //dtAnnualPMSpatialwVNA.Columns.Add("f_blank_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("f_crustal_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("f_EC_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("f_NH4_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("f_OC_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("f_SO4_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("f_NO3_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("f_water_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("f_other_mass_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("rrf_crustal_wvna");
                    dtAnnualPMSpatialwVNA.Columns.Add("rrf_ec");
                    dtAnnualPMSpatialwVNA.Columns.Add("rrf_nh4");
                    dtAnnualPMSpatialwVNA.Columns.Add("rrf_oc");
                    dtAnnualPMSpatialwVNA.Columns.Add("rrf_so4");
                    dtAnnualPMSpatialwVNA.Columns.Add("rrf_no3");
                    dtAnnualPMSpatialwVNA.Columns.Add("rrf_water");
                    dtAnnualPMSpatialwVNA.Columns.Add("rrf_other");
                }
                #endregion
                #region
                if (useSpecies)
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicSpatialFieldwVNA)
                    {
                        DataRow dr = dtAnnualPMSpatialwVNA.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.latitude;
                        dr[2] = k.Value.longitude;
                        dr[3] = CommonClass.ToFixed(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bPMAnnDV).Average(), 2);
                        dr[4] = CommonClass.ToFixed(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fPMAnnDV).Average(), 2);
                        //dr[5] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                        dr[5] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bCrustalMass).Average(), CommonClass.Species_calc_precision);
                        dr[6] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bECMass).Average(), CommonClass.Species_calc_precision);
                        dr[7] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bNH4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[8] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bOCMass).Average(), CommonClass.Species_calc_precision);
                        dr[9] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bSO4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[10] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bNO3Mass).Average(), CommonClass.Species_calc_precision);
                        dr[11] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bWaterMass).Average(), CommonClass.Species_calc_precision);
                        dr[12] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bOtherMass).Average(), CommonClass.Species_calc_precision);
                        //dr[14] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                        dr[13] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fCrustalMass).Average(), CommonClass.Species_calc_precision);
                        dr[14] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fECMass).Average(), CommonClass.Species_calc_precision);
                        dr[15] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fNH4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[16] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fOCMass).Average(), CommonClass.Species_calc_precision);
                        dr[17] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fSO4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[18] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fNO3Mass).Average(), CommonClass.Species_calc_precision);
                        dr[19] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fWaterMass).Average(), CommonClass.Species_calc_precision);
                        dr[20] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fOtherMass).Average(), CommonClass.Species_calc_precision);
                        dr[21] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fCrustalMass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bCrustalMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fCrustalMass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bCrustalMass).Average(), 4);
                        dr[22] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fECMass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bECMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fECMass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bECMass).Average(), 4);
                        dr[23] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fNH4Mass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bNH4Mass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fNH4Mass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bNH4Mass).Average(), 4);
                        dr[24] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fOCMass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bOCMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fOCMass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bOCMass).Average(), 4);
                        dr[25] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fSO4Mass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bSO4Mass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fSO4Mass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bSO4Mass).Average(), 4);
                        //dr[28] = Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fNO3Mass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bNO3rMass).Average(), 4);
                        dr[26] = Double.IsNaN(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bNO3Mass).Average() == 0 ? 0 : Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fNO3Mass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bNO3Mass).Average(), 4)) ? -9 : k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bNO3Mass).Average() == 0 ? -9 : Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fNO3Mass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bNO3Mass).Average(), 4);
                        dr[27] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fWaterMass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bWaterMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fWaterMass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bWaterMass).Average(), 4);
                        dr[28] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fOtherMass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bOtherMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.fOtherMass).Average() / k.Value.dicQuarterlySpatial_wVNA.Select(p => p.Value.bOtherMass).Average(), 4);
                        dtAnnualPMSpatialwVNA.Rows.Add(dr);
                    }
                }
                else
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicSpatialFieldwVNA)
                    {
                        DataRow dr = dtAnnualPMSpatialwVNA.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.latitude;
                        dr[2] = k.Value.longitude;
                        dr[3] = CommonClass.ToFixed(k.Value.dicpmSpatial.Select(p => p.Value[6]).ToList().Average(), 2);
                        dr[4] = CommonClass.ToFixed(k.Value.dicpmSpatial.Select(p => p.Value[7]).ToList().Average(), 2);
                        dtAnnualPMSpatialwVNA.Rows.Add(dr);
                    }
                }
                #endregion

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);

                //修正文件名称
                string strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Annual PM25 Spatial Field(wVNA).csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtAnnualPMSpatialwVNA, _resultFilePath + @"\" + strFile, "Year");
                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);
                dtAnnualPMSpatialwVNA.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool SaveAnnualPointSpatialFieldNearestSite(BaseScenario baseScenario, Dictionary<string, PMMonitorChina> dicSpatialFieldNearestSite, bool useSpecies)
        {
            if (!(baseScenario.configuration is AnnualPMAnalysisChinaConfiguration))
                return false;
            try
            {
                dicSpatialFieldNearestSite = dicSpatialFieldNearestSite.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                AnnualPMAnalysisChinaConfiguration annualPMAnalysisConfiguration = baseScenario.configuration as AnnualPMAnalysisChinaConfiguration;
                DataTable dtNSAnnualPMSpatial = new DataTable();
                #region
                dtNSAnnualPMSpatial.Columns.Add("_id");
                dtNSAnnualPMSpatial.Columns.Add("gridcell_lat");
                dtNSAnnualPMSpatial.Columns.Add("gridcell_long");
                dtNSAnnualPMSpatial.Columns.Add("b_pm25_ann_DV_ns");
                dtNSAnnualPMSpatial.Columns.Add("f_pm25_ann_DV_ns");
                //dtNSAnnualPMSpatial.Columns.Add("b_blank_mass");
                if (useSpecies)
                {
                    dtNSAnnualPMSpatial.Columns.Add("b_crustal_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("b_EC_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("b_NH4_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("b_OC_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("b_SO4_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("b_NO3_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("b_water_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("b_other_mass_ns");
                    //dtNSAnnualPMSpatial.Columns.Add("f_blank_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("f_crustal_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("f_EC_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("f_NH4_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("f_OC_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("f_SO4_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("f_NO3_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("f_water_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("f_other_mass_ns");
                    dtNSAnnualPMSpatial.Columns.Add("rrf_crustal");
                    dtNSAnnualPMSpatial.Columns.Add("rrf_ec");
                    dtNSAnnualPMSpatial.Columns.Add("rrf_nh4");
                    dtNSAnnualPMSpatial.Columns.Add("rrf_oc");
                    dtNSAnnualPMSpatial.Columns.Add("rrf_so4");
                    dtNSAnnualPMSpatial.Columns.Add("rrf_no3");
                    dtNSAnnualPMSpatial.Columns.Add("rrf_water");
                    dtNSAnnualPMSpatial.Columns.Add("rrf_other");
                }
                #endregion
                #region
                if (useSpecies)
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicSpatialFieldNearestSite)
                    {
                        DataRow dr = dtNSAnnualPMSpatial.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.latitude;
                        dr[2] = k.Value.longitude;
                        dr[3] = CommonClass.ToFixed(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bPMAnnDV).Average(), 2);
                        dr[4] = CommonClass.ToFixed(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fPMAnnDV).Average(), 2);
                        //dr[5] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                        dr[5] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bCrustalMass).Average(), CommonClass.Species_calc_precision);
                        dr[6] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bECMass).Average(), CommonClass.Species_calc_precision);
                        dr[7] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bNH4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[8] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bOCMass).Average(), CommonClass.Species_calc_precision);
                        dr[9] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bSO4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[10] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bNO3Mass).Average(), CommonClass.Species_calc_precision);
                        dr[11] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bWaterMass).Average(), CommonClass.Species_calc_precision);
                        dr[12] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bOtherMass).Average(), CommonClass.Species_calc_precision);
                        //dr[14] = Math.Round(annualPMAnalysisConfiguration.speciesFractionOptionsA.defaultBlankMass, CommonClass.Species_calc_precision);
                        dr[13] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fCrustalMass).Average(), CommonClass.Species_calc_precision);
                        dr[14] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fECMass).Average(), CommonClass.Species_calc_precision);
                        dr[15] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fNH4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[16] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fOCMass).Average(), CommonClass.Species_calc_precision);
                        dr[17] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fSO4Mass).Average(), CommonClass.Species_calc_precision);
                        dr[18] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fNO3Mass).Average(), CommonClass.Species_calc_precision);
                        dr[19] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fWaterMass).Average(), CommonClass.Species_calc_precision);
                        dr[20] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fOtherMass).Average(), CommonClass.Species_calc_precision);
                        dr[21] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fCrustalMass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bCrustalMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fCrustalMass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bCrustalMass).Average(), 4);
                        dr[22] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fECMass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bECMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fECMass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bECMass).Average(), 4);
                        dr[23] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fNH4Mass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bNH4Mass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fNH4Mass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bNH4Mass).Average(), 4);
                        dr[24] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fOCMass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bOCMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fOCMass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bOCMass).Average(), 4);
                        dr[25] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fSO4Mass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bSO4Mass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fSO4Mass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bSO4Mass).Average(), 4);
                        //dr[28] = Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fNO3Mass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bNO3rMass).Average(), 4);
                        dr[26] = Double.IsNaN(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bNO3Mass).Average() == 0 ? 0 : Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fNO3Mass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bNO3Mass).Average(), 4)) ? -9 : k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bNO3Mass).Average() == 0 ? -9 : Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fNO3Mass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bNO3Mass).Average(), 4);
                        dr[27] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fWaterMass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bWaterMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fWaterMass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bWaterMass).Average(), 4);
                        dr[28] = Double.IsNaN(Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fOtherMass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bOtherMass).Average(), 4)) ? -9 : Math.Round(k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.fOtherMass).Average() / k.Value.dicQuarterlySpatial_NS.Select(p => p.Value.bOtherMass).Average(), 4);
                        dtNSAnnualPMSpatial.Rows.Add(dr);
                    }
                }
                else
                {
                    foreach (KeyValuePair<string, PMMonitorChina> k in dicSpatialFieldNearestSite)
                    {
                        DataRow dr = dtNSAnnualPMSpatial.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.latitude;
                        dr[2] = k.Value.longitude;
                        dr[3] = CommonClass.ToFixed(k.Value.dicpmSpatial.Select(p => p.Value[4]).ToList().Average(), 2);
                        dr[4] = CommonClass.ToFixed(k.Value.dicpmSpatial.Select(p => p.Value[5]).ToList().Average(), 2);
                        dtNSAnnualPMSpatial.Rows.Add(dr);
                    }
                }
                #endregion

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as AnnualPMAnalysisChinaConfiguration).modelDataInputChina.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);

                //修正文件名称
                string strFile = annualPMAnalysisConfiguration.modelDataInputChina.scenarioName + " Nearest Site Annual PM25 Spatial Field.csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtNSAnnualPMSpatial, _resultFilePath + @"\" + strFile, "Year");
                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);
                dtNSAnnualPMSpatial.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

    }
}
