예제 #1
0
        // Simulation Methods


        /// <summary>Evaluate rule premises.</summary>
        private bool EvalPremises(
            EpanetNetwork net,
            long time1,
            long htime,
            double dsystem)
        {
            bool result = true;

            foreach (var p  in  _pchain)
            {
                if (p.logop == Rulewords.OR)
                {
                    if (!result)
                    {
                        result = p.CheckPremise(net, time1, htime, dsystem);
                    }
                }
                else
                {
                    if (!result)
                    {
                        return(false);
                    }
                    result = p.CheckPremise(net, time1, htime, dsystem);
                }
            }
            return(result);
        }
예제 #2
0
            /// <summary>Execute action, returns true if the link was alterated.</summary>
            public bool Execute(EpanetNetwork net, TraceSource log, double tol, long htime)
            {
                bool flag = false;

                StatType s = _link.SimStatus;
                double   v = _link.SimSetting;
                double   x = _setting;

                if (_status == Values.IS_OPEN && s <= StatType.CLOSED)
                {
                    // Switch link from closed to open
                    _link.SetLinkStatus(true);
                    flag = true;
                }
                else if (_status == Values.IS_CLOSED && s > StatType.CLOSED)
                {
                    // Switch link from not closed to closed
                    _link.SetLinkStatus(false);
                    flag = true;
                }
                else if (!double.IsNaN(x))
                {
                    // Change link's setting
                    switch (_link.Type)
                    {
                    case LinkType.PRV:
                    case LinkType.PSV:
                    case LinkType.PBV:
                        x /= net.FieldsMap.GetUnits(FieldType.PRESSURE);
                        break;

                    case LinkType.FCV:
                        x /= net.FieldsMap.GetUnits(FieldType.FLOW);
                        break;
                    }
                    if (Math.Abs(x - v) > tol)
                    {
                        _link.SetLinkSetting(x);
                        flag = true;
                    }
                }

                if (flag)
                {
                    if (net.StatFlag > 0) // Report rule action
                    {
                        LogRuleExecution(log, htime);
                    }
                    return(true);
                }

                return(false);
            }
예제 #3
0
        /// <summary>Computes P & Y coefficients for pipe k.</summary>
        private void ComputePipeCoeff(EpanetNetwork net, PipeHeadModelCalculators.Compute hlModel)
        {
            // For closed pipe use headloss formula: h = CBIG*q
            if (status <= StatType.CLOSED)
            {
                invHeadLoss    = 1.0 / Constants.CBIG;
                flowCorrection = flow;
                return;
            }

            hlModel(net, this, out invHeadLoss, out flowCorrection);
        }
예제 #4
0
        /// <summary>Determines new status for pumps, CVs, FCVs & pipes to tanks.</summary>
        public static bool LinkStatus(EpanetNetwork net, TraceSource log, IEnumerable <SimulationLink> links)
        {
            bool change = false;

            foreach (SimulationLink link  in  links)
            {
                if (link.LinkStatus(net, log))
                {
                    change = true;
                }
            }
            return(change);
        }
예제 #5
0
 /// <summary>Computes solution matrix coefficients for links.</summary>
 public static void ComputeMatrixCoeffs(
     EpanetNetwork net,
     PipeHeadModelCalculators.Compute hlModel,
     IEnumerable <SimulationLink> links,
     IList <Curve> curves,
     SparseMatrix smat,
     LsVariables ls)
 {
     foreach (SimulationLink link  in  links)
     {
         link.ComputeMatrixCoeff(net, hlModel, curves, smat, ls);
     }
 }
예제 #6
0
        /// <summary>Implements actions on action list, returns the number of actions executed.</summary>
        private static int TakeActions(EpanetNetwork net, TraceSource log, List <ActItem> actionList, long htime)
        {
            double tol = 1e-3;
            int    n   = 0;

            foreach (ActItem item  in  actionList)
            {
                if (item.action.Execute(net, log, tol, htime))
                {
                    n++;
                }
            }

            return(n);
        }
예제 #7
0
        /// <summary>Revises time step based on shortest time to fill or drain a tank.</summary>
        public static long MinimumTimeStep(
            EpanetNetwork net,
            IEnumerable <SimulationControl> controls,
            long htime,
            long tstep)
        {
            long newTStep = tstep;

            foreach (SimulationControl control  in  controls)
            {
                newTStep = control.GetRequiredTimeStep(net, htime, newTStep);
            }

            return(newTStep);
        }
예제 #8
0
        /// <summary>Updates status of a check valve.</summary>
        private static StatType CvStatus(EpanetNetwork net, StatType s, double dh, double q)
        {
            if (Math.Abs(dh) > net.HTol)
            {
                if (dh < -net.HTol)
                {
                    return(StatType.CLOSED);
                }

                return(q < -net.QTol ? StatType.CLOSED : StatType.OPEN);
            }
            else
            {
                return(q < -net.QTol ? StatType.CLOSED : s);
            }
        }
