Module: Atmospheric::Isa

Defined in:
lib/atmospheric/isa.rb

Constant Summary collapse

CONST =

2.1 Primary constants and characteristics Table 1 - Main constants and characteristics adopted for

the calculation of the ISO Standard Atmosphere
{
  g_n: 9.80665, # m.s-2
  N_A: 602.257e21, # Avogadro constant, mol-1
  p_n: 101325, # In Pascal
  rho_n: 1.225, # rho_n standard air density
  T_n: 288.15, # T_n standard thermodynamic air temperature at mean sea level
  R_star: 8.31432, # universal gas constant

  radius: 6356766, # radius of the Earth (m)
  k: 1.4 # adiabatic index, dimensionless
}
TEMPERATURE_LAYERS =

Table 4 - Temperature and vertical temperature gradients

[
  # H is Geopotential altitude (base altitude) above mean sea level, m
  # T is Temperature, K
  # B is Temperature gradient, "beta", K m^-1

  # This line is from ICAO 7488/3
  # [H: -5000, T: 320.65, B: -0.0065 ],

  # This line is from ISO 2533:1975
  {H: -2000, T: 301.15, B: -0.0065 },
  {H: 0,     T: 288.15, B: -0.0065 },
  {H: 11000, T: 216.65, B: 0       },
  {H: 20000, T: 216.65, B: 0.001   },
  {H: 32000, T: 228.65, B: 0.0028  },
  {H: 47000, T: 270.65, B: 0       },
  {H: 51000, T: 270.65, B: -0.0028 },
  {H: 71000, T: 214.65, B: -0.002  },
  {H: 80000, T: 196.65},
]

Class Method Summary collapse

Class Method Details

.air_number_density_from_H(geopotential_alt) ⇒ Object

2.10 Air number density Formula (17) n



248
249
250
251
252
253
# File 'lib/atmospheric/isa.rb', line 248

def air_number_density_from_H(geopotential_alt)
  temp = temperature_at_layer_from_H(geopotential_alt)
  p = pressure_from_H(geopotential_alt)

  CONST[:N_A] * p / (CONST[:R_star] * temp)
end

.air_particle_collision_frequency_from_H(geopotential_alt) ⇒ Object



282
283
284
285
286
# File 'lib/atmospheric/isa.rb', line 282

def air_particle_collision_frequency_from_H(geopotential_alt)
  temp = temperature_at_layer_from_H(geopotential_alt)
  n = air_number_density_from_H(geopotential_alt)
  air_particle_collision_frequency_from_temp(n, temp)
end

.air_particle_collision_frequency_from_temp(n, temp) ⇒ Object

2.13 Air-particle collision frequency Formula (20) omega



278
279
280
# File 'lib/atmospheric/isa.rb', line 278

def air_particle_collision_frequency_from_temp(n, temp)
  4 * (0.365e-9 ** 2) * ((3.141592654 / (CONST[:R_star] * CONST[:M])) ** 0.5) * n * CONST[:R_star] * (temp ** 0.5)
end

.density_from_H(geopotential_alt) ⇒ Object

