def test_under_1000m(): """Tests for altitude values under 1000.0 m """ z = np.array([50.0, 550.0, 850.0]) h = util.geometric_to_geopotential(z) expected_h = np.array([50.0, 550.0, 850.0]) expected_T = np.array([287.825, 284.575, 282.626]) expected_p = np.array([100720.0, 94890.0, 91523.0]) expected_rho = np.array([1.2191, 1.1616, 1.1281]) h, T, p, rho = coesa.table(h) assert_array_almost_equal(h, expected_h, decimal=0) assert_array_almost_equal(T, expected_T, decimal=3) assert_array_almost_equal(p, expected_p, decimal=-1) assert_array_almost_equal(rho, expected_rho, decimal=4)
def test_under_86km(): """Tests for altitude values between 35 and 86 km """ z = np.array([50000.0, 70000.0, 86000.0]) h = util.geometric_to_geopotential(z) expected_h = np.array([49610.0, 69238., 84852.0]) expected_T = np.array([270.65, 219.585, 186.87]) expected_p = np.array([79.779, 5.2209, 0.37338]) expected_rho = np.array([0.0010269, 0.000082829, 0.000006958]) h, T, p, rho = coesa.table(h) assert_array_almost_equal(h, expected_h, decimal=0) assert_array_almost_equal(T, expected_T, decimal=2) assert_array_almost_equal(p, expected_p, decimal=3) assert_array_almost_equal(rho, expected_rho, decimal=7)
def test_under_11km(): """Tests for altitude values between 1 and 11 km """ z = np.array([500.0, 2500.0, 6500.0, 9000.0, 11000.0]) h = util.geometric_to_geopotential(z) expected_h = np.array([500.0, 2499.0, 6493.0, 8987.0, 10981.0]) expected_T = np.array([284.900, 271.906, 245.943, 229.733, 216.774]) expected_p = np.array([95461.0, 74691.0, 44075.0, 30800.0, 22699.0]) expected_rho = np.array([1.1673, 0.95695, 0.62431, 0.46706, 0.36480]) h, T, p, rho = coesa.table(h) assert_array_almost_equal(h, expected_h, decimal=0) assert_array_almost_equal(T, expected_T, decimal=3) assert_array_almost_equal(p, expected_p, decimal=0) assert_array_almost_equal(rho, expected_rho, decimal=4)
def test_under_35km(): """Tests for altitude values between 11 and 35 km """ z = np.array([15000.0, 25000.0, 35000.0]) h = util.geometric_to_geopotential(z) expected_h = np.array([14965.0, 24902., 34808.0]) expected_T = np.array([216.65, 221.552, 236.513]) expected_p = np.array([12111.0, 2549.2, 574.59]) expected_rho = np.array([0.19476, 0.040084, 0.0084634]) h, T, p, rho = coesa.table(h) assert_array_almost_equal(h, expected_h, decimal=0) assert_array_almost_equal(T, expected_T, decimal=3) assert_array_almost_equal(p, expected_p, decimal=0) assert_array_almost_equal(rho, expected_rho, decimal=5)
def test_under_1000m(): """Tests for altitude values under 1000.0 m """ z = np.array([50.0, 550.0, 850.0]) h = util.geometric_to_geopotential(z) expected_h = np.array([50.0, 550.0, 850.0]) expected_T = np.array([287.825, 284.575, 282.626]) expected_p = np.array([100720.0, 94890.0, 91523.0]) expected_rho = np.array([1.2191, 1.1616, 1.1281]) h, T, p, rho = coesa.table(h) assert_array_almost_equal(h, expected_h, decimal=0) assert_array_almost_equal(T, expected_T, decimal=3) assert_array_almost_equal(p, expected_p, decimal=-1) assert_array_almost_equal(rho, expected_rho, decimal=4)
def test_under_86km(): """Tests for altitude values between 35 and 86 km """ z = np.array([50000.0, 70000.0, 86000.0]) h = util.geometric_to_geopotential(z) expected_h = np.array([49610.0, 69238., 84852.0]) expected_T = np.array([270.65, 219.585, 186.87]) expected_p = np.array([79.779, 5.2209, 0.37338]) expected_rho = np.array([0.0010269, 0.000082829, 0.000006958]) h, T, p, rho = coesa.table(h) assert_array_almost_equal(h, expected_h, decimal=0) assert_array_almost_equal(T, expected_T, decimal=2) assert_array_almost_equal(p, expected_p, decimal=3) assert_array_almost_equal(rho, expected_rho, decimal=7)
def test_under_35km(): """Tests for altitude values between 11 and 35 km """ z = np.array([15000.0, 25000.0, 35000.0]) h = util.geometric_to_geopotential(z) expected_h = np.array([14965.0, 24902., 34808.0]) expected_T = np.array([216.65, 221.552, 236.513]) expected_p = np.array([12111.0, 2549.2, 574.59]) expected_rho = np.array([0.19476, 0.040084, 0.0084634]) h, T, p, rho = coesa.table(h) assert_array_almost_equal(h, expected_h, decimal=0) assert_array_almost_equal(T, expected_T, decimal=3) assert_array_almost_equal(p, expected_p, decimal=0) assert_array_almost_equal(rho, expected_rho, decimal=5)
def test_under_11km(): """Tests for altitude values between 1 and 11 km """ z = np.array([500.0, 2500.0, 6500.0, 9000.0, 11000.0]) h = util.geometric_to_geopotential(z) expected_h = np.array([500.0, 2499.0, 6493.0, 8987.0, 10981.0]) expected_T = np.array([284.900, 271.906, 245.943, 229.733, 216.774]) expected_p = np.array([95461.0, 74691.0, 44075.0, 30800.0, 22699.0]) expected_rho = np.array([1.1673, 0.95695, 0.62431, 0.46706, 0.36480]) h, T, p, rho = coesa.table(h) assert_array_almost_equal(h, expected_h, decimal=0) assert_array_almost_equal(T, expected_T, decimal=3) assert_array_almost_equal(p, expected_p, decimal=0) assert_array_almost_equal(rho, expected_rho, decimal=4)
def test_geometric_to_geopotential(): z = np.array([50.0, 5550.0, 10450.0]) h = util.geometric_to_geopotential(z) expected_h = np.array([50.0, 5545.0, 10433.0]) assert_array_almost_equal(h, expected_h, decimal=0)
def table(x, kind="geopotential"): """Computes table of COESA atmosphere properties. Returns temperature, pressure and density COESA values at the given altitude. Parameters ---------- x : array_like Geopotential or geometric altitude (depending on kind) given in meters. kind : str Specifies the kind of interpolation as altitude x ('geopotential' or 'geometric'). Default is 'geopotential' Returns ------- h : array_like Given geopotential altitude in meters. T : array_like Temperature in Kelvin. p : array_like Pressure in Pascal. rho : array_like Density in kilograms per cubic meter. Note ---- Based on the U.S. 1976 Standard Atmosphere. """ # check the kind of altitude and raise an exception if necessary if kind == "geopotential": alt = x elif kind == "geometric": alt = util.geometric_to_geopotential(x) else: raise ValueError( "%s is unsupported: Use either geopotential or " "geometric." % kind ) h = np.asarray(alt) # check if altitude is out of bound and raise an exception if necessary if (h < H[0]).any() or (h > H[-1]).any(): raise ValueError( "the given altitude x is out of bound, this module is " "currently only valid for a geometric altitude between 0. and 86000. m" ) # K, molecule-scale temperature from eq. [23] of Notes reference tm = f_TM(h) + f_LM(h) * (h - f_H(h)) # K, absolute temperature from eq. [22] of Notes reference T = tm * f_M_o_M0(h) if h.shape: # if h is not a 0-d array (like a scalar) # Pa, intialization of the pressure vector p = np.zeros(len(h)) # points of h for which the molecular-scale temperature gradient is # zero zero_gradient = f_LM(h) == 0.0 # points of h for which the molecular-scale temperature gradient is not # zero not_zero_gradient = f_LM(h) != 0.0 # Pa, pressure from eq. [33b] of Notes reference p[zero_gradient] = f_P(h[zero_gradient]) * np.exp( -constants.g * M_0 * (h[zero_gradient] - f_H(h[zero_gradient])) / (Rs * f_TM(h[zero_gradient])) ) # Pa, pressure from eq. [33a] of Notes reference p[not_zero_gradient] = f_P(h[not_zero_gradient]) * ( f_TM(h[not_zero_gradient]) / ( f_TM(h[not_zero_gradient]) + f_LM(h[not_zero_gradient]) * (h[not_zero_gradient] - f_H(h[not_zero_gradient])) ) ) ** (constants.g * M_0 / (Rs * f_LM(h[not_zero_gradient]))) else: if f_LM(h) == 0: # Pa, pressure from eq. [33b] of Notes reference p = f_P(h) * np.exp(-constants.g * M_0 * (h - f_H(h)) / (Rs * f_TM(h))) else: # Pa, pressure from eq. [33a] of Notes reference p = f_P(h) * (f_TM(h) / (f_TM(h) + f_LM(h) * (h - f_H(h)))) ** ( constants.g * M_0 / (Rs * f_LM(h)) ) rho = p * M_0 / (Rs * tm) # kg / m^3, mass density return alt, T, p, rho
def test_geometric_to_geopotential(): z = np.array([50.0, 5550.0, 10450.0]) h = util.geometric_to_geopotential(z) expected_h = np.array([50.0, 5545.0, 10433.0]) assert_array_almost_equal(h, expected_h, decimal=0)
def table(x, kind='geopotential'): """Computes table of COESA atmosphere properties. Returns temperature, pressure and density COESA values at the given altitude. Parameters ---------- x : array_like Geopotential or geometric altitude (depending on kind) given in meters. kind : str Specifies the kind of interpolation as altitude x ('geopotential' or 'geometric'). Default is 'geopotential' Returns ------- h : array_like Given geopotential altitude in meters. T : array_like Temperature in Kelvin. p : array_like Pressure in Pascal. rho : array_like Density in kilograms per cubic meter. Notes ----- Based on the U.S. 1976 Standard Atmosphere. .. _`U.S. 1976 Standard Atmosphere`: http://ntrs.nasa.gov/search.jsp?R=19770009539 """ # check the kind of altitude and raise an exception if necessary if kind == 'geopotential': alt = x elif kind == 'geometric': alt = util.geometric_to_geopotential(x) else: raise ValueError("%s is unsupported: Use either geopotential or " "geometric." % kind) h = np.asarray(alt) # check if altitude is out of bound and raise an exception if necessary if (h < H[0]).any() or (h > H[-1]).any(): raise ValueError( "the given altitude x is out of bound, this module is " "currently only valid for a geometric altitude between 0. and 86000. m" ) # K, molecule-scale temperature from eq. [23] of Notes reference tm = f_TM(h) + f_LM(h) * (h - f_H(h)) # K, absolute temperature from eq. [22] of Notes reference T = tm * f_M_o_M0(h) if h.shape: # if h is not a 0-d array (like a scalar) # Pa, intialization of the pressure vector p = np.zeros(len(h)) # points of h for which the molecular-scale temperature gradient is zero zero_gradient = (f_LM(h) == 0.) # points of h for which the molecular-scale temperature gradient is not # zero not_zero_gradient = (f_LM(h) != 0.) # Pa, pressure from eq. [33b] of Notes reference p[zero_gradient] = f_P(h[zero_gradient]) * np.exp( -constants.g * M_0 * (h[zero_gradient] - f_H(h[zero_gradient])) / (Rs * f_TM(h[zero_gradient]))) # Pa, pressure from eq. [33a] of Notes reference p[not_zero_gradient] = f_P(h[not_zero_gradient]) * ( f_TM(h[not_zero_gradient]) / (f_TM(h[not_zero_gradient]) + f_LM(h[not_zero_gradient]) * (h[not_zero_gradient] - f_H(h[not_zero_gradient]))))**( constants.g * M_0 / (Rs * f_LM(h[not_zero_gradient]))) else: if f_LM(h) == 0: # Pa, pressure from eq. [33b] of Notes reference p = f_P(h) * np.exp(-constants.g * M_0 * (h - f_H(h)) / (Rs * f_TM(h))) else: # Pa, pressure from eq. [33a] of Notes reference p = f_P(h) * (f_TM(h) / (f_TM(h) + f_LM(h) * (h - f_H(h))))**(constants.g * M_0 / (Rs * f_LM(h))) rho = p * M_0 / (Rs * tm) # kg / m^3, mass density return alt, T, p, rho