Пример #1
0
        ///<summary>Computes coefficients of linearized network eqns.</summary>
        private void NewCoeffs()
        {
            _lsv.Clear();

            foreach (SimulationLink link  in  _links)
            {
                link.SimInvHeadLoss    = 0;
                link.SimFlowCorrection = 0;
            }

            SimulationLink.ComputeMatrixCoeffs(
                net,
                _pHlModel,
                _links,
                _curves,
                _smat,
                _lsv);                                                         // Compute link coeffs.

            SimulationNode.ComputeEmitterCoeffs(net, _junctions, _smat, _lsv); // Compute emitter coeffs.
            SimulationNode.ComputeNodeCoeffs(_junctions, _smat, _lsv);         // Compute node coeffs.
            SimulationValve.ComputeMatrixCoeffs(net, _lsv, _smat, _valves);    // Compute valve coeffs.
        }
Пример #2
0
        ///<summary>Init hydraulic simulation, preparing the linear solver and the hydraulic structures wrappers.</summary>
        /// <param name="net">Hydraulic network reference.</param>
        /// <param name="log">Logger reference.</param>
        public HydraulicSim(EpanetNetwork net, TraceSource log)
        {
            _running = false;
            _logger  = log;
            // this.CreateSimulationNetwork(net);


            _nodes     = new SimulationNode[net.Nodes.Count];
            _links     = new SimulationLink[net.Links.Count];
            _pumps     = new List <SimulationPump>();
            _tanks     = new List <SimulationTank>();
            _junctions = new List <SimulationNode>();
            _valves    = new List <SimulationValve>();

            var nodesById = new Dictionary <string, SimulationNode>(net.Nodes.Count);

            for (int i = 0; i < net.Nodes.Count; i++)
            {
                SimulationNode node;

                var networkNode = net.Nodes[i];

                if (networkNode.Type == NodeType.JUNC)
                {
                    node = new SimulationNode(networkNode, i);
                    _junctions.Add(node);
                }
                else
                {
                    node = new SimulationTank(networkNode, i);
                    _tanks.Add((SimulationTank)node);
                }

                _nodes[i]          = node;
                nodesById[node.Id] = node;
            }

            for (int i = 0; i < net.Links.Count; i++)
            {
                SimulationLink link;

                var networkLink = net.Links[i];

                if (networkLink is Valve)
                {
                    var valve = new SimulationValve(nodesById, networkLink, i);
                    _valves.Add(valve);
                    link = valve;
                }
                else if (networkLink is Pump)
                {
                    var pump = new SimulationPump(nodesById, networkLink, i);
                    _pumps.Add(pump);
                    link = pump;
                }
                else
                {
                    link = new SimulationLink(nodesById, networkLink, i);
                }

                _links[i] = link;
            }

            _rules = net.Rules.Select(r => new SimulationRule(r, _links, _nodes)).ToArray();

            _curves = net.Curves.ToArray();

            _controls = net.Controls.Select(x => new SimulationControl(_nodes, _links, x)).ToArray();


            this.net = net;
            _epat    = net.GetPattern(this.net.EPatId);
            _smat    = new SparseMatrix(_nodes, _links, _junctions.Count);
            _lsv     = new LsVariables(_nodes.Length, _smat.CoeffsCount);

            Htime = 0;

            switch (this.net.FormFlag)
            {
            case FormType.HW:
                _pHlModel = PipeHeadModelCalculators.HwModelCalculator;
                break;

            case FormType.DW:
                _pHlModel = PipeHeadModelCalculators.DwModelCalculator;
                break;

            case FormType.CM:
                _pHlModel = PipeHeadModelCalculators.CmModelCalculator;
                break;
            }

            foreach (SimulationLink link in _links)
            {
                link.InitLinkFlow();
            }

            foreach (SimulationNode node in _junctions)
            {
                if (node.Ke > 0.0)
                {
                    node.SimEmitter = 1.0;
                }
            }

            foreach (SimulationLink link in _links)
            {
                if ((link.Type == LinkType.PRV ||
                     link.Type == LinkType.PSV ||
                     link.Type == LinkType.FCV) &&
                    !double.IsNaN(link.Roughness))
                {
                    link.SimStatus = StatType.ACTIVE;
                }


                if (link.SimStatus <= StatType.CLOSED)
                {
                    link.SimFlow = Constants.QZERO;
                }
                else if (Math.Abs(link.SimFlow) <= Constants.QZERO)
                {
                    link.InitLinkFlow(link.SimStatus, link.SimSetting);
                }

                link.SimOldStatus = link.SimStatus;
            }


            Htime = 0;
            Rtime = this.net.RStep;
        }