예제 #9
0
        /// <summary>Determines new status for pumps, CVs, FCVs & pipes to tanks.</summary>
        private bool LinkStatus(EpanetNetwork net, TraceSource log)
        {
            bool change = false;

            double dh = first.SimHead - second.SimHead;

            StatType tStatus = status;

            if (tStatus == StatType.XHEAD || tStatus == StatType.TEMPCLOSED)
            {
                status = StatType.OPEN;
            }

            if (Type == LinkType.CV)
            {
                status = CvStatus(net, status, dh, flow);
            }

            var pump = this as SimulationPump;

            if (pump != null && status >= StatType.OPEN && setting > 0.0)
            {
                status = pump.PumpStatus(net, -dh);
            }

            if (Type == LinkType.FCV && !double.IsNaN(setting))
            {
                status = ((SimulationValve)this).FcvStatus(net, tStatus);
            }

            if (first is SimulationTank || second is SimulationTank)
            {
                TankStatus(net);
            }

            if (tStatus != status)
            {
                change = true;
                if (net.StatFlag == StatFlag.FULL)
                {
                    LogStatChange(net.FieldsMap, log, this, tStatus, status);
                }
            }

            return(change);
        }
예제 #10
0
 /// <summary>Checks if a particular premise is true.</summary>
 public bool CheckPremise(
     EpanetNetwork net,
     long time1,
     long htime,
     double dsystem)
 {
     if (_variable == Varwords.TIME || _variable == Varwords.CLOCKTIME)
     {
         return(CheckTime(net, time1, htime));
     }
     else if (_status > Values.IS_NUMBER)
     {
         return(CheckStatus());
     }
     else
     {
         return(CheckValue(net.FieldsMap, dsystem));
     }
 }
예제 #11
0
        /// <summary>Checks which rules should fire at current time.</summary>
        private static int Check(
            EpanetNetwork net,
            IEnumerable <SimulationRule> rules,
            TraceSource log,
            long htime,
            long dt,
            double dsystem)
        {
            // Start of rule evaluation time interval
            long time1 = htime - dt + 1;

            List <ActItem> actionList = new List <ActItem>();

            foreach (SimulationRule rule  in  rules)
            {
                UpdateActionList(rule, actionList, rule.EvalPremises(net, time1, htime, dsystem));
            }

            return(TakeActions(net, log, actionList, htime));
        }
예제 #12
0
        /// <summary>Generate multi-species quality report.</summary>
        ///  <param name="msxBin">Name of the MSX simulation output file.</param>
        /// <param name="net">Hydraulic network.</param>
        /// <param name="netMsx">MSX network.</param>
        /// <param name="tk2">Hydraulic network - MSX bridge.</param>
        /// <param name="values">Species report flag.</param>
        public void CreateMsxReport(string msxBin, EpanetNetwork net, EpanetMSX netMsx, EnToolkit2 tk2, bool[] values)
        {
            Rtime = 0;
            var nodes = netMsx.Network.Node;
            var links = netMsx.Network.Link;

            string[] nSpecies    = netMsx.GetSpeciesNames();
            int      reportCount = (int)((net.Duration - net.RStart) / net.RStep) + 1;

            var reader = new MsxReader(
                nodes.Length - 1,
                links.Length - 1,
                nSpecies.Length,
                netMsx.ResultsOffset);

            int totalSpecies = values == null ? nSpecies.Length : values.Count(b => b);

            reader.Open(msxBin);

            var nodesHead = new object[nSpecies.Length + 1];

            nodesHead[0] = _sheet.TransposedMode ? "Node/Time" : "Time/Node";

            var linksHead = new object[nSpecies.Length + 1];

            linksHead[0] = _sheet.TransposedMode ? "Link/Time" : "Time/Link";

            int count = 1;

            for (int i = 0; i < nSpecies.Length; i++)
            {
                if (values == null || values[i])
                {
                    nodesHead[count]   = nSpecies[i];
                    linksHead[count++] = nSpecies[i];
                }
            }

            var nodeRow = new object[totalSpecies + 1];

            for (int i = 1; i < nodes.Length; i++)
            {
                if (!nodes[i].Rpt)
                {
                    continue;
                }

                var spr = _sheet.NewSpreadsheet("Node&lt;&lt;" + tk2.ENgetnodeid(i) + "&gt;&gt;");
                spr.AddHeader(nodesHead);

                for (long time = net.RStart, period = 0;
                     time <= net.Duration;
                     time += net.RStep, period++)
                {
                    nodeRow[0] = time.GetClockTime();

                    for (int j = 0, ji = 0; j < nSpecies.Length; j++)
                    {
                        if (values == null || values[j])
                        {
                            nodeRow[ji++ + 1] = reader.GetNodeQual((int)period, i, j + 1);
                        }
                    }

                    spr.AddData(nodeRow);
                }
            }

            var linkRow = new object[totalSpecies + 1];

            for (int i = 1; i < links.Length; i++)
            {
                if (!links[i].Rpt)
                {
                    continue;
                }

                var spr = _sheet.NewSpreadsheet("Link&lt;&lt;" + tk2.ENgetlinkid(i) + "&gt;&gt;");
                spr.AddHeader(linksHead);

                for (long time = net.RStart, period = 0;
                     time <= net.Duration;
                     time += net.RStep, period++)
                {
                    linkRow[0] = time.GetClockTime();

                    for (int j = 0, ji = 0; j < nSpecies.Length; j++)
                    {
                        if (values == null || values[j])
                        {
                            linkRow[ji++ + 1] = reader.GetLinkQual((int)period, i, j + 1);
                        }
                    }

                    spr.AddData(linkRow);
                }
            }

            reader.Close();
        }
