public SimulationControl(IEnumerable <SimulationNode> nodes, IEnumerable <SimulationLink> links, Control @ref) { if (@ref.Node != null) { string nid = @ref.Node.Name; foreach (SimulationNode simulationNode in nodes) { if (simulationNode.Id.Equals(nid, StringComparison.OrdinalIgnoreCase)) { _node = simulationNode; break; } } } if (@ref.Link != null) { string linkId = @ref.Link.Name; foreach (SimulationLink simulationLink in links) { if (simulationLink.Link.Name.Equals(linkId, StringComparison.OrdinalIgnoreCase)) { _link = simulationLink; break; } } } _control = @ref; }
public Action(string[] tok, IEnumerable <SimulationLink> links, string label) { _label = label; int ntokens = tok.Length; Values k; if (ntokens != 6) { throw new ENException(ErrorCode.Err201); } SimulationLink link = links.FirstOrDefault(simLink => simLink.Link.Name.Equals(tok[2], StringComparison.OrdinalIgnoreCase)); if (link == null) { throw new ENException(ErrorCode.Err204); } if (link.Type == LinkType.CV) { throw new ENException(ErrorCode.Err207); } var s = (Values)(-1); double x = double.NaN; if (EnumsTxt.TryParse(tok[5], out k) && k > Values.IS_NUMBER) { s = k; } else { if (!tok[5].ToDouble(out x) || x < 0.0) { throw new ENException(ErrorCode.Err202); } } if (!double.IsNaN(x) && link.Type == LinkType.GPV) { throw new ENException(ErrorCode.Err202); } if (!double.IsNaN(x) && link.Type == LinkType.PIPE) { s = x == 0.0 ? Values.IS_CLOSED : Values.IS_OPEN; x = double.NaN; } _link = link; _status = s; _setting = x; }
private static void LogControlAction(TraceSource log, SimulationControl control, long htime) { SimulationNode n = control.Node; SimulationLink l = control.Link; string msg; switch (control.Type) { case ControlType.LOWLEVEL: case ControlType.HILEVEL: { string type = Keywords.w_JUNC; // NodeType type= NodeType.JUNC; var tank = n as SimulationTank; if (tank != null) { type = tank.IsReservoir ? Keywords.w_RESERV : Keywords.w_TANK; } msg = string.Format( Text.FMT54, htime.GetClockTime(), l.Type.ParseStr(), l.Link.Name, type, n.Id); break; } case ControlType.TIMER: case ControlType.TIMEOFDAY: msg = string.Format( Text.FMT55, htime.GetClockTime(), l.Type.ParseStr(), l.Link.Name); break; default: return; } log.Warning(msg); }
///<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); }
private static void LogStatChange(TraceSource log, FieldsMap fMap, SimulationLink link, StatType oldstatus) { StatType s1 = oldstatus; StatType s2 = link.SimStatus; try { if (s2 == s1) { double setting = link.SimSetting; switch (link.Type) { case LinkType.PRV: case LinkType.PSV: case LinkType.PBV: setting *= fMap.GetUnits(FieldType.PRESSURE); break; case LinkType.FCV: setting *= fMap.GetUnits(FieldType.FLOW); break; } log.Warning( string.Format( Text.FMT56, link.Type.ParseStr(), link.Link.Name, setting)); return; } StatType j1, j2; if (s1 == StatType.ACTIVE) { j1 = StatType.ACTIVE; } else if (s1 <= StatType.CLOSED) { j1 = StatType.CLOSED; } else { j1 = StatType.OPEN; } if (s2 == StatType.ACTIVE) { j2 = StatType.ACTIVE; } else if (s2 <= StatType.CLOSED) { j2 = StatType.CLOSED; } else { j2 = StatType.OPEN; } if (j1 != j2) { log.Warning( Text.FMT57, link.Type.ParseStr(), link.Link.Name, j1.ReportStr(), j2.ReportStr()); } } catch (ENException) {} }
/// <summary>Adjusts settings of links controlled by junction pressures after a hydraulic solution is found.</summary> public static bool PSwitch( TraceSource log, EpanetNetwork net, IEnumerable <SimulationControl> controls) { bool anychange = false; foreach (SimulationControl control in controls) { bool reset = false; if (control.Link == null) { continue; } // Determine if control based on a junction, not a tank if (control.Node != null && !(control.Node is SimulationTank)) { // Determine if control conditions are satisfied if (control.Type == ControlType.LOWLEVEL && control.Node.SimHead <= control.Grade + net.HTol) { reset = true; } if (control.Type == ControlType.HILEVEL && control.Node.SimHead >= control.Grade - net.HTol) { reset = true; } } SimulationLink link = control.Link; // Determine if control forces a status or setting change if (reset) { bool change = false; StatType s = link.SimStatus; if (link.Type == LinkType.PIPE) { if (s != control.Status) { change = true; } } if (link.Type == LinkType.PUMP) { if (link.SimSetting != control.Setting) { change = true; } } if (link.Type >= LinkType.PRV) { if (link.SimSetting != control.Setting) { change = true; } else if (double.IsNaN(link.SimSetting) && s != control.Status) { change = true; } } // If a change occurs, update status & setting if (change) { link.SimStatus = control.Status; if (link.Type > LinkType.PIPE) { link.SimSetting = control.Setting; } if (net.StatFlag == StatFlag.FULL) { LogStatChange(log, net.FieldsMap, link, s); } anychange = true; } } } return(anychange); }
/// <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); }
protected static void LogStatChange( FieldsMap fMap, TraceSource logger, SimulationLink link, StatType s1, StatType s2) { if (s1 == s2) { switch (link.Type) { case LinkType.PRV: case LinkType.PSV: case LinkType.PBV: link.setting *= fMap.GetUnits(FieldType.PRESSURE); break; case LinkType.FCV: link.setting *= fMap.GetUnits(FieldType.FLOW); break; } logger.Verbose( Text.FMT56, link.Type.ParseStr(), link.Link.Name, link.setting); return; } StatType j1, j2; if (s1 == StatType.ACTIVE) { j1 = StatType.ACTIVE; } else if (s1 <= StatType.CLOSED) { j1 = StatType.CLOSED; } else { j1 = StatType.OPEN; } if (s2 == StatType.ACTIVE) { j2 = StatType.ACTIVE; } else if (s2 <= StatType.CLOSED) { j2 = StatType.CLOSED; } else { j2 = StatType.OPEN; } if (j1 != j2) { logger.Verbose( Text.FMT57, link.Type.ParseStr(), link.Link.Name, j1.ReportStr(), j2.ReportStr()); } }
public Premise(string[] tok, Rulewords lOp, IEnumerable <SimulationNode> nodes, IEnumerable <SimulationLink> links) { Objects loType; Varwords lVar; object lObj; Operators lROp; if (tok.Length != 5 && tok.Length != 6) { throw new ENException(ErrorCode.Err201); } EnumsTxt.TryParse(tok[1], out loType); if (loType == Objects.SYSTEM) { EnumsTxt.TryParse(tok[2], out lVar); switch (lVar) { case Varwords.DEMAND: case Varwords.TIME: case Varwords.CLOCKTIME: lObj = Objects.SYSTEM; break; default: throw new ENException(ErrorCode.Err201); } } else { if (!EnumsTxt.TryParse(tok[3], out lVar)) { throw new ENException(ErrorCode.Err201); } switch (loType) { case Objects.NODE: case Objects.JUNC: case Objects.RESERV: case Objects.TANK: loType = Objects.NODE; break; case Objects.LINK: case Objects.PIPE: case Objects.PUMP: case Objects.VALVE: loType = Objects.LINK; break; default: throw new ENException(ErrorCode.Err201); } if (loType == Objects.NODE) { SimulationNode node = nodes.FirstOrDefault(simNode => simNode.Node.Name.Equals(tok[2], StringComparison.OrdinalIgnoreCase)); if (node == null) { throw new ENException(ErrorCode.Err203); } switch (lVar) { case Varwords.DEMAND: case Varwords.HEAD: case Varwords.GRADE: case Varwords.LEVEL: case Varwords.PRESSURE: break; case Varwords.FILLTIME: case Varwords.DRAINTIME: if (node is SimulationTank) { throw new ENException(ErrorCode.Err201); } break; default: throw new ENException(ErrorCode.Err201); } lObj = node; } else { SimulationLink link = links .FirstOrDefault(simLink => simLink.Link.Name.Equals(tok[2], StringComparison.OrdinalIgnoreCase)); if (link == null) { throw new ENException(ErrorCode.Err204); } switch (lVar) { case Varwords.FLOW: case Varwords.STATUS: case Varwords.SETTING: break; default: throw new ENException(ErrorCode.Err201); } lObj = link; } } Operators op; if (!EnumsTxt.TryParse(loType == Objects.SYSTEM ? tok[3] : tok[4], out op)) { throw new ENException(ErrorCode.Err201); } switch (op) { case Operators.IS: lROp = Operators.EQ; break; case Operators.NOT: lROp = Operators.NE; break; case Operators.BELOW: lROp = Operators.LT; break; case Operators.ABOVE: lROp = Operators.GT; break; default: lROp = op; break; } // BUG: Baseform bug lStat == Rule.Values.IS_NUMBER Values lStat = Values.IS_NUMBER; double lVal = double.NaN; if (lVar == Varwords.TIME || lVar == Varwords.CLOCKTIME) { lVal = tok.Length == 6 ? Utilities.GetHour(tok[4], tok[5]) : Utilities.GetHour(tok[4]); lVal *= 3600; if (lVal < 0.0) { throw new ENException(ErrorCode.Err202); } } else { Values k; if (!EnumsTxt.TryParse(tok[tok.Length - 1], out k) || lStat <= Values.IS_NUMBER) { if (lStat == (Values)(-1) || lStat <= Values.IS_NUMBER) { if (!tok[tok.Length - 1].ToDouble(out lVal)) { throw new ENException(ErrorCode.Err202); } if (lVar == Varwords.FILLTIME || lVar == Varwords.DRAINTIME) { lVal *= 3600.0; } } } else { lStat = k; } } _status = lStat; _value = lVal; logop = lOp; _relop = lROp; _variable = lVar; _object = lObj; }
/// <summary>Checks if numerical condition on a variable is true.</summary> private bool CheckValue(FieldsMap fMap, double dsystem) { const double TOL = 0.001D; double x; SimulationLink link = _object as SimulationLink; SimulationNode node = _object as SimulationNode; switch (_variable) { case Varwords.DEMAND: if ((Objects)_object == Objects.SYSTEM) { x = dsystem * fMap.GetUnits(FieldType.DEMAND); } else { x = node.SimDemand * fMap.GetUnits(FieldType.DEMAND); } break; case Varwords.HEAD: case Varwords.GRADE: x = node.SimHead * fMap.GetUnits(FieldType.HEAD); break; case Varwords.PRESSURE: x = (node.SimHead - node.Elevation) * fMap.GetUnits(FieldType.PRESSURE); break; case Varwords.LEVEL: x = (node.SimHead - node.Elevation) * fMap.GetUnits(FieldType.HEAD); break; case Varwords.FLOW: x = Math.Abs(link.SimFlow) * fMap.GetUnits(FieldType.FLOW); break; case Varwords.SETTING: if (double.IsNaN(link.SimSetting)) { return(false); } x = link.SimSetting; switch (link.Type) { case LinkType.PRV: case LinkType.PSV: case LinkType.PBV: x *= fMap.GetUnits(FieldType.PRESSURE); break; case LinkType.FCV: x *= fMap.GetUnits(FieldType.FLOW); break; } break; case Varwords.FILLTIME: { if (!(_object is SimulationTank)) { return(false); } SimulationTank tank = (SimulationTank)_object; if (tank.IsReservoir) { return(false); } if (tank.SimDemand <= Constants.TINY) { return(false); } x = (tank.Vmax - tank.SimVolume) / tank.SimDemand; break; } case Varwords.DRAINTIME: { if (!(_object is SimulationTank)) { return(false); } SimulationTank tank = (SimulationTank)_object; if (tank.IsReservoir) { return(false); } if (tank.SimDemand >= -Constants.TINY) { return(false); } x = (tank.Vmin - tank.SimVolume) / tank.SimDemand; break; } default: return(false); } switch (_relop) { case Operators.EQ: if (Math.Abs(x - _value) > TOL) { return(false); } break; case Operators.NE: if (Math.Abs(x - _value) < TOL) { return(false); } break; case Operators.LT: if (x > _value + TOL) { return(false); } break; case Operators.LE: if (x > _value - TOL) { return(false); } break; case Operators.GT: if (x < _value - TOL) { return(false); } break; case Operators.GE: if (x < _value + TOL) { return(false); } break; } return(true); }
private static void LogBadValve(TraceSource log, SimulationLink link, long htime) { log.Warning(Properties.Text.FMT61, htime.GetClockTime(), link.Link.Name); }