def doit(): # planet data ecc_A = 0.0 # eccentricity of planet A ecc_B = 0.4 # eccecntricity of planet B a_A = 1.0 # semi-major axis of planet A a_B = 4.0**(1. / 3.) # semi-major axis of planet B # integration data nsteps_year = 365 # number of steps per year nyears = 4 # total integration time (years) s = solar_system_integrator.SolarSystem() s.add_planet(a_A, ecc_A, loc="perihelion") s.add_planet(a_B, ecc_B, loc="aphelion") sol = s.integrate(nsteps_year, nyears) # plotting for n in range(len(sol[0].x)): pylab.clf() # plot the foci pylab.scatter([0], [0], s=250, marker=(5, 1), color="k") pylab.scatter([0], [0], s=200, marker=(5, 1), color="y") # plot planet A pylab.plot(sol[0].x, sol[0].y, color="r") pylab.scatter([sol[0].x[n]], [sol[0].y[n]], s=100, color="r") # plot planet B pylab.plot(sol[1].x, sol[1].y, color="b") pylab.scatter([sol[1].x[n]], [sol[1].y[n]], s=100, color="b") pylab.axis([-2.5, 1.5, -1.8, 1.8]) pylab.axis("off") ax = pylab.gca() ax.set_aspect("equal", "datalim") f = pylab.gcf() f.set_size_inches(9.6, 7.2) pylab.text(0.05, 0.05, "time = %6.3f yr" % sol[0].t[n], transform=f.transFigure) pylab.text(0.05, 0.9, "a = %6.3f, e = %5.2f" % (a_A, ecc_A), color="r", transform=f.transFigure) pylab.text(0.05, 0.85, "a = %6.3f, e = %5.2f" % (a_B, ecc_B), color="b", transform=f.transFigure) pylab.savefig("orbit_%04d.png" % n)
def doit(): # planet data ecc_E = 0.016710 # eccentricity of planet Earth ecc_M = 0.093315 # eccecntricity of planet Mars a_E = 1.0 # semi-major axis of planet Earth a_M = 1.523679 # semi-major axis of planet Mars # integration data nsteps_year = 365 * 2 # number of steps per year nyears = 0.6 # total integration time (years) s = solar_system_integrator.SolarSystem() # Earth initialization # set the initial conditions. The initial position is perihelion #y[0] = a_E*(1.0 - ecc_E) # x #y[1] = 0.0 # y # at perihelion, all the veloicity is in the y-direction. #y[2] = 0.0 # v_x # v_y^2 = (GM/a) (1+e)/(1-e) (see C&O Eq. 2.33 for example) # This is the perihelion velocity. For a = 1, e = 0, v = 2 pi #y[3] = -math.sqrt( (G*M_sun/a_E) * (1.0 + ecc_E) / (1.0 - ecc_E)) # Mars initialization # set the initial conditions. The initial position is perihelion #y[4] = a_M*(1.0 - ecc_M) # x #y[5] = 0.0 # y # at perihelion, all the veloicity is in the y-direction. #y[6] = 0.0 # v_x # v_y^2 = (GM/a) (1+e)/(1-e) (see C&O Eq. 2.33 for example) # This is the perihelion velocity. For a = 1, e = 0, v = 2 pi #y[7] = -math.sqrt( (G*M_sun/a_M) * (1.0 + ecc_M) / (1.0 - ecc_M)) # These initial conditions were found by putting Mars and Earth # both at their perihelion, but with their velocities in the # opposite direction (i.e. we want them to go backwards). This # configuration is opposition, and is setup by using the commented # out initial conditions above. We then integrated backwards for 1/4 # year (91 steps) to get these starting coordinates (note, we reverse # the direction of the velocity to get it orbitting in the forward # direction.) # Earth x = -0.04631900088483218 y = -0.9994219951994862 vx = 6.277324691390798 vy = -0.185920887199495 vp0 = solar_system_integrator.PlanetPosVel(x, y, vx, vy) s.add_planet(a_E, ecc_E, loc="specify", pos_vel=vp0) # Mars x = 0.7856599524256417 y = -1.203323492875661 vx = 4.280834571016523 vy = 3.272064392180777 vp0 = solar_system_integrator.PlanetPosVel(x, y, vx, vy) s.add_planet(a_M, ecc_M, loc="specify", pos_vel=vp0) # integrate sol = s.integrate(nsteps_year, nyears) # some background stars N = 10 xpos = [] ypos = [] for s in range(N): xpos.append(random.uniform(3.0, 3.9)) ypos.append(random.uniform(-1.4, 1.9)) if both_sides: xpos_left = [] ypos_left = [] for s in range(N): xpos_left.append(random.uniform(-2.4, -1.4)) ypos_left.append(random.uniform(-1.4, 1.9)) # ================================================================ # plotting # ================================================================ for n in range(len(sol[0].x)): f = plt.figure() # plot the foci plt.scatter([0], [0], s=1600, marker=(20, 1), color="k") plt.scatter([0], [0], s=1500, marker=(20, 1), color="#FFFF00") # plot Earth plt.plot(sol[0].x, sol[0].y, color="b") plt.scatter([sol[0].x[n]], [sol[0].y[n]], s=100, color="b") # plot Mars plt.plot(sol[1].x, sol[1].y, color="r") plt.scatter([sol[1].x[n]], [sol[1].y[n]], s=100, color="r") # draw a line connecting Earth and Mars and extending a bit # further out slope = (sol[1].y[n] - sol[0].y[n]) / (sol[1].x[n] - sol[0].x[n]) xpt = 3.5 ypt = sol[0].y[n] + slope * (xpt - sol[0].x[n]) plt.plot([sol[0].x[n], xpt], [sol[0].y[n], ypt], "b--") # draw some random background stars for s in range(N): plt.scatter([xpos[s]], [ypos[s]], s=200, marker=(5, 1), color="c") if both_sides: xpt = -2.5 ypt = sol[0].y[n] + slope * (xpt - sol[0].x[n]) plt.plot([sol[0].x[n], xpt], [sol[0].y[n], ypt], "b--") for s in range(N): plt.scatter([xpos_left[s]], [ypos_left[s]], s=200, marker=(5, 1), color="c") plt.axis([-2.5, 4.0, -1.5, 2.0]) plt.axis("off") ax = plt.gca() ax.set_aspect("equal", "datalim") f.set_size_inches(12.8, 7.2) plt.xlabel("AU") plt.ylabel("AU") plt.text(-1.5, -1.5, "time = %6.3f yr" % sol[0].t[n]) plt.title("Retrograde Mars") plt.savefig("retrograde_%04d.png" % n) plt.close()
def sidereal_solar(): # set the semi-major axis and eccentricity a = 1.0 e = 0.0 ss = ssi.SolarSystem() ss.add_planet(a, e, loc="perihelion") # compute the period of the orbit from Kepler's law and ... P_orbital = ss.period(0) # ... set the rotation period P_rotation = 0.5 * P_orbital omega = 2 * math.pi / P_rotation # integrate nsteps_per_year = 720 num_years = 2 sol = ss.integrate(nsteps_per_year, num_years) # ================================================================ # plotting # ================================================================ for n in range(len(sol[0].t)): plt.clf() # plot the foci plt.scatter([0], [0], s=250, marker=(5, 1), color="k") plt.scatter([0], [0], s=200, marker=(5, 1), color="y") # plot the orbit plt.plot(sol[0].x, sol[0].y, color="0.5", ls="--") # plot planet theta = np.radians(np.arange(360)) r = 0.05 # exaggerate the planet's size x_surface = sol[0].x[n] + r * np.cos(theta) y_surface = sol[0].y[n] + r * np.sin(theta) plt.fill(x_surface, y_surface, "c", edgecolor="c", zorder=100) # plot a point on the planet's surface xpt = sol[0].x[n] + r * np.cos(omega * sol[0].t[n] + math.pi / 2.0) ypt = sol[0].y[n] + r * np.sin(omega * sol[0].t[n] + math.pi / 2.0) plt.scatter([xpt], [ypt], s=25, color="k", zorder=100) plt.axis([-1.2, 1.2, -1.2, 1.2]) ax = plt.gca() ax.set_aspect("equal", "datalim") plt.subplots_adjust(left=0.05, right=0.98, bottom=0.05, top=0.98) f = plt.gcf() f.set_size_inches(7.2, 7.2) plt.axis("off") plt.savefig("sidereal_solar_{:04d}.png".format(n))
def doit(): s = solar_system_integrator.SolarSystem() # set the semi-major axis and eccentricity a = 1.5874 e = 0.5 # set the initial coordinates -- perihelion s.add_planet(a, e, loc="perihelion") # compute the period of the orbit from Kepler's law and make # the timestep by 1/720th of a period P = math.sqrt(a**3) # put 720 steps per period (the input is steps per year) sol = s.integrate(720 / P, P) # set up some intervals (start time, end time) to shade. # Note, the length of the intervals should be the same intervals = [] intervals.append(interval(0, P / 12)) intervals.append(interval(P / 2, 7.0 * P / 12.0)) intervals.append(interval(9.5 * P / 12, 10.5 * P / 12.0)) for i in range(len(intervals)): if intervals[i].start < 0 or intervals[i].end > P: print "ERROR: interval {} not contained in a single orbit".format( i) print "interval {}, dt = {}".format( i, intervals[i].end - intervals[i].start) # plot the orbit iframe = 0 for n in range(len(sol[0].x)): pylab.clf() pylab.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9) ax = pylab.gca() ax.set_aspect("equal", "datalim") pylab.axis("off") # plot the foci pylab.scatter([0], [0], s=350, marker=(5, 1), color="k", zorder=10) pylab.scatter([0], [0], s=300, marker=(5, 1), color="y", zorder=10) # plot planet pylab.plot(sol[0].x, sol[0].y, color="r") pylab.scatter([sol[0].x[n]], [sol[0].y[n]], s=100, color="r", zorder=10) # shade the intervals for i in range(len(intervals)): # one vertex is the Sun x = [0] y = [0] for m in range(len(sol[0].x)): if sol[0].t[m] >= intervals[i].start and \ sol[0].t[m] <= min(intervals[i].end,sol[0].t[n]): x.append(sol[0].x[m]) y.append(sol[0].y[m]) elif (sol[0].t[m] > intervals[i].end): break pylab.fill(x, y, alpha=0.20, facecolor="b") xmin = -a * (1.0 + e) xmax = a * (1.0 - e) dx = xmax - xmin pylab.axis([xmin - 0.1 * dx, xmax + 0.1 * dx, -1.5, 1.5]) f = pylab.gcf() f.set_size_inches(9.6, 7.2) pylab.savefig("second_law_%04d.png" % n)
def orbitalenergy(): # set the semi-major axis and eccentricity a = 1.5874 * AU e = 0.4 orbit = ss.SolarSystem(GM=G * M_sun, year=year) orbit.add_planet(a, e, loc="perihelion") # compute the period of the orbit from Kepler's law and make # the timestep by 1/720th of a period P = orbit.period(0) print "period = ", P / year sol = orbit.integrate(360, P / year) # ================================================================ # plotting # ================================================================ # plot the orbit iframe = 0 # v1 for n in range(len(sol[0].t)): plt.clf() # plot the foci plt.scatter([0], [0], s=250, marker=(5, 1), color="k") plt.scatter([0], [0], s=200, marker=(5, 1), color="y") # plot planet plt.plot(sol[0].x, sol[0].y, color="r") plt.scatter([sol[0].x[n]], [sol[0].y[n]], s=100, color="r") # compute the kinetic energy / kg KE = 0.5 * (sol[0].vx[n]**2 + sol[0].vy[n]**2) # compute the potential energy / kg r = math.sqrt(sol[0].x[n]**2 + sol[0].y[n]**2) PE = -G * M_sun / r plt.axis([-4 * AU, 2 * AU, -4 * AU, 2 * AU]) f = plt.gcf() f.set_size_inches(7.2, 7.2) ax = plt.gca() ax.set_aspect("equal", "datalim") plt.title("Orbital Energy") plt.text(-3.5 * AU, -3 * AU, "KE / unit mass (J/kg): %10.5e" % (KE)) plt.text(-3.5 * AU, -3.3 * AU, "PE / unit mass (J/kg): %10.5e" % (PE)) plt.text(-3.5 * AU, -3.6 * AU, "total energy / unit mass (J/kg): %10.5e" % (PE + KE)) plt.xlabel("x [m]") plt.ylabel("y [m]") ax.xaxis.set_major_formatter(plt.ScalarFormatter(useMathText=True)) ax.yaxis.set_major_formatter(plt.ScalarFormatter(useMathText=True)) plt.savefig("orbitalenergy_%04d.png" % n)
# we work in units of AU, yr, and M_sun # in these units, G = 4 pi^2 # planet data ecc_A = 0.0 # eccentricity of planet A ecc_B = 0.4 # eccecntricity of planet B a_A = 1.0 # semi-major axis of planet A # we want the perihelion distance of planet B to be the same # as planet a r_p_A = a_A * (1.0 - ecc_A) a_B = r_p_A / (1.0 - ecc_B) ss = ssi.SolarSystem() ss.add_planet(a_A, ecc_A, loc="perihelion") ss.add_planet(a_B, ecc_B, loc="perihelion") P_B = ss.period(1) # integration data nsteps_year = 365 # number of steps per year sol = ss.integrate(nsteps_year, P_B) sol_A = sol[0] sol_B = sol[1] nsteps = len(sol_A.x)
def seasons(): # set the semi-major axis and eccentricity a = 1.0 # AU e = 0.0 s = ssi.SolarSystem() s.add_planet(a, e, loc="perihelion") P = s.period(0) nsteps_per_year = 360 num_years = 1 sol = s.integrate(nsteps_per_year, num_years) # apply a projection to account for the inclination # wrt the observer inc = 80 sol[0].y = sol[0].y * np.cos(np.radians(inc)) # ================================================================ # plotting # ================================================================ # plot the orbit for n in range(len(sol[0].t)): plt.clf() # plot the Sun at the foci plt.scatter([0], [0], s=2600, marker=(20, 1), color="k", zorder=0) plt.scatter([0], [0], s=2500, marker=(20, 1), color="#FFFF00", zorder=0) # plot the orbit plt.plot(sol[0].x, sol[0].y, color="0.5", ls="--", zorder=-50) # plot planet -- hide it with zorder if sol[0].y[n] > 0: z = -20 else: z = 20 theta = np.radians(np.arange(360)) r = 0.075 # exaggerate the planet's size x_surface = sol[0].x[n] + r * np.cos(theta) y_surface = sol[0].y[n] + r * np.sin(theta) plt.fill(x_surface, y_surface, "b", edgecolor="b", zorder=z) # axis tilt = np.radians(23.5) L = 0.1 x = [-L * np.sin(tilt), L * np.sin(tilt)] y = [-L * np.cos(tilt), L * np.cos(tilt)] plt.plot(sol[0].x[n] + x, sol[0].y[n] + y, color="k", lw=2, zorder=z) # equator y = [r * np.sin(tilt), -r * np.sin(tilt)] x = [-r * np.cos(tilt), r * np.cos(tilt)] plt.plot(sol[0].x[n] + x, sol[0].y[n] + y, color="k", lw=1, ls="--", zorder=z) plt.axis([-1.2, 1.2, -0.9, 0.9]) f = plt.gcf() f.set_size_inches(9.6, 7.2) plt.title("Seasons") plt.axis("off") ax = plt.gca() ax.set_aspect("equal", "datalim") plt.savefig("seasons_{:04d}".format(n))
def orbitalenergy(): # set the semi-major axis and eccentricity a = 0.387 e = 0.2056 ss = ssi.SolarSystem() ss.add_planet(a, e, loc="perihelion") P_orbital = ss.period(0) # set the rotation period P_rotation = (2. / 3.) * P_orbital omega = 2 * math.pi / P_rotation print "orbital period = ", P_orbital nsteps_per_year = int(360 / P_orbital) nyears = 4 * P_orbital sol = ss.integrate(nsteps_per_year, nyears) # ================================================================ # plotting # ================================================================ for n in range(len(sol[0].t)): plt.clf() # plot the foci plt.scatter([0], [0], s=1600, marker=(20, 1), color="k") plt.scatter([0], [0], s=1500, marker=(20, 1), color="#FFFF00") # plot the orbit plt.plot(sol[0].x, sol[0].y, color="0.5") # plot planet theta = np.radians(np.arange(360)) r = 0.03 # exaggerate the planet's size x_surface = sol[0].x[n] + r * np.cos(theta) y_surface = sol[0].y[n] + r * np.sin(theta) plt.fill(x_surface, y_surface, color="r", alpha=1.0, zorder=1000) # plot a point on the planet's surface xpt = sol[0].x[n] + r * np.cos(omega * sol[0].t[n] + math.pi) ypt = sol[0].y[n] + r * np.sin(omega * sol[0].t[n] + math.pi) plt.scatter([xpt], [ypt], s=25, color="k") plt.axis([-0.5, 0.5, -0.5, 0.5]) plt.axis("off") ax = plt.gca() ax.set_aspect("equal", "datalim") plt.subplots_adjust(left=0.05, right=0.98, bottom=0.05, top=0.98) f = plt.gcf() plt.text(0.5, 0.925, r"Mercury: $P_\mathrm{rotation} = (2/3) P_\mathrm{orbital}$", transform=f.transFigure, horizontalalignment="center") f.set_size_inches(7.2, 7.2) plt.savefig("mercury_rotation_{:04d}.png".format(n))
def sidereal(): # set the semi-major axis and eccentricity a = 1.0 e = 0.0 ss = ssi.SolarSystem() x = 0.0 y = -a*(1.0 + e) vx = math.sqrt((ss.GM/a)*(1.0+e)/(1.0-e)) vy = 0.0 pos = ssi.PlanetPosVel(x, y, vx, vy) ss.add_planet(a, e, loc="specify", pos_vel=pos) # compute the period of the orbit from Kepler's law P_orbital = ss.period(0) # set the rotation period -- this is the sidereal day #P_rotation = 0.99726968*day # Earth P_rotation = 0.05*P_orbital omega = 2*math.pi/P_rotation # compute the length of the solar day P_solar = P_rotation/(1.0 - P_rotation/P_orbital) print "period = ", P_orbital print "sidereal day = ", P_rotation print "solar day = ", P_solar # We will maintain two trajectories: full_orbit is the full orbit # of the planet. orbit is just a small segment carrying 2 # sidereal days # evolve for 2 sidereral days with lots of frames to get a smooth # animation tmax = 2.0*P_rotation nsteps = 1000 # fraction of a year we are doing f = tmax/P_orbital orbit = ss.integrate(nsteps/f, f) dt = orbit[0].t[1] - orbit[0].t[0] # evolve the full orbit for plotting purposes nsteps_per_year = 720.0 full_orbit = ss.integrate(nsteps_per_year, 1.0) # ================================================================ # plotting # ================================================================ # plot the orbit iframe = 0 for n in range(len(orbit[0].t)): plt.clf() # plot the foci plt.scatter([0], [0], s=1600, marker=(20,1), color="k") plt.scatter([0], [0], s=1500, marker=(20,1), color="#FFFF00") # plot the orbit plt.plot(full_orbit[0].x, full_orbit[0].y, color="0.5") # plot planet theta = np.radians(np.arange(360)) r = 0.075 # exaggerate the planet's size x_surface = orbit[0].x[n] + r*np.cos(theta) y_surface = orbit[0].y[n] + r*np.sin(theta) plt.fill(x_surface, y_surface, "b", edgecolor="b", zorder=1000) # plot a point on the planet's surface xpt = orbit[0].x[n] + 1.2*r*np.cos(omega*orbit[0].t[n]+math.pi/2.0) ypt = orbit[0].y[n] + 1.2*r*np.sin(omega*orbit[0].t[n]+math.pi/2.0) plt.scatter([xpt], [ypt], s=15, color="k") plt.axis([-1.2, 1.2, -1.2, 1.2]) f = plt.gcf() f.set_size_inches(7.2, 7.2) plt.title("Sidereal vs. Solar Day") plt.axis("off") ax = plt.gca() ax.set_aspect("equal", "datalim") plt.text(-1.0, -1.2, "Note: length of day exaggerated", fontsize=9, color="0.5") if (orbit[0].t[n] >= P_rotation - 0.5*dt and orbit[0].t[n] <= P_rotation + 0.5*dt): n_sidereal = n # special lines if (orbit[0].t[n] >= P_rotation - 0.5*dt and orbit[0].t[n] <= P_solar + 0.5*dt): plt.plot([orbit[0].x[n_sidereal], orbit[0].x[n_sidereal]], [orbit[0].y[n_sidereal], 0], linestyle=":", color="0.5") # special notes if (orbit[0].t[n] < 1.5*dt): plt.text(-1.0, -1.15, "Noon (Sun is on the meridian)") for d in range(150): plt.savefig("earth_{:04d}.png".format(iframe)) iframe += 1 elif (orbit[0].t[n] >= P_rotation - 0.5*dt and orbit[0].t[n] <= P_rotation + 0.5*dt): plt.text(-1.0, -1.15, "1 Sidereal period (Earth rotated 360 degrees)") for d in range(150): plt.savefig("earth_{:04d}.png".format(iframe)) iframe += 1 elif (orbit[0].t[n] >= P_solar - 0.5*dt and orbit[0].t[n] <= P_solar + 0.5*dt): plt.text(-1.0, -1.15, "1 Solar period (Sun is back on the meridian)") for d in range(150): plt.savefig("earth_{:04d}.png".format(iframe)) iframe += 1 plt.savefig("earth_{:04d}.png".format(iframe)) iframe += 1
def asteroids(): ss = ssi.SolarSystem() # Jupiter P_jupiter = 12 # years e = 0.0 ss.add_planet_by_period(P_jupiter, e, loc="perihelion") # an asteroid, with some eccentricity but 1/2 the period e = 0.3 ss.add_planet_by_period(0.5*P_jupiter, e, loc="perihelion") # add some background asteroids with random orbits a_min = 2.0 a_max = 3.5 n_asteroids = 50 for n in range(n_asteroids): a = random.uniform(a_min, a_max) e = random.uniform(0.0, 0.4) if n % 2 == 0: loc="perihelion" else: loc="aphelion" ss.add_planet(a, e, loc=loc, rot="random") # integrate nsteps_per_year = 45.0 sol = ss.integrate(nsteps_per_year, 2*P_jupiter) # plots iframe = 0 for n in range(len(sol[0].t)): plt.clf() # plot the Sun plt.scatter([0], [0], s=1600, marker=(20,1), color="k") plt.scatter([0], [0], s=1500, marker=(20,1), color="#FFFF00") # plot Jupiter plt.plot(sol[0].x, sol[0].y, color="k") plt.scatter([sol[0].x[n]], [sol[0].y[n]], s=500, color="k") # plot our asteroid plt.plot(sol[1].x, sol[1].y, color="r") plt.scatter([sol[1].x[n]], [sol[1].y[n]], s=50, color="r") # and the background asteroids for k in range(2, 2+n_asteroids): plt.plot(sol[k].x, sol[k].y, color="0.85", zorder=-100) plt.scatter([sol[k].x[n]], [sol[k].y[n]], s=25, color="0.5", zorder=-100) f = plt.gcf() f.set_size_inches(7.2, 7.2) plt.axis("off") ax = plt.gca() ax.set_aspect("equal", "datalim") # if jupiter is at perihelion, the pause and annotate perihelion = False if n == 0: perihelion = True elif n > 0 and n < len(sol[0].t)-1: if sol[0].y[n]*sol[0].y[n+1] < 0.0 and sol[0].x[n] > 0.0: perihelion = True if perihelion: plt.text(0.5, 0.96, "Jupiter and our asteroid are at their closest point", horizontalalignment="center", transform=f.transFigure, fontsize="large") plt.text(0.5, 0.92, "The gravitational force on the asteroid is always", horizontalalignment="center", transform=f.transFigure) plt.text(0.5, 0.89, "strongest and in the same direction here", horizontalalignment="center", transform=f.transFigure) plt.arrow(sol[1].x[n], sol[1].y[n], 1.0, 0.0, color="r", length_includes_head=True, head_width = 0.2, width=0.05, overhang=-0.1) for k in range(150): plt.savefig("asteroids_{:04d}.png".format(iframe)) iframe += 1 plt.savefig("asteroids_{:04d}.png".format(iframe)) iframe += 1