예제 #13
0
        /// <summary>Generate quality report.</summary>
        ///  <param name="qualFile">Name of the quality simulation output file.</param>
        /// <param name="net">Hydraulic network.</param>
        /// <param name="nodes">Show nodes quality flag.</param>
        /// <param name="links">Show links quality flag.</param>
        public void CreateQualReport(string qualFile, EpanetNetwork net, bool nodes, bool links)
        {
            Rtime = 0;

            int reportCount = (int)((net.Duration - net.RStart) / net.RStep) + 1;

            using (QualityReader dseek = new QualityReader(qualFile, net.FieldsMap)) {
                var netNodes = net.Nodes;
                var netLinks = net.Links;

                var nodesHead = new object[dseek.Nodes + 1];
                nodesHead[0] = _sheet.TransposedMode ? "Node/Time" : "Time/Node";
                for (int i = 0; i < netNodes.Count; i++)
                {
                    nodesHead[i + 1] = netNodes[i].Name;
                }

                var linksHead = new object[dseek.Links + 1];
                linksHead[0] = _sheet.TransposedMode ? "Link/Time" : "Time/Link";
                for (int i = 0; i < netLinks.Count; i++)
                {
                    linksHead[i + 1] = netLinks[i].Name;
                }

                var resultSheets = new XlsxWriter.Spreadsheet[HydVariable.Values.Length];

                for (int i = 0; i < QualVariable.Values.Length; i++)
                {
                    var qvar = QualVariable.Values[i];
                    if ((!qvar.isNode || !nodes) && (qvar.isNode || !links))
                    {
                        continue;
                    }

                    resultSheets[i] = _sheet.NewSpreadsheet(qvar.name);
                    resultSheets[i].AddHeader(qvar.isNode ? nodesHead : linksHead);
                }

                var nodeRow = new object[dseek.Nodes + 1];
                var linkRow = new object[dseek.Links + 1];

                using (var qIt = dseek.GetEnumerator())
                    for (long time = net.RStart; time <= net.Duration; time += net.RStep)
                    {
                        if (!qIt.MoveNext())
                        {
                            return;
                        }

                        var step = qIt.Current;
                        if (step == null)
                        {
                            continue;
                        }

                        nodeRow[0] = time.GetClockTime();
                        linkRow[0] = time.GetClockTime();

                        if (resultSheets[(int)QualVariable.Type.Nodes] != null)
                        {
                            for (int i = 0; i < dseek.Nodes; i++)
                            {
                                nodeRow[i + 1] = (double)step.GetNodeQuality(i);
                            }

                            resultSheets[(int)QualVariable.Type.Nodes].AddData(nodeRow);
                        }

                        if (resultSheets[(int)QualVariable.Type.Links] != null)
                        {
                            for (int i = 0; i < dseek.Links; i++)
                            {
                                linkRow[i + 1] = (double)step.GetLinkQuality(i);
                            }

                            resultSheets[(int)QualVariable.Type.Links].AddData(linkRow);
                        }

                        Rtime = time;
                    }
            }
        }