Пример #3
0
        ///<summary>Solve the linear equation system to compute the links flows and nodes heads.</summary>
        /// <returns>Solver steps and relative error.</returns>
        protected void NetSolve(out int iter, out double relerr)
        {
            iter   = 0;
            relerr = 0.0;

            int nextCheck = net.CheckFreq;

            if (net.StatFlag == StatFlag.FULL)
            {
                LogRelErr(iter, relerr);
            }

            int maxTrials = net.MaxIter;

            if (net.ExtraIter > 0)
            {
                maxTrials += net.ExtraIter;
            }

            double relaxFactor = 1.0;
            int    errcode     = 0;

            iter = 1;

            while (iter <= maxTrials)
            {
                //Compute coefficient matrices A & F and solve A*H = F
                // where H = heads, A = Jacobian coeffs. derived from
                // head loss gradients, & F = flow correction terms.
                NewCoeffs();

                //dumpMatrixCoeffs(new File("dumpMatrix.txt"),true);

                // Solution for H is returned in F from call to linsolve().
                errcode = _smat.LinSolve(
                    _junctions.Count,
                    _lsv.AiiVector,
                    _lsv.AijVector,
                    _lsv.RhsCoeffs);

                // Ill-conditioning problem
                if (errcode > 0)
                {
                    // If control valve causing problem, fix its status & continue,
                    // otherwise end the iterations with no solution.
                    if (SimulationValve.CheckBadValve(
                            net,
                            _logger,
                            _valves,
                            Htime,
                            _smat.GetOrder(errcode)))
                    {
                        continue;
                    }

                    break;
                }

                // Update current solution.
                // (Row[i] = row of solution matrix corresponding to node i).
                foreach (SimulationNode node  in  _junctions)
                {
                    node.SimHead = _lsv.GetRhsCoeff(_smat.GetRow(node.Index)); // Update heads
                }

                // Update flows
                relerr = NewFlows(relaxFactor);

                // Write convergence error to status report if called for
                if (net.StatFlag == StatFlag.FULL)
                {
                    LogRelErr(iter, relerr);
                }

                relaxFactor = 1.0;

                bool valveChange = false;

                //  Apply solution damping & check for change in valve status
                if (net.DampLimit > 0.0)
                {
                    if (relerr <= net.DampLimit)
                    {
                        relaxFactor = 0.6;
                        valveChange = SimulationValve.ValveStatus(net, _logger, _valves);
                    }
                }
                else
                {
                    valveChange = SimulationValve.ValveStatus(net, _logger, _valves);
                }

                // Check for convergence
                if (relerr <= net.HAcc)
                {
                    //  We have convergence. Quit if we are into extra iterations.
                    if (iter > net.MaxIter)
                    {
                        break;
                    }

                    //  Quit if no status changes occur.
                    bool statChange = valveChange;

                    if (SimulationLink.LinkStatus(net, _logger, _links))
                    {
                        statChange = true;
                    }

                    if (SimulationControl.PSwitch(_logger, net, _controls))
                    {
                        statChange = true;
                    }

                    if (!statChange)
                    {
                        break;
                    }

                    //  We have a status change so continue the iterations
                    nextCheck = iter + net.CheckFreq;
                }
                else if (iter <= net.MaxCheck && iter == nextCheck)
                {
                    // No convergence yet. See if its time for a periodic status
                    // check  on pumps, CV's, and pipes connected to tanks.
                    SimulationLink.LinkStatus(net, _logger, _links);
                    nextCheck += net.CheckFreq;
                }

                iter++;
            }


            foreach (SimulationNode node  in  _junctions)
            {
                node.SimDemand = node.SimDemand + node.SimEmitter;
            }

            if (errcode > 0)
            {
                LogHydErr(_smat.GetOrder(errcode));
                errcode = 110;
                return;
            }

            if (errcode != 0)
            {
                throw new ENException((ErrorCode)errcode);
            }
        }