50 #include "FGFDMExec.h"
51 #include "FGStandardAtmosphere.h"
60 :
FGAtmosphere(fdmex), StdSLpressure(StdDaySLpressure), TemperatureBias(0.0),
61 TemperatureDeltaGradient(0.0), VaporMassFraction(0.0),
62 SaturatedVaporPressure(0.0), StdAtmosTemperatureTable(9),
63 MaxVaporMassFraction(10)
65 Name =
"FGStandardAtmosphere";
87 StdAtmosTemperatureTable << 0.0000 << 518.67
88 << 36089.2388 << 389.97
89 << 65616.7979 << 389.97
90 << 104986.8766 << 411.57
91 << 154199.4751 << 487.17
92 << 167322.8346 << 487.17
93 << 232939.6325 << 386.37
94 << 278385.8268 << 336.5028
95 << 298556.4304 << 336.5028;
106 MaxVaporMassFraction << 0.0000 << 35000.
107 << 3280.8399 << 31000.
108 << 6561.6798 << 28000.
109 << 13123.3596 << 22000.
110 << 19685.0394 << 8900.
111 << 26246.7192 << 4700.
112 << 32808.3990 << 1300.
113 << 39370.0787 << 230.
115 << 52493.4383 << 38.;
117 unsigned int numRows = StdAtmosTemperatureTable.GetNumRows();
121 StdLapseRates = LapseRates;
126 GradientFadeoutAltitude = StdAtmosTemperatureTable(numRows, 0);
129 PressureBreakpoints.resize(numRows);
131 StdPressureBreakpoints = PressureBreakpoints;
152 bool FGStandardAtmosphere::InitModel(
void)
158 GradientFadeoutAltitude = StdAtmosTemperatureTable(StdAtmosTemperatureTable.GetNumRows(), 0);
160 TemperatureDeltaGradient = 0.0;
161 TemperatureBias = 0.0;
162 LapseRates = StdLapseRates;
164 PressureBreakpoints = StdPressureBreakpoints;
166 SLpressure = StdSLpressure;
168 SLdensity = StdSLdensity;
169 SLsoundspeed = StdSLsoundspeed;
200 double BaseAlt = StdAtmosTemperatureTable(1,0);
201 unsigned int numRows = StdAtmosTemperatureTable.GetNumRows();
204 for (b=0; b < numRows-2; ++b) {
205 double testAlt = StdAtmosTemperatureTable(b+2,0);
206 if (GeoPotAlt < testAlt)
212 double deltaH = GeoPotAlt - BaseAlt;
213 double Lmb = LapseRates[b];
216 double Exp =
g0 / (Rdry*Lmb);
217 double factor = Tmb/(Tmb + Lmb*deltaH);
218 return PressureBreakpoints[b]*pow(factor, Exp);
220 return PressureBreakpoints[b]*exp(-
g0*deltaH/(Rdry*Tmb));
236 SLsoundspeed = sqrt(SHRatio*
Reng*SLtemperature);
250 if (GeoPotAlt >= 0.0) {
251 T = StdAtmosTemperatureTable.GetValue(GeoPotAlt);
253 if (GeoPotAlt <= GradientFadeoutAltitude)
254 T -= TemperatureDeltaGradient * GeoPotAlt;
259 T = StdAtmosTemperatureTable.GetValue(0.0) + GeoPotAlt*LapseRates[0];
262 T += TemperatureBias;
264 if (GeoPotAlt <= GradientFadeoutAltitude)
265 T += TemperatureDeltaGradient * GradientFadeoutAltitude;
277 if (GeoPotAlt >= 0.0)
278 return StdAtmosTemperatureTable.GetValue(GeoPotAlt);
280 return StdAtmosTemperatureTable.GetValue(0.0) + GeoPotAlt*LapseRates[0];
294 double BaseAlt = StdAtmosTemperatureTable(1,0);
295 unsigned int numRows = StdAtmosTemperatureTable.GetNumRows();
298 for (b=0; b < numRows-2; ++b) {
299 double testAlt = StdAtmosTemperatureTable(b+2,0);
300 if (GeoPotAlt < testAlt)
306 double deltaH = GeoPotAlt - BaseAlt;
307 double Lmb = LapseRates[b];
310 double Exp =
g0 / (Rdry*Lmb);
311 double factor = Tmb/(Tmb + Lmb*deltaH);
312 return StdPressureBreakpoints[b]*pow(factor, Exp);
314 return StdPressureBreakpoints[b]*exp(-
g0*deltaH/(Rdry*Tmb));
334 if (GeoPotAlt <= GradientFadeoutAltitude)
335 TemperatureBias -= TemperatureDeltaGradient * (GradientFadeoutAltitude - GeoPotAlt);
347 if (unit == eCelsius || unit == eKelvin)
385 if (unit == eCelsius || unit == eKelvin)
400 std::cout <<
"Altitude (ft) Temp (F) Pressure (psf) Density (sl/ft3)" << std::endl;
401 std::cout <<
"------------- -------- -------------- ----------------" << std::endl;
402 for (
int i=0; i<280000; i+=1000) {
404 std::cout << std::setw(12) << std::setprecision(2) << i
405 <<
" " << std::setw(9) << std::setprecision(2) << Temperature - 459.67
406 <<
" " << std::setw(13) << std::setprecision(4) << Pressure
407 <<
" " << std::setw(18) << std::setprecision(8) << Density
424 unsigned int numRows = StdAtmosTemperatureTable.GetNumRows();
427 for (
unsigned int bh=0; bh < numRows-1; bh++)
429 double t0 = StdAtmosTemperatureTable(bh+1,1);
430 double t1 = StdAtmosTemperatureTable(bh+2,1);
431 double h0 = StdAtmosTemperatureTable(bh+1,0);
432 double h1 = StdAtmosTemperatureTable(bh+2,0);
433 LapseRates.push_back((t1 - t0) / (h1 - h0) - TemperatureDeltaGradient);
441 PressureBreakpoints[0] = SLpress;
443 for (
unsigned int b=0; b<PressureBreakpoints.size()-1; b++) {
444 double BaseTemp = StdAtmosTemperatureTable(b+1,1);
445 double BaseAlt = StdAtmosTemperatureTable(b+1,0);
446 double UpperAlt = StdAtmosTemperatureTable(b+2,0);
447 double deltaH = UpperAlt - BaseAlt;
448 double Tmb = BaseTemp
450 + (GradientFadeoutAltitude - BaseAlt)*TemperatureDeltaGradient;
451 if (LapseRates[b] != 0.00) {
452 double Lmb = LapseRates[b];
453 double Exp =
g0 / (Rdry*Lmb);
454 double factor = Tmb/(Tmb + Lmb*deltaH);
455 PressureBreakpoints[b+1] = PressureBreakpoints[b]*pow(factor, Exp);
457 PressureBreakpoints[b+1] = PressureBreakpoints[b]*exp(-
g0*deltaH/(Rdry*Tmb));
466 TemperatureBias = TemperatureDeltaGradient = 0.0;
478 SLpressure = StdSLpressure;
487 StdDensityBreakpoints.clear();
488 for (
unsigned int i = 0; i < StdPressureBreakpoints.size(); i++)
489 StdDensityBreakpoints.push_back(StdPressureBreakpoints[i] / (Rdry * StdAtmosTemperatureTable(i + 1, 1)));
498 for (; b < StdDensityBreakpoints.size() - 2; b++) {
499 if (density >= StdDensityBreakpoints[b + 1])
504 double Tmb = StdAtmosTemperatureTable(b + 1, 1);
505 double Hb = StdAtmosTemperatureTable(b + 1, 0);
506 double Lmb = StdLapseRates[b];
507 double pb = StdDensityBreakpoints[b];
509 double density_altitude = 0.0;
513 double Exp = -1.0 / (1.0 +
g0/(Rdry*Lmb));
514 density_altitude = Hb + (Tmb / Lmb) * (pow(density / pb, Exp) - 1);
516 double Factor = -Rdry*Tmb /
g0;
517 density_altitude = Hb + Factor * log(density / pb);
529 for (; b < StdPressureBreakpoints.size() - 2; b++) {
530 if (pressure >= StdPressureBreakpoints[b + 1])
535 double Tmb = StdAtmosTemperatureTable(b + 1, 1);
536 double Hb = StdAtmosTemperatureTable(b + 1, 0);
537 double Lmb = StdLapseRates[b];
538 double Pb = StdPressureBreakpoints[b];
540 double pressure_altitude = 0.0;
544 double Exp = -Rdry*Lmb /
g0;
545 pressure_altitude = Hb + (Tmb / Lmb) * (pow(pressure / Pb, Exp) - 1);
548 double Factor = -Rdry*Tmb /
g0;
549 pressure_altitude = Hb + Factor * log(pressure / Pb);
560 return a*exp(b*temperature_degC/(c+temperature_degC));
567 if (SaturatedVaporPressure < Pressure) {
568 double VaporPressure = Pressure*VaporMassFraction / (VaporMassFraction+Rdry/Rwater);
569 if (VaporPressure > SaturatedVaporPressure)
570 VaporMassFraction = Rdry * SaturatedVaporPressure / (Rwater * (Pressure - SaturatedVaporPressure));
574 double maxFraction = 1E-6*MaxVaporMassFraction.GetValue(GeoPotAlt);
576 if ((VaporMassFraction > maxFraction) || (VaporMassFraction < 0.0))
577 VaporMassFraction = maxFraction;
580 Reng = (VaporMassFraction*Rwater + Rdry)/(1.0 + VaporMassFraction);
589 VaporMassFraction = Rdry * VaporPressure / (Rwater * (Pressure - VaporPressure));
597 double dewpoint_degC;
598 double VaporPressure = Pressure*VaporMassFraction / (VaporMassFraction+Rdry/Rwater);
600 if (VaporPressure <= 0.0)
603 double x = log(VaporPressure/
a);
604 dewpoint_degC = c*x / (b - x);
616 VaporMassFraction = Rdry * VaporPressure / (Rwater * (Pressure - VaporPressure));
624 double VaporPressure = Pressure*VaporMassFraction / (VaporMassFraction+Rdry/Rwater);
639 double VaporPressure = Pressure*VaporMassFraction / (VaporMassFraction+Rdry/Rwater);
640 return 100.0*VaporPressure/SaturatedVaporPressure;
648 double VaporPressure = 0.01*RH*SaturatedVaporPressure;
649 VaporMassFraction = Rdry * VaporPressure / (Rwater * (Pressure - VaporPressure));
657 return VaporMassFraction*1E6;
665 VaporMassFraction = frac*1E-6;
671 void FGStandardAtmosphere::bind(
void)
675 PropertyManager->
Tie(
"atmosphere/delta-T",
this, eRankine,
678 PropertyManager->
Tie(
"atmosphere/SL-graded-delta-T",
this, eRankine,
681 PropertyManager->
Tie(
"atmosphere/P-sl-psf",
this, ePSF,
682 (PMFi)&FGStandardAtmosphere::GetPressureSL,
684 PropertyManager->
Tie(
"atmosphere/dew-point-R",
this, eRankine,
687 PropertyManager->
Tie(
"atmosphere/vapor-pressure-psf",
this, ePSF,
690 PropertyManager->
Tie(
"atmosphere/saturated-vapor-pressure-psf",
this, ePSF,
692 PropertyManager->
Tie(
"atmosphere/RH",
this,
695 PropertyManager->
Tie(
"atmosphere/vapor-fraction-ppm",
this,
719 void FGStandardAtmosphere::Debug(
int from)
721 if (debug_lvl <= 0)
return;
727 if (debug_lvl & 2 ) {
728 if (from == 0) std::cout <<
"Instantiated: FGStandardAtmosphere" << std::endl;
729 if (from == 1) std::cout <<
"Destroyed: FGStandardAtmosphere" << std::endl;
731 if (debug_lvl & 4 ) {
733 if (debug_lvl & 8 ) {
735 if (debug_lvl & 16) {
737 if (debug_lvl & 128) {
739 if (debug_lvl & 64) {