示例#1
0
        ///<summary>Creates new segments in outflow links from nodes.</summary>
        /// <param name="dt">Step duration in seconds.</param>
        private void Release(long dt)
        {
            foreach (QualityLink qL  in  _links)
            {
                if (qL.Flow == 0.0)
                {
                    continue;
                }

                // Find flow volume released to link from upstream node
                // (NOTE: Flow volume is allowed to be > link volume.)
                QualityNode qN = qL.UpStreamNode;
                double      q  = Math.Abs(qL.Flow);
                double      v  = q * dt;

                // Include source contribution in quality released from node.
                double c = qN.Quality + qN.SourceContribution;

                // If link has a last seg, check if its quality
                // differs from that of the flow released from node.
                if (qL.Segments.Count > 0)
                {
                    QualitySegment seg = qL.Segments.Last.Value;

                    // Quality of seg close to that of node
                    if (Math.Abs(seg.C - c) < _net.Ctol)
                    {
                        seg.C  = (seg.C * seg.V + c * v) / (seg.V + v);
                        seg.V += v;
                    }
                    else // Otherwise add a new seg to end of link
                    {
                        qL.Segments.AddLast(new QualitySegment(v, c));
                    }
                }
                else // If link has no segs then add a new one.
                {
                    qL.Segments.AddLast(new QualitySegment(qL.LinkVolume, c));
                }
            }
        }
示例#2
0
        ///<summary>Initializes WQ solver system</summary>

        public QualitySim(EpanetNetwork net, TraceSource ignored)
        {
//        this.log = log;
            _net = net;

            _nodes = net.Nodes.Select(QualityNode.Create).ToArray();
            _tanks = _nodes.OfType <QualityTank>().ToArray();
            _juncs = _nodes.Where(x => !(x is QualityTank)).ToArray();
            _links = net.Links.Select(n => new QualityLink(net.Nodes, _nodes, n)).ToArray();


            /*
             * this.nodes = new List<QualityNode>(net.Nodes.Count);
             * this.links = new List<QualityLink>(net.Links.Count);
             * this.tanks = new List<QualityTank>(net.Tanks.Count());
             * this.juncs = new List<QualityNode>(net.Junctions.Count());
             *
             * foreach (Node n in net.Nodes) {
             *  QualityNode qN = QualityNode.Create(n);
             *
             *  this.nodes.Add(qN);
             *
             *  var tank = qN as QualityTank;
             *
             *  if (tank != null)
             *      this.tanks.Add(tank);
             *  else
             *      this.juncs.Add(qN);
             * }
             *
             * foreach (Link n  in  net.Links)
             *  this.links.Add(new QualityLink(net.Nodes, this.nodes, n));
             *
             */

            _bucf      = 1.0;
            _tucf      = 1.0;
            _reactflag = false;

            _qualflag = _net.QualFlag;

            if (_qualflag != QualType.NONE)
            {
                if (_qualflag == QualType.TRACE)
                {
                    foreach (QualityNode qN  in  _nodes)
                    {
                        if (qN.Node.Name.Equals(_net.TraceNode, StringComparison.OrdinalIgnoreCase))
                        {
                            _traceNode         = qN;
                            _traceNode.Quality = 100.0;
                            break;
                        }
                    }
                }

                if (_net.Diffus > 0.0)
                {
                    _sc = _net.Viscos / _net.Diffus;
                }
                else
                {
                    _sc = 0.0;
                }

                _bucf = GetUcf(_net.BulkOrder);
                _tucf = GetUcf(_net.TankOrder);

                _reactflag = GetReactflag();
            }


            _wbulk   = 0.0;
            _wwall   = 0.0;
            _wtank   = 0.0;
            _wsource = 0.0;

            _htime     = 0;
            _rtime     = _net.RStart;
            _qtime     = 0;
            _nperiods  = 0;
            _elevUnits = _net.FieldsMap.GetUnits(FieldType.ELEV);
        }