예제 #14
0
        /// <summary>Generate hydraulic report.</summary>
        ///  <param name="hydBinFile">Name of the hydraulic simulation output file.</param>
        /// <param name="net">Hydraulic network.</param>
        /// <param name="values">Variables report flag.</param>
        public void CreateHydReport(string hydBinFile, EpanetNetwork net, bool[] values)
        {
            Rtime = 0;
            HydraulicReader dseek       = new HydraulicReader(new BinaryReader(File.OpenRead(hydBinFile)));
            int             reportCount = (int)((net.Duration - net.RStart) / net.RStep) + 1;
            var             nodes       = net.Nodes;
            var             links       = net.Links;

            object[] nodesHead = new object[dseek.Nodes + 1];
            nodesHead[0] = _sheet.TransposedMode ? "Node/Time" : "Time/Node";
            for (int i = 0; i < nodes.Count; i++)
            {
                nodesHead[i + 1] = nodes[i].Name;
            }

            var linksHead = new object[dseek.Links + 1];

            linksHead[0] = _sheet.TransposedMode ? "Link/Time" : "Time/Link";
            for (int i = 0; i < links.Count; i++)
            {
                linksHead[i + 1] = links[i].Name;
            }

            XlsxWriter.Spreadsheet[] resultSheets = new XlsxWriter.Spreadsheet[HydVariable.Values.Length];
            // Array.Clear(resultSheets, 0, resultSheets.Length);

            for (int i = 0; i < resultSheets.Length; i++)
            {
                if (values != null && !values[i])
                {
                    continue;
                }
                resultSheets[i] = _sheet.NewSpreadsheet(HydVariable.Values[i].name);
                resultSheets[i].AddHeader(HydVariable.Values[i].isNode ? nodesHead : linksHead);
            }

            var nodeRow = new object[dseek.Nodes + 1];
            var linkRow = new object[dseek.Links + 1];

            for (long time = net.RStart; time <= net.Duration; time += net.RStep)
            {
                var step = dseek.GetStep(time);

                if (step == null)
                {
                    Rtime = time;
                    continue;
                }

                nodeRow[0] = time.GetClockTime();
                linkRow[0] = time.GetClockTime();

                // NODES HEADS
                if (resultSheets[(int)HydVariable.Type.Head] != null)
                {
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        nodeRow[i + 1] = step.GetNodeHead(i, nodes[i], net.FieldsMap);
                    }

                    resultSheets[(int)HydVariable.Type.Head].AddData(nodeRow);
                }

                // NODES DEMANDS
                if (resultSheets[(int)HydVariable.Type.Demands] != null)
                {
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        nodeRow[i + 1] = step.GetNodeDemand(i, nodes[i], net.FieldsMap);
                    }

                    resultSheets[(int)HydVariable.Type.Demands].AddData(nodeRow);
                }

                // NODES PRESSURE
                if (resultSheets[(int)HydVariable.Type.Pressure] != null)
                {
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        nodeRow[i + 1] = step.GetNodePressure(i, nodes[i], net.FieldsMap);
                    }

                    resultSheets[(int)HydVariable.Type.Pressure].AddData(nodeRow);
                }

                // LINK FLOW
                if (resultSheets[(int)HydVariable.Type.Flows] != null)
                {
                    for (int i = 0; i < links.Count; i++)
                    {
                        linkRow[i + 1] = step.GetLinkFlow(i, links[i], net.FieldsMap);
                    }

                    resultSheets[(int)HydVariable.Type.Flows].AddData(linkRow);
                }

                // LINK VELOCITY
                if (resultSheets[(int)HydVariable.Type.Velocity] != null)
                {
                    for (int i = 0; i < links.Count; i++)
                    {
                        linkRow[i + 1] = step.GetLinkVelocity(i, links[i], net.FieldsMap);
                    }

                    resultSheets[(int)HydVariable.Type.Velocity].AddData(linkRow);
                }

                // LINK HEADLOSS
                if (resultSheets[(int)HydVariable.Type.Headloss] != null)
                {
                    for (int i = 0; i < links.Count; i++)
                    {
                        linkRow[i + 1] = step.GetLinkHeadLoss(i, links[i], net.FieldsMap);
                    }

                    resultSheets[(int)HydVariable.Type.Headloss].AddData(linkRow);
                }

                // LINK FRICTION
                if (resultSheets[(int)HydVariable.Type.Friction] != null)
                {
                    for (int i = 0; i < links.Count; i++)
                    {
                        linkRow[i + 1] = step.GetLinkFriction(i, links[i], net.FieldsMap);
                    }

                    resultSheets[(int)HydVariable.Type.Friction].AddData(linkRow);
                }

                Rtime = time;
            }

            dseek.Close();
        }
예제 #15
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);
        }
예제 #16
0
        /// <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);
        }
예제 #17
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);
        }
예제 #18
0
            /// <summary>Checks if condition on system time holds.</summary>
            private bool CheckTime(EpanetNetwork net, long time1, long htime)
            {
                long t1, t2;

                switch (_variable)
                {
                case Varwords.TIME:
                    t1 = time1;
                    t2 = htime;
                    break;

                case Varwords.CLOCKTIME:
                    t1 = (time1 + net.Tstart) % Constants.SECperDAY;
                    t2 = (htime + net.Tstart) % Constants.SECperDAY;
                    break;

                default:
                    return(false);
                }

                var x = (long)_value;

                switch (_relop)
                {
                case Operators.LT:
                    if (t2 >= x)
                    {
                        return(false);
                    }
                    break;

                case Operators.LE:
                    if (t2 > x)
                    {
                        return(false);
                    }
                    break;

                case Operators.GT:
                    if (t2 <= x)
                    {
                        return(false);
                    }
                    break;

                case Operators.GE:
                    if (t2 < x)
                    {
                        return(false);
                    }
                    break;

                case Operators.EQ:
                case Operators.NE:
                    var flag = false;
                    if (t2 < t1)
                    {
                        if (x >= t1 || x <= t2)
                        {
                            flag = true;
                        }
                    }
                    else
                    {
                        if (x >= t1 && x <= t2)
                        {
                            flag = true;
                        }
                    }
                    if (_relop == Operators.EQ && !flag)
                    {
                        return(true);
                    }
                    if (_relop == Operators.NE && flag)
                    {
                        return(true);
                    }
                    break;
                }

                return(true);
            }
