/// <summary> /// Adds a water packet to the lake. /// This method is to be used by upstream connections. /// /// </summary> /// <param name="Start">Start of inflow period</param> /// <param name="End">End of inflow period</param> /// <param name="Water"></param> public void AddWaterPacket(DateTime Start, DateTime End, IWaterPacket Water) { Water.Tag(ID); _waterReceivedSinceLastUpdate += Water.Volume; CurrentStoredWater.Add(Water); }
/// <summary> /// This is the timestepping method /// </summary> /// <param name="TimeStep"></param> public void Update(DateTime NewTime) { TimeSpan TimeStep = NewTime.Subtract(CurrentTime); //Log input of water. Could be zero Output.Inflow.AddSiValue(CurrentTime, NewTime, _waterReceivedSinceLastUpdate / TimeStep.TotalSeconds); _waterReceivedSinceLastUpdate = 0; double vol = CurrentStoredWater.Volume; //loop the sources foreach (ISource IWS in Sources) { CurrentStoredWater.Add(IWS.GetSourceWater(CurrentTime, TimeStep)); } //Update output Output.Sources.AddSiValue(CurrentTime, NewTime, (CurrentStoredWater.Volume - vol) / TimeStep.TotalSeconds); vol = CurrentStoredWater.Volume; //Loop the groundwater sources foreach (var gwb in GroundwaterBoundaries.Where(var => var.IsSource(CurrentTime))) { CurrentStoredWater.Add(gwb.GetSourceWater(CurrentTime, TimeStep)); } //Update output Output.GroundwaterInflow.AddSiValue(CurrentTime, NewTime, (CurrentStoredWater.Volume - vol) / TimeStep.TotalSeconds); vol = CurrentStoredWater.Volume; //Loop the precipitation foreach (ISource IWS in Precipitation) { CurrentStoredWater.Add(IWS.GetSourceWater(CurrentTime, TimeStep)); } //Update output Output.Precipitation.AddSiValue(CurrentTime, NewTime, (CurrentStoredWater.Volume - vol) / TimeStep.TotalSeconds); vol = CurrentStoredWater.Volume; //Loop the Evaporation boundaries foreach (var IEB in _evapoBoundaries) { CurrentStoredWater.Evaporate(IEB.GetSinkVolume(CurrentTime, TimeStep)); } //Update output Output.Evaporation.AddSiValue(CurrentTime, NewTime, -(CurrentStoredWater.Volume - vol) / TimeStep.TotalSeconds); vol = CurrentStoredWater.Volume; //loop the sinks if (CurrentStoredWater.Volume > 0) { foreach (var IWS in Sinks) { double sinkvolume = IWS.GetSinkVolume(CurrentTime, TimeStep); IWS.ReceiveSinkWater(CurrentTime, TimeStep, CurrentStoredWater.Substract(sinkvolume)); } } //Update output Output.Sinks.AddSiValue(CurrentTime, NewTime, (vol - CurrentStoredWater.Volume) / TimeStep.TotalSeconds); vol = CurrentStoredWater.Volume; //Loop the groundwater sinks if (CurrentStoredWater.Volume > 0) { foreach (var gwb in GroundwaterBoundaries.Where(var => !var.IsSource(CurrentTime))) { double sinkvolume = gwb.GetSinkVolume(CurrentTime, TimeStep); gwb.ReceiveSinkWater(CurrentTime, TimeStep, CurrentStoredWater.Substract(sinkvolume)); } } //Update output Output.GroundwaterOutflow.AddSiValue(CurrentTime, NewTime, (vol - CurrentStoredWater.Volume) / TimeStep.TotalSeconds); vol = CurrentStoredWater.Volume; IWaterPacket WaterToRoute; //Now substract the water that is to be routed if (CurrentStoredWater.Volume > Volume) //Only go here if there is a surplus of water. { WaterToRoute = CurrentStoredWater.Substract(CurrentStoredWater.Volume - Volume); //Write routed water. The value is the average value for the timestep Output.Outflow.AddSiValue(CurrentTime, NewTime, WaterToRoute.Volume / TimeStep.TotalSeconds); SendWaterDownstream(WaterToRoute, CurrentTime, NewTime); } else { Output.Outflow.AddSiValue(CurrentTime, NewTime, 0); } //Write current volume to output. The calculated volume is at the end of the timestep Output.StoredVolume.AddSiValue(NewTime, CurrentStoredWater.Volume); //Move the water in time. Consider if this the right place to do it or it should be at the beginning of the time step CurrentStoredWater.MoveInTime(TimeStep, ChemicalFactory.Instance.LakeReactions, Area); //Log Output Output.Log(CurrentStoredWater, CurrentTime, NewTime); CurrentTime = NewTime; }