예제 #1
0
    def _retrieve_result(self, altitude_cm):
        """Calls NRLMSISE library's main function"""
        if self.last_alt == altitude_cm:
            return

        self.inp.alt = altitude_cm / 1e5
        gtd7(self.inp, self.flags, self.output)

        self.last_alt = altitude_cm
예제 #2
0
def calculateDragAcceleration(stateVec, ecpoh, satMass):
    """ Calculate the acceleration due to atmospheric draf acting on the
    satellite at a given state (3 positions and 3 velocities) and epoch.
    Use NRLMSISE2000 atmospheric model with globally defined solar activity
    proxies:
        F10_7A - 81-day average F10.7.
        F10_7 - daily F10.7 for the previous day.
        MagneticIndex - daily magnetic index AP.
        NRLMSISEaph - nrlmsise_00_header.ap_array with magnetic values.#
    
    Arguments
    ----------
    numpy.ndarray of shape (1,6) with three Cartesian positions and three
        velocities in an inertial reference frame in metres and metres per
            second, respectively.
    epoch - float corresponding to the epoch at which the rate of change is
        to be computed.
    Returns
    ----------
    numpy.ndarray of shape (1,3) with three Cartesian components of the
        acceleration in m/s2 given in an inertial reference frame.
    """
    #    " Prepare the atmospheric density model inputs. "
    #    #TODO - calculate the altitude, latitude, longitude
    altitude_km = numpy.linalg.norm(
        stateVec[:3]
    ) / 1000.0  #TODO this isn't altitude in km, but radius in km. Is this OK?
    NRLMSISEinput = nrlmsise_00_header.nrlmsise_input(year=0,
                                                      doy=0,
                                                      sec=0.0,
                                                      alt=altitude_km,
                                                      g_lat=0.0,
                                                      g_long=0.0,
                                                      lst=0.0,
                                                      f107A=F10_7A,
                                                      f107=F10_7,
                                                      ap=MagneticIndex,
                                                      ap_a=NRLMSISEaph)
    nrlmsise_00_header.lstCalc(
        NRLMSISEinput)  # Calculate the local solar time.

    " Use the calculated atmospheric density to compute the drag force. "
    NRLMSISEoutpt = nrlmsise_00_header.nrlmsise_output()
    nrlmsise_00.gtd7(NRLMSISEinput, NRLMSISEflags, NRLMSISEoutpt)
    atmosphericDensity = NRLMSISEoutpt.d[
        5] / 1000.0  # Change from gm/cm3 to kg/m3
    dragForce = -0.5 * atmosphericDensity * dragArea * Cd * numpy.power(
        stateVec[3:], 2)  # Drag foce in Newtons.
    return dragForce / satMass
예제 #3
0
 def get_density(self, altitude_cm):
     self.input.alt = altitude_cm / 1e5
     gtd7(self.input, self.flags, self.output)
     return self.output.d[5]
def NRLMSISE_00(pos, time, pos_type='eci'):
    ''' Courtesy of Ellie Sansom '''
    """
    Inputs: inertial position and time
    Outputs: [altitude, temp, atm_pres, atm density, sos, dyn_vis]
    """

    from nrlmsise_00_header import nrlmsise_input, nrlmsise_output, nrlmsise_flags
    from nrlmsise_00 import gtd7

    time = Time(time, format='jd', scale='utc')

    # Convert ECI to LLH coordinates
    if pos_type == 'eci':
        Pos_LLH = ECEF2LLH(ECI2ECEF_pos(pos, time))
    elif pos_type == 'ecef':
        Pos_LLH = ECEF2LLH(pos)
    elif pos_type == 'llh':
        Pos_LLH = pos
    else:
        print('NRLMSISE_00 error: Invalid pos_type')
        exit()
    g_lat = np.rad2deg(Pos_LLH[0][0])
    g_long = np.rad2deg(Pos_LLH[1][0])
    alt = Pos_LLH[2][0]

    # Break up time into year, day of year, and seconds of the day
    yDay = time.yday.split(':')
    yr = float(yDay[0])
    doy = float(yDay[1])
    sec = float(yDay[2]) * 60 * 60 + float(yDay[3]) * 60 + float(yDay[4])

    # Assign our variables into the nrmsise inputs
    Input = nrlmsise_input(yr, doy, sec, alt / 1000, g_lat, g_long)
    Output = nrlmsise_output()
    Flags = nrlmsise_flags()

    # Switches
    for i in range(1, 24):
        Flags.switches[i] = 1

    # GTD7 atmospheric model subroutine
    gtd7(Input, Flags, Output)

    # Temperature at alt [deg K]
    T = Output.t[1]

    # Molecular number densities [m-3]
    He = Output.d[0]  # He
    O = Output.d[1]  # O
    N2 = Output.d[2]  # N2
    O2 = Output.d[3]  # O2
    Ar = Output.d[4]  # Ar
    H = Output.d[6]  # H
    N = Output.d[7]  # N
    #    ano_O  = Output.d[8] # Anomalous oxygen
    sum_mass = He + O + N2 + O2 + Ar + H + N

    # Molar mass
    He_mass = 4.0026  # g/mol
    O_mass = 15.9994  # g/mol
    N2_mass = 28.013  # g/mol
    O2_mass = 31.998  # g/mol
    Ar_mass = 39.948  # g/mol
    H_mass = 1.0079  # g/mol
    N_mass = 14.0067  # g/mol

    # Molecular weight of air [kg/mol]
    mol_mass_air = (He_mass * He + O_mass * O + N2_mass * N2 + O2_mass * O2 +
                    Ar_mass * Ar + H_mass * H + N_mass * N) / (1000 * sum_mass)

    # Total mass density [kg*m-3]
    po = Output.d[5] * 1000

    Ru = 8.3144621  # Universal gas constant [J/(K*mol)]
    R = Ru / mol_mass_air  # Individual gas constant [J/(kg*K)] #287.058

    # Ideal gas law
    atm_pres = po * T * R

    # Speed of sound in atm
    sos = 331.3 * np.sqrt(1 + T / 273.15)

    # Dynamic viscosity (http://en.wikipedia.org/wiki/Viscosity)
    C = 120  #Sutherland's constant for air [deg K]
    mu_ref = 18.27e-6  # Reference viscosity [[mu_Pa s] * e-6]
    T_ref = 291.15  # Reference temperature [deg K]

    dyn_vis = mu_ref * (T_ref + C) / (T + C) * (T / T_ref)**1.5

    return T, atm_pres, po, sos, dyn_vis
