1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 3 Header: FGStandardAtmosphere.h 4 Author: Jon Berndt 5 Date started: 5/2011 6 7 ------------- Copyright (C) 2011 Jon S. Berndt (jon@jsbsim.org) ------------- 8 9 This program is free software; you can redistribute it and/or modify it under 10 the terms of the GNU Lesser General Public License as published by the Free 11 Software Foundation; either version 2 of the License, or (at your option) any 12 later version. 13 14 This program is distributed in the hope that it will be useful, but WITHOUT 15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 17 details. 18 19 You should have received a copy of the GNU Lesser General Public License along 20 with this program; if not, write to the Free Software Foundation, Inc., 59 21 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 23 Further information about the GNU Lesser General Public License can also be 24 found on the world wide web at http://www.gnu.org. 25 26 HISTORY 27 -------------------------------------------------------------------------------- 28 5/2011 JSB Created 29 30 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 31 SENTRY 32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 33 34 #ifndef FGSTANDARDATMOSPHERE_H 35 #define FGSTANDARDATMOSPHERE_H 36 37 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 38 INCLUDES 39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 40 41 #include <vector> 42 43 #include "math/FGTable.h" 44 #include "models/FGAtmosphere.h" 45 46 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 47 FORWARD DECLARATIONS 48 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 49 50 namespace JSBSim { 51 52 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 53 CLASS DOCUMENTATION 54 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 55 56 /** Models the 1976 U.S. Standard Atmosphere, with the ability to modify the 57 temperature and pressure. A base feature of the model is the temperature 58 profile that is stored as an FGTable object with this data: 59 60 @code 61 GeoMet Alt Temp GeoPot Alt GeoMet Alt 62 (ft) (deg R) (km) (km) 63 --------- -------- ---------- ---------- 64 0.0 518.67 // 0.000 0.000 65 36151.6 390.0 // 11.000 11.019 66 65823.5 390.0 // 20.000 20.063 67 105518.4 411.6 // 32.000 32.162 68 155347.8 487.2 // 47.000 47.350 69 168677.8 487.2 // 51.000 51.413 70 235570.9 386.4 // 71.000 71.802 71 282152.2 336.5; // 84.852 86.000 72 @endcode 73 74 The pressure is calculated at lower altitudes through the use of two equations 75 that are presented in the U.S. Standard Atmosphere document (see references). 76 Density, kinematic viscosity, speed of sound, etc., are all calculated based 77 on various constants and temperature and pressure. At higher altitudes (above 78 86 km (282152 ft) a different and more complicated method of calculating 79 pressure is used. 80 81 The temperature may be modified through the use of several methods. Ultimately, 82 these access methods allow the user to modify the sea level standard 83 temperature, and/or the sea level standard pressure, so that the entire profile 84 will be consistently and accurately calculated. 85 86 <h2> Properties </h2> 87 @property atmosphere/delta-T 88 @property atmosphere/T-sl-dev-F 89 90 @author Jon Berndt 91 @see "U.S. Standard Atmosphere, 1976", NASA TM-X-74335 92 */ 93 94 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 95 CLASS DECLARATION 96 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 97 98 class FGStandardAtmosphere : public FGAtmosphere { 99 public: 100 /// Constructor 101 FGStandardAtmosphere(FGFDMExec*); 102 103 /// Destructor 104 virtual ~FGStandardAtmosphere(); 105 106 bool InitModel(void) override; 107 108 // ************************************************************************* 109 /// @name Temperature access functions. 110 /// There are several ways to get the temperature, and several modeled 111 /// temperature values that can be retrieved. The U.S. Standard Atmosphere 112 /// temperature either at a specified altitude, or at sea level can be 113 /// retrieved. These two temperatures do NOT include the effects of any bias 114 /// or delta gradient that may have been supplied by the user. The modeled 115 /// temperature and the modeled temperature at sea level can also be 116 /// retrieved. These two temperatures DO include the effects of an optionally 117 /// user-supplied bias or delta gradient. 118 // @{ 119 /// Returns the actual modeled temperature in degrees Rankine at a specified 120 /// altitude. 121 /// @param altitude The altitude above sea level (ASL) in feet. 122 /// @return Modeled temperature in degrees Rankine at the specified altitude. 123 double GetTemperature(double altitude) const override; 124 125 /// Returns the standard temperature in degrees Rankine at a specified 126 /// altitude. 127 /// @param altitude The altitude in feet above sea level (ASL) to get the 128 /// temperature at. 129 /// @return The STANDARD temperature in degrees Rankine at the specified 130 /// altitude. 131 virtual double GetStdTemperature(double altitude) const; 132 133 /// Returns the standard sea level temperature in degrees Rankine. 134 /// @return The STANDARD temperature at sea level in degrees Rankine. GetStdTemperatureSL()135 virtual double GetStdTemperatureSL() const { return StdSLtemperature; } 136 137 /// Returns the ratio of the standard temperature at the supplied altitude 138 /// over the standard sea level temperature. GetStdTemperatureRatio(double h)139 virtual double GetStdTemperatureRatio(double h) const { return GetStdTemperature(h)/StdSLtemperature; } 140 141 /// Returns the temperature bias over the sea level value in degrees Rankine. GetTemperatureBias(eTemperature to)142 virtual double GetTemperatureBias(eTemperature to) const 143 { if (to == eCelsius || to == eKelvin) return TemperatureBias/1.80; else return TemperatureBias; } 144 145 /// Returns the temperature gradient to be applied on top of the standard 146 /// temperature gradient. GetTemperatureDeltaGradient(eTemperature to)147 virtual double GetTemperatureDeltaGradient(eTemperature to) 148 { if (to == eCelsius || to == eKelvin) return TemperatureDeltaGradient/1.80; else return TemperatureDeltaGradient; } 149 150 /// Sets the Sea Level temperature, if it is to be different than the 151 /// standard. 152 /// This function will calculate a bias - a difference - from the standard 153 /// atmosphere temperature and will apply that bias to the entire 154 /// temperature profile. This is one way to set the temperature bias. Using 155 /// the SetTemperatureBias function will replace the value calculated by 156 /// this function. 157 /// @param t the temperature value in the unit provided. 158 /// @param unit the unit of the temperature. 159 void SetTemperatureSL(double t, eTemperature unit=eFahrenheit) override; 160 161 /// Sets the temperature at the supplied altitude, if it is to be different 162 /// than the standard temperature. 163 /// This function will calculate a bias - a difference - from the standard 164 /// atmosphere temperature at the supplied altitude and will apply that 165 /// calculated bias to the entire temperature profile. If a graded delta is 166 /// present, that will be included in the calculation - that is, regardless 167 /// of any graded delta present, a temperature bias will be determined so that 168 /// the temperature requested in this function call will be reached. 169 /// @param t The temperature value in the unit provided. 170 /// @param h The altitude in feet above sea level. 171 /// @param unit The unit of the temperature. 172 void SetTemperature(double t, double h, eTemperature unit=eFahrenheit) override; 173 174 /// Sets the temperature bias to be added to the standard temperature at all 175 /// altitudes. 176 /// This function sets the bias - the difference - from the standard 177 /// atmosphere temperature. This bias applies to the entire 178 /// temperature profile. Another way to set the temperature bias is to use the 179 /// SetSLTemperature function, which replaces the value calculated by 180 /// this function with a calculated bias. 181 /// @param t the temperature value in the unit provided. 182 /// @param unit the unit of the temperature. 183 virtual void SetTemperatureBias(eTemperature unit, double t); 184 185 /// Sets a Sea Level temperature delta that is ramped out by 86 km. 186 /// The value of the delta is used to calculate a delta gradient that is 187 /// applied to the temperature at all altitudes below 86 km (282152 ft). 188 /// For instance, if a temperature of 20 degrees F is supplied, the delta 189 /// gradient would be 20/282152 - or, about 7.09E-5 degrees/ft. At sea level, 190 /// the full 20 degrees would be added to the standard temperature, 191 /// but that 20 degree delta would be reduced by 7.09E-5 degrees for every 192 /// foot of altitude above sea level, so that by 86 km, there would be no 193 /// further delta added to the standard temperature. 194 /// The graded delta can be used along with the a bias to tailor the 195 /// temperature profile as desired. 196 /// @param t the sea level temperature delta value in the unit provided. 197 /// @param unit the unit of the temperature. 198 virtual void SetSLTemperatureGradedDelta(eTemperature unit, double t); 199 200 /// Sets the temperature delta value at the supplied altitude/elevation above 201 /// sea level, to be added to the standard temperature and ramped out by 202 /// 86 km. 203 /// This function computes the sea level delta from the standard atmosphere 204 /// temperature at sea level. 205 /// @param t the temperature skew value in the unit provided. 206 /// @param unit the unit of the temperature. 207 virtual void SetTemperatureGradedDelta(double t, double h, eTemperature unit=eFahrenheit); 208 209 /// This function resets the model to apply no bias or delta gradient to the 210 /// temperature. 211 /// The delta gradient and bias values are reset to 0.0, and the standard 212 /// temperature is used for the entire temperature profile at all altitudes. 213 virtual void ResetSLTemperature(); 214 //@} 215 216 // ************************************************************************* 217 /// @name Pressure access functions. 218 //@{ 219 /// Returns the pressure at a specified altitude in psf. 220 double GetPressure(double altitude) const override; 221 222 /// Returns the standard pressure at the specified altitude. 223 virtual double GetStdPressure(double altitude) const; 224 225 /** Sets the sea level pressure for modeling an off-standard pressure 226 profile. This could be useful in the case where the pressure at an 227 airfield is known or set for a particular simulation run. 228 @param pressure The pressure in the units specified. 229 @param unit the unit of measure that the specified pressure is 230 supplied in.*/ 231 void SetPressureSL(ePressure unit, double pressure) override; 232 233 /** Resets the sea level to the Standard sea level pressure, and recalculates 234 dependent parameters so that the pressure calculations are standard. */ 235 virtual void ResetSLPressure(); 236 //@} 237 238 // ************************************************************************* 239 /// @name Density access functions. 240 //@{ 241 /// Returns the standard density at a specified altitude 242 virtual double GetStdDensity(double altitude) const; 243 //@} 244 245 // ************************************************************************* 246 ///@name Humidity access functions 247 //@{ 248 /** Sets the dew point. 249 @param dewpoint The dew point in the units specified 250 @param unit The unit of measure that the specified dew point is supplied 251 in. */ 252 void SetDewPoint(eTemperature unit, double dewpoint); 253 /** Returns the dew point. 254 @param to The unit of measure that the dew point should be supplied in. */ 255 double GetDewPoint(eTemperature to) const; 256 /** Sets the partial pressure of water vapor. 257 @param Pv The vapor pressure in the units specified 258 @param unit The unit of measure that the specified vapor pressure is 259 supplied in. */ 260 void SetVaporPressure(ePressure unit, double Pv); 261 /** Returns the partial pressure of water vapor. 262 @param to The unit of measure that the water vapor should be supplied in. 263 */ 264 double GetVaporPressure(ePressure to) const; 265 /** Returns the saturated pressure of water vapor. 266 @param to The unit of measure that the water vapor should be supplied in. 267 */ 268 double GetSaturatedVaporPressure(ePressure to) const; 269 /** Sets the relative humidity. 270 @param RH The relative humidity in percent. */ 271 void SetRelativeHumidity(double RH); 272 /// Returns the relative humidity in percent. 273 double GetRelativeHumidity(void) const; 274 /** Sets the vapor mass per million of dry air mass units. 275 @param frac The fraction of water in ppm of dry air. */ 276 void SetVaporMassFractionPPM(double frac); 277 /// Returns the vapor mass per million of dry air mass units (ppm). 278 double GetVaporMassFractionPPM(void) const; 279 //@} 280 281 /// Prints the U.S. Standard Atmosphere table. 282 virtual void PrintStandardAtmosphereTable(); 283 284 protected: 285 /// Standard sea level conditions 286 double StdSLtemperature, StdSLdensity, StdSLpressure, StdSLsoundspeed; 287 288 double TemperatureBias; 289 double TemperatureDeltaGradient; 290 double GradientFadeoutAltitude; 291 double VaporMassFraction; 292 double SaturatedVaporPressure; 293 294 FGTable StdAtmosTemperatureTable; 295 FGTable MaxVaporMassFraction; 296 std::vector<double> LapseRates; 297 std::vector<double> PressureBreakpoints; 298 std::vector<double> StdPressureBreakpoints; 299 std::vector<double> StdDensityBreakpoints; 300 std::vector<double> StdLapseRates; 301 302 void Calculate(double altitude) override; 303 304 /// Recalculate the lapse rate vectors when the temperature profile is altered 305 /// in a way that would change the lapse rates, such as when a gradient is 306 /// applied. 307 /// This function is also called to initialize the lapse rate vector. 308 void CalculateLapseRates(); 309 310 /// Calculate (or recalculate) the atmospheric pressure breakpoints at the 311 /// altitudes in the standard temperature table. 312 void CalculatePressureBreakpoints(double SLpress); 313 314 /// Calculate the atmospheric density breakpoints at the 315 /// altitudes in the standard temperature table. 316 void CalculateStdDensityBreakpoints(); 317 318 /// Convert a geometric altitude to a geopotential altitude GeopotentialAltitude(double geometalt)319 double GeopotentialAltitude(double geometalt) const { return (geometalt * EarthRadius) / (EarthRadius + geometalt); } 320 321 /// Convert a geopotential altitude to a geometric altitude GeometricAltitude(double geopotalt)322 double GeometricAltitude(double geopotalt) const { return (geopotalt * EarthRadius) / (EarthRadius - geopotalt); } 323 324 /** Calculates the density altitude given any temperature or pressure bias. 325 Calculated density for the specified geometric altitude given any temperature 326 or pressure biases is passed in. 327 @param density 328 @param geometricAlt 329 @see 330 https://en.wikipedia.org/wiki/Density_altitude 331 https://wahiduddin.net/calc/density_altitude.htm 332 */ 333 double CalculateDensityAltitude(double density, double geometricAlt) override; 334 335 /** Calculates the pressure altitude given any temperature or pressure bias. 336 Calculated density for the specified geometric altitude given any temperature 337 or pressure biases is passed in. 338 @param pressure 339 @param geometricAlt 340 @see 341 https://en.wikipedia.org/wiki/Pressure_altitude 342 */ 343 double CalculatePressureAltitude(double pressure, double geometricAlt) override; 344 345 /// Calculate the pressure of water vapor with the Magnus formula. 346 double CalculateVaporPressure(double temperature); 347 348 /// Validate the value of the vapor mass fraction 349 void ValidateVaporMassFraction(double geometricAlt); 350 351 /// Calculate the SL density CalculateSLDensity(void)352 void CalculateSLDensity(void) { SLdensity = SLpressure / (Reng * SLtemperature); } 353 354 /// Calculate the SL density and sound speed 355 void CalculateSLSoundSpeedAndDensity(void); 356 357 void bind(void) override; 358 void Debug(int from) override; 359 360 /// Earth radius in ft as defined for ISA 1976 361 static constexpr double EarthRadius = 6356766.0 / fttom; 362 /** Sonntag constants based on ref [2]. They are valid for temperatures 363 between -45 degC (-49 degF) and 60 degC (140 degF) with a precision of 364 +/-0.35 degC (+/-0.63 degF) */ 365 static constexpr double a = 611.2/psftopa; // psf 366 static constexpr double b = 17.62; // 1/degC 367 static constexpr double c = 243.12; // degC 368 /// Mean molecular weight for water - slug/mol 369 static constexpr double Mwater = 18.016 * kgtoslug / 1000.0; 370 static constexpr double Rdry = Rstar / Mair; 371 static constexpr double Rwater = Rstar / Mwater; 372 }; 373 374 } // namespace JSBSim 375 376 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 377 #endif 378