added international standard atmosphere

This commit is contained in:
Chunxiao Li 2020-03-27 17:01:55 +08:00
parent 702694bc8c
commit 0e258cb1fa
14 changed files with 121 additions and 122 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
pyatmos/.DS_Store vendored

Binary file not shown.

View 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}

View 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.
'''

View File

@ -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.
'''

Binary file not shown.

View File

@ -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

View File

@ -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

View File

@ -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