示例#3
0
        ///<summary>Initializes water quality segments.</summary>
        private void Initsegs()
        {
            foreach (QualityLink qL  in  _links)
            {
                qL.FlowDir = true;

                if (qL.Flow < 0.0)
                {
                    qL.FlowDir = false;
                }

                qL.Segments.Clear();

                double c;

                // Find quality of downstream node
                QualityNode j = qL.DownStreamNode;

                if (j is QualityTank)
                {
                    c = ((QualityTank)j).Concentration;
                }
                else
                {
                    c = j.Quality;
                }

                // Fill link with single segment with this quality
                qL.Segments.AddLast(new QualitySegment(qL.LinkVolume, c));
            }

            // Initialize segments in tanks that use them
            foreach (QualityTank qT  in  _tanks)
            {
                Tank tank = (Tank)qT.Node;

                // Skip reservoirs & complete mix tanks
                if (tank.Type == NodeType.RESERV || tank.MixModel == MixType.MIX1)
                {
                    continue;
                }

                double c = qT.Concentration;

                qT.Segments.Clear();

                // Add 2 segments for 2-compartment model
                if (tank.MixModel == MixType.MIX2)
                {
                    double v = Math.Max(0, qT.Volume - tank.V1Max);
                    qT.Segments.AddLast(new QualitySegment(v, c));
                    v = qT.Volume - v;
                    qT.Segments.AddLast(new QualitySegment(v, c));
                }
                else
                {
                    // Add one segment for FIFO & LIFO models
                    double v = qT.Volume;
                    qT.Segments.AddLast(new QualitySegment(v, c));
                }
            }
        }
示例#4
0
        ///<summary>Accumulates mass flow at nodes and updates nodal quality.</summary>
        /// <param name="dt">Step duration in seconds.</param>
        private void Accumulate(long dt)
        {
            //  Re-set memory used to accumulate mass & volume
            foreach (QualityNode qN  in  _nodes)
            {
                qN.VolumeIn           = 0;
                qN.MassIn             = 0;
                qN.SourceContribution = 0;
            }

            foreach (QualityLink qL  in  _links)
            {
                QualityNode j = qL.DownStreamNode; //  Downstream node
                if (qL.Segments.Count > 0)         //  Accumulate concentrations
                {
                    j.MassIn   = j.MassIn + qL.Segments.First.Value.C;
                    j.VolumeIn = j.VolumeIn + 1;
                }
                j = qL.UpStreamNode;
                if (qL.Segments.Count > 0) // Upstream node
                {                          // Accumulate concentrations
                    j.MassIn   = j.MassIn + qL.Segments.Last.Value.C;
                    j.VolumeIn = j.VolumeIn + 1;
                }
            }

            foreach (QualityNode qN  in  _nodes)
            {
                if (qN.VolumeIn > 0.0)
                {
                    qN.SourceContribution = qN.MassIn / qN.VolumeIn;
                }
            }

            //  Move mass from first segment of each pipe into downstream node
            foreach (QualityNode qN  in  _nodes)
            {
                qN.VolumeIn = 0;
                qN.MassIn   = 0;
            }

            foreach (QualityLink qL  in  _links)
            {
                QualityNode j = qL.DownStreamNode;
                double      v = Math.Abs(qL.Flow) * dt;


                while (v > 0.0)
                {
                    if (qL.Segments.Count == 0)
                    {
                        break;
                    }

                    QualitySegment seg = qL.Segments.First.Value;

                    // Volume transported from this segment is
                    // minimum of flow volume & segment volume
                    // (unless leading segment is also last segment)
                    double vseg = seg.V;
                    vseg = Math.Min(vseg, v);

                    if (qL.Segments.Count == 1)
                    {
                        vseg = v;
                    }

                    double cseg = seg.C;
                    j.VolumeIn = j.VolumeIn + vseg;
                    j.MassIn   = j.MassIn + vseg * cseg;

                    v -= vseg;

                    // If all of segment's volume was transferred, then
                    // replace leading segment with the one behind it
                    // (Note that the current seg is recycled for later use.)
                    if (v >= 0.0 && vseg >= seg.V)
                    {
                        qL.Segments.RemoveFirst();
                    }
                    else
                    {
                        seg.V -= vseg;
                    }
                }
            }
        }