예제 #19
0
        /// <summary>
        /// Updates next time step by checking if any rules will fire before then;
        /// also updates tank levels.
        /// </summary>
        public static void MinimumTimeStep(
            EpanetNetwork net,
            TraceSource log,
            SimulationRule[] rules,
            List <SimulationTank> tanks,
            long htime,
            long tstep,
            double dsystem,
            out long tstepOut,
            out long htimeOut)
        {
            long dt;  // Normal time increment for rule evaluation
            long dt1; // Actual time increment for rule evaluation

            // Find interval of time for rule evaluation
            long tnow = htime;        // Start of time interval for rule evaluation
            long tmax = tnow + tstep; // End of time interval for rule evaluation

            //If no rules, then time increment equals current time step
            if (rules.Length == 0)
            {
                dt  = tstep;
                dt1 = dt;
            }
            else
            {
                // Otherwise, time increment equals rule evaluation time step and
                // first actual increment equals time until next even multiple of
                // Rulestep occurs.
                dt  = net.RuleStep;
                dt1 = net.RuleStep - tnow % net.RuleStep;
            }

            // Make sure time increment is no larger than current time step
            dt  = Math.Min(dt, tstep);
            dt1 = Math.Min(dt1, tstep);

            if (dt1 == 0)
            {
                dt1 = dt;
            }

            // Step through time, updating tank levels, until either
            // a rule fires or we reach the end of evaluation period.
            //
            // Note: we are updating the global simulation time (Htime)
            //       here because it is used by functions in RULES.C(this class)
            //       to evaluate rules when checkrules() is called.
            //       It is restored to its original value after the
            //       rule evaluation process is completed (see below).
            //       Also note that dt1 will equal dt after the first
            //       time increment is taken.

            do
            {
                htime += dt1;                                              // Update simulation clock
                SimulationTank.StepWaterLevels(tanks, net.FieldsMap, dt1); // Find new tank levels
                if (Check(net, rules, log, htime, dt1, dsystem) != 0)
                {
                    break;                        // Stop if rules fire
                }
                dt  = Math.Min(dt, tmax - htime); // Update time increment
                dt1 = dt;                         // Update actual increment
            }while (dt > 0);

            //Compute an updated simulation time step (*tstep)
            // and return simulation time to its original value
            tstepOut = htime - tnow;
            htimeOut = tnow;
        }
예제 #20
0
        /// <summary>Write simulation summary to one worksheet.</summary>
        ///  <param name="inpFile">Hydraulic network file name.</param>
        /// <param name="net">Hydraulic network.</param>
        /// <param name="msxFile">MSX file.</param>
        /// <param name="msx">MSX solver.</param>
        public void WriteSummary(string inpFile, EpanetNetwork net, string msxFile, EpanetMSX msx)
        {
            var sh = _sheet.NewSpreadsheet("Summary");

            try {
                FieldsMap fMap = net.FieldsMap;

                if (net.Title != null)
                {
                    for (int i = 0; i < net.Title.Count && i < 3; i++)
                    {
                        if (!string.IsNullOrEmpty(net.Title[i]))
                        {
                            sh.AddData(
                                net.Title[i].Length > 70
                                ? net.Title[i].Substring(0, 70)
                                : net.Title[i]);
                        }
                    }
                }

                sh.AddData("\n");
                sh.AddData(Text.FMT19, inpFile);
                sh.AddData(Text.FMT20, net.Junctions.Count());

                int nReservoirs = net.Reservoirs.Count();
                int nTanks      = net.Tanks.Count();
                int nValves     = net.Valves.Count();
                int nPumps      = net.Pumps.Count();
                int nPipes      = net.Links.Count - nPumps - nValves;

                sh.AddData(Text.FMT21a, nReservoirs);
                sh.AddData(Text.FMT21b, nTanks);
                sh.AddData(Text.FMT22, nPipes);
                sh.AddData(Text.FMT23, nPumps);
                sh.AddData(Text.FMT24, nValves);
                sh.AddData(Text.FMT25, net.FormFlag.ParseStr());

                sh.AddData(Text.FMT26, net.HStep.GetClockTime());
                sh.AddData(Text.FMT27, net.HAcc);
                sh.AddData(Text.FMT27a, net.CheckFreq);
                sh.AddData(Text.FMT27b, net.MaxCheck);
                sh.AddData(Text.FMT27c, net.DampLimit);
                sh.AddData(Text.FMT28, net.MaxIter);

                switch (net.Duration == 0 ? QualType.NONE : net.QualFlag)
                {
                case QualType.NONE:
                    sh.AddData(Text.FMT29, "None");
                    break;

                case QualType.CHEM:
                    sh.AddData(Text.FMT30, net.ChemName);
                    break;

                case QualType.TRACE:
                    sh.AddData(Text.FMT31, "Trace From Node", net.GetNode(net.TraceNode).Name);
                    break;

                case QualType.AGE:
                    sh.AddData(Text.FMT32, "Age");
                    break;
                }

                if (net.QualFlag != QualType.NONE && net.Duration > 0)
                {
                    sh.AddData(Text.FMT33, "Time Step", net.QStep.GetClockTime());
                    sh.AddData(
                        Text.FMT34,
                        "Tolerance",
                        fMap.RevertUnit(FieldType.QUALITY, net.Ctol),
                        fMap.GetField(FieldType.QUALITY).Units);
                }

                sh.AddData(Text.FMT36, net.SpGrav);
                sh.AddData(Text.FMT37a, net.Viscos / Constants.VISCOS);
                sh.AddData(Text.FMT37b, net.Diffus / Constants.DIFFUS);
                sh.AddData(Text.FMT38, net.DMult);
                sh.AddData(
                    Text.FMT39,
                    fMap.RevertUnit(FieldType.TIME, net.Duration),
                    fMap.GetField(FieldType.TIME).Units);

                if (msxFile != null && msx != null)
                {
                    sh.AddData("");
                    sh.AddData("MSX data file", msxFile);
                    sh.AddData("Species");
                    Species[] spe = msx.Network.Species;
                    for (int i = 1; i < msx.Network.Species.Length; i++)
                    {
                        sh.AddData(spe[i].Id, spe[i].Units);
                    }
                }
            }
            catch (IOException) {}
            catch (ENException e) {
                Debug.Print(e.ToString());
            }
        }
