I am completing a project on planetary motion in Python and the first task is to write a code for the orbit of earth around the sun. This is what I have so far:
def earth_orbit(rEar,v0):
#r0 = xEar[0] = rEar
#v0 = vyEar[0] = np.sqrt(mu/rEar)
#Set parameters:
N = 365 # Earth days in a year
dt = 1.00/N # Time Step: Fractions of a year - 1 Earth day (i.e. 1/365)
mu = 4*np.pi**2 # Gravitational parameter
#Create an array, for all variables, of size N with all entries equal to zero:
xEar = np.zeros((N,))
yEar = np.zeros((N,))
vxEar = np.zeros((N,))
vyEar = np.zeros((N,))
# Initial Conditions:
xEar[0] = rEar # (x0 = r, y0 = 0) in AU
vyEar[0] = v0 #units: AU/yr
#Implement Verlet Algorithm:
for k in range(0,N-1):
rEar = (xEar[k]**2+yEar[k]**2)**0.5
vxEar[k+1] = vxEar[k] - (mu*xEar[k])/((rEar)**3)*dt
xEar [k+1] = xEar[k] + vxEar[k+1]*dt
vyEar[k+1] = vyEar[k] - (mu*yEar[k])/((rEar)**3)*dt
yEar [k+1] = yEar[k] + vyEar[k+1]*dt
#Plot:
a = plt.plot(xEar, yEar, 'go', markersize = 1, label = 'Earth trajectory')
plt.plot(0,0,'yo', label = 'Sun positon') #yellow marker for the sun
plt.plot(xEar[0],0,'bo', label = 'Earth initial positon') #dark blue marker for earth's initial position
plt.axis('equal')
plt.xlabel ('x')
plt.ylabel ('y')
return a, xEar, yEar
This works well, however for subsequent parts of the project I've been told that I shouldn't use AU for this base code as it'll cause difficulties. I've tried changing the gravitational parameter and putting the inputs in standard units but the graph becomes just 2 dots (the values of xEar and vyEar remain constant) instead of a circular orbit and I don't know why this is?
Due to the definition of the gravitational constant, when you change the length unit, you have to change the value of mu by the cube of the scaling factor.
I pulled the definition of mu outside of the function for convenience.
import numpy as np
import matplotlib.pyplot as plt
def earth_orbit(rEar, v0):
#Set parameters:
N = 365 # Earth days in a year
dt = 1. / N # Time Step: Fractions of a year - 1 Earth day (i.e. 1/365)
#Create an array, for all variables, of size N with all entries equal to zero:
xEar = np.zeros((N,))
yEar = np.zeros((N,))
vxEar = np.zeros((N,))
vyEar = np.zeros((N,))
# Initial Conditions:
xEar[0] = rEar # (x0 = r, y0 = 0) in AU
vyEar[0] = v0 #units: AU/yr
#Implement Verlet Algorithm:
for k in range(0, N-1):
rEar = (xEar[k]**2+yEar[k]**2)**0.5
vxEar[k+1] = vxEar[k] - ((mu * xEar[k]) / (rEar**3)) * dt
xEar [k+1] = xEar[k] + vxEar[k+1]*dt
vyEar[k+1] = vyEar[k] - ((mu * yEar[k]) / (rEar**3)) * dt
yEar [k+1] = yEar[k] + vyEar[k+1]*dt
#Plot:
a = plt.plot(xEar, yEar, 'go', markersize = 1, label = 'Earth trajectory')
plt.plot(0,0,'yo', label = 'Sun positon') # yellow marker
plt.plot(xEar[0],0,'bo', label = 'Earth initial positon') # dark blue marker
plt.axis('equal')
plt.xlabel ('x')
plt.ylabel ('y')
return a, xEar, yEar
# average distance earth-sun (1 AU) in meter
au_to_m = 149_597_870_700.
mu = au_to_m**3 * 4 * np.pi**2 # Gravitational parameter
earth_orbit(au_to_m, np.sqrt(mu / au_to_m));
Related
I want to sum together the values of R_scat from both iterations of the while loop, and then add those products together too (i.e. add the values of R_i together) to give me one single value, but I am unsure how to do this. Here is the code:
# Libraries
import numpy as np
from scipy.integrate import odeint
# Tow counter propagating beams in x-axis
laser_x = np.linspace(0, 100, 100)
laser_negx= np.linspace(0, -100, 100)
# Constant parameters
m_Rb = 1.443*10**-25 #mass of rubidium 87
k_b = 1.38*10**-23
hbar = 1.05*10**-34
Rabi = 46.567*10**6 #Rabi frequency
L = 38.116*10**6 #spontaneous decay rate
# Changable paramaters
#delta_omega = -20*10**-6
#delta_omega = np.linspace(-20*10**6, 0, 15)
#delta_omega = np.array([-20*10**6, -15*10**6, -10*10**6, -5*10**6]) #difference in the laser frequency and the atomic resonance frequency
lmbda = 700*10**-9 #wavelength of laser light
k = (2*np.pi)/lmbda #wavevector of laser light
V = 1.25*10**-4 #volume of MOT space
length = 5*10**-2 #length of MOT
Bohr = 9.274*10**-24
B = 5*10**-4
# Maxwell Boltzmann distribution variables
T = 300
v = np.linspace(0, 10, 5)
# Number of particles emittied
T_oven = 300 #oven temperature
P = 10**(4.312-(4040/T_oven)) #vapour pressure for liquid phase (use 4.857 for solid phase)
A = 5*10**-4 #area of the oven aperture
n = P/(k_b*T_oven) #atomic number density
I_oven = ((n*A)/4) * (2/(np.pi)**0.5) * ((2*k_b*T_oven)/m_Rb)**0.5
#print("The flux of atoms from the oven is", format(I_oven, '.1E'))
# Finding the rate of capture and population for the excited and ground states to find the scattering force
i = 0
delta_omega = np.array([-20*10**6, -10*10**6])
while i<len(delta_omega):
delta = delta_omega[i] + (k*v)
R_scat = L/2 * (Rabi**2/2)/(delta**2+(Rabi**2/2)+(L**2/4))
R_i = np.sum(R_scat)
print(R_scat)
print(R_i)
i = i+1
Here are the results I get from running this code:
[11184874.83348512 14217317.42150675 9999470.28332243 5605001.76872253
3272710.81864173]
44279375.125678554
[13353256.50318438 12896933.7374322 7756401.89830628 4365821.90749169
2646088.0800265 ]
41018502.126441054
What if you will create R_sum before while loop and make it an adder for R_i?
R_sum = 0
while i<len(delta_omega):
delta = delta_omega[i] + (k*v)
R_scat = L/2 * (Rabi**2/2)/(delta**2+(Rabi**2/2)+(L**2/4))
R_i = np.sum(R_scat)
R_sum += R_i
print(R_scat)
print(R_i)
i = i+1
print(R_sum) # sum of all values from both iterations
Need help finishing the Code specifically steps 3 and 4.
Problem
Compute the temperature (K) profile throughout a cylindrical SiGe wire with thermal conductivity k = 4.2 W/(m*K), length L = 0.05 m, and radius R = 0.005 m.
The boundary conditions are given in the figure below. The solid lines correspond to zero-flux boundary conditions, the long-dashed line to open boundaries with a known temperature, and the short-dashed lines to open boundaries with known flux via convection (the listed T is the “ambient” T). In this figure, assume z (in m) varies in the horizontal direction while r (in m) varies in the vertical direction (the upper left corner is the origin).
Justify your approach. Plot the temperature distribution throughout the wire using a 2D color- map with proper labels. Include contour lines.
https://www.chegg.com/homework-help/questions-and-answers/problem-2-compute-temperature-k-profile-throughout-cylindrical-sige-wire-thermal-conductiv-q96105385
Code
# Problem 2
# Import the required modules
import numpy as np
import matplotlib.pyplot as plt
# Constants
k = 4.2 # Thermal conductivity in W/(m.K)
L = 0.05 # Length in m
R = 0.005 # Radius in m
T = 575 # Ambient temp. in K
T1 = 423 # K
h1 = 45 # kW/(m^2.K)
T2 = 348 # K
h2 = 650 # kW/(m^2.K)
Ta = 298 # K
h = 7.5 # kW/(m^2.K)
# Iteration parameters
maxit = 2000
tol = 0.0001 # Relative tolerance
merr = 1e5
lam = 1.4 # Parameter for convergence rate
# Setup grid
dr = 0.01
nr = int(R/dr) + 1
nz = int(L/dr) + 1
rr = np.linspace(0,R,num=nr,endpoint=True);
zz = np.linspace(0,L,num=nz,endpoint=True);
# Step 1 - Initial Guesses
M = np.ones((nz,nr)) # Create 2D array w/ ones (z = # of rows, r = # of col)
M = M*T # Matrix of T now
# Step 2 - Apply Boundary Conditions
M[0,0:nr] = T; M[-1,0:nr] = T1;
M[0:nz,0] = T2; M[0:nz,-1] = Ta;
# Step 3 and 4 - Apply LDE, walking over nodes
cc = 0; # Counter
a = k*dr*dr/(4*R)
while merr > tol:
Mold = np.copy(M) # Save current values to old
M[-1,-1]=(2*M[-2,-1]+2*M[-1,-2])/(4+a) # Corner
for j in range(1,nz-1):
M[j,-1]=(2*M[j,-2]+M[j-1,-1]+M[j+1,-1])/(4+a)
for i in range(1,nr-1):
M[-1,i]=(M[-1,i-1]+M[-1,i+1]+2*M[-2,i])/(4+a)
for i in range(1,70):
M[0,i]=(M[0,i-1]+M[0,i+1]+2*M[1,i])/(4+a)
for j in range(1,nz-1):
for i in range(1,nr-1):
M[j,i] = (M[j,i-1]+M[j,i+1]+M[j-1,i]+M[j+1,i])/(4+a)
M = lam*M+(1-lam)*Mold # Adjust for convergence rate
ea = np.abs((M-Mold)/Mold)
cc = cc + 1;
merr = np.max(ea)
# Plot color mesh
X, Y = np.meshgrid(rr, zz)
p = plt.pcolormesh(rr, zz, M, cmap="RdBu", shading="flat", vmin=0, vmax=100)
ct = plt.contour(X, Y, M, cmap="gray", levels=10, vmin=0, vmax=100)
c = plt.colorbar(p)
plt.xlabel("R (m)")
plt.ylabel("Z (m)")
c.set_label("Teamperature (K)")
plt.show()
# Print Results
print("Converged in %d iterations" % cc)
print("Max error is %f" % merr)
print("Mean Teamperature along central axis %f K" %(np.mean(M[:,0])))
I am attempting to create a Langevin simulation using python. Currently, I have code which updates the x and y coordinates of a single point based on the Langevin equations, and returns all of these positions in two arrays (x array and y array). I want to plot these changes in position as a moving scatter plot to show how the particle moves over time. How can I do this? Below is what I have so far:
# IMPORT STATEMENTS
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# CONSTANTS
v = 3.12e-5 # swimming speed of B. Subtilis [m/s]
M = 1 # moment of B. Subtilis
k = 1.38e-23 # Boltzmann constant [m^2kg/s^2K]
T = 293 # Room temperature [K]
eta = 0.1 # viscosity of water [Pa s]
a = 2e-6 # spherical cell radius [m]
Dr = k*T/8*np.pi*eta*a**3 # rotational diffusion coefficient of B. Subtilis
# ADJUSTABLE PARAMETERS
B = 1 # strength of the magnetic field [T]
t = 100 # time over which motion is observed [s]
dt = 1 # time step between recorded positions
N = 1000 # number of cells
#INITIAL CONDITIONS
theta_i = 0 # initial swimming orientation [radians]
xi = 0.001 # initial x position [m]
yi = 0.001 # initial y position [m]
x = []
y = []
# MAIN SCRIPT
for i in range (0,t,dt):
theta_j = (theta_i + M*B*np.sin(theta) + np.sqrt(2*Dr)*ksi)*dt
xj = (xi + v*np.cos(theta))*dt
yj = (yi + v*np.sin(theta))*dt
x.append(xj)
y.append(yj)
theta_i = theta_j
xi = xj
yi = yj
take a look at this:
https://github.com/mohammadjafariph/Brownian-Motion-Simulation
animated versions are available
I am trying to write a code for the orbit of the earth in SI using a symplectic integrator, my attempt is as follows:
import numpy as np
import matplotlib.pyplot as plt
#Set parameters
G = 6.67348e-11
mEar = 5.972e24
mSun = 1.989e30
def earth_orbit(x0, y0, vx0, vy0, N):
dt = 1/N #timestep
pos_arr = np.zeros((N,2)) #empty array to store position
vel_arr = np.zeros((N,2)) #empty array to store velocities
#Initial conditions
# x0 = x
# y0 = y
# vx0 = vx
# vy0 = vy
pos_arr[0] = (x0,y0) #set the intial positions in the array
vel_arr[0] = (vx0,vy0) #set the initial velocities in the array
#Implement Verlet Algorithm
for k in range (N-1):
pos_arr[k+1] = pos_arr[k] + vel_arr[k]*dt #update positions
force = -G * mSun * mEar * pos_arr[k+1] / (np.linalg.norm(pos_arr[k+1])**3) #force calculation
vel_arr[k+1] = vel_arr[k] + (force/mEar) * dt #update velocities
#Plot:
plt.plot(pos_arr, 'go', markersize = 1, label = 'Earth trajectory')
# plt.plot(0,0,'yo', label = 'Sun positon') # yellow marker
# plt.plot(pos_arr[0],'bo', label = 'Earth initial positon') # dark blue marker
plt.axis('equal')
plt.xlabel ('x')
plt.ylabel ('y')
return pos_arr, vel_arr
earth_orbit(149.59787e9, 0, 0, 29800, 1000)
The output is 2 dots and I can't figure out if this is a unit issue or a calculation issue?
Display the trajectory
pos_arr contains the x and y coordinates in its columns. To display the whole trajectory, plt.plot(pos_arr[:,0], pos_arr[:,1]) can thus be used. I would prefer to use plt.plot(*pos_arr.T) as a shorter alternative. The line that displays the trajectory must be replaced by:
plt.plot(*pos_arr.T, 'g', label = 'Earth trajectory')
Change the timestep
Here the timestep (in second) is chosen as 1/N, where N is the number of iterations. So, the total duration of the simulation is equal to timestep * N = 1 second ! For N=1000, you can instead try with timestep = 3600*12 (half-day), so that the total duration is a little less than 1.5 years. I suggest passing the duration as a parameter of the function earth_orbit and then setting timestep as duration / N.
def earth_orbit(x0, y0, vx0, vy0, N=1000, duration=3.15e7):
dt = duration / N
...
As said in the comments, this is not the Verlet algorithm, but the symplectic Euler algorithm. The difference is in the initialization, but in comparing against a more exact reference solution and with several step sizes, the difference in the orders, 2 vs. 1, will be quite visible.
A short change to the time loop ensuring that the velocities are at the half-time steps as required for Leapfrog Verlet could look like this:
def force(pos): return -G * mSun * mEar * pos_arr[k+1] / (np.linalg.norm(pos_arr[k+1])**3) #force calculation
pos_arr[0] = (x0,y0) #set the intial positions in the array
vel_arr[0] = (vx0,vy0) #set the initial velocities in the array
vel_arr[0] += (force(pos_arr[0])/mEar) * (0.5*dt) #correct for velocity at half-time
#Implement Verlet Algorithm
for k in range (N-1):
pos_arr[k+1] = pos_arr[k] + vel_arr[k] * dt #update positions
vel_arr[k+1] = vel_arr[k] + (force(pos_arr[k+1])/mEar) * dt #update velocities
this is my first post on here.
So I am trying to make a model solar system using visual python. I am defining each planet as a sphere, with radius, distance from sun, mass, and momentum variables. Then each planet (or body) is put into a list structure. As you can see currently I have a list with [earth, moon, mars] the sun is excluded for reason i will explain shortly.
So my problem comes when I'm trying to calculate the force caused by each body on each other body. What I am doing here is, for every ith value in the bodies list, the force between that and the nth body is calculated, the force on the ith body in the list bodies is the sum of the force between the ith body and each nth body from 0 to the end of the list. (i.e. the sum of all the forces due to every other body in the list)
This works correctly for the moon and mars (2nd and 3rd items in the list) but not for the earth. The output for the code below is,
<3.57799e+022, 0, 0>
<4.3606e+020, 0, 0>
<1.64681e+021, 0, 0>
<-1.#IND, -1.#IND, -1.#IND> - this is the total force on earth.
<0, 2.07621e+027, 0>
<0, 9.83372e+027, 0>
from visual import *
AU = 149.6e9
MU = 384.4e6 # moon - earth orbital - radius
MarU = 227.92e9
G =6.673e-11
sun_mass =2e30
sun_radius =6.96e8
earth_mass =6e24
earth_radius =6.37e6
moon_mass =7.35e22
moon_radius =1.74e6
mars_mass = 6.41e23
mars_radius = 3390000
sun = sphere ( pos =(0 , 0 ,0) , velocity = vector (0 ,0 ,0) ,mass = sun_mass , radius =0.1* AU , color = color . yellow )
earth = sphere ( pos =( AU , 0 ,0) ,mass = earth_mass , radius =63170000, color = color . cyan ,make_trail=True )# create a list of gravitating objects
moon = sphere ( pos =( AU+MU , 0 ,0) ,mass = moon_mass , radius =17380000 , color = color . white, make_trail=True )
mars = sphere ( pos =( MarU , 0 ,0) ,mass = mars_mass , radius = mars_radius , color = color . red, make_trail=True )
#initialise values:
we = 1.9578877e-7
wm = sqrt(G*earth.mass/3.38e8**3)
wma = 9.617e-5
dt = 3*60
earth.mom = vector(0,1.5e11*earth.mass*we,0)
mars.mom = vector(0, 9.833720638948e+27,0)
moon.mom = moon.mass*(earth.mom/earth.mass+vector(0,-3.48e8*wm,0))
bodies = [earth, moon, mars]
*N = 0
initialdiff = 0
for i in bodies:
initialdiff = i.pos - sun.pos
TotalForce = (G * i. mass * sun. mass * norm ( initialdiff )/ initialdiff . mag2)
print TotalForce
while N < len(bodies):
if N!=i:
diff = i.pos - bodies[N].pos
Force = (G * i. mass * bodies[N]. mass * norm ( diff )/ diff . mag2)
TotalForce = TotalForce + Force
i.mom = i.mom+TotalForce*dt
N = N+1
else:
N = N+1
print earth.mom
print moon.mom
print mars.mom*
Thanks for any help you can give.
'''Abel Tilahun HW 3 '''
# 02/03 / 2015
# make the necessary imports , visual import gives visual output, cos, sin and pi allows calculation of the positions
# in real time. The numpy arange import returns evenly spaced values within a given interval (angles)
from visual import *
from math import cos,sin,pi
from numpy import arange
# i used 'a' to magnify the sizes of the planet for better visualization
a=600
# the following line defines a sphere for the sun centered at the origin(0,0,0) all the other planets are positioned at a radial distance from this center.
Sun=sphere(pos=(0,0,0),radius=6955500*(a/100),color=color.yellow)
#the next 5 commands code the planets with their center being positioned at a distance of the radii of their orbit. Their radii are multiplied by a factor of 'a' to magnify them
Mercury=sphere(pos=vector(579e5,0,0),radius=2440*(a),color=color.red)
Venus=sphere(pos=vector(1082e5,0,0),radius=6052*a,color=color.orange)
Earth=sphere(pos=vector(1496e5,0,0),radius=6371*a,color=color.green)
Mars=sphere(pos=vector(2279e5,0,0),radius=3386*a,color=color.white)
Jupiter=sphere(pos=vector(7785e5,0,0),radius=69173*(a),color=color.cyan)
Saturn=sphere(pos=[14334e5,0,0],radius=57316*(a),color=color.magenta)
# the for loop calculates position of the planets by changing
# the arange function increases the angle from 0 to pi with a small increment of 0.025 each time
for theta in arange(0,100*pi,0.025):
rate(30)
x = 579e5*cos(theta)
y = 579e5*sin(theta)
Mercury.pos = [x,y,0]
x = 1082e5*cos(theta)
y = 1082e5*sin(theta)
Venus.pos = [x,y,0]
x = 1496e5*cos(theta)
y = 1496e5*sin(theta)
Earth.pos = [x,y,0]
x = 2279e5*cos(theta)
y = 2279e5*sin(theta)
Mars.pos = [x,y,0]
x = 7785e5*cos(theta)
y = 7785e5*sin(theta)
Jupiter.pos = [x,y,0]
x = 14334e5*cos(theta)
y = 14334e5*sin(theta)
Saturn.pos = [x,y,0]