///<summary>Chezy-Manning model calculator, which is implemented through the Hazen-Williams model.</summary>
 public static void CmModelCalculator(
     EpanetNetwork net,
     SimulationLink sl,
     out double invheadloss,
     out double flowcorrection)
 {
     HwModelCalculator(net, sl, out invheadloss, out flowcorrection);
 }
        ///<summary>Hazen-Williams model calculator.</summary>
        public static void HwModelCalculator(
            EpanetNetwork net,
            SimulationLink sL,
            out double invHeadLoss,
            out double flowCorrection)
        {
            // Evaluate headloss coefficients
            double q  = Math.Abs(sL.SimFlow);   // Absolute flow
            double ml = sL.Link.Km;             // Minor loss coeff.
            double r  = sL.Link.FlowResistance; // Resistance coeff.

            double r1 = 1.0 * r + ml;

            // Use large P coefficient for small flow resistance product
            if (r1 * q < net.RQtol)
            {
                invHeadLoss    = 1d / net.RQtol;
                flowCorrection = sL.SimFlow / net.HExp;
                return;
            }

            double hpipe = r * Math.Pow(q, net.HExp); // Friction head loss
            double p     = net.HExp * hpipe;          // Q*dh(friction)/dQ
            double hml;

            if (ml > 0d)
            {
                hml = ml * q * q; // Minor head loss
                p  += 2d * hml;   // Q*dh(Total)/dQ
            }
            else
            {
                hml = 0d;
            }

            p = sL.SimFlow / p; // 1 / (dh/dQ)

            invHeadLoss    = Math.Abs(p);
            flowCorrection = p * (hpipe + hml);
        }
Exemplo n.º 3
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.
        }
Exemplo n.º 4
0
        /// <summary>Simulate water quality during one hydraulic step.</summary>
        public bool SimulateSingleStep(List <SimulationNode> hydNodes, List <SimulationLink> hydLinks, long hydStep)
        {
            int count = 0;

            foreach (QualityNode qN  in  _nodes)
            {
                qN.Demand = hydNodes[count++].SimDemand;
            }

            count = 0;
            foreach (QualityLink qL  in  _links)
            {
                SimulationLink hL = hydLinks[count++];
                qL.Flow = hL.SimStatus <= StatType.CLOSED ? 0d : hL.SimFlow;
            }

            _htime += hydStep;

            if (_qualflag != QualType.NONE && _qtime < _net.Duration)
            {
                if (_reactflag && _qualflag != QualType.AGE)
                {
                    Ratecoeffs();
                }

                if (_qtime == 0)
                {
                    Initsegs();
                }
                else
                {
                    Reorientsegs();
                }
            }

            long tstep = Nextqual();

            return(tstep != 0);
        }
        private const double AC = -5.14214965799e-03; // AA*AB

        ///<summary>Darcy-Weishbach model calculator.</summary>
        public static void DwModelCalculator(
            EpanetNetwork net,
            SimulationLink sL,
            out double invHeadLoss,
            out double flowCorrection)
        {
            Link   link           = sL.Link;
            double simFlow        = sL.SimFlow;
            double q              = Math.Abs(simFlow);   // Absolute flow
            double km             = link.Km;             // Minor loss coeff.
            double flowResistance = link.FlowResistance; // Resistance coeff.
            double roughness      = link.Kc;
            double diameter       = link.Diameter;
            bool   isOne          = sL.Type > LinkType.PIPE;

            double resistance;

            if (isOne)
            {
                resistance = 1d;
            }
            else
            {
                double s = net.Viscos * diameter;
                double w = q / s;

                if (w >= A1)
                {
                    double y1 = A8 / Math.Pow(w, 0.9d);
                    double y2 = roughness / (3.7 * diameter) + y1;
                    double y3 = A9 * Math.Log(y2);
                    resistance = 1.0 / (y3 * y3);
                }
                else if (w > A2)
                {
                    double y2 = roughness / (3.7 * diameter) + AB;
                    double y3 = A9 * Math.Log(y2);
                    double fa = 1.0 / (y3 * y3);
                    double fb = (2.0 + AC / (y2 * y3)) * fa;
                    double r2 = w / A2;
                    double x1 = 7.0 * fa - fb;
                    double x2 = 0.128 - 17.0 * fa + 2.5 * fb;
                    double x3 = -0.128 + 13.0 * fa - (fb + fb);
                    double x4 = r2 * (0.032 - 3.0 * fa + 0.5 * fb);
                    resistance = x1 + r2 * (x2 + r2 * (x3 + x4));
                }
                else if (w > A4)
                {
                    resistance = A3 * s / q;
                }
                else
                {
                    resistance = 8d;
                }
            }

            double r1 = resistance * flowResistance + km;

            // Use large P coefficient for small flow resistance product
            if (r1 * q < net.RQtol)
            {
                invHeadLoss    = 1d / net.RQtol;
                flowCorrection = simFlow / net.HExp;
            }
            else
            {
                // Compute P and Y coefficients
                double hpipe = r1 * (q * q); // Total head loss
                double p     = 2d * r1 * q;  // |dh/dQ|
                invHeadLoss    = 1d / p;
                flowCorrection = simFlow < 0 ? -hpipe * invHeadLoss : hpipe * invHeadLoss;
            }
        }
Exemplo n.º 6
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;
        }
Exemplo n.º 7
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);
            }
        }