def test_atmospheric_demise(): # Test an orbital decay that hits Earth. No analytic solution. R = Earth.R.to(u.km).value orbit = Orbit.circular(Earth, 230 * u.km) t_decay = 48.2179 * u.d # not an analytic value # parameters of a body C_D = 2.2 # dimentionless (any value would do) A_over_m = ((np.pi / 4.0) * (u.m**2) / (100 * u.kg)).to_value( u.km**2 / u.kg) # km^2/kg # parameters of the atmosphere rho0 = rho0_earth.to(u.kg / u.km**3).value # kg/km^3 H0 = H0_earth.to(u.km).value # km tofs = [365] * u.d # actually hits the ground a bit after day 48 lithobrake_event = LithobrakeEvent(R) events = [lithobrake_event] rr, _ = cowell( Earth.k, orbit.r, orbit.v, tofs, ad=atmospheric_drag_exponential, R=R, C_D=C_D, A_over_m=A_over_m, H0=H0, rho0=rho0, events=events, ) assert_quantity_allclose(norm(rr[0].to(u.km).value), R, atol=1) # below 1km assert_quantity_allclose(lithobrake_event.last_t, t_decay, rtol=1e-2) # make sure having the event not firing is ok tofs = [1] * u.d lithobrake_event = LithobrakeEvent(R) events = [lithobrake_event] rr, _ = cowell( Earth.k, orbit.r, orbit.v, tofs, ad=atmospheric_drag_exponential, R=R, C_D=C_D, A_over_m=A_over_m, H0=H0, rho0=rho0, events=events, ) assert lithobrake_event.last_t == tofs[-1]
def test_atmospheric_drag_exponential(): # http://farside.ph.utexas.edu/teaching/celestial/Celestialhtml/node94.html#sair (10.148) # Given the expression for \dot{r} / r, aproximate \Delta r \approx F_r * \Delta t R = Earth.R.to(u.km).value k = Earth.k.to(u.km**3 / u.s**2).value # Parameters of a circular orbit with h = 250 km (any value would do, but not too small) orbit = Orbit.circular(Earth, 250 * u.km) r0, _ = orbit.rv() r0 = r0.to(u.km).value # Parameters of a body C_D = 2.2 # dimentionless (any value would do) A_over_m = ((np.pi / 4.0) * (u.m**2) / (100 * u.kg)).to_value( u.km**2 / u.kg) # km^2/kg B = C_D * A_over_m # Parameters of the atmosphere rho0 = rho0_earth.to(u.kg / u.km**3).value # kg/km^3 H0 = H0_earth.to(u.km).value # km tof = 100000 # s dr_expected = -B * rho0 * np.exp(-(norm(r0) - R) / H0) * np.sqrt( k * norm(r0)) * tof # Assuming the atmospheric decay during tof is small, # dr_expected = F_r * tof (Newton's integration formula), where # F_r = -B rho(r) |r|^2 sqrt(k / |r|^3) = -B rho(r) sqrt(k |r|) def f(t0, u_, k): du_kep = func_twobody(t0, u_, k) ax, ay, az = atmospheric_drag_exponential(t0, u_, k, R=R, C_D=C_D, A_over_m=A_over_m, H0=H0, rho0=rho0) du_ad = np.array([0, 0, 0, ax, ay, az]) return du_kep + du_ad rr, _ = cowell( Earth.k, orbit.r, orbit.v, [tof] * u.s, f=f, ) assert_quantity_allclose(norm(rr[0].to(u.km).value) - norm(r0), dr_expected, rtol=1e-2)
def test_atmospheric_drag(): # http://farside.ph.utexas.edu/teaching/celestial/Celestialhtml/node94.html#sair (10.148) # given the expression for \dot{r} / r, aproximate \Delta r \approx F_r * \Delta t R = Earth.R.to(u.km).value k = Earth.k.to(u.km**3 / u.s**2).value # parameters of a circular orbit with h = 250 km (any value would do, but not too small) orbit = Orbit.circular(Earth, 250 * u.km) r0, _ = orbit.rv() r0 = r0.to(u.km).value # parameters of a body C_D = 2.2 # dimentionless (any value would do) A = ((np.pi / 4.0) * (u.m**2)).to(u.km**2).value # km^2 m = 100 # kg B = C_D * A / m # parameters of the atmosphere rho0 = rho0_earth.to(u.kg / u.km**3).value # kg/km^3 H0 = H0_earth.to(u.km).value # km tof = 100000 # s dr_expected = -B * rho0 * np.exp(-(norm(r0) - R) / H0) * np.sqrt( k * norm(r0)) * tof # assuming the atmospheric decay during tof is small, # dr_expected = F_r * tof (Newton's integration formula), where # F_r = -B rho(r) |r|^2 sqrt(k / |r|^3) = -B rho(r) sqrt(k |r|) rr, _ = cowell( Earth.k, orbit.r, orbit.v, [tof] * u.s, ad=atmospheric_drag, R=R, C_D=C_D, A=A, m=m, H0=H0, rho0=rho0, ) assert_quantity_allclose(norm(rr[0].to(u.km).value) - norm(r0), dr_expected, rtol=1e-2)
def test_altitude_crossing(): # Test decreasing altitude cross over Earth. No analytic solution. R = Earth.R.to(u.km).value orbit = Orbit.circular(Earth, 230 * u.km) t_flight = 48.209538 * u.d # Parameters of a body C_D = 2.2 # Dimensionless (any value would do) A_over_m = ((np.pi / 4.0) * (u.m**2) / (100 * u.kg)).to_value( u.km**2 / u.kg) # km^2/kg # Parameters of the atmosphere rho0 = rho0_earth.to(u.kg / u.km**3).value # kg/km^3 H0 = H0_earth.to(u.km).value # km tofs = [50] * u.d thresh_alt = 50 # km altitude_cross_event = AltitudeCrossEvent(thresh_alt, R) events = [altitude_cross_event] def f(t0, u_, k): du_kep = func_twobody(t0, u_, k) ax, ay, az = atmospheric_drag_exponential(t0, u_, k, R=R, C_D=C_D, A_over_m=A_over_m, H0=H0, rho0=rho0) du_ad = np.array([0, 0, 0, ax, ay, az]) return du_kep + du_ad rr, _ = cowell( Earth.k, orbit.r, orbit.v, tofs, events=events, f=f, ) assert_quantity_allclose(norm(rr[0].to(u.km).value) - thresh_alt, R) assert_quantity_allclose(altitude_cross_event.last_t, t_flight, rtol=1e-2)
def setup(self): from poliastro.twobody import Orbit self.R = Earth.R.to(u.km).value self.k = Earth.k.to(u.km**3 / u.s**2).value self.orbit = Orbit.circular(Earth, 250 * u.km) # parameters of a body self.C_D = 2.2 # dimentionless (any value would do) self.A_over_m = ((np.pi / 4.0) * (u.m**2) / (100 * u.kg)).to_value( u.km**2 / u.kg) # km^2/kg self.B = self.C_D * self.A_over_m # parameters of the atmosphere self.rho0 = rho0_earth.to(u.kg / u.km**3) # kg/km^3 self.H0 = H0_earth.to(u.km).value self.tof = [60.0] * u.s
def test_atmospheric_demise(): # Test an orbital decay that hits Earth. No analytic solution. R = Earth.R.to(u.km).value orbit = Orbit.circular(Earth, 230 * u.km) t_decay = 48.2179 * u.d # parameters of a body C_D = 2.2 # dimentionless (any value would do) A = ((np.pi / 4.0) * (u.m**2)).to(u.km**2).value # km^2 m = 100 # kg # parameters of the atmosphere rho0 = rho0_earth.to(u.kg / u.km**3).value # kg/km^3 H0 = H0_earth.to(u.km).value # km tofs = [365] * u.d # actually hits the ground a bit after day 48 lithobrake_event = LithobrakeEvent(R) events = [lithobrake_event] rr, _ = cowell( Earth.k, orbit.r, orbit.v, tofs, ad=atmospheric_drag, R=R, C_D=C_D, A=A, m=m, H0=H0, rho0=rho0, events=events, ) assert_quantity_allclose(norm(rr[0].to(u.km).value), R, atol=1) # below 1km # last_t is not an analytic value assert_quantity_allclose(lithobrake_event.last_t, t_decay, rtol=1e-2)
# adder = 2*np.pi * u.rad # for i in range(1,len(lons)): # if np.abs(lons[i].value-lons[i-1].value) > 1: # sgn=np.sign(lons[i].value-lons[i-1].value) # lons[i:] += -sgn*adder #interpolation of manipulated and folded points #flats = interp1d(tofs,lats) #flons = interp1d(tofs,lons) #tofs = np.linspace(0,T*3600*24*u.s,int(T*3600*24/dt)) #lats = flats(tofs) * u.rad #lons = (lons.value) % (2*np.pi) * u.rad return lons,lats rho0 = rho0_earth.to(u.kg / u.km ** 3).value H0 = H0_earth.to(u.km).value @jit def J2_and_drag(t0, state, k, J2, R, C_D, A_over_m, H0, rho0): return J2_perturbation(t0, state, k, J2, R) + atmospheric_drag_exponential( t0, state, k, R, C_D, A_over_m, H0, rho0 )
#C_D = 2.2 # dimentionless (any value would do) #Min kommentar: ändrade från den betämda luftmotståndskonstanten C_D = 2 till att testa olika värden(värdena 1.02 till 2.0) i en vektor. #Min kommentar: Dessutom lade jag till en for-loop för att programmet skulle ge mig svar för olika värden på C_D. #C_D = np.array([1.22, 1.44, 1.66 ]) C_D = np.arange( 1.50, 1.6, 0.1 ) #Min kommentar: Jag bytade från np.array till np.arange(börjar:1.5,slutar2.0,hoppar0.1) for x in C_D: A_over_m = ((np.pi / 4.0) * (u.m**2) / (100 * u.kg)).to_value( u.km**2 / u.kg ) # km^2/kg #Min kommentar: Här tror jag vi antar att föremålet väger 100kg, men jag förstår inte area-beräkningen? B = x * A_over_m #Min kommentar: Skrev in x istället för C_D # parameters of the atmosphere rho0 = rho0_earth.to(u.kg / u.km**3).value # kg/km^3 H0 = H0_earth.to( u.km ).value #Min kommentar: Ändras atmosfärens egenskaper ju högre radien är i det här programmet? #[<matplotlib.lines.Line2D at 0x7ffb5f511048>] #Orbital Decay #If atmospheric drag causes the orbit to fully decay, additional code is needed to stop the integration when the satellite reaches the surface. #Please note that you will likely want to use a more sophisticated atmosphere model than the one in atmospheric_drag for these sorts of computations. orbit = Orbit.circular( Earth, 230 * u.km, epoch=Time(0.0, format="jd", scale="tdb") ) #Min kommentar: Här tror jag att jag kan ändra på värdet hos radien på omloppsbanan tofs = TimeDelta( np.linspace(0 * u.h, 100 * u.d, num=200) ) #Min kommentar: Här tror jag deltatiden beskrivs, att den mäter mellan noll timmar till ett max antal dagar, samt att den mäter 2000 gånger.