added international standard atmosphere
This commit is contained in:
parent
702694bc8c
commit
0e258cb1fa
BIN
pyatmos/.DS_Store
vendored
BIN
pyatmos/.DS_Store
vendored
Binary file not shown.
103
pyatmos/StandardAtmosphere/StandardAtmosphere.py
Normal file
103
pyatmos/StandardAtmosphere/StandardAtmosphere.py
Normal file
@ -0,0 +1,103 @@
|
||||
import numpy as np
|
||||
|
||||
# physical constants:
|
||||
g = 9.80665 # standard gravity acceleration in [m/s^2]
|
||||
R = 8314.32/28.9644 # gas constant for dry air in [J/kg/K] from the 1976 United States Standard Atmosphere(USSA) Model
|
||||
R_e = 6371000.8 # Earth's volumetric radius in [m]
|
||||
# temperature and pressure at the Mean Sea Level(MSL)
|
||||
t_msl = 288.15 # temperature in [K]
|
||||
p_msl = 101325 # pressure in [Pa]
|
||||
h_msl = 0 # altitude in [m]
|
||||
|
||||
def lapse_tp(t_lower, p_lower, lr, h_lower, h_upper):
|
||||
'''
|
||||
Calculate the temperature and pressure at a given geopotential altitude above base of a specific layer.
|
||||
The temperature is computed by the linear interpolation with the slope defined by lapse rates.
|
||||
The pressure is computed from the hydrostatic equations and the perfect gas law.
|
||||
See the detailed documentation in http://www.pdas.com/hydro.pdf
|
||||
|
||||
Usage:
|
||||
[t_upper, p_upper] = lapse_tp(t_lower, p_lower, lr, h_lower, h_upper)
|
||||
|
||||
Inputs:
|
||||
t_lower -> [float] temperature in [K] at the lower boundary of the subset in the specific layer
|
||||
p_lower -> [float] pressure in [Pa] at the lower boundary of the subset in the specific layer
|
||||
lr -> [float] lapse rate in [K/m] for the specific layer
|
||||
h_lower -> [float] geopotential altitude in [m] at the lower boundary of the subset in the specific layer
|
||||
h_upper -> [float] geopotential altitude in [m] at the upper boundary of the subset in the specific layer
|
||||
|
||||
Outputs:
|
||||
t1 -> [float] temperature in [K] at the upper boundary of the subset in the specific layer
|
||||
p1 -> [float] pressure in [Pa] at the upper boundary of the subset in the specific layer
|
||||
|
||||
Reference: Public Domain Aeronautical Software(http://www.pdas.com/atmos.html)
|
||||
https://gist.github.com/buzzerrookie/5b6438c603eabf13d07e
|
||||
'''
|
||||
if lr == 0:
|
||||
t_upper = t_lower
|
||||
p_upper = p_lower * np.exp(-g / R / t_lower * (h_upper - h_lower))
|
||||
else:
|
||||
t_upper = t_lower + lr * (h_upper - h_lower)
|
||||
p_upper = p_lower * (t_upper / t_lower) ** (-g / lr / R)
|
||||
|
||||
return t_upper,p_upper
|
||||
|
||||
def isa(altitude,altitude_type='geometric'):
|
||||
'''
|
||||
Implements the International Standard Atmosphere(ISA) Model up to 86km.
|
||||
The standard atmosphere is defined as a set of layers by specified geopotential altitudes and lapse rates.
|
||||
The temperature is computed by linear interpolation with the slope defined by the lapse rate.
|
||||
The pressure is computed from the hydrostatic equations and the perfect gas law; the density follows from the perfect gas law.
|
||||
|
||||
Usage:
|
||||
[temperature, pressure, density] = isa(altitude)
|
||||
[temperature, pressure, density] = isa(altitude,'geopotential')
|
||||
|
||||
Inputs:
|
||||
altitude -> [float] altitude in [m]
|
||||
|
||||
Parameters:
|
||||
altitude_type -> [optional, string, default='geometric'] type of altitude. It can either be 'geopotential' or 'geometric'.
|
||||
Relationship between the 'geopotential' and 'geometric' altitude can be found in http://www.pdas.com/hydro.pdf
|
||||
|
||||
Outputs:
|
||||
temperature -> [float] temperature in [K] at the local altitude
|
||||
pressure -> [float] pressure in [Pa] at the local altitude
|
||||
density -> [float] density in [kg/m^3] at the local altitude
|
||||
|
||||
Note: the geopotential altitude should be in [610,84852] m and the geometric altitude should be in [-611,86000] m
|
||||
|
||||
Reference: U.S. Standard Atmosphere, 1976, U.S. Government Printing Office, Washington, D.C.
|
||||
Public Domain Aeronautical Software(http://www.pdas.com/atmos.html)
|
||||
https://gist.github.com/buzzerrookie/5b6438c603eabf13d07e
|
||||
https://ww2.mathworks.cn/help/aerotbx/ug/atmosisa.html
|
||||
'''
|
||||
# the lower atmosphere below 86km is separated into seven layers
|
||||
geopotential_alt = [-610,11000, 20000, 32000, 47000, 51000,71000,84852] # Geopotential altitudes above MSL in [m]
|
||||
geometric_alt = [-611,11019, 20063, 32162, 47350, 51413, 71802,86000] # Geometric altitudes above MSL in [m]
|
||||
lr = np.array([-6.5, 0, 1, 2.8, 0, -2.8, -2])/1e3 # Lapse rate in [K/m]
|
||||
|
||||
t0,p0,h0 = t_msl,p_msl,h_msl
|
||||
|
||||
if altitude_type == 'geopotential':
|
||||
if altitude < geopotential_alt[0] or altitude > geopotential_alt[-1]:
|
||||
raise Exception("geopotential altitude should be in [-0.610, 84.852] km")
|
||||
elif altitude_type == 'geometric':
|
||||
if altitude < geometric_alt[0] or altitude > geometric_alt[-1]:
|
||||
raise Exception("geometric altitude should be in [-0.611, 86.0] km")
|
||||
# convert geometric altitude to geopotential altitude
|
||||
altitude = altitude*R_e/(altitude+R_e)
|
||||
else:
|
||||
raise Exception("The type of altitude should either be 'geopotential' or 'geometric'")
|
||||
|
||||
for i in range(len(lr)):
|
||||
if altitude <= geopotential_alt[i+1]:
|
||||
temperature, pressure = lapse_tp(t0, p0, lr[i], h0, altitude)
|
||||
break
|
||||
else:
|
||||
# if altitudes are greater than the first several layers, then it has to integeate these layers first.
|
||||
t0, p0 = lapse_tp(t0, p0, lr[i], h0, geopotential_alt[i+1])
|
||||
h0 = geopotential_alt[i+1]
|
||||
|
||||
density = pressure / (R * temperature)
|
||||
return {'temperature':temperature,'pressure':pressure,'density':density}
|
13
pyatmos/StandardAtmosphere/__init__.py
Normal file
13
pyatmos/StandardAtmosphere/__init__.py
Normal file
@ -0,0 +1,13 @@
|
||||
'''
|
||||
pyatmos StandardAtmosphere subpackage
|
||||
|
||||
This subpackage defines the following functions:
|
||||
|
||||
# =================== Standard Atmosphere Model================= #
|
||||
|
||||
isa - Implements the International Standard Atmosphere(ISA) Model up to 86km.
|
||||
|
||||
# ===================== utility functions ==================== #
|
||||
|
||||
lapse_tp - Calculate the temperature and pressure at a given geopotential altitude above base of a specific layer.
|
||||
'''
|
@ -1,6 +1,5 @@
|
||||
'''
|
||||
pyatmos package
|
||||
|
||||
This package is an archive of scientific routines that can be used to
|
||||
perform the estimation of papameters for various atmosphere models.
|
||||
This package is an archive of scientific routines that implements the estimation of atmospheric properties for various atmosphere models.
|
||||
'''
|
BIN
pyatmos/atmosclasses/.DS_Store
vendored
BIN
pyatmos/atmosclasses/.DS_Store
vendored
Binary file not shown.
@ -1,10 +0,0 @@
|
||||
'''
|
||||
pyatmos atmosclasses subpackage
|
||||
|
||||
This subpackage defines a class that facilitates the parameter estimation for various atmosphere model
|
||||
|
||||
Class structure:
|
||||
|
||||
Coordinate
|
||||
'''
|
||||
from .coordinate import Coordinate
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,110 +0,0 @@
|
||||
from astropy.time import Time
|
||||
|
||||
from ..msise.nrlmsise00 import nrlmsise00
|
||||
|
||||
class Coordinate(object):
|
||||
'''
|
||||
space-time coordinate class
|
||||
|
||||
The coordinate of this class can be initialized using the following
|
||||
constructor method:
|
||||
|
||||
x = coordinate(t,lat,lon,alt)
|
||||
|
||||
Once initialized, each class instance defines the following class
|
||||
attributes:
|
||||
|
||||
t : time, default in UTC
|
||||
lat : latitude, default in degrees
|
||||
lon : longitude, default in degrees
|
||||
alt : altitude, default in km
|
||||
|
||||
Each class instance provides the following methods:
|
||||
|
||||
nrlmsise00() : Estimate the atmosphere parameters at a specific coordinate using the nrlmsise00 model
|
||||
'''
|
||||
def __init__(self,t,lat,lon,alt):
|
||||
self.t = t
|
||||
self.lat = lat
|
||||
self.lon = lon
|
||||
self.alt = alt
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
return 't = {:s} UTC\nlat = {:f} deg\nlon = {:f} deg\nalt = {:f} km'.format(self.t,self.lat,self.lon,self.alt)
|
||||
|
||||
def nrlmsise00(self,sw_obs_pre,omode='Oxygen',aphmode='NoAph'):
|
||||
'''
|
||||
Estimate the atmosphere parameters at a specific coordinate(time and location) using the nrlmsise00 model.
|
||||
|
||||
Usage:
|
||||
para_input,para_output = st.nrlmsis00_data(sw_obs_pre,[omode,aphmode])
|
||||
|
||||
Inputs:
|
||||
st -> [Coordinate class instance] It can be initialized by defining a specific set of time and location
|
||||
sw_obs_pre -> [2d str array] space weather data
|
||||
omode -> [str, optional, default = 'Oxygen'] If 'Oxygen', Anomalous Oxygen density will be included. If 'NoOxygen', Anomalous Oxygen density will be excluded.
|
||||
aphmode -> [str, optional, default = 'NoAph'] If NoAph', 3-hour geomagnetic index will not be used. If Aph', 3h geomagnetic index will be used.
|
||||
|
||||
Outputs:
|
||||
para_input -> [dictionary] parameters for time, location, solar radiation index, and geomagnetic index
|
||||
para_output -> [dictionary] parameters for atmospheric density and temperature
|
||||
|
||||
Examples:
|
||||
>>> from pyatmos.msise import download_sw,read_sw
|
||||
>>> from pyatmos.atmosclasses import Coordinate
|
||||
|
||||
>>> # Download or update the space weather file from www.celestrak.com
|
||||
>>> swfile = download_sw()
|
||||
>>> # Read the space weather data
|
||||
>>> sw_obs_pre = read_sw(swfile)
|
||||
>>>
|
||||
>>> # Test 1
|
||||
>>> # Set a specific time and location
|
||||
>>> t = '2015-10-05 03:00:00' # time(UTC)
|
||||
>>> lat,lon = 25,102 # latitude and longitude [degree]
|
||||
>>> alt = 70 # altitude [km]
|
||||
>>> # Initialize a coordinate instance by a space-time point
|
||||
>>> st = Coordinate(t,lat,lon,alt)
|
||||
>>>
|
||||
>>> para_input,para_output = st.nrlmsise00(sw_obs_pre)
|
||||
>>> print(para_input)
|
||||
{'doy': 278, 'year': 2015, 'sec': 10800.0, 'alt': 70, 'g_lat': 25, 'g_long': 102, 'lst': 9.8, 'f107A': 150, 'f107': 150, 'ap': 4, 'ap_a': array([4, 4, 4, 4, 4, 4, 4])}
|
||||
>>> print(para_output)
|
||||
>>> {'d': {'He': 9100292488300570.0, 'O': 0, 'N2': 1.3439413974205876e+21, 'O2': 3.52551376755781e+20, 'AR': 1.6044163757370681e+19, 'RHO': 8.225931818480755e-05, 'H': 0, 'N': 0, 'ANM O': 0}, 't': {'TINF': 1027.3184649, 'TG': 219.9649472491653}}
|
||||
>>>
|
||||
>>> # Test 2
|
||||
>>> t = '2004-07-08 10:30:50'
|
||||
>>> lat,lon,alt = -65,-120,100
|
||||
>>> st = Coordinate(t,lat,lon,alt)
|
||||
>>> para_input,para_output = st.nrlmsise00(sw_obs_pre)
|
||||
>>> print(para_input)
|
||||
{'doy': 190, 'year': 2004, 'sec': 37850.0, 'alt': 100, 'g_lat': -65, 'g_long': -120, 'lst': 2.5138888888888893, 'f107A': 109.0, 'f107': 79.3, 'ap': 2, 'ap_a': array([2. , 2. , 2. , 2. , 2. , 3.125, 4.625])}
|
||||
>>> print(para_output)
|
||||
{'d': {'He': 119477307274636.89, 'O': 4.1658304136233e+17, 'N2': 7.521248904485598e+18, 'O2': 1.7444969074975662e+18, 'AR': 7.739495767665198e+16, 'RHO': 4.584596293339505e-07, 'H': 22215754381448.5, 'N': 152814261016.3964, 'ANM O': 1.8278224834873257e-37}, 't': {'TINF': 1027.3184649, 'TG': 192.5868649143824}}
|
||||
>>>
|
||||
>>> # Test 3
|
||||
>>> t = '2010-02-15 12:18:37'
|
||||
>>> lat,lon,alt = 85,210,500
|
||||
>>> st = Coordinate(t,lat,lon,alt)
|
||||
>>> para_input,para_output = st.nrlmsise00(sw_obs_pre,'NoOxygen','Aph')
|
||||
>>> print(para_input)
|
||||
{'doy': 46, 'year': 2010, 'sec': 44317.0, 'alt': 500, 'g_lat': 85, 'g_long': 210, 'lst': 2.310277777777779, 'f107A': 83.4, 'f107': 89.4, 'ap': 14, 'ap_a': array([14. , 5. , 7. , 6. , 15. , 5.375, 4. ])}
|
||||
>>> print(para_output)
|
||||
{'d': {'He': 3314507585382.5425, 'O': 3855595951659.0874, 'N2': 19285497858.028534, 'O2': 395599656.3119481, 'AR': 146073.85956102316, 'RHO': 1.2650700238089615e-13, 'H': 171775437382.8238, 'N': 38359828672.39737, 'ANM O': 5345258193.554493}, 't': {'TINF': 776.3155804924045, 'TG': 776.3139192714452}}
|
||||
>>>
|
||||
>>> # Test 4
|
||||
>>> t = '2019-08-20 23:10:59'
|
||||
>>> lat,lon,alt = 3,5,900
|
||||
>>> st = Coordinate(t,lat,lon,alt)
|
||||
>>> para_input,para_output = st.nrlmsise00(sw_obs_pre,aphmode = 'Aph')
|
||||
>>> print(para_input)
|
||||
{'doy': 232, 'year': 2019, 'sec': 83459.0, 'alt': 900, 'g_lat': 3, 'g_long': 5, 'lst': 23.51638888888889, 'f107A': 67.4, 'f107': 67.7, 'ap': 4, 'ap_a': array([4. , 4. , 3. , 3. , 5. , 3.625, 3.5 ])}
|
||||
>> print(para_output)
|
||||
{'d': {'He': 74934329990.0412, 'O': 71368139.39199762, 'N2': 104.72048033793158, 'O2': 0.09392848471935447, 'AR': 1.3231114543012155e-07, 'RHO': 8.914971667362366e-16, 'H': 207405192640.34592, 'N': 3785341.821909535, 'ANM O': 1794317839.638502}, 't': {'TINF': 646.8157488121493, 'TG': 646.8157488108872}}
|
||||
'''
|
||||
para_input,para_output = nrlmsise00(Time(self.t),self.lat,self.lon,self.alt,sw_obs_pre,omode,aphmode)
|
||||
return para_input,para_output
|
||||
|
||||
|
||||
|
@ -3,6 +3,10 @@ pyatmos msise subpackage
|
||||
|
||||
This subpackage defines the following functions:
|
||||
|
||||
# ==================== nrlmisise-00 model =================== #
|
||||
|
||||
nrlmsise00 - Implements the NRLMSISE 00 model
|
||||
|
||||
# =================== spaceweather functions ================= #
|
||||
|
||||
download_sw - Download or update the space weather file from www.celestrak.com
|
||||
|
Loading…
x
Reference in New Issue
Block a user