diff --git a/.DS_Store b/.DS_Store index ac10530..52224ac 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/pyatmos/.DS_Store b/pyatmos/.DS_Store index 323f3f7..480070a 100644 Binary files a/pyatmos/.DS_Store and b/pyatmos/.DS_Store differ diff --git a/pyatmos/StandardAtmosphere/StandardAtmosphere.py b/pyatmos/StandardAtmosphere/StandardAtmosphere.py new file mode 100644 index 0000000..f49c896 --- /dev/null +++ b/pyatmos/StandardAtmosphere/StandardAtmosphere.py @@ -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} \ No newline at end of file diff --git a/pyatmos/StandardAtmosphere/__init__.py b/pyatmos/StandardAtmosphere/__init__.py new file mode 100644 index 0000000..b136d90 --- /dev/null +++ b/pyatmos/StandardAtmosphere/__init__.py @@ -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. +''' \ No newline at end of file diff --git a/pyatmos/__init__.py b/pyatmos/__init__.py index 31a90cc..395a39d 100644 --- a/pyatmos/__init__.py +++ b/pyatmos/__init__.py @@ -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. ''' \ No newline at end of file diff --git a/pyatmos/atmosclasses/.DS_Store b/pyatmos/atmosclasses/.DS_Store deleted file mode 100644 index 6120ca3..0000000 Binary files a/pyatmos/atmosclasses/.DS_Store and /dev/null differ diff --git a/pyatmos/atmosclasses/__init__.py b/pyatmos/atmosclasses/__init__.py deleted file mode 100644 index 4356368..0000000 --- a/pyatmos/atmosclasses/__init__.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/pyatmos/atmosclasses/__pycache__/__init__.cpython-37.pyc b/pyatmos/atmosclasses/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index 7dfc191..0000000 Binary files a/pyatmos/atmosclasses/__pycache__/__init__.cpython-37.pyc and /dev/null differ diff --git a/pyatmos/atmosclasses/__pycache__/coordinate.cpython-37.pyc b/pyatmos/atmosclasses/__pycache__/coordinate.cpython-37.pyc deleted file mode 100644 index cf22aca..0000000 Binary files a/pyatmos/atmosclasses/__pycache__/coordinate.cpython-37.pyc and /dev/null differ diff --git a/pyatmos/atmosclasses/__pycache__/position.cpython-37.pyc b/pyatmos/atmosclasses/__pycache__/position.cpython-37.pyc deleted file mode 100644 index ec4b4ef..0000000 Binary files a/pyatmos/atmosclasses/__pycache__/position.cpython-37.pyc and /dev/null differ diff --git a/pyatmos/atmosclasses/__pycache__/spacetime.cpython-37.pyc b/pyatmos/atmosclasses/__pycache__/spacetime.cpython-37.pyc deleted file mode 100644 index b7f5bb4..0000000 Binary files a/pyatmos/atmosclasses/__pycache__/spacetime.cpython-37.pyc and /dev/null differ diff --git a/pyatmos/atmosclasses/__pycache__/timespace.cpython-37.pyc b/pyatmos/atmosclasses/__pycache__/timespace.cpython-37.pyc deleted file mode 100644 index e11fd29..0000000 Binary files a/pyatmos/atmosclasses/__pycache__/timespace.cpython-37.pyc and /dev/null differ diff --git a/pyatmos/atmosclasses/coordinate.py b/pyatmos/atmosclasses/coordinate.py deleted file mode 100644 index f4f9168..0000000 --- a/pyatmos/atmosclasses/coordinate.py +++ /dev/null @@ -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 - - - diff --git a/pyatmos/msise/__init__.py b/pyatmos/msise/__init__.py index bab9148..8577228 100644 --- a/pyatmos/msise/__init__.py +++ b/pyatmos/msise/__init__.py @@ -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