]> git.mxchange.org Git - flightgear.git/blob - src/FDM/YASim/Atmosphere.cpp
YASim-0.1.3 updates.
[flightgear.git] / src / FDM / YASim / Atmosphere.cpp
1 #include "Math.hpp"
2 #include "Atmosphere.hpp"
3 namespace yasim {
4
5 // Copied from McCormick, who got it from "The ARDC Model Atmosphere"
6 // Note that there's an error in the text in the first entry,
7 // McCormick lists 299.16/101325/1.22500, but those don't agree with
8 // R=287.  I chose to correct the temperature to 288.20, since 79F is
9 // pretty hot for a "standard" atmosphere.
10 //                             meters   kelvin      Pa   kg/m^3
11 float Atmosphere::data[][4] = {{ 0,     288.20, 101325, 1.22500 },
12                                { 900,   282.31,  90971, 1.12260 },
13                                { 1800,  276.46,  81494, 1.02690 },
14                                { 2700,  270.62,  72835, 0.93765 },
15                                { 3600,  264.77,  64939, 0.85445 },
16                                { 4500,  258.93,  57752, 0.77704 },
17                                { 5400,  253.09,  51226, 0.70513 },
18                                { 6300,  247.25,  45311, 0.63845 },
19                                { 7200,  241.41,  39963, 0.57671 },
20                                { 8100,  235.58,  35140, 0.51967 },
21                                { 9000,  229.74,  30800, 0.46706 },
22                                { 9900,  223.91,  26906, 0.41864 },
23                                { 10800, 218.08,  23422, 0.37417 },
24                                { 11700, 216.66,  20335, 0.32699 },
25                                { 12600, 216.66,  17654, 0.28388 },
26                                { 13500, 216.66,  15327, 0.24646 },
27                                { 14400, 216.66,  13308, 0.21399 },
28                                { 15300, 216.66,  11555, 0.18580 },
29                                { 16200, 216.66,  10033, 0.16133 },
30                                { 17100, 216.66,   8712, 0.14009 },
31                                { 18000, 216.66,   7565, 0.12165 },
32                                { 18900, 216.66,   6570, 0.10564 }};
33
34 // Universal gas constant for air, in SI units.  P = R * rho * T.
35 // P in pascals (N/m^2), rho is kg/m^3, T in kelvin.
36 const float R = 287.1;
37
38 float Atmosphere::getStdTemperature(float alt)
39 {
40     return getRecord(alt, 1);
41 }
42
43 float Atmosphere::getStdPressure(float alt)
44 {
45     return getRecord(alt, 2);
46 }
47
48 float Atmosphere::getStdDensity(float alt)
49 {
50     return getRecord(alt, 3);
51 }
52
53 float Atmosphere::calcVEAS(float spd, float pressure, float temp)
54 {
55     static float rho0 = getStdDensity(0);
56     float densityRatio = calcDensity(pressure, temp) / rho0;
57     return spd * Math::sqrt(densityRatio);
58 }
59
60 float Atmosphere::calcVCAS(float spd, float pressure, float temp)
61 {
62     // Stolen shamelessly from JSBSim.  Constants that appear:
63     //   2/5  == gamma-1
64     //   5/12 == 1/(gamma+1)
65     //   4/5  == 2*(gamma-1)
66     //  14/5  == 2*gamma
67     //  28/5  == 4*gamma
68     // 144/25 == (gamma+1)^2
69
70     float m2 = calcMach(spd, temp);
71     m2 = m2*m2; // mach^2
72
73     float cp; // pressure coefficient
74     if(m2 < 1) {
75         // (1+(mach^2)/5)^(gamma/(gamma-1))
76         cp = Math::pow(1+0.2*m2, 3.5);
77     } else {
78         float tmp0 = ((144/25.) * m2) / (28/5.*m2 - 4/5.);
79         float tmp1 = ((14/5.) * m2 - (2/5.)) * (5/12.);
80         cp = Math::pow(tmp0, 3.5) * tmp1;
81     }
82
83     // Conditions at sea level
84     float p0 = getStdPressure(0);
85     float rho0 = getStdDensity(0);
86
87     float tmp = Math::pow((pressure/p0)*(cp-1) + 1, (2/7.));
88     return Math::sqrt((7*p0/rho0)*(tmp-1));
89 }
90
91 float Atmosphere::calcDensity(float pressure, float temp)
92 {
93     return pressure / (R * temp);
94 }
95
96 float Atmosphere::calcMach(float spd, float temp)
97 {
98     return spd / Math::sqrt(1.4 * R * temp);
99 }
100
101 float Atmosphere::getRecord(float alt, int recNum)
102 {
103     int hi = (sizeof(data) / (4*sizeof(float))) - 1;
104     int lo = 0;
105
106     // safety valve, clamp to the edges of the table
107     if(alt < data[0][0])       hi=1;
108     else if(alt > data[hi][0]) lo = hi-1;
109
110     // binary search
111     while(1) {
112         if(hi-lo == 1) break;
113         int mid = (hi+lo)>>1;
114         if(alt < data[mid][0]) hi = mid;
115         else lo = mid;
116     }
117
118     // interpolate
119     float frac = (alt - data[lo][0])/(data[hi][0] - data[lo][0]);
120     float a = data[lo][recNum];
121     float b = data[hi][recNum];
122     return a + frac * (b-a);
123 }
124
125 }; // namespace yasim