def plot_satellite_orbit_plotly(eccentricity, orbital_period, inclination, RAAN, argument_of_perigee, number): standard_gravitational_parameter = 3.986004418e14 orbital_period = int(orbital_period * 60) semi_major_axis = calculate_semi_major_axis( orbital_period, standard_gravitational_parameter) earth_radius = 6.371009e6 semi_major_axis = semi_major_axis / earth_radius ke = pyasl.KeplerEllipse( semi_major_axis, orbital_period, e=eccentricity, Omega=RAAN, i=inclination, w=argument_of_perigee, ) t = np.linspace(0, orbital_period, 200) cis_vector = ke.xyzPos(t) ascn, descn = ke.xyzNodes_LOSZ() orbit = go.Scatter3d( x=cis_vector[:, 0], y=cis_vector[:, 1], z=cis_vector[:, 2], mode="lines", name=f"Orbit {number}", ) ascending_node = go.Scatter3d( x=[ascn[0]], y=[ascn[1]], z=[ascn[2]], mode="markers", name=f"Ascending node {number}", ) descending_node = go.Scatter3d( x=[descn[0]], y=[descn[1]], z=[descn[2]], mode="markers", name=f"Descending node {number}", ) periapsis = go.Scatter3d( x=[cis_vector[0, 0]], y=[cis_vector[0, 1]], z=[cis_vector[0, 2]], mode="markers", name=f"Periapsis {number}", ) return [orbit, ascending_node, descending_node, periapsis]
def zeroD_e(plotTitle): # Independent Variables waterDepth = 4000 # (m) albedo = c.albedo_Earth # how much light gets reflected by atmosphere epsilon = c.epsilonSurface_Earth # how good of a blackbody the body is R_star = c.R_Sun # Radius of star (AU) d_planet = c.d_Earth # Distance of planet from body it is orbiting (AU) T_star = c.T_Sun # Surface Temperature of star (K) e = float(input("Eccentricity (0.01671): ")) # Eccentricity of planet periodFractions = 1000 # number of fractions of period # Initialisation heat_capacity = waterDepth * 1000 * 4200 # (J / K m^2) period = math.pow(d_planet, 1.5) # Period of planet's orbit (years) Power_output = PowerOut(T_star) # Power output of star (Watts/m^2) solar_Constant = planetInsolation(Power_output, R_star, d_planet) t = [0] T = [0] ke = pyasl.KeplerEllipse(d_planet, period, e, Omega=0., i=0.0, w=0.0) heat_in = generate_heat_in(ke, periodFractions, d_planet, solar_Constant, albedo) # print(*heat_in, sep="\n") <- Used for debugging # Generating Surface Temperature Data heat_content = heat_capacity * T[0] # (J / m^2) periods = int(input('Number of periods (1500): ')) for i in range(periods): for j in range(periodFractions): t.append(t[-1] + (period / periodFractions)) heat_out = epsilon * PowerOut(T[-1]) heat_content += (heat_in[j] - heat_out) * (period / periodFractions) * c.SiY T.append(heat_content / heat_capacity) # (K) # Plotting data fig = plt.figure(plotTitle) plt.plot(t, T, c='r', linewidth=1.75) # Modifying Visual aspect of plot fig = beautifyPlot(fig, plotTitle, 'time (years)', 'Surface temperature (K)') fig = plotCelciusLine(fig, t[0], t[-1]) fig = addLegend(fig) return fig
def insolation_single(plotTitle, iterated, parsedE): if not iterated: e = float(input("Eccentricity: ")) else: e = parsedE # Independent Variables R_star = c.R_Sun # Radius of star (AU) d_planet = c.d_Earth # Distance of planet from body it is orbiting (AU) T_star = c.T_Sun # (K) periodFractions = 1000 # fraction of period acts as timeStep # Initialisation period = math.pow(d_planet, 1.5) solar_Constant = solarConstant(T_star, R_star, d_planet) t = [] L = [] ke = pyasl.KeplerEllipse(d_planet, period, e, Omega=0., i=0.0, w=0.0) # Generating Data for i in range(periodFractions): t.append(((i / periodFractions) * period) * 365.25) r = ke.radius((i / periodFractions) * period) # Applying Kepler's First Law to find r newL = solar_Constant / (r / d_planet) ** 2 # Calculating insolation based on position in orbit relative to the starting point L.append(newL) if not iterated: # Plotting data fig = plt.figure(plotTitle) plt.plot(t, L, c='r', linewidth=1.75) # Modifying Visual aspect of plot fig = beautifyPlot(fig, plotTitle + ' (e=' + str(e) + ')', 'time (days)', 'Light Insolation (W/m^2)') return fig else: return t, L
Produced for "Python for Mechanical and Aerospace Engineering" by Alex Kenan, ISBN 978-1-7360606-0-5 and 978-1-7360606-1-2. Copyright © 2020 Alexander Kenan. Some Rights Reserved. This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. See http://creativecommons.org/licenses/by-nc-sa/4.0/ for more information. """ import numpy as np from PyAstronomy import pyasl import matplotlib.pyplot as plt import matplotlib.animation as animation import mpl_toolkits.mplot3d.axes3d as p3 # Create a Keplerian elliptical orbit with # semi-major axis of 1.0 length units, # a period of 1.0 time units, eccentricity of 0.5, # longitude of ascending node of 0 degrees, an inclination # of 30 deg, and a periapsis argument of 0 deg. orbit = pyasl.KeplerEllipse(a=1.0, per=1.0, e=0.50, Omega=0.0, i=30.0, w=0.0) # Get a time axis t = np.linspace(0, 4, 200) # Calculate the orbit position at the given points # in a Cartesian coordinate system. pos = orbit.xyzPos(t) # Plot x and y coordinates of the orbit with a few different options # 2D, animated, and space ''' plt.style.use('dark_background') fig, ax = plt.subplots() l = plt.plot(pos[::,1], pos[::,0], 'k-')
def calcOrbit(): """ This is a tool to produce a Keplerian orbit in RA,Dec,RV to verify exosoft. It just computes Kepler orbit positions and velocities then rotates them into the observed values in the plane of the sky. NOTE: the accuracy of the output values is to 'one part in 10^5', due to the simple center differencing used to calculate the velocities from the positions and times. Outputs are 2 files matching formats used in exosoft DI and RV. outBaseName+'DIdata.dat' has columns: #1. JD #2. RA (x) ["] #3. RA ERROR ["] #4. Dec (y) ["] #5. Dec ERROR ["] outBaseName+'RVdata.dat' has colunns: #1. JD #6. RV of primary (or secondary) rel to CofM [m/s] #7. RV ERROR [m/s] """ quiet = False ## Important output directory and filename settings ################################################### # Computer Directory outDir='./' # Base name for output files outBaseName='syntheticdata_' ## Basic sample settings ######################## NumDataPointsOutRV = 25 #must be much less than 10000. values between 10-500 are suitable. NumDataPointsOutDI = 10 #must be much less than 10000. values between 10-500 are suitable. storePrimaryRVs = True percentError = 0.5 #error is set to a percentage of the median realizeErrors = True percentCoverage = 100.00 #percent of total orbit for data to span. Over 100% is ok if you want overlapping data. ## System settings ################## M_secondary = 1.0*(const.M_jup.value/const.M_sun.value) # [Solar masses] M_primary = 1.0 # [Solar masses] distance = 20.0 # [parsecs] #Orbital Elements TimeLastPeri =2450639.5 # [JD] e =0.048 # Eccentricity [unitless] period = 11.9 # [years] Omega =100.6*np.pi/180# Longitude of ascending node [deg] omega = 14.8*np.pi/180 # Argument of periastron [deg] i = 45.0*np.pi/180 # Inclination [deg] km_to_arcsec = 1.0/(const.au.value/1000.0)/distance # convert km to arcsecond massratio=M_primary/M_secondary mu = const.G.cgs.value*M_primary*(const.M_sun.value*1000.0)*(1.0 + 1.0/massratio) #gravitational parameter a = (mu*(period*sec_per_year)**2/4.0/np.pi**2)**(1.0/3.0) #in cm a_km = a/1.0e5 #to km a_AU = a_km/(const.au.value/1000.0) #to AU a2 = a_km/(massratio + 1.0) a1 = a_km - a2 # Semimajor axis of the low-mass component (in km) # print input orbital elements if quiet==False: print("\n\nOrbital Elements Used:\ne = "+str(e)) print("period = "+str(period)+" Years") print("LongAN = "+str(Omega*180.0/np.pi)+" deg") print("ArgPeri = "+str(omega*180.0/np.pi)+" deg") print("a_total = "+str(a_AU)+" AU") print("inclination = "+str(i*180.0/np.pi)+" deg") print("Time of Last Periapsis = "+str(TimeLastPeri)+" JD") print("Mass 1 = "+str(M_primary)+" Msun") print("Mass 2 = "+str(M_secondary)+" Msun") print("Mass 2 = "+str(M_secondary*(const.M_sun.value/const.M_jup.value))+" Mjupiter") print("System distance = "+str(distance)+" PC, or "+str(1.0/(distance/1000.0))+' [mas]') #settings prints if storePrimaryRVs: print("Saving RVs of primary star relative to Center of Mass\n") else: print("Saving RVs of companion relative to Center of Mass\n") print('Errors were calculated as '+str(percentError)+"% of the median value in the observables") if realizeErrors: print('Data values were realized from the errors') else: print('Data values are perfect with NO realization of the errors') print(str(NumDataPointsOutRV)+" RV, and "+str(NumDataPointsOutDI)+" DI epochs will be calculated and stored") print('The data will cover '+str(percentCoverage)+'% of the total orbit.\n') # Positions of both components in km relative to center of mass ke = pyasl.KeplerEllipse(a1, period, e=e, Omega=0.) NptsBIG = 10000 t = (np.arange(NptsBIG) - 1)/(NptsBIG - 2.)*period ## update t to cover the percent of total orbit requested. #print 'len(t) before = '+str(len(t)) t2=np.empty(( int((percentCoverage/100)*len(t)) )) if percentCoverage<=100.0: t2[0:t2.size]=t[0:t2.size] elif percentCoverage<200.0: t2[0:t.size]=t t2[t.size:]=t[0:( int(((percentCoverage-100.0)/100)*len(t)) )]+period t=t2 #print 'len(t) after = '+str(len(t)) pos_A = ke.xyzPos(t) pos_B = -pos_A/massratio # Velocities in km/s using centered differencing vel_A = (pos_A[2:] - pos_A[:-2])/(t[2] - t[0])/(86400*365.2422) pos_A = pos_A[1:-1] vel_B = (pos_B[2:] - pos_B[:-2])/(t[2] - t[0])/(86400*365.2422) pos_B = pos_B[1:-1] t = t[1:-1] # Construct rotation matrix (from wikipedia [http://en.wikipedia.org/wiki/Orbital_elements#Euler_angle_transformations]) x1 = np.cos(Omega)*np.cos(omega) - np.sin(Omega)*np.cos(i)*np.sin(omega) x2 = np.sin(Omega)*np.cos(omega) + np.cos(Omega)*np.cos(i)*np.sin(omega) x3 = np.sin(i)*np.sin(omega) y1 = -np.cos(Omega)*np.sin(omega) - np.sin(Omega)*np.cos(i)*np.cos(omega) y2 = -np.sin(Omega)*np.sin(omega) + np.cos(Omega)*np.cos(i)*np.cos(omega) y3 = np.sin(i)*np.cos(omega) z1 = np.sin(i)*np.sin(Omega) z2 = -np.sin(i)*np.cos(Omega) z3 = np.cos(i) rotmat = np.asarray([[x1, x2, x3], [y1, y2, y3], [z1, z2, z3]]) # Rotate positions, velocities pos_A = np.dot(pos_A, rotmat) vel_A = np.dot(vel_A, rotmat) pos_B = np.dot(pos_B, rotmat) vel_B = np.dot(vel_B, rotmat) ## Randomly re-sample position, vel and time arrays to requested number of samples pos_Anew = [] pos_Bnew = [] vel_Anew = [] vel_Bnew = [] tnew = [] i=0 js=[] while i<NumDataPointsOutRV: j = np.random.randint(0,len(t)) if j not in js: js.append(j) pos_Anew.append(pos_A[j]) pos_Bnew.append(pos_B[j]) vel_Anew.append(vel_A[j]) vel_Bnew.append(vel_B[j]) tnew.append(t[j]) i+=1 pos_A = np.array(pos_Anew) pos_B = np.array(pos_Bnew) vel_A = np.array(vel_Anew) vel_B = np.array(vel_Bnew) t=np.array(tnew) #make an ary for raw forms of the data. data = np.zeros((pos_A.shape[0], 8)) data[:, 0] = t*2*np.pi/period #1. phase data[:, 1] = t # 2. time (years) data[:, 2] = pos_A[:, 0]*km_to_arcsec #3. x position of secondary (arcsec) data[:, 3] = pos_A[:, 1]*km_to_arcsec #4. y position of secondary (arcsec) data[:, 4] = vel_A[:, 2] #5. radial velocity of secondary (km/s) data[:, 5] = pos_B[:, 0]*km_to_arcsec #6. x position of primary (arcsec) data[:, 6] = pos_B[:, 1]*km_to_arcsec #7. y position of primary (arcsec) data[:, 7] = vel_B[:, 2] #8. radial velocity of primary (km/s) #update raw forms to initial NewBEAT versions data2 = np.zeros((pos_A.shape[0],5)) data2[:,0] = data[:, 1]*days_per_year+TimeLastPeri #JD data2[:,1] = pos_A[:, 1]*km_to_arcsec - pos_B[:, 1]*km_to_arcsec #Ythi=Xplot=RA separation between two bodies based on primary being at 0,0 ["] data2[:,2] = pos_A[:, 0]*km_to_arcsec - pos_B[:, 0]*km_to_arcsec #Xthi=Yplot=Dec separation between two bodies based on primary being at 0,0 ["] data2[:,3] = vel_B[:, 2]*1000.0 # RV of primary compared to center of mass origin[ m/s] data2[:,4] = vel_A[:, 2]*1000.0 # RV of secondary compared to center of mass origin[ m/s] #calculate error and use it to realize the errors in the DI data if requested errorRA = np.median(np.abs(data2[:,1]))*(percentError/100.0) errorDec = np.median(np.abs(data2[:,2]))*(percentError/100.0) errorRA = np.max([errorRA,errorDec]) errorDec = np.max([errorRA,errorDec]) #print 'Using larger of two DI errors for both = '+str(errorDec) if realizeErrors: for i in range(pos_A.shape[0]): data2[i,1]+=np.random.normal(0,errorRA) data2[i,2] += np.random.normal(0,errorDec) #calculate error and use it to realize the errors in the RV data if requested errorRVprimary = np.median(np.abs(data2[:,3]))*(percentError/100.0) errorRVsecondary = np.median(np.abs(data2[:,4]))*(percentError/100.0) if realizeErrors: for i in range(pos_A.shape[0]): data2[i,3] += np.random.normal(0,errorRVprimary) data2[i,4] += np.random.normal(0,errorRVsecondary) ######################################################### #load up data for into arys for exosoft DI, exosoft RV. ######################################################### #dataDI2 has columns: #1. JD #2. RA (x) ["] #3. RA ERROR ["] #4. Dec (y) ["] #5. Dec ERROR ["] #dataRV has colunns: #1. JD #6. RV of primary (or secondary) rel to CofM [m/s] #7. RV ERROR [m/s] dataDI2 = np.empty((pos_A.shape[0],5)) dataDI2[:,0] = data2[:, 0]#1. JD dataDI2[:,1] = data2[:,1]#2. RA (x) ["] dataDI2[:,2] = errorRA #3. RA ERROR ["] dataDI2[:,3] = data2[:,2]#4. Dec (y) ["] dataDI2[:,4] = errorDec#5. Dec ERROR ["] dataRV = np.empty((pos_A.shape[0],3)) dataRV[:,0] = data2[:, 0]#1. JD if storePrimaryRVs: dataRV[:,1] = data2[:,3] #RV primary [m/s] dataRV[:,2] = errorRVprimary#RV primary error [m/s] else: dataRV[:,1] = data2[:,4]#RV secondary [m/s] dataRV[:,2] = errorRVsecondary#RV secondary error [m/s] if True: ## Randomly re-sample the DI data to half that of the RV to mimick the fact that there is usually more much RV data than DI data dataDI3=[] i=0 js=[] while i<NumDataPointsOutDI: j = np.random.randint(0,len(dataDI2[:,0])) if j not in js: js.append(j) dataDI3.append(dataDI2[j,:]) i+=1 dataDI3 = np.array(dataDI3) else: dataDI3 = dataDI2 #print "resulting RV data files have "+str(len(dataRV[:,0]))+" epochs" #print "resulting DI data files have "+str(len(dataDI3[:,0]))+" epochs" ##write files to disk if False: # raw all-in-one format, NOT for ExoSOFT use. np.savetxt(os.path.join(outDir,outBaseName+'.dat'), data, fmt="%.10g") if True: # 2 files for ExoSOFT use np.savetxt(os.path.join(outDir,outBaseName+'RVdata.dat'), dataRV, fmt="%.10g") np.savetxt(os.path.join(outDir,outBaseName+'DIdata.dat'), dataDI3, fmt="%.10g") if quiet==False: print('\nOutput data files written to:\n'+outDir)
def modelview(StellarRadius, limb1, limb2, PlanetRadius, PlanetImpact, MoonRadius, MoonAxis, MoonEccentricity, MoonAscendingNode, MoonLongitudePeriastron, MoonInclination, PhaseToHighlight, Quality): """Calculate the 3D model view. This is the vector version (v2)""" # Convert values from km to internal measure (stellar radius = 1) PlanetRadius = PlanetRadius / StellarRadius MoonRadius = MoonRadius / StellarRadius MoonAxis = MoonAxis / StellarRadius # Make background unicolor black or white #allwhite = plt.Circle((0, 0), 100, color=(1, 1, 1)) #allblack = plt.Circle((0, 0), 100, color=(0, 0, 0)) #plt.gcf().gca().add_artist(allwhite) # Alternatively plot a gradient map as background X = [[-1, 0], [0, 1]] plt.imshow(X, interpolation='bicubic', cmap=cm.gray, extent=(-1.1, 1.1, -1.1, 1.1), alpha=1) # Star StarQuality = Quality StarQuality = 100 for i in range(StarQuality): Impact = i / float(StarQuality) LimbDarkening = QuadraticLimbDarkening(Impact, limb1, limb2) Sun = plt.Circle((0, 0), 1 - i / float(StarQuality), color=(LimbDarkening, LimbDarkening, LimbDarkening)) # for a yellow shaded star, replace the last LimbDarkening with 0 plt.gcf().gca().add_artist(Sun) # Moon's orbit: Kepler ellipse normalized to 1x1 stellar radii Ellipse = pyasl.KeplerEllipse(MoonAxis, MoonAxis, e=MoonEccentricity, Omega=MoonAscendingNode, w=MoonLongitudePeriastron, i=MoonInclination) NumerOfSamples = 1 / float(Quality) time = np.linspace(0., MoonAxis, Quality) coordinates = np.zeros((len(time), 3), dtype=np.float) for i in xrange(len(time)): coordinates[i, ::] = Ellipse.xyzPos(time[i]) OccultedDataPoints = [] # To clip the moon ellipse "behind" the planet for i in range(Quality / 2): CurrentMoonImpact = coordinates[i, 1] CurrentHorizontalMoonPosition = coordinates[i, 0] CurrentDistanceMoonPlanet = sqrt( CurrentMoonImpact**2 + CurrentHorizontalMoonPosition**2) * StellarRadius if CurrentDistanceMoonPlanet < PlanetRadius * StellarRadius: OccultedDataPoints.append(i) if len(OccultedDataPoints) > 0: FirstOcculted = OccultedDataPoints[0] LastOcculted = OccultedDataPoints[-1] + 1 plt.plot(-coordinates[:FirstOcculted, 0], coordinates[:FirstOcculted, 1] + PlanetImpact, 'k', zorder=5) plt.plot(-coordinates[LastOcculted:, 0], coordinates[LastOcculted:, 1] + PlanetImpact, 'k', zorder=5) else: plt.plot(-coordinates[::, 0], coordinates[::, 1] + PlanetImpact, 'k', zorder=5) # Planet PlanetCircle = plt.Circle((0, PlanetImpact), PlanetRadius, color='k', zorder=4) plt.gcf().gca().add_artist(PlanetCircle) # Moon PosPhase = PhaseToHighlight / float(NumerOfSamples) coordinates[1, ::] = Ellipse.xyzPos(time[PosPhase]) if PhaseToHighlight < 0.5: CurrentOrder = 2 # behind the planet else: CurrentOrder = 4 # in front of the planet MoonCircle = plt.Circle( (-coordinates[1, 0], coordinates[1, 1] + PlanetImpact), MoonRadius, color='k', zorder=CurrentOrder) plt.gcf().gca().add_artist(MoonCircle) # Square not functional? plt.axis([-1.1, +1.1, -1.1, +1.1], set_aspect='equal', fontsize=16) return plt
def riverwithoutnoise(StellarRadius, limb1, limb2, PlanetRadius, PlanetAxis, PlanetImpact, PlanetPeriod, MoonRadius, MoonAxis, MoonEccentricity, MoonAscendingNode, MoonLongitudePeriastron, MoonInclination, ShowPlanetMoonEclipses, Quality, NumberOfSamples): """Core function projecting Kepler Moon Ellipse onto PixelGrid""" # Moon's orbit: Kepler ellipse normalized to 1x1 stellar radii NormalizedMoonAxis = MoonAxis / StellarRadius NormalizedMoonRadius = MoonRadius / StellarRadius CounterFullEclipses = 0 CounterPartialEclipses = 0 CurrentEclipsedRatio = 0 Ellipse = pyasl.KeplerEllipse(NormalizedMoonAxis, NormalizedMoonAxis, e=MoonEccentricity, Omega=MoonAscendingNode, w=MoonLongitudePeriastron, i=MoonInclination) time = np.linspace(0., NormalizedMoonAxis, NumberOfSamples) coordinates = np.zeros((len(time), 3), dtype=np.float) for i in xrange(len(time)): coordinates[i, ::] = Ellipse.xyzPos(time[i]) StretchSpace = 5 # 5 Grid size [multiples of planet transit duration] UnStretchedTransitDuration = PlanetPeriod / pi * arcsin( sqrt((MoonRadius + StellarRadius)**2) / PlanetAxis) cache = np.zeros((NumberOfSamples, Quality), dtype=np.float) output = np.zeros((NumberOfSamples, StretchSpace * Quality), dtype=np.float) ma = forTrans.MandelAgolLC() # Prepare light curves ma["T0"] = 0 ma["b"] = 0. ma["linLimb"] = limb1 ma["quadLimb"] = limb2 ma["per"] = PlanetPeriod ma["a"] = PlanetAxis / StellarRadius ma["p"] = MoonRadius / StellarRadius time = np.linspace(ma["per"] - (0.5 * UnStretchedTransitDuration), ma["per"] + (0.5 * UnStretchedTransitDuration), Quality) for i in range(NumberOfSamples): # Fetch curves: The core of this function CurrentMoonImpact = coordinates[i, 1] # Position-dependent moon impact CurrentHorizontalMoonPosition = coordinates[i, 0] ma["i"] = ImpactToInclination(CurrentMoonImpact + PlanetImpact, StellarRadius, PlanetAxis) cache[i, ::] = ma.evaluate(time) # Fetch each curve # Mutual eclipses: calculate distance moon --> planet [km] if ShowPlanetMoonEclipses: CurrentDistanceMoonPlanet = sqrt( CurrentMoonImpact**2 + CurrentHorizontalMoonPosition**2) * StellarRadius CurrentEclipsedRatio = EclipsedRatio(CurrentDistanceMoonPlanet, PlanetRadius, MoonRadius) for k in range(Quality): # Transform flux from e.g. 0.995 to -5ppm cache[i, k] = -(1 - cache[i, k]) * 10**6 # And reduce the flux according to the eclipsed area if ShowPlanetMoonEclipses and cache[i, k] < 0: cache[i, k] = -(1 - cache[i, k]) * (1 - CurrentEclipsedRatio) for i in range(NumberOfSamples): # Apply time shift due to moon orbit for k in range(Quality): HorizontalPixelPosition = (coordinates[i, 0] * Quality) / 2 MidShift = (0.5 * StretchSpace - 0.5) * Quality output[i, k + HorizontalPixelPosition + MidShift] = cache[i, k] return output
def __init__(self, planes=1, nodes_per_plane=4, inclination=0, semi_major_axis=6372000, ecc=0.0, minCommunicationsAltitude=100000, minSatElevation=40, linkingMethod='SPARSE', arcOfAscendingNodes=360.0): """ Parameters ---------- planes : int the number of planes in the constillation nodes_per_plane : int the number of satellites per plane inclination : float the inclination of all planes in constillation semi_major_axis : float semi major axis of the orbits (radius, if orbits circular) ecc : float the eccentricity of the orbits; range = 0.0 - 1.0 minCommunicationsAltitude : int32 The minimum altitude that inter satellite links must pass above the Earth's surface. minSatElevation : int The minimum angle of elevation in degrees above the horizon a satellite needs to have for a ground station to communicate with it. linkingMethod : string The current linking method used by the constillation currently only used for generating GML files. arcOfAscendingNodes : float The angle of arc (in degrees) that the ascending nodes of all the orbital planes is evenly spaced along. Ex, seting this to 180 results in a Pi constellation like Iridium """ self.number_of_planes = planes self.nodes_per_plane = nodes_per_plane self.total_sats = planes * nodes_per_plane self.ground_node_counter = 0 self.inclination = inclination self.semi_major_axis = semi_major_axis self.period = self.calculateOrbitPeriod( semi_major_axis=self.semi_major_axis) self.eccentricity = ecc self.current_time = 0 self.number_of_isl_links = 0 self.number_of_gnd_links = 0 self.total_links = 0 self.link_array_size = LINK_ARRAY_SIZE self.min_communications_altitude = 100000 self.min_sat_elevation = 40 self.linking_method = 'SPARSE' self.G = None # this is not written to zero, because it has it's own init # function a a few lines down: initSatelliteArray() self.satellites_array = np.empty(self.total_sats, dtype=SATELLITE_DTYPE) # declare an empty ground self.groundpoints_array = np.zeros(NUM_GROUND_POINTS, dtype=GROUNDPOINT_DTYPE) # declare an empty link array self.link_array = np.zeros(self.link_array_size, dtype=LINK_DTYPE) # figure out how many degrees to space right ascending nodes of the planes self.raan_offsets = [(arcOfAscendingNodes / self.number_of_planes) * i for i in range(0, self.number_of_planes)] # generate a list with a kepler ellipse solver object for each plane self.plane_solvers = [] for raan in self.raan_offsets: self.plane_solvers.append( pyasl.KeplerEllipse( per=self.period, # how long the orbit takes in seconds a=self. semi_major_axis, # if circular orbit, this is same as radius e=self. eccentricity, # generally close to 0 for leo constillations Omega=raan, # right ascention of the ascending node w=0.0, # initial time offset / mean anamoly i=self.inclination)) # orbit inclination # figure out the time offsets for nodes withen a plane self.time_offsets = [(self.period / nodes_per_plane) * i for i in range(0, nodes_per_plane)] # initialize the satellite array self.initSatelliteArray()
def zeroD_e_mmm(plotTitle): # Independent Variables waterDepth = 4000 # (m) albedo = c.albedo_Earth # how much light gets reflected by atmosphere epsilon = c.epsilonSurface_Earth # how good of a blackbody the body is R_star = c.R_Sun # Radius of star (AU) d_planet = c.d_Earth # Distance of planet from body it is orbiting (AU) T_star = c.T_Sun # Surface Temperature of star (K) periodFractions = 365 # number of fractions of period # Global Initialisation heat_capacity = waterDepth * 1000 * 4200 # (J / K m^2) period = math.pow(d_planet, 1.5) # Period of planet's orbit (years) Power_Output = PowerOut(T_star) # incidentPower from star (W) solar_Constant = planetInsolation(Power_Output, R_star, d_planet) # Insolation incident on the planet's surface (W/m^2) eccentricities = generateList(0, 1, 0.01) minTemps = [] meanTemps = [] maxTemps = [] for e in eccentricities: # Iterating through each eccentricity from 0.01 to 0.99 # Initialisation T = [0] heat_content = heat_capacity * T[0] # (J / m^2) periods = 1000 tempMin = 1E24 ke = pyasl.KeplerEllipse(d_planet, period, e, Omega=0., i=0.0, w=0.0) heat_in = generate_heat_in(ke, periodFractions, d_planet, solar_Constant, albedo) tempMean = 0 countMean = 0 for k in range(periods): for i in range(periodFractions): heat_out = epsilon * PowerOut(T[-1]) heat_content += (heat_in[i] - heat_out) * (period / periodFractions * c.SiY) T.append(heat_content / heat_capacity) # (K) if periods - k < 20: # Only keeps track of minimum temperatures for the last 20 periods in EBM if T[-1] < tempMin: tempMin = T[-1] # keeping track of the minimum temperature tempMean += T[-1] countMean += 1 minTemps.append(tempMin) maxTemps.append(max(T)) meanTemps.append(tempMean / countMean) print(str(round(e, 2))) # Plotting data fig = plt.figure(plotTitle) plt.plot(eccentricities, minTemps, c='r', linewidth=0.75, label='Minimum') plt.plot(eccentricities, meanTemps, c='g', linewidth=0.75, label="Mean") plt.plot(eccentricities, maxTemps, c='b', linewidth=0.75, label='Maximum') # Modifying Visual aspect of plot fig = beautifyPlot(fig, plotTitle, 'Eccentricity', 'Surface temperature (K)') fig = plotCelciusLine(fig, min(eccentricities), max(eccentricities)) fig = addLegend(fig, 'upper left', 'Plots: ') return fig
def orbit(): # Instantiate a Keplerian elliptical orbit with # semi-major axis of __ length units, # a period of __ time units, eccentricity of __, # longitude of ascending node of __ degrees, an inclination # of __ deg, and a periapsis argument of __ deg. ke = pyasl.KeplerEllipse(1.3, 10., e=0.9, Omega=70., i=10.0, w=110.0) # Get a time axis t = np.linspace(0, 20, 100) # Calculate the orbit position at the given points # in a Cartesian coordinate system. pos = ke.xyzPos(t) #print("Shape of output array: ", pos.shape) # x, y, and z coordinates for 50th time point #print("x, y, z for 50th point: ", pos[50, ::]) # Calculate orbit radius radius = ke.radius(t) # Calculate velocity on orbit vel = ke.xyzVel(t) # Find the nodes of the orbit (Observer at -z) ascn, descn = ke.xyzNodes_LOSZ() velocity = np.zeros(vel.shape[0]) for i in range(vel.shape[0]): velocity[i] = velocity[i] + (vel[i][0]**2 + vel[i][1]**2 + vel[i][2]**2)**(0.5) print(velocity.size) vmin = velocity.min() vmax = velocity.max() #Freq Shift smax = 480 smin = 240 if (vmax - vmin < 0.001): sh = 0 else: sh = (smax - smin) / (vmax - vmin) for i in range(velocity.shape[0]): velocity[i] = (velocity[i] - vmin) * sh + smin s = np.zeros(1) for i in range(velocity.size): if (velocity[i] < 270): f = 240 elif (velocity[i] < 300): f = 270 elif (velocity[i] < 320): f = 300 elif (velocity[i] < 360): f = 320 elif (velocity[i] < 400): f = 360 elif (velocity[i] < 450): f = 400 else: f = 450 #print(f) x = np.zeros(480) #x[f]=20/radius[i] x[f] = np.exp(-1 * radius[i]) * 100 y = np.fft.irfft(x) s = np.concatenate((s, y), axis=0) print(s.size) write_wavfile("e=0.9_exp.wav", 4096, s)
def zeroD_e_bar(plotTitle): # Independent Variables waterDepth = 4000 # (m) albedo = c.albedo_Earth # how much light gets reflected by atmosphere (0-1) epsilon = c.epsilonSurface_Earth # how good of a blackbody the body is (0-1) R_star = c.R_Sun # Radius of star (AU) d_planet = c.d_Earth # Distance of planet from body it is orbiting (AU) T_star = c.T_Sun # Surface Temperature of star (K) periodFractions = 365 # number of fractions of period # Global Initialisation heat_capacity = waterDepth * 1000 * 4200 # (J / K m^2) period = math.pow(d_planet, 1.5) # Period of planet's orbit (years) Power_Output = PowerOut( T_star) # Power irradiated from the star's surface (W/m^2) solar_Constant = planetInsolation( Power_Output, R_star, d_planet) # Insolation incident on the planet's surface (W/m^2) eccentricities = generateList( 0, 1, 0.01) # List containing all the eccentricities being plotted minTemps = [] maxTemps = [] for e in eccentricities: # Iterating through each eccentricity from 0.01 to 0.99 # Initialisation T = [0] heat_content = heat_capacity * T[0] # (J / m^2) periods = 1000 tempMin = 1E24 ke = pyasl.KeplerEllipse(d_planet, period, e, Omega=0., i=0.0, w=0.0) heat_in = generate_heat_in(ke, periodFractions, d_planet, solar_Constant, albedo) for k in range(periods): for i in range(periodFractions): heat_out = epsilon * PowerOut(T[-1]) heat_content += (heat_in[i] - heat_out) * (period / periodFractions * c.SiY) T.append(heat_content / heat_capacity) # (K) if periods - k < 20: # Only keeps track of minimum temperatures for the last 20 periods in EBM if T[-1] < tempMin: tempMin = T[ -1] # Keeping track of the minimum temperature print(str(round(e, 2))) minTemps.append(tempMin) maxTemps.append(max(T)) # Plotting data fig = plt.figure(plotTitle) for i in range(len(eccentricities)): # Height minimum minBarHeight = 2 height = round(maxTemps[i] - minTemps[i], 3) if height < minBarHeight: height = minBarHeight barWidth = 0.006 # Set to 0.006 for default or 0.01 for connected bars plt.bar(round(eccentricities[i], 2), height, width=barWidth, bottom=round(minTemps[i], 3), align='center', color='r') # Modifying Visual aspect of plot fig = beautifyPlot(fig, plotTitle, 'Eccentricity', 'Surface temperature (K)') fig = plotCelciusLine(fig, min(eccentricities), max(eccentricities)) fig = addLegend(fig, 'upper left', 'Plots: ') return fig