예제 #1
0
        ///<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);
        }
예제 #2
0
        /// <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);
        }