Calculate density for a given geopotential altitude ‘H` (m) above mean sea level Formula (14) rho



210
211
212
213
214
215
# File 'lib/atmospheric/isa.rb', line 210

def density_from_H(geopotential_alt)
  temp = temperature_at_layer_from_H(geopotential_alt)
  p = pressure_from_H(geopotential_alt)

  p / (CONST[:R] * temp)
end

.dynamic_viscosity(temp) ⇒ Object

2.15 Dynamic viscosity Formula (22) mu (Pa s)



307
308
309
310
311
312
313
# File 'lib/atmospheric/isa.rb', line 307

def dynamic_viscosity(temp)
  # Sutherland's empirical constants in the equation for dynamic viscosity
  capital_b_s = 1.458e-6
  capital_s = 110.4

  (capital_b_s * (temp ** (1.5))) / (temp + capital_s)
end

.dynamic_viscosity_from_H(geopotential_alt) ⇒ Object



315
316
317
318
# File 'lib/atmospheric/isa.rb', line 315

def dynamic_viscosity_from_H(geopotential_alt)
  temp = temperature_at_layer_from_H(geopotential_alt)
  dynamic_viscosity(temp)
end

.geometric_altitude_from_geopotential(geopotential_alt) ⇒ Object

2.3 Formula (8) H to h h(m)



39
40
41
# File 'lib/atmospheric/isa.rb', line 39

def geometric_altitude_from_geopotential(geopotential_alt)
  CONST[:radius] * geopotential_alt / (CONST[:radius] - geopotential_alt)
end

.geopotential_altitude_from_geometric(geometric_alt) ⇒ Object

2.3 Formula (9) h to H H(m)



46
47
48
# File 'lib/atmospheric/isa.rb', line 46

def geopotential_altitude_from_geometric(geometric_alt)
  CONST[:radius] * geometric_alt / (CONST[:radius] + geometric_alt)
end

.gravity_at_geometric(geometric_alt) ⇒ Object

2.3 Formula (7) g(h)



52
53
54
55
# File 'lib/atmospheric/isa.rb', line 52

def gravity_at_geometric(geometric_alt)
  temp = CONST[:radius] / (CONST[:radius] + geometric_alt)
  CONST[:g_n] * temp * temp
end

.gravity_at_geopotential(geopotential_alt) ⇒ Object



57
58
59
60
# File 'lib/atmospheric/isa.rb', line 57

def gravity_at_geopotential(geopotential_alt)
  geometric_h = geometric_altitude_from_geopotential(geopotential_alt)
  gravity_at_geometric(geometric_h)
end

.kelvin_to_celsius(kelvin) ⇒ Object



344
345
346
# File 'lib/atmospheric/isa.rb', line 344

def kelvin_to_celsius(kelvin)
  kelvin - 273.15
end

.kinematic_viscosity(temp) ⇒ Object

2.16 Kinematic viscosity Formula (23) v



323
324
325
# File 'lib/atmospheric/isa.rb', line 323

def kinematic_viscosity(temp)
  dynamic_viscosity(temp) / CONST[:rho_n]
end

.kinematic_viscosity_from_H(geopotential_alt) ⇒ Object



327
328
329
330
# File 'lib/atmospheric/isa.rb', line 327

def kinematic_viscosity_from_H(geopotential_alt)
  temp = temperature_at_layer_from_H(geopotential_alt)
  dynamic_viscosity(temp) / density_from_H(geopotential_alt)
end

.locate_lower_layer(geopotential_alt) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/atmospheric/isa.rb', line 84

def locate_lower_layer(geopotential_alt)
  # Return first layer if lower than lowest
  return 0 if geopotential_alt < TEMPERATURE_LAYERS[0][:H]

  # Return second last layer if beyond last layer
  i = TEMPERATURE_LAYERS.length - 1
  return i - 1 if geopotential_alt >= TEMPERATURE_LAYERS[i][:H]

  # find last layer with H larger than our H
  TEMPERATURE_LAYERS.each_with_index do |layer, i|
    return i if layer[:H] > geopotential_alt
  end

  nil
end

.mean_air_particle_speed_from_H(geopotential_alt) ⇒ Object



263
264
265
266
# File 'lib/atmospheric/isa.rb', line 263

def mean_air_particle_speed_from_H(geopotential_alt)
  temp = temperature_at_layer_from_H(geopotential_alt)
  mean_air_particle_speed_from_temp(temp)
end

.mean_air_particle_speed_from_temp(temp) ⇒ Object

2.11 Mean air-particle speed Formula (18) v_bar CORRECT



259
260
261
# File 'lib/atmospheric/isa.rb', line 259

def mean_air_particle_speed_from_temp(temp)
  1.595769 * Math.sqrt(CONST[:R] * temp)
end

.mean_free_path_of_air_particles_from_H(geopotential_alt) ⇒ Object

2.12 Mean free path of air particles Formula (19) l



271
272
273
# File 'lib/atmospheric/isa.rb', line 271

def mean_free_path_of_air_particles_from_H(geopotential_alt)
  1 / (1.414213562 * 3.141592654 * (0.365e-9 ** 2) * air_number_density_from_H(geopotential_alt))
end

.p_p_n_from_H(geopotential_alt) ⇒ Object



201
202
203
# File 'lib/atmospheric/isa.rb', line 201

def p_p_n_from_H(geopotential_alt)
  pressure_from_H(geopotential_alt) / CONST[:p_n]
end

.pa_to_mbar(pascal) ⇒ Object



170
171
172
# File 'lib/atmospheric/isa.rb', line 170

def pa_to_mbar(pascal)
  pascal * 0.01
end

.pa_to_mmhg(pascal) ⇒ Object

puts “PRE-CALCULATED PRESSURE LAYERS:” pp @pressure_layers



166
167
168
# File 'lib/atmospheric/isa.rb', line 166

def pa_to_mmhg(pascal)
  pascal * 0.007500616827
end

.pressure_from_H(geopotential_alt) ⇒ Object

Pressure for a given geopotential altitude ‘H` (m) above mean sea level



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/atmospheric/isa.rb', line 175

