///<summary>Get the shortest time step to activate the control.</summary> private long GetRequiredTimeStep(EpanetNetwork net, long htime, long tstep) { long t = 0; // Node control if (Node != null) { if (!(Node is SimulationTank)) // Check if node is a tank { return(tstep); } double h = _node.SimHead; // Current tank grade double q = _node.SimDemand; // Flow into tank if (Math.Abs(q) <= Constants.QZERO) { return(tstep); } if ((h < Grade && Type == ControlType.HILEVEL && q > 0.0) || // Tank below hi level & filling (h > Grade && Type == ControlType.LOWLEVEL && q < 0.0)) // Tank above low level & emptying { SimulationTank tank = (SimulationTank)Node; double v = tank.FindVolume(net.FieldsMap, Grade) - tank.SimVolume; t = (long)Math.Round(v / q); // Time to reach level } } // Time control if (Type == ControlType.TIMER) { if (Time > htime) { t = Time - htime; } } // Time-of-day control if (Type == ControlType.TIMEOFDAY) { long t1 = (htime + net.Tstart) % Constants.SECperDAY; long t2 = Time; if (t2 >= t1) { t = t2 - t1; } else { t = Constants.SECperDAY - t1 + t2; } } // Revise time step if (t > 0 && t < tstep) { SimulationLink link = Link; // Check if rule actually changes link status or setting if (link != null && (link.Type > LinkType.PIPE && link.SimSetting != Setting) || (link.SimStatus != Status)) { tstep = t; } } return(tstep); }
/// <summary>Implements simple controls based on time or tank levels.</summary> public static int StepActions( TraceSource log, EpanetNetwork net, IEnumerable <SimulationControl> controls, long htime) { int setsum = 0; // Examine each control statement foreach (SimulationControl control in controls) { bool reset = false; // Make sure that link is defined if (control.Link == null) { continue; } // Link is controlled by tank level var node = control.Node as SimulationTank; if (node != null) { double h = node.SimHead; double vplus = Math.Abs(node.SimDemand); SimulationTank tank = node; double v1 = tank.FindVolume(net.FieldsMap, h); double v2 = tank.FindVolume(net.FieldsMap, control.Grade); if (control.Type == ControlType.LOWLEVEL && v1 <= v2 + vplus) { reset = true; } if (control.Type == ControlType.HILEVEL && v1 >= v2 - vplus) { reset = true; } } // Link is time-controlled if (control.Type == ControlType.TIMER) { if (control.Time == htime) { reset = true; } } // Link is time-of-day controlled if (control.Type == ControlType.TIMEOFDAY) { if ((htime + net.Tstart) % Constants.SECperDAY == control.Time) { reset = true; } } // Update link status & pump speed or valve setting if (reset) { StatType s1, s2; SimulationLink link = control.Link; if (link.SimStatus <= StatType.CLOSED) { s1 = StatType.CLOSED; } else { s1 = StatType.OPEN; } s2 = control.Status; double k1 = link.SimSetting; double k2 = k1; if (control.Link.Type > LinkType.PIPE) { k2 = control.Setting; } if (s1 != s2 || k1 != k2) { link.SimStatus = s2; link.SimSetting = k2; if (net.StatFlag != StatFlag.NO) { LogControlAction(log, control, htime); } setsum++; } } } return(setsum); }