Beispiel #1
0
        /// <summary>Complete mix tank model.</summary>
        ///  <param name="tank">Tank to be updated.</param>
        /// <param name="dt">Step duration in seconds.</param>
        private void Tankmix1(QualityTank tank, long dt)
        {
            // React contents of tank
            double c = Tankreact(tank.Concentration, tank.Volume, ((Tank)tank.Node).Kb, dt);

            // Determine tank & volumes
            double vold = tank.Volume;

            tank.Volume = tank.Volume + tank.Demand * dt;

            double vin = tank.VolumeIn;

            double cin;

            if (vin > 0.0)
            {
                cin = tank.MassIn / vin;
            }
            else
            {
                cin = 0.0;
            }

            // Compute inflow concen.
            double cmax = Math.Max(c, cin);

            // Mix inflow with tank contents
            if (vin > 0.0)
            {
                c = (c * vold + cin * vin) / (vold + vin);
            }
            c = Math.Min(c, cmax);
            c = Math.Max(c, 0.0);
            tank.Concentration = c;
            tank.Quality       = tank.Concentration;
        }
Beispiel #2
0
        /// <summary>2-compartment tank model (seg1 = mixing zone,seg2 = ambient zone).</summary>
        /// <param name="tank">Tank to be updated.</param>
        /// <param name="dt">Step duration in seconds.</param>
        private void Tankmix2(QualityTank tank, long dt)
        {
            if (tank.Segments.Count == 0)
            {
                return;
            }

            QualitySegment seg1 = tank.Segments.Last.Value;
            QualitySegment seg2 = tank.Segments.First.Value;

            seg1.C = Tankreact(seg1.C, seg1.V, ((Tank)tank.Node).Kb, dt);
            seg2.C = Tankreact(seg2.C, seg2.V, ((Tank)tank.Node).Kb, dt);

            // Find inflows & outflows
            double vnet  = tank.Demand * dt;
            double vin   = tank.VolumeIn;
            double cin   = vin > 0.0 ? tank.MassIn / vin : 0.0;
            double v1Max = ((Tank)tank.Node).V1Max;

            // Tank is filling
            double vt = 0.0;

            if (vnet > 0.0)
            {
                vt = Math.Max(0.0, seg1.V + vnet - v1Max);
                if (vin > 0.0)
                {
                    seg1.C = (seg1.C * seg1.V + cin * vin) / (seg1.V + vin);
                }
                if (vt > 0.0)
                {
                    seg2.C = (seg2.C * seg2.V + seg1.C * vt) / (seg2.V + vt);
                }
            }

            // Tank is emptying
            if (vnet < 0.0)
            {
                if (seg2.V > 0.0)
                {
                    vt = Math.Min(seg2.V, -vnet);
                }
                if (vin + vt > 0.0)
                {
                    seg1.C = (seg1.C * seg1.V + cin * vin + seg2.C * vt) / (seg1.V + vin + vt);
                }
            }

            // Update segment volumes
            if (vt > 0.0)
            {
                seg1.V = v1Max;
                if (vnet > 0.0)
                {
                    seg2.V += vt;
                }
                else
                {
                    seg2.V = Math.Max(0.0, seg2.V - vt);
                }
            }
            else
            {
                seg1.V += vnet;
                seg1.V  = Math.Min(seg1.V, v1Max);
                seg1.V  = Math.Max(0.0, seg1.V);
                seg2.V  = 0.0;
            }

            tank.Volume = Math.Max(tank.Volume + vnet, 0.0);
            // Use quality of mixed compartment (seg1) to
            // represent quality of tank since this is where
            // outflow begins to flow from
            tank.Concentration = seg1.C;
            tank.Quality       = tank.Concentration;
        }