def pressure_from_H(geopotential_alt)
  i = locate_lower_layer(geopotential_alt)
  lower_temperature_layer = TEMPERATURE_LAYERS[i]
  beta = lower_temperature_layer[:B]
  capital_h_b = lower_temperature_layer[:H]
  capital_t_b = lower_temperature_layer[:T]
  temp = temperature_at_layer_from_H(geopotential_alt)
  pb = pressure_layers[i]

  if beta != 0
    # Formula (12)
    pb * (1 + ((beta / capital_t_b) * (geopotential_alt - capital_h_b))) ** (-CONST[:g_n] / (beta * CONST[:R]))
  else
    # Formula (13)
    pb * Math.exp(-(CONST[:g_n] / (CONST[:R] * temp)) * (geopotential_alt - capital_h_b))
  end
end

.pressure_from_H_mbar(geopotential_alt) ⇒ Object



193
194
195
# File 'lib/atmospheric/isa.rb', line 193

def pressure_from_H_mbar(geopotential_alt)
  pa_to_mbar(pressure_from_H(geopotential_alt))
end

.pressure_from_H_mmhg(geopotential_alt) ⇒ Object



197
198
199
# File 'lib/atmospheric/isa.rb', line 197

def pressure_from_H_mmhg(geopotential_alt)
  pa_to_mmhg(pressure_from_H(geopotential_alt))
end

.pressure_layersObject

