ningshuxia
2024-06-18 e83dca6e861b622b54d3392ca0d3f1f1eb69f7c9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
using IStation.Epanet.Enums;
using System.Collections;
 
namespace IStation.Epanet.Network.Structures
{
 
    ///<summary>2D graph used to map volume, pump, efficiency and head loss curves.</summary>
    public sealed class Curve : Element, IEnumerable<EnPoint>
    {
        private readonly List<EnPoint> _points = new List<EnPoint>();
 
        public Curve(string name) : base(name) { }
 
        public override ElementType ElementType => ElementType.CURVE;
 
        /// <summary>Computes intercept and slope of head v. flow curve at current flow.</summary>
        /// <param name="fMap"></param>
        /// <param name="q">Flow value.</param>
        /// <param name="h0">Head at zero flow (y-intercept).</param>
        /// <param name="r">dHead/dFlow (slope).</param>
        public void GetCoeff(FieldsMap fMap, double q, out double h0, out double r)
        {
            q *= fMap.GetUnits(FieldType.FLOW);
 
            int npts = _points.Count;
 
            var k2 = 0;
            while (k2 < npts && _points[k2].X < q) k2++;
 
            if (k2 == 0) k2++;
            else if (k2 == npts) k2--;
 
            int k1 = k2 - 1;
 
            r = (_points[k2].Y - _points[k1].Y) / (_points[k2].X - _points[k1].X);
            h0 = _points[k1].Y - r * _points[k1].X;
 
            h0 /= fMap.GetUnits(FieldType.HEAD);
            r *= fMap.GetUnits(FieldType.FLOW) / fMap.GetUnits(FieldType.HEAD);
 
        }
 
        ///<summary>Curve type.</summary>
        public CurveType Type { get; set; } //TODO: parse it correctly
 
        /// <summary>Compute the linear interpolation of a 2d cartesian graph.</summary>
        /// <param name="x">The abscissa value.</param>
        /// <returns>The interpolated value.</returns>
        public double Interpolate(double x)
        {
            var p = _points;
            int m = _points.Count - 1;
 
            if (x <= p[0].X) return p[0].Y;
 
            for (int i = 1; i <= m; i++)
            {
                if (p[i].X >= x)
                {
                    double dx = p[i].X - p[i - 1].X;
                    double dy = p[i].Y - p[i - 1].Y;
                    if (Math.Abs(dx) < Constants.TINY) return p[i].Y;
 
                    return p[i].Y - (p[i].X - x) * dy / dx;
                }
            }
 
            return p[m].Y;
        }
 
        #region partial implementation of IList<EnPoint>
 
        public void Add(double x, double y) { _points.Add(new EnPoint(x, y)); }
 
        IEnumerator IEnumerable.GetEnumerator() { return _points.GetEnumerator(); }
        public IEnumerator<EnPoint> GetEnumerator() { return _points.GetEnumerator(); }
 
        public int Count => _points.Count;
        public EnPoint this[int index] => _points[index];
 
        #endregion
 
    }
 
}