示例#1
0
        public static ISink GetSinkModel(string ModelID)
        {
            ISink NewModel = null;

            switch (ModelID)
            {
            case "SmallLakesSink":
                NewModel = new SmallLakesSink();
                break;

            case "StreamSink":
                NewModel = new StreamSink();
                break;

            case "LakeSink":
                NewModel = new LakeSink();
                break;

            case "ConstructedWetland":
                NewModel = new ConstructedWetlandSink();
                break;

            case "ConceptualSourceReducer":
                NewModel = new ConceptualSourceReducer();
                break;
            }
            return(NewModel);
        }
示例#2
0
 public static ISink GetSinkModel(string ModelID)
 {
   ISink NewModel = null;
   switch (ModelID)
   {
     case "SmallLakesSink":
       NewModel = new SmallLakesSink();
       break;
     case "StreamSink":
       NewModel = new StreamSink();
       break;
     case "LakeSink":
       NewModel = new LakeSink();
       break;
     case "ConstructedWetland":
       NewModel = new ConstructedWetlandSink();
       break;
     case "ConceptualSourceReducer":
       NewModel = new ConceptualSourceReducer();
       break;
   }
   return NewModel;
 }
示例#3
0
    public void Calibrate(MainModel MW, DateTime CStart, DateTime CEnd)
    {
      dt.Columns.Add("ID15", typeof(int));
      dt.Columns.Add("No_iterations", typeof(int));
      dt.Columns.Add("LastError", typeof(double));
      dt.Columns.Add("GWRatio", typeof(double));
      dt.Columns.Add("IntRatio", typeof(double));
      dt.Columns.Add("MainRatio", typeof(double));

      dt.Columns.Add("RedFactor", typeof(double));
      dt.PrimaryKey = new DataColumn[]{ dt.Columns[0]};
      DateTime CurrentTime = CStart;


      string gwsourcename =MW.SourceModels.Single(s=>s.GetType()==typeof(GroundWaterSource)).Name;
      foreach (var item in MW.AllCatchments.Values)
      {
        var row = dt.NewRow();
        row[0] = item.ID;
        CurrentTime = CStart;

        double gwleach = 0;
        double gwsourec = 0;
        double gwConcDeg = 0;
        double intsource = 0;
        double intred = 0;
        double upstream = 0;
        double mainred = 0;

        while (CurrentTime < CEnd)
        {
          double IntMass = 0;
          var CurrentState = MW.StateVariables.Rows.Find(new object[] { item.ID, CurrentTime });

          gwleach += (double) CurrentState["Leaching"];

          gwsourec += (double)CurrentState[gwsourcename];
          IntMass = (double)CurrentState[gwsourcename];

          foreach (var conc in MW.InternalReductionModels.Where(s => s.GetType() == typeof(ConceptualSourceReducer) && ((ConceptualSourceReducer)s).SourceModelName == gwsourcename))
          {
            gwConcDeg += (double)CurrentState[conc.Name];
            IntMass -= (double)CurrentState[conc.Name];
          }

          foreach (var intsou in MW.SourceModels.Where(s => s.Name != gwsourcename))
          {
            intsource += (double)CurrentState[intsou.Name];
            IntMass += (double)CurrentState[intsou.Name];
          }

          foreach (var conc in MW.InternalReductionModels.Where(s => s.GetType() != typeof(ConceptualSourceReducer)))
          {
            intred += (double)CurrentState[conc.Name];
            IntMass -= (double)CurrentState[conc.Name];
          }

          foreach (var mainr in MW.MainStreamRecutionModels)
          {
            if (!CurrentState.IsNull(mainr.Name))
            {
              mainred += (double)CurrentState[mainr.Name];
              IntMass -= (double)CurrentState[mainr.Name];
            }
          }
          if (!CurrentState.IsNull("DownStreamOutput"))
          {
            IntMass = (double)CurrentState["DownStreamOutput"] - IntMass;

            upstream += IntMass;
          }
          CurrentTime = CurrentTime.AddMonths(1);
        }

        if (gwleach == 0)
          row["GWRatio"]=1;
        else
          row["GWRatio"] = (gwleach - gwsourec + gwConcDeg) / gwleach;
        row["IntRatio"] = intred / (gwsourec - gwConcDeg + intsource);
        row["MainRatio"] = mainred / (gwsourec - gwConcDeg + intsource - intred + upstream);

        dt.Rows.Add(row);
      }

      
       CurrentTime = CStart;

      this.MW = MW;
      List<Catchment> SortedCatchments = new List<Catchment>();

      ConceptualSourceReducer GWCor = new ConceptualSourceReducer();
      GWCor.Name = "Calibrator";
      GWCor.SourceModelName = "GroundWater";

      var LastConceptual = MW.InternalReductionModels.LastOrDefault(c => c.GetType() == typeof(ConceptualSourceReducer));
      if (LastConceptual == null)
        MW.InternalReductionModels.Insert(0, GWCor);
      else
        MW.InternalReductionModels.Insert(MW.InternalReductionModels.IndexOf(LastConceptual) + 1, GWCor);

      if (!MW.StateVariables.Columns.Contains(GWCor.Name))
        MW.StateVariables.Columns.Add(GWCor.Name, typeof(double));

      ConceptualSourceReducer IntCor = new ConceptualSourceReducer();
      IntCor.Name = "Calib_Int";
      MW.InternalReductionModels.Add(IntCor);
      if (!MW.StateVariables.Columns.Contains(IntCor.Name))
        MW.StateVariables.Columns.Add(IntCor.Name, typeof(double));

      ConceptualSourceReducer MainCor = new ConceptualSourceReducer();
      MainCor.Name = "Calib_Main";
      MW.MainStreamRecutionModels.Add(MainCor);
      if (!MW.StateVariables.Columns.Contains(MainCor.Name))
        MW.StateVariables.Columns.Add(MainCor.Name, typeof(double));

      foreach (var item in MW.EndCatchments)
      {
        GetCatchmentsWithObs(item, SortedCatchments);
      }
      foreach (var item in MW.AllCatchments.Values)
      {
        GWCor.Reduction.Add(item.ID, 0);
        IntCor.Reduction.Add(item.ID, 0);
        MainCor.Reduction.Add(item.ID, 0);
      }
      int totaliter = 0;
      foreach (var v in SortedCatchments)
      {
        List<double> Errors = new List<double>();
        double localdamp = DampingFactor;
        double currentreducer = 0;
        double Error = double.MaxValue;
        int itercount = 0;

        var row = dt.Rows.Find(v.ID);

        NewMessage("Calibrating " + v.ID);
        while (Math.Abs(Error) > AbsoluteConvergence & itercount < MaxNoOfIterations)
        {
          v.ObsNitrate = null;
          v.SimNitrate = null;
          double accgws = 0;
          double accs = 0;
          double accsink = 0;
          double accmainsink = 0;
          double obssum = 0;

          CurrentTime = CStart;
          while (CurrentTime < CEnd)
          {
            v.MoveInTime(CurrentTime);
            double obsn =v.Measurements.Nitrate.GetValue(CurrentTime, InterpolationMethods.DeleteValue);
            if (obsn != v.Measurements.Nitrate.DeleteValue)
            {
              obssum += obsn;
              accgws += AccumulateUpstream(GWCor.SourceModelName, v, CurrentTime);
              foreach (var s in MW.InternalReductionModels)
                accsink += AccumulateUpstream(s.Name, v, CurrentTime);
              foreach (var s in MW.SourceModels.Where(ss => ss.Name != GWCor.SourceModelName))
                accs += AccumulateUpstream(s.Name, v, CurrentTime);
              foreach (var s in MW.MainStreamRecutionModels)
                accmainsink += AccumulateUpstream(s.Name, v, CurrentTime);
            }
            CurrentTime = CurrentTime.AddMonths(1);
          }

          double[] sim;
          double[] obs;
          v.ObsNitrate.AlignRemoveDeletevalues(v.SimNitrate, out obs, out sim);
          double simerror = obs.Sum() - sim.Sum();


          Error = (accs + accgws - accsink - accmainsink) - obssum;

          if (itercount == 0 & double.IsNaN(Error))
          {
            NewMessage("Initial error is NAN. Could not calibrate " + v.ID);
            break;
          }


          
          currentreducer = Error / accgws * localdamp;

          Errors.Add(Error);
          NewMessage(Error.ToString());

          if (double.IsNaN(Error) || (itercount > 2 && Math.Abs(Error) > Errors.Skip(itercount - 3).Take(3).Select(e => Math.Abs(e)).Max()))
          {
            SendReducUpstream(v, GWCor.Reduction, currentreducer, "GWRatio", true);
            SendReducUpstream(v, IntCor.Reduction, InternalRatio * currentreducer, "IntRatio", true);
            SendReducUpstream(v, MainCor.Reduction, MainRatio * currentreducer, "MainRatio", true);

            NewMessage("Reduce damping and resetting reducer to first value");
            localdamp *= 0.5;
            currentreducer = Errors.First() / accgws * localdamp;

            Error = 2 * AbsoluteConvergence; //To make sure we do not NAN for testing in the next iteration.
          }

          SendReducUpstream(v, GWCor.Reduction, currentreducer, "GWRatio",false);
          SendReducUpstream(v, IntCor.Reduction, InternalRatio * currentreducer, "IntRatio", false);
          SendReducUpstream(v, MainCor.Reduction, MainRatio * currentreducer, "MainRatio", false);
          itercount++;
        }
        totaliter += itercount;

        row[0] = v.ID;
        row[1] = itercount;
        row[2] = Error;
        row["RedFactor"] = GWCor.Reduction[v.ID];

        NewMessage(v.ID + " calibrated in " + itercount + " iterations. Final error: " + Error + ". ReductionFactor: " + GWCor.Reduction[v.ID]);
      }
      NewMessage("Total number of model calls: " + totaliter);
      var outdir = Path.GetDirectoryName(MW.AlldataFile.FileName);
      GWCor.DebugPrint(outdir, MW.AllCatchments);
      IntCor.DebugPrint(outdir, MW.AllCatchments);
      MainCor.DebugPrint(outdir, MW.AllCatchments);

      using (ShapeWriter sw = new ShapeWriter(Path.Combine(outdir, "CalibrationResult")) { Projection = MainModel.projection })
      {
        for (int i = 0; i < dt.Rows.Count; i++)
        {
          GeoRefData gd = new GeoRefData() { Geometry = MW.AllCatchments[(int)dt.Rows[i][0]].Geometry };
          gd.Data = dt.Rows[i];
          sw.Write(gd);
        }
      }




    }