Base pressure values given defined ‘TEMPERATURE_LAYERS` and constants



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/atmospheric/isa.rb', line 126

def pressure_layers
  return @pressure_layers if @pressure_layers

  # assuming TEMPERATURE_LAYERS index 1 base altitude is zero (mean sea level)
  p = []

  TEMPERATURE_LAYERS.each_with_index do |x, i|
    last_i = (i == 0) ? 0 : i - 1
    last_layer = TEMPERATURE_LAYERS[last_i]
    beta = last_layer[:B]

    if last_layer[:H] <= 0
      pb = CONST[:p_n]
      capital_h_b = 0
      capital_t_b = CONST[:T_n]
    else
      pb = p[last_i]
      capital_h_b = last_layer[:H]
      capital_t_b = last_layer[:T]
    end

    current_layer = TEMPERATURE_LAYERS[i]
    geopotential_alt = current_layer[:H]
    temp = current_layer[:T]

    p[i] = if beta != 0
      # Formula (12)
      pb * (1 + ((beta / capital_t_b) * (geopotential_alt - capital_h_b))) ** (-CONST[:g_n] / (beta * CONST[:R]))
    else
      # Formula (13)
      pb * Math.exp(-(CONST[:g_n] / (CONST[:R] * temp)) * (geopotential_alt - capital_h_b))
    end
  end

  @pressure_layers = p
end

.pressure_scale_height_from_H(geopotential_alt) ⇒ Object



240
241
242
243
# File 'lib/atmospheric/isa.rb', line 240

def pressure_scale_height_from_H(geopotential_alt)
  temp = temperature_at_layer_from_H(geopotential_alt)
  (CONST[:R] * temp) / gravity_at_geopotential(geopotential_alt)
end

.pressure_scale_height_from_temp(temp) ⇒ Object

2.9 Pressure scale height Formula (16) H_p



236
237
238
# File 'lib/atmospheric/isa.rb', line 236

def pressure_scale_height_from_temp(temp)
  (CONST[:R] * temp) / CONST[:g_n]
end

.rho_rho_n_from_H(geopotential_alt) ⇒ Object



217
218
219
# File 'lib/atmospheric/isa.rb', line 217

def rho_rho_n_from_H(geopotential_alt)
  density_from_H(geopotential_alt) / CONST[:rho_n]
end

.root_rho_rho_n_from_H(geopotential_alt) ⇒ Object



221
222
223
# File 'lib/atmospheric/isa.rb', line 221

def root_rho_rho_n_from_H(geopotential_alt)
  Math.sqrt(rho_rho_n_from_H(geopotential_alt))
end

.specific_weight_from_H(geopotential_alt) ⇒ Object

Specific weight Formula (15) gamma



229
230
231
# File 'lib/atmospheric/isa.rb', line 229

def specific_weight_from_H(geopotential_alt)
  density_from_H(geopotential_alt) * gravity_at_geopotential(geopotential_alt)
end

.speed_of_sound_from_H(geopotential_alt) ⇒ Object



298
299
300
301
# File 'lib/atmospheric/isa.rb', line 298

def speed_of_sound_from_H(geopotential_alt)
  temp = temperature_at_layer_from_H(geopotential_alt)
  speed_of_sound_from_temp(temp)
end

.speed_of_sound_from_temp(temp) ⇒ Object

2.14 Speed of sound Formula (21) a (ms-1) CORRECT



292
293
294
295
296
# File 'lib/atmospheric/isa.rb', line 292

def speed_of_sound_from_temp(temp)
  # `kappa` (ratio of c_p / c_v) = 1.4 (see 2.14)
  kappa = 1.4
  Math.sqrt(kappa * CONST[:R] * temp)
end

.temperature_at_layer_celcius(geopotential_alt) ⇒ Object



80
81
82
# File 'lib/atmospheric/isa.rb', line 80

def temperature_at_layer_celcius(geopotential_alt)
  kelvin_to_celsius(temperature_at_layer_from_H(geopotential_alt))
end

.temperature_at_layer_from_H(geopotential_alt) ⇒ Object

Formula (11) T



70
71
72
73
74
75
76
77
78
# File 'lib/atmospheric/isa.rb', line 70

def temperature_at_layer_from_H(geopotential_alt)
  lower_layer_index = locate_lower_layer(geopotential_alt)
  lower_layer = TEMPERATURE_LAYERS[lower_layer_index]
  beta = lower_layer[:B]
  capital_t_b = lower_layer[:T]
  capital_h_b = lower_layer[:H]

  capital_t_b + (beta * (geopotential_alt - capital_h_b))
end

.thermal_conductivity_from_H(geopotential_alt) ⇒ Object



339
340
341
342
# File 'lib/atmospheric/isa.rb', line 339

def thermal_conductivity_from_H(geopotential_alt)
  temp = temperature_at_layer_from_H(geopotential_alt)
  thermal_conductivity_from_temp(temp)
end

.thermal_conductivity_from_temp(temp) ⇒ Object

2.17 Thermal conductivity Formula (24) lambda



335
336
337
# File 'lib/atmospheric/isa.rb', line 335

def thermal_conductivity_from_temp(temp)
  (2.648151e-3 * (temp ** (1.5))) / (temp + (245.4 * (10 ** (-12.0/temp))))
end