Beispiel #3
0
        /// <summary>Last In-First Out (LIFO) tank model.</summary>
        ///  <param name="tank">Tank to be updated.</param>
        /// <param name="dt">Step duration in seconds.</param>
        private void Tankmix4(QualityTank tank, long dt)
        {
            if (tank.Segments.Count == 0)
            {
                return;
            }

            // React contents of each compartment
            if (_reactflag)
            {
                for (LinkedListNode <QualitySegment> el = tank.Segments.Last; el != null; el = el.Previous)
                {
                    QualitySegment seg = el.Value;
                    seg.C = Tankreact(seg.C, seg.V, ((Tank)tank.Node).Kb, dt);
                }
            }

            // Find inflows & outflows
            double vnet = tank.Demand * dt;
            double vin  = tank.VolumeIn;
            double cin;

            if (vin > 0.0)
            {
                cin = tank.MassIn / tank.VolumeIn;
            }
            else
            {
                cin = 0.0;
            }

            tank.Volume        = Math.Max(0.0, tank.Volume + vnet);
            tank.Concentration = tank.Segments.Last.Value.C;

            // If tank filling, then create new last seg
            if (vnet > 0.0)
            {
                if (tank.Segments.Count > 0)
                {
                    QualitySegment seg = tank.Segments.Last.Value;
                    // Quality is the same, so just add flow volume to last seg
                    if (Math.Abs(seg.C - cin) < _net.Ctol)
                    {
                        seg.V += vnet;
                    }
                    // Otherwise add a new last seg to tank
                    // Which points to old last seg
                    else
                    {
                        tank.Segments.AddLast(new QualitySegment(vin, cin));
                    }
                }
                else
                {
                    tank.Segments.AddLast(new QualitySegment(vin, cin));
                }

                tank.Concentration = tank.Segments.Last.Value.C;
            }
            // If net emptying then remove last segments until vnet consumed
            else if (vnet < 0.0)
            {
                double vsum = 0.0;
                double csum = 0.0;
                vnet = -vnet;

                while (vnet > 0.0)
                {
                    if (tank.Segments.Count == 0)
                    {
                        break;
                    }

                    QualitySegment seg = tank.Segments.Last.Value;
                    if (seg == null)
                    {
                        break;
                    }

                    double vseg = seg.V;
                    vseg = Math.Min(vseg, vnet);
                    if (tank.Segments.Count == 1)
                    {
                        vseg = vnet;
                    }

                    vsum += vseg;
                    csum += seg.C * vseg;
                    vnet -= vseg;

                    if (vnet >= 0.0 && vseg >= seg.V)
                    {
                        tank.Segments.RemoveLast(); //(2.00.12 - LR)
                    }
                    else
                    {
                        // Remaining volume in segment
                        seg.V -= vseg;
                    }
                }
                // Reported tank quality is mixture of flow released and any inflow
                tank.Concentration = (csum + tank.MassIn) / (vsum + vin);
            }
            tank.Quality = tank.Concentration;
        }
Beispiel #4
0
        /// <summary>First-In-First-Out (FIFO) tank model.</summary>
        /// <param name="tank">Tank to be updated.</param>
        /// <param name="dt">Step duration in seconds.</param>
        ///
        private void Tankmix3(QualityTank tank, long dt)
        {
            if (tank.Segments.Count == 0)
            {
                return;
            }

            // React contents of each compartment
            if (_reactflag)
            {
                foreach (QualitySegment seg  in  tank.Segments)
                {
                    seg.C = Tankreact(seg.C, seg.V, ((Tank)tank.Node).Kb, dt);
                }
            }

            // Find inflows & outflows
            double vnet = tank.Demand * dt;
            double vin  = tank.VolumeIn;
            double vout = vin - vnet;
            double cin;

            if (vin > 0.0)
            {
                cin = tank.MassIn / tank.VolumeIn;
            }
            else
            {
                cin = 0.0;
            }

            tank.Volume = Math.Max(tank.Volume + vnet, 0.0);

            // Withdraw flow from first segment
            double vsum = 0.0;
            double csum = 0.0;

            while (vout > 0.0)
            {
                if (tank.Segments.Count == 0)
                {
                    break;
                }

                QualitySegment seg  = tank.Segments.First.Value;
                double         vseg = seg.V; // Flow volume from leading seg
                vseg = Math.Min(vseg, vout);
                if (tank.Segments.Count == 1)
                {
                    vseg = vout;
                }
                vsum += vseg;
                csum += seg.C * vseg;
                vout -= vseg; // Remaining flow volume
                if (vout >= 0.0 && vseg >= seg.V)
                {
                    tank.Segments.RemoveFirst();
                }
                else
                {
                    // Remaining volume in segment
                    seg.V -= vseg;
                }
            }

            // Use quality withdrawn from 1st segment
            // to represent overall quality of tank
            if (vsum > 0.0)
            {
                tank.Concentration = csum / vsum;
            }
            else
            {
                tank.Concentration = tank.Segments.First.Value.C;
            }

            tank.Quality = tank.Concentration;

            // Add new last segment for new flow entering tank
            if (vin > 0.0)
            {
                if (tank.Segments.Count > 0)
                {
                    QualitySegment seg = tank.Segments.Last.Value;

                    // Quality is the same, so just add flow volume to last seg
                    if (Math.Abs(seg.C - cin) < _net.Ctol)
                    {
                        seg.V += vin;
                    }
                    else // Otherwise add a new seg to tank
                    {
                        tank.Segments.AddLast(new QualitySegment(vin, cin));
                    }
                }
                else //  If no segs left then add a new one.
                {
                    tank.Segments.AddLast(new QualitySegment(vin, cin));
                }
            }
        }