示例#4
0
        public void Calibrate(MainModel MW, DateTime CStart, DateTime CEnd)
        {
            dt.Columns.Add("ID15", typeof(int));
            dt.Columns.Add("No_iterations", typeof(int));
            dt.Columns.Add("LastError", typeof(double));
            dt.Columns.Add("GWRatio", typeof(double));
            dt.Columns.Add("IntRatio", typeof(double));
            dt.Columns.Add("MainRatio", typeof(double));

            dt.Columns.Add("RedFactor", typeof(double));
            dt.PrimaryKey = new DataColumn[] { dt.Columns[0] };
            DateTime CurrentTime = CStart;


            string gwsourcename = MW.SourceModels.Single(s => s.GetType() == typeof(GroundWaterSource)).Name;

            foreach (var item in MW.AllCatchments.Values)
            {
                var row = dt.NewRow();
                row[0]      = item.ID;
                CurrentTime = CStart;

                double gwleach   = 0;
                double gwsourec  = 0;
                double gwConcDeg = 0;
                double intsource = 0;
                double intred    = 0;
                double upstream  = 0;
                double mainred   = 0;

                while (CurrentTime < CEnd)
                {
                    double IntMass      = 0;
                    var    CurrentState = MW.StateVariables.Rows.Find(new object[] { item.ID, CurrentTime });

                    gwleach += (double)CurrentState["Leaching"];

                    gwsourec += (double)CurrentState[gwsourcename];
                    IntMass   = (double)CurrentState[gwsourcename];

                    foreach (var conc in MW.InternalReductionModels.Where(s => s.GetType() == typeof(ConceptualSourceReducer) && ((ConceptualSourceReducer)s).SourceModelName == gwsourcename))
                    {
                        gwConcDeg += (double)CurrentState[conc.Name];
                        IntMass   -= (double)CurrentState[conc.Name];
                    }

                    foreach (var intsou in MW.SourceModels.Where(s => s.Name != gwsourcename))
                    {
                        intsource += (double)CurrentState[intsou.Name];
                        IntMass   += (double)CurrentState[intsou.Name];
                    }

                    foreach (var conc in MW.InternalReductionModels.Where(s => s.GetType() != typeof(ConceptualSourceReducer)))
                    {
                        intred  += (double)CurrentState[conc.Name];
                        IntMass -= (double)CurrentState[conc.Name];
                    }

                    foreach (var mainr in MW.MainStreamRecutionModels)
                    {
                        if (!CurrentState.IsNull(mainr.Name))
                        {
                            mainred += (double)CurrentState[mainr.Name];
                            IntMass -= (double)CurrentState[mainr.Name];
                        }
                    }
                    if (!CurrentState.IsNull("DownStreamOutput"))
                    {
                        IntMass = (double)CurrentState["DownStreamOutput"] - IntMass;

                        upstream += IntMass;
                    }
                    CurrentTime = CurrentTime.AddMonths(1);
                }

                if (gwleach == 0)
                {
                    row["GWRatio"] = 1;
                }
                else
                {
                    row["GWRatio"] = (gwleach - gwsourec + gwConcDeg) / gwleach;
                }
                row["IntRatio"]  = intred / (gwsourec - gwConcDeg + intsource);
                row["MainRatio"] = mainred / (gwsourec - gwConcDeg + intsource - intred + upstream);

                dt.Rows.Add(row);
            }


            CurrentTime = CStart;

            this.MW = MW;
            List <Catchment> SortedCatchments = new List <Catchment>();

            ConceptualSourceReducer GWCor = new ConceptualSourceReducer();

            GWCor.Name            = "Calibrator";
            GWCor.SourceModelName = "GroundWater";

            var LastConceptual = MW.InternalReductionModels.LastOrDefault(c => c.GetType() == typeof(ConceptualSourceReducer));

            if (LastConceptual == null)
            {
                MW.InternalReductionModels.Insert(0, GWCor);
            }
            else
            {
                MW.InternalReductionModels.Insert(MW.InternalReductionModels.IndexOf(LastConceptual) + 1, GWCor);
            }

            if (!MW.StateVariables.Columns.Contains(GWCor.Name))
            {
                MW.StateVariables.Columns.Add(GWCor.Name, typeof(double));
            }

            ConceptualSourceReducer IntCor = new ConceptualSourceReducer();

            IntCor.Name = "Calib_Int";
            MW.InternalReductionModels.Add(IntCor);
            if (!MW.StateVariables.Columns.Contains(IntCor.Name))
            {
                MW.StateVariables.Columns.Add(IntCor.Name, typeof(double));
            }

            ConceptualSourceReducer MainCor = new ConceptualSourceReducer();

            MainCor.Name = "Calib_Main";
            MW.MainStreamRecutionModels.Add(MainCor);
            if (!MW.StateVariables.Columns.Contains(MainCor.Name))
            {
                MW.StateVariables.Columns.Add(MainCor.Name, typeof(double));
            }

            foreach (var item in MW.EndCatchments)
            {
                GetCatchmentsWithObs(item, SortedCatchments);
            }
            foreach (var item in MW.AllCatchments.Values)
            {
                GWCor.Reduction.Add(item.ID, 0);
                IntCor.Reduction.Add(item.ID, 0);
                MainCor.Reduction.Add(item.ID, 0);
            }
            int totaliter = 0;

            foreach (var v in SortedCatchments)
            {
                List <double> Errors         = new List <double>();
                double        localdamp      = DampingFactor;
                double        currentreducer = 0;
                double        Error          = double.MaxValue;
                int           itercount      = 0;

                var row = dt.Rows.Find(v.ID);

                NewMessage("Calibrating " + v.ID);
                while (Math.Abs(Error) > AbsoluteConvergence & itercount < MaxNoOfIterations)
                {
                    v.ObsNitrate = null;
                    v.SimNitrate = null;
                    double accgws      = 0;
                    double accs        = 0;
                    double accsink     = 0;
                    double accmainsink = 0;
                    double obssum      = 0;

                    CurrentTime = CStart;
                    while (CurrentTime < CEnd)
                    {
                        v.MoveInTime(CurrentTime);
                        double obsn = v.Measurements.Nitrate.GetValue(CurrentTime, InterpolationMethods.DeleteValue);
                        if (obsn != v.Measurements.Nitrate.DeleteValue)
                        {
                            obssum += obsn;
                            accgws += AccumulateUpstream(GWCor.SourceModelName, v, CurrentTime);
                            foreach (var s in MW.InternalReductionModels)
                            {
                                accsink += AccumulateUpstream(s.Name, v, CurrentTime);
                            }
                            foreach (var s in MW.SourceModels.Where(ss => ss.Name != GWCor.SourceModelName))
                            {
                                accs += AccumulateUpstream(s.Name, v, CurrentTime);
                            }
                            foreach (var s in MW.MainStreamRecutionModels)
                            {
                                accmainsink += AccumulateUpstream(s.Name, v, CurrentTime);
                            }
                        }
                        CurrentTime = CurrentTime.AddMonths(1);
                    }

                    double[] sim;
                    double[] obs;
                    v.ObsNitrate.AlignRemoveDeletevalues(v.SimNitrate, out obs, out sim);
                    double simerror = obs.Sum() - sim.Sum();


                    Error = (accs + accgws - accsink - accmainsink) - obssum;

                    if (itercount == 0 & double.IsNaN(Error))
                    {
                        NewMessage("Initial error is NAN. Could not calibrate " + v.ID);
                        break;
                    }



                    currentreducer = Error / accgws * localdamp;

                    Errors.Add(Error);
                    NewMessage(Error.ToString());

                    if (double.IsNaN(Error) || (itercount > 2 && Math.Abs(Error) > Errors.Skip(itercount - 3).Take(3).Select(e => Math.Abs(e)).Max()))
                    {
                        SendReducUpstream(v, GWCor.Reduction, currentreducer, "GWRatio", true);
                        SendReducUpstream(v, IntCor.Reduction, InternalRatio * currentreducer, "IntRatio", true);
                        SendReducUpstream(v, MainCor.Reduction, MainRatio * currentreducer, "MainRatio", true);

                        NewMessage("Reduce damping and resetting reducer to first value");
                        localdamp     *= 0.5;
                        currentreducer = Errors.First() / accgws * localdamp;

                        Error = 2 * AbsoluteConvergence; //To make sure we do not NAN for testing in the next iteration.
                    }

                    SendReducUpstream(v, GWCor.Reduction, currentreducer, "GWRatio", false);
                    SendReducUpstream(v, IntCor.Reduction, InternalRatio * currentreducer, "IntRatio", false);
                    SendReducUpstream(v, MainCor.Reduction, MainRatio * currentreducer, "MainRatio", false);
                    itercount++;
                }
                totaliter += itercount;

                row[0]           = v.ID;
                row[1]           = itercount;
                row[2]           = Error;
                row["RedFactor"] = GWCor.Reduction[v.ID];

                NewMessage(v.ID + " calibrated in " + itercount + " iterations. Final error: " + Error + ". ReductionFactor: " + GWCor.Reduction[v.ID]);
            }
            NewMessage("Total number of model calls: " + totaliter);
            var outdir = Path.GetDirectoryName(MW.AlldataFile.FileName);

            GWCor.DebugPrint(outdir, MW.AllCatchments);
            IntCor.DebugPrint(outdir, MW.AllCatchments);
            MainCor.DebugPrint(outdir, MW.AllCatchments);

            using (ShapeWriter sw = new ShapeWriter(Path.Combine(outdir, "CalibrationResult"))
            {
                Projection = MainModel.projection
            })
            {
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    GeoRefData gd = new GeoRefData()
                    {
                        Geometry = MW.AllCatchments[(int)dt.Rows[i][0]].Geometry
                    };
                    gd.Data = dt.Rows[i];
                    sw.Write(gd);
                }
            }
        }