예제 #21
0
        /// <summary>Closes link flowing into full or out of empty tank.</summary>
        private void TankStatus(EpanetNetwork net)
        {
            double         q  = flow;
            SimulationNode n1 = First;
            SimulationNode n2 = Second;

            // Make node n1 be the tank
            if (!(n1 is SimulationTank))
            {
                if (!(n2 is SimulationTank))
                {
                    return; // neither n1 or n2 is a tank
                }
                // N2 is a tank, swap !
                SimulationNode n = n1;
                n1 = n2;
                n2 = n;
                q  = -q;
            }

            double h = n1.SimHead - n2.SimHead;

            SimulationTank tank = (SimulationTank)n1;

            // Skip reservoirs & closed links
            if (tank.Area == 0.0 || status <= StatType.CLOSED)
            {
                return;
            }

            // If tank full, then prevent flow into it
            if (tank.SimHead >= tank.Hmax - net.HTol)
            {
                //Case 1: Link is a pump discharging into tank
                if (Type == LinkType.PUMP)
                {
                    if (Second == n1)
                    {
                        status = StatType.TEMPCLOSED;
                    }
                }
                else if (CvStatus(net, StatType.OPEN, h, q) == StatType.CLOSED)
                {
                    //  Case 2: Downstream head > tank head
                    status = StatType.TEMPCLOSED;
                }
            }

            // If tank empty, then prevent flow out of it
            if (tank.SimHead <= tank.Hmin + net.HTol)
            {
                // Case 1: Link is a pump discharging from tank
                if (Type == LinkType.PUMP)
                {
                    if (First == n1)
                    {
                        status = StatType.TEMPCLOSED;
                    }
                }
                // Case 2: Tank head > downstream head
                else if (CvStatus(net, StatType.CLOSED, h, q) == StatType.OPEN)
                {
                    status = StatType.TEMPCLOSED;
                }
            }
        }
예제 #22
0
        /// <summary>Compute P, Y and matrix coeffs.</summary>
        private void ComputeMatrixCoeff(
            EpanetNetwork net,
            PipeHeadModelCalculators.Compute hlModel,
            IList <Curve> curves,
            SparseMatrix smat,
            LsVariables ls)
        {
            switch (Type)
            {
            // Pipes
            case LinkType.CV:
            case LinkType.PIPE:
                ComputePipeCoeff(net, hlModel);
                break;

            // Pumps
            case LinkType.PUMP:
                ((SimulationPump)this).ComputePumpCoeff(net);
                break;

            // Valves
            case LinkType.PBV:
            case LinkType.TCV:
            case LinkType.GPV:
            case LinkType.FCV:
            case LinkType.PRV:
            case LinkType.PSV:
                // If valve status fixed then treat as pipe
                // otherwise ignore the valve for now.
                if (!((SimulationValve)this).ComputeValveCoeff(net, curves))
                {
                    return;
                }
                break;

            default:
                return;
            }

            int n1 = first.Index;
            int n2 = second.Index;

            ls.AddNodalInFlow(n1, -flow);
            ls.AddNodalInFlow(n2, +flow);

            ls.AddAij(smat.GetNdx(Index), -invHeadLoss);

            if (!(first is SimulationTank))
            {
                ls.AddAii(smat.GetRow(n1), +invHeadLoss);
                ls.AddRhsCoeff(smat.GetRow(n1), +flowCorrection);
            }
            else
            {
                ls.AddRhsCoeff(smat.GetRow(n2), +(invHeadLoss * first.SimHead));
            }

            if (!(second is SimulationTank))
            {
                ls.AddAii(smat.GetRow(n2), +invHeadLoss);
                ls.AddRhsCoeff(smat.GetRow(n2), -flowCorrection);
            }
            else
            {
                ls.AddRhsCoeff(smat.GetRow(n1), +(invHeadLoss * second.SimHead));
            }
        }