예제 #5
0
	def __init__(self, h, doy=172, year=0, sec=29000, g_lat=60, g_long=120,
		lst=16, f107A=150, f107=150, ap=4):

		# Cantera Solution object
		self.gas = ct.Solution('air.xml')

		# Discretised altitude steps
		self.h = h

		# Average molecular diameter of gas
		self.d = 4E-10

		self.steps = len(h)

		self.output = [nrl_head.nrlmsise_output() for _ in range(self.steps)]
		self.input = [nrl_head.nrlmsise_input() for _ in range(self.steps)]
		self.flags = nrl_head.nrlmsise_flags()
		self.aph = nrl_head.ap_array()

		# Set magnetic values array
		for index in range(7):
			self.aph.a[index] = 100

		# Output in metres (as opposed to centimetres)
		self.flags.switches[0] = 0

		# Set other flags to TRUE (see docstring of nrlmsise_00_header.py)
		for index in range(24):
			self.flags.switches[index] = 1

		for index in range(self.steps):
			self.input[index].doy = doy
			self.input[index].year = year
			self.input[index].sec = sec
			self.input[index].alt = self.h[index] / 1000
			self.input[index].g_lat = g_lat
			self.input[index].g_long = g_long
			self.input[index].lst = lst
			self.input[index].f107A = f107A
			self.input[index].f107 = f107
			self.input[index].ap = ap
			#self.input[index].ap_a = self.aph

		# Run NRLMSISE00 model
		for index in range(self.steps):
			nrlmsise.gtd7(self.input[index], self.flags, self.output[index])

		# Pre-allocate memory
		self.rho = np.zeros(self.steps)
		self.T = np.zeros(self.steps)
		self.a = np.zeros(self.steps)
		self.k = np.zeros(self.steps)
		self.mu = np.zeros(self.steps)
		self.cp = np.zeros(self.steps)
		self.cv = np.zeros(self.steps)

		# Extract density and temperature
		for index in range(self.steps):
			self.rho[index] = self.output[index].d[5]
			self.T[index] = self.output[index].t[1]

		# Query Cantera for gas state
		for index, alt in enumerate(self.h):
			self.gas.TD = self.T[index], self.rho[index]
			self.cp[index] = self.gas.cp
			self.cv[index] = self.gas.cv
			self.mu[index] = self.gas.viscosity

		# Perfect gas constant for air (J/kgK)
		self.R = self.cp - self.cv

		# Ratio of specific heats (J/kgK)
		self.k = self.cp / self.cv

		# Pressure and speed of sound
		self.p = self.rho * self.T * self.R
		self.a = fcl.speed_of_sound(self.k, self.R, self.T)

		print 'ATMOSPHERIC MODEL COMPUTED (NRLMSISE00)'

		return None
예제 #6
0
 def get_density(self, altitude_cm):
     self.input.alt = altitude_cm / 1e5
     gtd7(self.input, self.flags, self.output)
     return self.output.d[5]