atmospheric 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.adoc +652 -183
- data/lib/atmospheric/export/altitude_attrs.rb +238 -0
- data/lib/atmospheric/export/altitude_convertable_model.rb +84 -0
- data/lib/atmospheric/export/altitude_table.rb +51 -0
- data/lib/atmospheric/export/hypsometrical_table.rb +38 -0
- data/lib/atmospheric/export/iso_25331975/group_one.rb +15 -27
- data/lib/atmospheric/export/iso_25331975/group_one_attrs.rb +88 -0
- data/lib/atmospheric/export/iso_25331975/group_three.rb +14 -27
- data/lib/atmospheric/export/iso_25331975/group_three_attrs.rb +87 -0
- data/lib/atmospheric/export/iso_25331975/group_two.rb +14 -28
- data/lib/atmospheric/export/iso_25331975/group_two_attrs.rb +96 -0
- data/lib/atmospheric/export/iso_25331975.rb +5 -17
- data/lib/atmospheric/export/iso_25331985/pressure_attrs.rb +19 -0
- data/lib/atmospheric/export/iso_25331985/table_five_six_attrs.rb +19 -0
- data/lib/atmospheric/export/iso_25331985.rb +42 -63
- data/lib/atmospheric/export/iso_25331997.rb +21 -39
- data/lib/atmospheric/export/iso_25332025/altitude_attrs_group.rb +27 -0
- data/lib/atmospheric/export/iso_25332025/combined_altitude_attrs_group.rb +44 -0
- data/lib/atmospheric/export/iso_25332025.rb +81 -0
- data/lib/atmospheric/export/pressure_attrs.rb +93 -0
- data/lib/atmospheric/export/{target.rb → utils.rb} +10 -13
- data/lib/atmospheric/export.rb +3 -1
- data/lib/atmospheric/isa.rb +119 -114
- data/lib/atmospheric/unit_value_float.rb +24 -0
- data/lib/atmospheric/unit_value_integer.rb +24 -0
- data/lib/atmospheric/version.rb +1 -1
- data/lib/atmospheric.rb +1 -0
- metadata +38 -28
- data/lib/atmospheric/export/hypsometrical_tables.rb +0 -34
- data/lib/atmospheric/export/iso_25331975/group_base.rb +0 -72
- data/lib/atmospheric/export/iso_25332024.rb +0 -205
- data/spec/fixtures/iso-2533-1975-table5.yaml +0 -18297
- data/spec/fixtures/iso-2533-1975-table6.yaml +0 -18298
- data/spec/fixtures/iso-2533-1975-table7.yaml +0 -16265
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "iso_25331975"
|
4
|
+
require_relative "iso_25332025/combined_altitude_attrs_group"
|
5
|
+
|
6
|
+
module Atmospheric
|
7
|
+
module Export
|
8
|
+
module Iso25332025
|
9
|
+
class AltitudesInMeters < CombinedAltitudeAttrsGroup
|
10
|
+
def steps
|
11
|
+
(
|
12
|
+
(-5000..31_950).step(50) +
|
13
|
+
(32_000..50_900).step(100) +
|
14
|
+
(51_000..80_000).step(200)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class AltitudesInFeet < CombinedAltitudeAttrsGroup
|
20
|
+
def steps
|
21
|
+
(
|
22
|
+
(-16_500..-13_750).step(250) +
|
23
|
+
(-14_000..104_800).step(200) +
|
24
|
+
(105_000..262_500).step(500)
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def steps_unit
|
29
|
+
:feet
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class AltitudesForPressure < CombinedAltitudeAttrsGroup
|
34
|
+
def steps
|
35
|
+
(-1000..4599).step(1)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class HypsometricalMbar < HypsometricalTable
|
40
|
+
# TODO: when Ruby's step does not create inaccurate floating point numbers
|
41
|
+
# This is a hack to solve a Ruby bug with floating point calcuations
|
42
|
+
# > (20.0..1770.9).step(0.1).to_a
|
43
|
+
# ...
|
44
|
+
# 1769.4,
|
45
|
+
# 1769.5,
|
46
|
+
# 1769.6000000000001, # <== we need to clean these
|
47
|
+
# 1769.7,
|
48
|
+
# 1769.8000000000002, # <== we need to clean these
|
49
|
+
# The last `map` should be removed if this bug is fixed
|
50
|
+
def steps
|
51
|
+
(
|
52
|
+
(5.0..19.99).step(0.01).to_a.map { |v| v.round(2) } +
|
53
|
+
(20.0..1770.9).step(0.1).to_a.map { |v| v.round(1) }
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
def steps_unit
|
58
|
+
:mbar
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class << self
|
63
|
+
def table_atmosphere_meters
|
64
|
+
AltitudesInMeters.new.set_attrs
|
65
|
+
end
|
66
|
+
|
67
|
+
def table_atmosphere_feet
|
68
|
+
AltitudesInFeet.new.set_attrs
|
69
|
+
end
|
70
|
+
|
71
|
+
def table_hypsometrical_altitude
|
72
|
+
AltitudesForPressure.new.set_attrs
|
73
|
+
end
|
74
|
+
|
75
|
+
def table_hypsometrical_mbar
|
76
|
+
HypsometricalMbar.new.set_attrs
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "lutaml/model"
|
4
|
+
require_relative "utils"
|
5
|
+
require_relative "../unit_value_float"
|
6
|
+
require_relative "../unit_value_integer"
|
7
|
+
|
8
|
+
module Atmospheric
|
9
|
+
module Export
|
10
|
+
class PressureAttrs < Lutaml::Model::Serializable
|
11
|
+
include Utils
|
12
|
+
attribute :pressure_mbar, UnitValueFloat
|
13
|
+
attribute :pressure_mmhg, UnitValueFloat
|
14
|
+
attribute :geometric_altitude_m, UnitValueFloat
|
15
|
+
attribute :geometric_altitude_ft, UnitValueInteger
|
16
|
+
attribute :geopotential_altitude_m, UnitValueFloat
|
17
|
+
attribute :geopotential_altitude_ft, UnitValueInteger
|
18
|
+
|
19
|
+
key_value do
|
20
|
+
map "pressure-mbar", to: :pressure_mbar
|
21
|
+
map "pressure-mmhg", to: :pressure_mmhg
|
22
|
+
map "geopotential-altitude-m", to: :geopotential_altitude_m
|
23
|
+
map "geopotential-altitude-ft", to: :geopotential_altitude_ft
|
24
|
+
map "geometric-altitude-m", to: :geometric_altitude_m
|
25
|
+
map "geometric-altitude-ft", to: :geometric_altitude_ft
|
26
|
+
end
|
27
|
+
|
28
|
+
xml do
|
29
|
+
root "hypsometrical-attributes"
|
30
|
+
map_element "pressure-mbar", to: :pressure_mbar
|
31
|
+
map_element "pressure-mmhg", to: :pressure_mmhg
|
32
|
+
map_element "geometric-altitude-m", to: :geometric_altitude_m
|
33
|
+
map_element "geometric-altitude-ft", to: :geometric_altitude_ft
|
34
|
+
map_element "geopotential-altitude-m", to: :geopotential_altitude_m
|
35
|
+
map_element "geopotential-altitude-ft", to: :geopotential_altitude_ft
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_pressure(value:, unit: :mbar, precision: :reduced)
|
39
|
+
method_name = "geopotential_altitude_from_pressure_#{unit}"
|
40
|
+
gp_h_m = Isa::NormalPrecision.instance.send(method_name, value)
|
41
|
+
gp_h_ft = m_to_ft(gp_h_m)
|
42
|
+
gm_h_m = Isa::NormalPrecision.instance.geometric_altitude_from_geopotential(gp_h_m)
|
43
|
+
gm_h_ft = m_to_ft(gm_h_m)
|
44
|
+
|
45
|
+
realize_altitudes(gm_h_m, gm_h_ft, gp_h_m, gp_h_ft, precision: precision)
|
46
|
+
realize_pressures(value, unit: unit)
|
47
|
+
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
# TODO: Not sure why we need round(1) for meter values
|
52
|
+
def realize_altitudes(hgmm, hgmf, hgpm, hgpf, precision: :reduced)
|
53
|
+
self.geometric_altitude_m = UnitValueFloat.new(
|
54
|
+
value: precision == :reduced ? hgmm.round(1) : hgmm,
|
55
|
+
unitsml: "m"
|
56
|
+
)
|
57
|
+
|
58
|
+
self.geometric_altitude_ft = UnitValueInteger.new(
|
59
|
+
value: precision == :reduced ? hgmf.round : hgmf,
|
60
|
+
unitsml: "ft"
|
61
|
+
)
|
62
|
+
|
63
|
+
self.geopotential_altitude_m = UnitValueFloat.new(
|
64
|
+
value: precision == :reduced ? hgpm.round(1) : hgpm,
|
65
|
+
unitsml: "m"
|
66
|
+
)
|
67
|
+
|
68
|
+
self.geopotential_altitude_ft = UnitValueInteger.new(
|
69
|
+
value: precision == :reduced ? hgpf.round : hgpf,
|
70
|
+
unitsml: "ft"
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
def realize_pressures(input, unit:)
|
75
|
+
# pattern: [value in mbar, value in mmhg]
|
76
|
+
mbar, mmhg = case unit
|
77
|
+
when :mbar
|
78
|
+
[input,
|
79
|
+
Isa::NormalPrecision.instance.mbar_to_mmhg(input)]
|
80
|
+
when :mmhg
|
81
|
+
[Isa::NormalPrecision.instance.mmhg_to_mbar(input),
|
82
|
+
input]
|
83
|
+
else
|
84
|
+
raise ArgumentError,
|
85
|
+
"Invalid unit: #{unit}. Use :mbar or :mmhg."
|
86
|
+
end
|
87
|
+
|
88
|
+
self.pressure_mbar = UnitValueFloat.new(value: mbar, unitsml: "mbar")
|
89
|
+
self.pressure_mmhg = UnitValueFloat.new(value: mmhg, unitsml: "mmhg")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -1,9 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Atmospheric
|
4
4
|
module Export
|
5
|
+
module Utils
|
6
|
+
def values_in_m_ft(value, unit: :meters)
|
7
|
+
case unit
|
8
|
+
when :meters
|
9
|
+
[value.to_f, m_to_ft(value)]
|
10
|
+
when :feet
|
11
|
+
[ft_to_m(value), value.to_f]
|
12
|
+
end
|
13
|
+
end
|
5
14
|
|
6
|
-
module Target
|
7
15
|
def round_to_sig_figs(num, num_sig_figs)
|
8
16
|
num.round(num_sig_figs - Math.log10(num).ceil).to_f
|
9
17
|
end
|
@@ -15,17 +23,6 @@ module Atmospheric
|
|
15
23
|
def ft_to_m(feet)
|
16
24
|
feet * 0.3048
|
17
25
|
end
|
18
|
-
|
19
|
-
def to_yaml
|
20
|
-
to_h
|
21
|
-
.to_yaml(indentation: 4)
|
22
|
-
.gsub("\n- ", "\n\n - ")
|
23
|
-
.gsub(/^(.*):\n/, "\n\\1:") # Make fancy
|
24
|
-
end
|
25
|
-
|
26
|
-
def to_file(hash = to_yaml)
|
27
|
-
File.write(filename, hash)
|
28
|
-
end
|
29
26
|
end
|
30
27
|
end
|
31
28
|
end
|
data/lib/atmospheric/export.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Atmospheric
|
2
4
|
module Export
|
3
5
|
end
|
@@ -6,4 +8,4 @@ end
|
|
6
8
|
require_relative "export/iso_25331975"
|
7
9
|
require_relative "export/iso_25331997"
|
8
10
|
require_relative "export/iso_25331985"
|
9
|
-
require_relative "export/
|
11
|
+
require_relative "export/iso_25332025"
|
data/lib/atmospheric/isa.rb
CHANGED
@@ -1,104 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bigdecimal"
|
2
4
|
require "bigdecimal/math"
|
5
|
+
require "singleton"
|
3
6
|
|
4
7
|
module Atmospheric
|
5
8
|
module Isa
|
6
9
|
# International Standard Atmosphere (ISA) (ISO 2533:1975)
|
7
10
|
# ICAO Standard Atmosphere (ICAO Doc 7488/3, 1994)
|
8
11
|
|
9
|
-
class
|
10
|
-
|
11
|
-
|
12
|
-
@precision = :normal # Note the initial make_constants run won't see this
|
13
|
-
|
14
|
-
def num(str)
|
15
|
-
if @precision == :high
|
16
|
-
BigDecimal(str)
|
17
|
-
else
|
18
|
-
str.to_f
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def sqrt(num)
|
23
|
-
if @precision == :high
|
24
|
-
BigMath.sqrt(num, 100)
|
25
|
-
else
|
26
|
-
Math.sqrt(num)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def log10(num)
|
31
|
-
if @precision == :high
|
32
|
-
BigMath.log(num, 100) / BigMath.log(10, 100)
|
33
|
-
else
|
34
|
-
Math.log10(num)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# rubocop:disable Metrics/AbcSize
|
39
|
-
# rubocop:disable Metrics/MethodLength
|
40
|
-
def make_constants
|
41
|
-
# 2.1 Primary constants and characteristics
|
42
|
-
# Table 1 - Main constants and characteristics adopted for
|
43
|
-
# the calculation of the ISO Standard Atmosphere
|
44
|
-
@constants = {
|
45
|
-
# g_n gravitation at mean sea level (m.s-2)
|
46
|
-
g_n: num("9.80665"),
|
47
|
-
|
48
|
-
# Avogadro constant (mol-1)
|
49
|
-
N_A: num("6.02257e+23"),
|
50
|
-
|
51
|
-
# p_n pressure at mean sea level (Pa)
|
52
|
-
p_n: num("101325"),
|
53
|
-
|
54
|
-
# rho_n standard air density
|
55
|
-
rho_n: num("1.225"),
|
56
|
-
|
57
|
-
# T_n standard thermodynamic air temperature at mean sea level
|
58
|
-
T_n: num("288.15"),
|
59
|
-
|
60
|
-
# universal gas constant
|
61
|
-
R_star: num("8.31432"),
|
62
|
-
|
63
|
-
# radius of the Earth (m)
|
64
|
-
radius: num("6356766"),
|
65
|
-
|
66
|
-
# adiabatic index (dimensionless)
|
67
|
-
k: num("1.4"),
|
68
|
-
}
|
69
|
-
|
70
|
-
# 2.2 The equation of the static atmosphere and the perfect gas law
|
71
|
-
# Formula (2)
|
72
|
-
# M: air molar mass at sea level, kg.kmol-1
|
73
|
-
# Value given in 2.1 as M: 28.964720
|
74
|
-
@constants[:M] =
|
75
|
-
(@constants[:rho_n] * @constants[:R_star] * @constants[:T_n]) \
|
76
|
-
/ @constants[:p_n]
|
77
|
-
|
78
|
-
# Formula (3)
|
79
|
-
# R: specific gas constant, J.K-1.kg-1.
|
80
|
-
# Value given in 2.1 as R: 287.05287
|
81
|
-
@constants[:R] = @constants[:R_star] / @constants[:M]
|
82
|
-
|
83
|
-
@sqrt2 = sqrt(num("2"))
|
84
|
-
@pi = if @precision == :high then BigMath.PI(100) else Math::PI end
|
85
|
-
end
|
86
|
-
# rubocop:enable Metrics/AbcSize
|
87
|
-
# rubocop:enable Metrics/MethodLength
|
88
|
-
|
89
|
-
public
|
12
|
+
class Algorithms
|
13
|
+
attr_accessor :precision
|
14
|
+
attr_reader :pressure_layers, :constants, :sqrt2, :pi
|
90
15
|
|
91
16
|
def set_precision(precision)
|
92
|
-
@precision =
|
17
|
+
@precision = precision == :high ? :high : :normal
|
93
18
|
remove_instance_variable(:@pressure_layers) \
|
94
19
|
if defined?(@pressure_layers)
|
95
20
|
make_constants
|
96
21
|
end
|
97
|
-
end
|
98
22
|
|
99
|
-
make_constants
|
100
|
-
|
101
|
-
class << self
|
102
23
|
# 2.3 Geopotential and geometric altitides; acceleration of free fall
|
103
24
|
|
104
25
|
# 2.3 Formula (8)
|
@@ -149,11 +70,10 @@ module Atmospheric
|
|
149
70
|
|
150
71
|
def temperature_at_layer_celcius(geopotential_alt)
|
151
72
|
kelvin_to_celsius(
|
152
|
-
temperature_at_layer_from_geopotential(geopotential_alt)
|
73
|
+
temperature_at_layer_from_geopotential(geopotential_alt)
|
153
74
|
)
|
154
75
|
end
|
155
76
|
|
156
|
-
# rubocop:disable Metrics/AbcSize
|
157
77
|
def locate_lower_layer(geopotential_alt)
|
158
78
|
# Return first layer if lower than lowest
|
159
79
|
return 0 if geopotential_alt < num(TEMPERATURE_LAYERS[0][:H])
|
@@ -169,7 +89,6 @@ module Atmospheric
|
|
169
89
|
|
170
90
|
nil
|
171
91
|
end
|
172
|
-
# rubocop:enable Metrics/AbcSize
|
173
92
|
|
174
93
|
# Table 4 - Temperature and vertical temperature gradients
|
175
94
|
#
|
@@ -190,15 +109,12 @@ module Atmospheric
|
|
190
109
|
{ H: "47000", T: "270.65", B: "0" },
|
191
110
|
{ H: "51000", T: "270.65", B: "-0.0028" },
|
192
111
|
{ H: "71000", T: "214.65", B: "-0.002" },
|
193
|
-
{ H: "80000", T: "196.65" }
|
112
|
+
{ H: "80000", T: "196.65" }
|
194
113
|
].freeze
|
195
114
|
|
196
115
|
# 2.7 Pressure
|
197
116
|
|
198
117
|
# Base pressure values given defined `TEMPERATURE_LAYERS` and constants
|
199
|
-
# rubocop:disable Metrics/AbcSize
|
200
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
201
|
-
# rubocop:disable Metrics/MethodLength
|
202
118
|
def pressure_layers
|
203
119
|
return @pressure_layers if @pressure_layers
|
204
120
|
|
@@ -225,22 +141,19 @@ module Atmospheric
|
|
225
141
|
temp = num(current_layer[:T])
|
226
142
|
height_diff = geopotential_alt - capital_h_b
|
227
143
|
|
228
|
-
p_i = if beta
|
144
|
+
p_i = if beta.zero?
|
145
|
+
# Formula (13)
|
146
|
+
pressure_formula_beta_zero(p_b, temp, height_diff)
|
147
|
+
else
|
229
148
|
# Formula (12)
|
230
149
|
pressure_formula_beta_nonzero(p_b, beta, capital_t_b,
|
231
150
|
height_diff)
|
232
|
-
else
|
233
|
-
# Formula (13)
|
234
|
-
pressure_formula_beta_zero(p_b, temp, height_diff)
|
235
151
|
end
|
236
152
|
p[i] = p_i
|
237
153
|
end
|
238
154
|
|
239
155
|
@pressure_layers = p
|
240
156
|
end
|
241
|
-
# rubocop:enable Metrics/AbcSize
|
242
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
243
|
-
# rubocop:enable Metrics/MethodLength
|
244
157
|
|
245
158
|
# Formula (12)
|
246
159
|
def pressure_formula_beta_nonzero(p_b, beta, temp, height_diff)
|
@@ -265,8 +178,6 @@ module Atmospheric
|
|
265
178
|
pascal * num("0.01")
|
266
179
|
end
|
267
180
|
|
268
|
-
# rubocop:disable Metrics/AbcSize
|
269
|
-
# rubocop:disable Metrics/MethodLength
|
270
181
|
# Pressure for a given geopotential altitude `H` (m) above mean sea level
|
271
182
|
def pressure_from_geopotential(geopotential_alt)
|
272
183
|
i = locate_lower_layer(geopotential_alt)
|
@@ -278,16 +189,14 @@ module Atmospheric
|
|
278
189
|
p_b = pressure_layers[i]
|
279
190
|
height_diff = geopotential_alt - capital_h_b
|
280
191
|
|
281
|
-
if beta
|
282
|
-
# Formula (12)
|
283
|
-
pressure_formula_beta_nonzero(p_b, beta, capital_t_b, height_diff)
|
284
|
-
else
|
192
|
+
if beta.zero?
|
285
193
|
# Formula (13)
|
286
194
|
pressure_formula_beta_zero(p_b, temp, height_diff)
|
195
|
+
else
|
196
|
+
# Formula (12)
|
197
|
+
pressure_formula_beta_nonzero(p_b, beta, capital_t_b, height_diff)
|
287
198
|
end
|
288
199
|
end
|
289
|
-
# rubocop:enable Metrics/AbcSize
|
290
|
-
# rubocop:enable Metrics/MethodLength
|
291
200
|
|
292
201
|
def pressure_from_geopotential_mbar(geopotential_alt)
|
293
202
|
pa_to_mbar(pressure_from_geopotential(geopotential_alt))
|
@@ -452,8 +361,6 @@ module Atmospheric
|
|
452
361
|
# ADD 1
|
453
362
|
# Formulae used in the calculation of the relationships
|
454
363
|
# between geopotential altitude and pressure
|
455
|
-
# rubocop:disable Metrics/AbcSize
|
456
|
-
# rubocop:disable Metrics/MethodLength
|
457
364
|
def geopotential_altitude_from_pressure_mbar(pressure)
|
458
365
|
if pressure >= pa_to_mbar(pressure_layers[2]) # H <= 11 000 m
|
459
366
|
(num("3.731444") - pressure**num("0.1902631")) / num("8.41728e-5")
|
@@ -461,10 +368,10 @@ module Atmospheric
|
|
461
368
|
(num("3.1080387") - log10(pressure)) / num("6.848325e-5")
|
462
369
|
elsif pressure >= pa_to_mbar(pressure_layers[4]) # H <= 32 000 m
|
463
370
|
(num("1.2386515") - pressure**num("0.02927125")) \
|
464
|
-
|
371
|
+
/ (num("5.085177e-6") * pressure**num("0.02927125"))
|
465
372
|
elsif pressure >= pa_to_mbar(pressure_layers[5]) # H <= 47 000 m
|
466
373
|
(num("1.9630052") - pressure**num("0.08195949")) \
|
467
|
-
|
374
|
+
/ (num("2.013664e-5") * pressure**num("0.08195949"))
|
468
375
|
end
|
469
376
|
end
|
470
377
|
|
@@ -481,8 +388,106 @@ module Atmospheric
|
|
481
388
|
/ (num("2.013664e-5") * pressure**num("0.08195949"))
|
482
389
|
end
|
483
390
|
end
|
484
|
-
|
485
|
-
|
391
|
+
|
392
|
+
def mbar_to_mmhg(mbar)
|
393
|
+
# Convert mbar to Pa, then Pa to mmHg
|
394
|
+
pa = mbar / num("0.01") # or mbar * 100
|
395
|
+
pa_to_mmhg(pa)
|
396
|
+
end
|
397
|
+
|
398
|
+
def mmhg_to_mbar(mmhg)
|
399
|
+
# Convert mmHg to Pa, then Pa to mbar
|
400
|
+
pa = mmhg / num("0.007500616827")
|
401
|
+
pa_to_mbar(pa)
|
402
|
+
end
|
403
|
+
|
404
|
+
private
|
405
|
+
|
406
|
+
def num(str)
|
407
|
+
if @precision == :high
|
408
|
+
BigDecimal(str)
|
409
|
+
else
|
410
|
+
str.to_f
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
def sqrt(num)
|
415
|
+
if @precision == :high
|
416
|
+
BigMath.sqrt(num, 100)
|
417
|
+
else
|
418
|
+
Math.sqrt(num)
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
def log10(num)
|
423
|
+
if @precision == :high
|
424
|
+
BigMath.log(num, 100) / BigMath.log(10, 100)
|
425
|
+
else
|
426
|
+
Math.log10(num)
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
def make_constants
|
431
|
+
# 2.1 Primary constants and characteristics
|
432
|
+
# Table 1 - Main constants and characteristics adopted for
|
433
|
+
# the calculation of the ISO Standard Atmosphere
|
434
|
+
@constants = {
|
435
|
+
# g_n gravitation at mean sea level (m.s-2)
|
436
|
+
g_n: num("9.80665"),
|
437
|
+
|
438
|
+
# Avogadro constant (mol-1)
|
439
|
+
N_A: num("6.02257e+23"),
|
440
|
+
|
441
|
+
# p_n pressure at mean sea level (Pa)
|
442
|
+
p_n: num("101325"),
|
443
|
+
|
444
|
+
# rho_n standard air density
|
445
|
+
rho_n: num("1.225"),
|
446
|
+
|
447
|
+
# T_n standard thermodynamic air temperature at mean sea level
|
448
|
+
T_n: num("288.15"),
|
449
|
+
|
450
|
+
# universal gas constant
|
451
|
+
R_star: num("8.31432"),
|
452
|
+
|
453
|
+
# radius of the Earth (m)
|
454
|
+
radius: num("6356766"),
|
455
|
+
|
456
|
+
# adiabatic index (dimensionless)
|
457
|
+
k: num("1.4")
|
458
|
+
}
|
459
|
+
|
460
|
+
# 2.2 The equation of the static atmosphere and the perfect gas law
|
461
|
+
# Formula (2)
|
462
|
+
# M: air molar mass at sea level, kg.kmol-1
|
463
|
+
# Value given in 2.1 as M: 28.964720
|
464
|
+
@constants[:M] =
|
465
|
+
(@constants[:rho_n] * @constants[:R_star] * @constants[:T_n]) / @constants[:p_n]
|
466
|
+
|
467
|
+
# Formula (3)
|
468
|
+
# R: specific gas constant, J.K-1.kg-1.
|
469
|
+
# Value given in 2.1 as R: 287.05287
|
470
|
+
@constants[:R] = @constants[:R_star] / @constants[:M]
|
471
|
+
|
472
|
+
@sqrt2 = sqrt(num("2"))
|
473
|
+
@pi = @precision == :high ? BigMath.PI(100) : Math::PI
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
class HighPrecision < Algorithms
|
478
|
+
include Singleton
|
479
|
+
|
480
|
+
def initialize
|
481
|
+
set_precision(:high)
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
class NormalPrecision < Algorithms
|
486
|
+
include Singleton
|
487
|
+
|
488
|
+
def initialize
|
489
|
+
set_precision(:normal)
|
490
|
+
end
|
486
491
|
end
|
487
492
|
end
|
488
493
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "lutaml/model"
|
4
|
+
|
5
|
+
module Atmospheric
|
6
|
+
class UnitValueFloat < Lutaml::Model::Serializable
|
7
|
+
attribute :value, :float
|
8
|
+
attribute :unitsml, :string
|
9
|
+
attribute :type, :string, default: -> { "float" }
|
10
|
+
|
11
|
+
key_value do
|
12
|
+
map "value", to: :value
|
13
|
+
map "unitsml", to: :unitsml
|
14
|
+
map "type", to: :type, render_default: true
|
15
|
+
end
|
16
|
+
|
17
|
+
xml do
|
18
|
+
root "unitl-value-float"
|
19
|
+
map_content to: :value
|
20
|
+
map_attribute :unitsml, to: :unitsml
|
21
|
+
map_attribute :type, to: :type, render_default: true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "lutaml/model"
|
4
|
+
|
5
|
+
module Atmospheric
|
6
|
+
class UnitValueInteger < Lutaml::Model::Serializable
|
7
|
+
attribute :value, :integer
|
8
|
+
attribute :unitsml, :string
|
9
|
+
attribute :type, :string, default: -> { "integer" }
|
10
|
+
|
11
|
+
key_value do
|
12
|
+
map "value", to: :value
|
13
|
+
map "unitsml", to: :unitsml
|
14
|
+
map "type", to: :type, render_default: true
|
15
|
+
end
|
16
|
+
|
17
|
+
xml do
|
18
|
+
root "unit-value-integer"
|
19
|
+
map_content to: :value
|
20
|
+
map_attribute :unitsml, to: :unitsml
|
21
|
+
map_attribute :type, to: :type, render_default: true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/atmospheric/version.rb
CHANGED