예제 #23
0
        public static void main(string[] args)
        {
            TraceSource log = new TraceSource(typeof(EPATool).FullName, SourceLevels.All);

            string hydFile  = null;
            string qualFile = null;
            var    net      = new EpanetNetwork();

            List <NodeVariableType> nodesVariables = new List <NodeVariableType>();
            List <LinkVariableType> linksVariables = new List <LinkVariableType>();

            string        inFile      = "";
            List <long>   targetTimes = new List <long>();
            List <string> targetNodes = new List <string>();
            List <string> targetLinks = new List <string>();

            int parseMode = 0;

            foreach (string arg in args)
            {
                if (arg.EndsWith(".inp", StringComparison.OrdinalIgnoreCase))
                {
                    parseMode = 0;
                    inFile    = arg;
                    if (!File.Exists(inFile))
                    {
                        ConsoleLog("END_RUN_ERR");
                        Console.Error.WriteLine("File not found !");
                        return;
                    }
                    continue;
                }

                switch (arg)
                {
                case "-T":
                case "-t":
                    parseMode = 1;
                    continue;

                case "-N":
                case "-n":
                    parseMode = 2;
                    continue;

                case "-L":
                case "-l":
                    parseMode = 3;
                    continue;
                }

                switch (parseMode)
                {
                case 1:
                    targetTimes.Add((long)(Utilities.GetHour(arg) * 3600));
                    break;

                case 2:
                    targetNodes.Add(arg);
                    break;

                case 3:
                    targetLinks.Add(arg);
                    break;
                }
            }

            try {
                InputParser parserInp = InputParser.Create(FileType.INP_FILE);
                net = parserInp.Parse(new EpanetNetwork(), inFile);


                if (targetTimes.Count > 0)
                {
                    foreach (long time  in  targetTimes)
                    {
                        string epanetTime = time.GetClockTime();
                        if (time < net.RStart)
                        {
                            throw new Exception("Target time \"" + epanetTime + "\" smaller than simulation start time");
                        }

                        if (time > net.Duration)
                        {
                            throw new Exception("Target time \"" + epanetTime + "\" bigger than simulation duration");
                        }

                        if ((time - net.RStart) % net.RStep != 0)
                        {
                            throw new Exception("Target time \"" + epanetTime + "\" not found");
                        }
                    }
                }

                foreach (string nodeName  in  targetNodes)
                {
                    if (net.GetNode(nodeName) == null)
                    {
                        throw new Exception("Node \"" + nodeName + "\" not found");
                    }
                }

                foreach (string linkName  in  targetLinks)
                {
                    if (net.GetLink(linkName) == null)
                    {
                        throw new Exception("Link \"" + linkName + "\" not found");
                    }
                }

                nodesVariables.Add(NodeVariableType.ELEVATION);
                nodesVariables.Add(NodeVariableType.BASEDEMAND);

                if (net.QualFlag != QualType.NONE)
                {
                    nodesVariables.Add(NodeVariableType.INITQUALITY);
                }

                nodesVariables.Add(NodeVariableType.PRESSURE);
                nodesVariables.Add(NodeVariableType.HEAD);
                nodesVariables.Add(NodeVariableType.DEMAND);

                if (net.QualFlag != (QualType.NONE))
                {
                    nodesVariables.Add(NodeVariableType.QUALITY);
                }

                linksVariables.Add(LinkVariableType.LENGHT);
                linksVariables.Add(LinkVariableType.DIAMETER);
                linksVariables.Add(LinkVariableType.ROUGHNESS);
                linksVariables.Add(LinkVariableType.FLOW);
                linksVariables.Add(LinkVariableType.VELOCITY);
                linksVariables.Add(LinkVariableType.UNITHEADLOSS);
                linksVariables.Add(LinkVariableType.FRICTIONFACTOR);

                if (net.QualFlag != QualType.NONE)
                {
                    linksVariables.Add(LinkVariableType.QUALITY);
                }

                hydFile = Path.GetTempFileName(); // "hydSim.bin"

                ConsoleLog("START_RUNNING");

                HydraulicSim hydSim = new HydraulicSim(net, log);
                hydSim.Simulate(hydFile);


                if (net.QualFlag != QualType.NONE)
                {
                    qualFile = Path.GetTempFileName(); // "qualSim.bin"

                    QualitySim q = new QualitySim(net, log);
                    q.Simulate(hydFile, qualFile);
                }


                HydraulicReader hydReader = new HydraulicReader(new BinaryReader(File.OpenRead(hydFile)));

                StreamWriter nodesTextWriter = null;
                StreamWriter linksTextWriter = null;
                string       nodesOutputFile = null;

                if (targetNodes.Count == 0 && targetLinks.Count == 0 || targetNodes.Count > 0)
                {
                    nodesOutputFile = Path.GetFullPath(inFile) + ".nodes.out";
                    nodesTextWriter = new StreamWriter(nodesOutputFile, false, Encoding.UTF8);

                    nodesTextWriter.Write('\t');
                    foreach (NodeVariableType nodeVar  in  nodesVariables)
                    {
                        nodesTextWriter.Write('\t');
                        nodesTextWriter.Write(nodeVar.ToString());
                    }
                    nodesTextWriter.Write("\n\t");

                    foreach (NodeVariableType nodeVar  in  nodesVariables)
                    {
                        nodesTextWriter.Write('\t');
                        nodesTextWriter.Write(net.FieldsMap.GetField(ToFieldType(nodeVar)).Units);
                    }
                    nodesTextWriter.Write('\n');
                }


                if (targetNodes.Count == 0 && targetLinks.Count == 0 || targetLinks.Count > 0)
                {
                    string linksOutputFile = Path.GetFullPath(inFile) + ".links.out";
                    linksTextWriter = new StreamWriter(linksOutputFile, false, Encoding.UTF8);

                    linksTextWriter.Write('\t');
                    foreach (LinkVariableType linkVar  in  linksVariables)
                    {
                        linksTextWriter.Write('\t');
                        linksTextWriter.Write(linkVar.ToString());
                    }
                    linksTextWriter.Write("\n\t");

                    foreach (LinkVariableType linkVar  in  linksVariables)
                    {
                        linksTextWriter.Write('\t');
                        if (linkVar < 0)
                        {
                            continue;
                        }
                        linksTextWriter.Write(net.FieldsMap.GetField((FieldType)linkVar).Units);
                    }
                    linksTextWriter.Write('\n');
                }


                for (long time = net.RStart; time <= net.Duration; time += net.RStep)
                {
                    AwareStep step = hydReader.GetStep((int)time);

                    int i = 0;

                    if (targetTimes.Count > 0 && !targetTimes.Contains(time))
                    {
                        continue;
                    }

                    if (nodesTextWriter != null)
                    {
                        foreach (Node node  in  net.Nodes)
                        {
                            if (targetNodes.Count > 0 && !targetNodes.Contains(node.Name))
                            {
                                continue;
                            }

                            nodesTextWriter.Write(node.Name);

                            nodesTextWriter.Write('\t');
                            nodesTextWriter.Write(time.GetClockTime());

                            foreach (NodeVariableType nodeVar  in  nodesVariables)
                            {
                                nodesTextWriter.Write('\t');
                                double val = GetNodeValue(nodeVar, net.FieldsMap, step, node, i);
                                nodesTextWriter.Write(ConvertToScientifcNotation(val, 1000, 0.01, 2));
                            }

                            nodesTextWriter.Write('\n');

                            i++;
                        }
                    }

                    i = 0;

                    if (linksTextWriter != null)
                    {
                        foreach (Link link  in  net.Links)
                        {
                            if (targetLinks.Count > 0 && !targetLinks.Contains(link.Name))
                            {
                                continue;
                            }

                            linksTextWriter.Write(link.Name);

                            linksTextWriter.Write('\t');
                            linksTextWriter.Write(time.GetClockTime());

                            foreach (LinkVariableType linkVar  in  linksVariables)
                            {
                                linksTextWriter.Write('\t');
                                double val = GetLinkValue(
                                    linkVar,
                                    net.FormFlag,
                                    net.FieldsMap,
                                    step,
                                    link,
                                    i);
                                linksTextWriter.Write(ConvertToScientifcNotation(val, 1000, 0.01, 2));
                            }

                            linksTextWriter.Write('\n');

                            i++;
                        }
                    }
                }

                if (nodesTextWriter != null)
                {
                    nodesTextWriter.Close();
                    ConsoleLog("NODES FILE \"" + nodesOutputFile + "\"");
                }

                if (linksTextWriter != null)
                {
                    linksTextWriter.Close();
                    ConsoleLog("LINKS FILES \"" + nodesOutputFile + "\"");
                }

                ConsoleLog("END_RUN_OK");
            }
            catch (ENException e) {
                ConsoleLog("END_RUN_ERR");
                Debug.Print(e.ToString());
            }
            catch (IOException e) {
                ConsoleLog("END_RUN_ERR");
                Debug.Print(e.ToString());
            }
            catch (Exception e) {
                ConsoleLog("END_RUN_ERR");
                Debug.Print(e.ToString());
            }

            if (!string.IsNullOrEmpty(hydFile))
            {
                File.Delete(hydFile);
            }

            if (!string.IsNullOrEmpty(qualFile))
            {
                File.Delete(qualFile);
            }
        }
예제 #24
0
 public EnToolkit2(EpanetNetwork net)
 {
     _net   = net;
     _links = net.Links;
     _nodes = net.Nodes;
 }