multiple arrays plot from for loop - python

I am new here (newbie) so the question is maybe obvious.
I have coded a membrane shape.
Now I variate the initial angle from 0 to 180 degrees with a interval (1 degrees) and plot the membranes on the same plot with the nested loop.
However if i plot the membranes with various initial angle with the first loop, the membrane shows a different shape than with the nested loop. The first loop shows the correct form and the nested loop does something I dont want.
I can't figure out in the code how this come.
import numpy as np
import matplotlib.pyplot as plt
import math
rho = 1000
g = 9.81
H_up = 5.15 # H - 2.7 # H = 7.85 #Water depth
H_down = 2.15 # D - 2.7 # D = 4.85
h_d = 5.3
p = h_d * rho * g
T = h_d/2 * p
alfa = h_d / (H_up-H_down)
T = 1/2 * alfa * rho * g * h_d**2
phi_0 = math.acos(rho * g / 2 * (H_up ** 2 - H_down ** 2) / T - 1)
def geometry(p, phi):
rho = 1000
g = 9.81
H_up = 5.15 # H - 2.7
H_down = 2.15 # D - 2.7
h_d = 5.3 # [m] gate height
alfa = h_d / (H_up-H_down)#1.5 # 1*10**10
T = 1/2 * alfa * rho * g * h_d**2 #50000 # [N/m] 1/2 * rho * g * (H - D)**2 / (1 + np.cos(phi1)) # h_d/2 * h_d * rho * g
t = 1.6 * 10 ** -2 # [m] thickness sheet
sigma = T / t #[N/m^2]
E = 3800 * 10**3 /t #3200 / t * 10 ** 3 # [N/m**2] 900*10**6
epsilon = sigma / E
f = (1 + epsilon)
dphi = - f * p / T
dx = f * np.cos(phi)
dy = f * np.sin(phi)
return (dphi, dx, dy)
steps = 100
dS = 30./steps
phi = np.zeros(steps)
x = np.zeros(steps)
y = np.zeros(steps)
p = np.zeros(steps)
case = 1
for i in range (len(y)-1):
phi[0] = phi_0 #geometry(p[i-1], phi[i])[3]
phi[i] = phi[i-1] + geometry(p[i-1], 0)[0] * dS
x[i] = x[i - 1] + geometry(p[i-1], phi[i])[1] * dS
x[i+1] = x[i]
y[i] = y[i - 1] + geometry(p[i-1], phi[i])[2] * dS
y[i+1] = y[i]
if y[i] > H_up and case == 1:
case = 2
if y[i] < H_down and case == 2:
case = 3
if y[i] < 0 and case == 3:
break
if case == 1:
p[i] = (H_up - (H_up - y[i])) * rho * g
if case == 2:
p[i] = H_up * rho * g
if case == 3:
p[i] = (H_down - y[i]) * rho * g
plt.plot(x,y)
plt.xlabel('x [m]')
plt.ylabel('y [m]')
plt.show()
phi1 = np.linspace(0, np.pi, 180)
phi = np.zeros(steps)
x = np.zeros(steps)
y = np.zeros(steps)
p = np.zeros(steps)
case = 1
for j in range (len(phi1)):
phi2 = phi1[j]
for i in range (len(y)-1):
phi[0] = phi2 #geometry(p[i-1], phi[i])[3]
phi[i] = phi[i-1] + geometry(p[i-1], phi[i])[0] * dS
x[i] = x[i - 1] + geometry(p[i-1], phi[i])[1] * dS
y[i] = y[i - 1] + geometry(p[i-1], phi[i])[2] * dS
if y[i - 1] > H_up and case == 1:
case = 2
if y[i - 1] < H_down and case == 2:
case = 3
if y[i - 1] < 0 and case == 3 and max(y) > 10:
plt.plot(x, y)
phi = np.zeros(steps)
x = np.zeros(steps)
y = np.zeros(steps)
p = np.zeros(steps)
break
if case == 1:
p[i] = (H_up - (H_up - y[i])) * rho * g
if case == 2:
p[i] = H_up * rho * g # upstream waterlevel - bottom # 40000 # [N/m^2]
if case == 3:
p[i] = (H_down - y[i]) * rho * g
plt.show()

Related

Calculate eccentricity vector of planetary ring particles

I wish to set-up an initially circular (e=0) system of planetary rings which I can later perturb over time and see how the eccentricity changes. However, my calculation of the eccentricity vector returns -1 as the value of my initial ring, rather than zero.
The eccentricity vector equation takes this form
import numpy as np
import matplotlib.pyplot as plt
G = 6.674e-20 # km^3 kg^-1 s^-2
day = 60.0 * 60.0 * 24.0
dt = day / 10.0
Mass = 5.683e26
N = 30000
delta = np.random.random(1) * 2.0 * np.pi / N
angles = np.linspace(0.0, 2.0 * np.pi, N) + delta
radius = np.random.uniform(low = 1e6, high = 2e6, size = (N)) # ring radius
xrings, yrings = radius * np.cos(angles), radius * np.sin(angles) # positions
vxrings, vyrings = np.sqrt((G * Mass) / radius) * -np.sin(angles), np.sqrt((G * Mass) / radius) * np.cos(angles) # velocities
dist = np.hypot(xrings, yrings) # distance between particles
# update positions
xrings += (vxrings * dt)
yrings += (vyrings * dt)
#update velocities
vxrings -= (G * Mass * xrings / (dist ** 3.0 + 1.0e6) * dt)
vyrings -= (G * Mass * yrings / (dist ** 3.0 + 1.0e6) * dt)
v = np.hypot(vxrings, vyrings)
mu = G*Mass
e = (((abs(v)**2) / mu) - (1/abs(dist)))*radius - (((radius*v) / mu)*v)
plt.plot(e, radius)
plt.show()
I have tried interchanging dist and radius in various ways within the equation as I know the radius needs to be with respect to the central mass, but to no avail.
I think the problem is arising due to the fact that it is a vector equation and when you have implemented it, you've used the magnitudes of radius and velocity when you should have used their vectors.
Implementing either equation from the wiki (with the vectors for r and v) gives the expected result of e being 0 when dt is 0:
import numpy as np
import matplotlib.pyplot as plt
G = 6.674e-20 # km^3 kg^-1 s^-2
day = 60.0 * 60.0 * 24.0
dt = day / 10.0
Mass = 5.683e26
mu = G*Mass
dt = 0
N = 30000
delta = np.random.random(1) * 2.0 * np.pi / N
angles = np.linspace(0.0, 2.0 * np.pi, N) + delta
radius = np.random.uniform(low = 1e6, high = 2e6, size = (N)) # ring radius
xrings, yrings = radius * np.cos(angles), radius * np.sin(angles) # positions
vxrings, vyrings = np.sqrt((G * Mass) / radius) * -np.sin(angles), np.sqrt((G * Mass) / radius) * np.cos(angles) # velocities
dist = np.hypot(xrings, yrings) # distance between particles
# update positions
xrings += (vxrings * dt)
yrings += (vyrings * dt)
# #update velocities
vxrings -= (G * Mass * xrings / (dist ** 3.0 + 1.0e6) * dt)
vyrings -= (G * Mass * yrings / (dist ** 3.0 + 1.0e6) * dt)
# Convert to array of vectors assuming there is no motion out of the plane
r_vector = np.array([[i, j, 0 ] for i, j in zip(xrings, yrings)])
v_vector = np.array([[i, j, 0] for i, j in zip(vxrings, vyrings)])
# Implement the equation as given in the wiki page
# Cross product method
h = [np.cross(i, j) for i, j in zip(r_vector, v_vector)] # r cross v
v_h = [np.cross(i, j)/mu for i, j in zip(v_vector, h)] # v cross h over mu
r_normalised = [i/np.linalg.norm(i) for i in r_vector]
e_vector_cross = [i-j for i,j in zip(v_h, r_normalised)]
absolute_e_cross = [np.linalg.norm(i) for i in e_vector_cross]
plt.figure()
plt.title('Cross product method')
plt.xlabel('Eccentricity')
plt.ylabel('Radius')
plt.plot(absolute_e_cross, radius)
# Dot product method
first_factor = [np.linalg.norm(i)**2/mu -1/np.linalg.norm(j) for i, j in zip(v_vector, r_vector)]
first = [i*j for i, j in zip(first_factor, r_vector)]
second_factor = [np.dot(i, j)/mu for i, j in zip(r_vector, v_vector)]
second = [i*j for i, j in zip(second_factor, v_vector)]
e_vector_dot = [i-j for i, j in zip(first, second)]
absolute_e_dot = [np.linalg.norm(i) for i in e_vector_dot]
plt.figure()
plt.title('Dot product method')
plt.xlabel('Eccentricity')
plt.ylabel('Radius')
plt.plot(absolute_e_dot, radius)
Output:

I want to have the pendulum blob in my double pendulum

In this code I want to have animation something like this. But I dont want the other pendulums that come into picture later. Just the initial one. Currently this is my output. This is the image after the animation completes. In the animation, I want to have a ball(blob) which plots the red lines and another one which plots the green lines.
import numpy as np
from numpy import cos, sin, arange, pi
import matplotlib.pyplot as plt
import matplotlib.animation as animation
h = 0.0002 #the change in runge kutta
figsize = 6
dpi = 1000
N = 200000 # iterations
L1=1 #length 1
L2=1.5 #lenth 2
m1=50 #mass of bob 1
m2=1 #mass of bob2
g = 9.81#gravity
theta_01 = (np.pi/180)*90
theta_02 = (np.pi/180)*60
w_1 = 0
w_2 = 0
# dw/dt function oft theta 1
def funcdwdt1(theta1,theta2,w1,w2):
cos12 = cos(theta1 - theta2)#for wrirting the main equation in less complex manner
sin12 = sin(theta1 - theta2)
sin1 = sin(theta1)
sin2 = sin(theta2)
denom = cos12**2*m2 - m1 - m2
ans = ( L1*m2*cos12*sin12*w1**2 + L2*m2*sin12*w2**2
- m2*g*cos12*sin2 + (m1 + m2)*g*sin1)/(L1*denom)
return ans
# dw/dt function oft thetas 2
def funcdwdt2(theta2,theta1,w1,w2):
cos12 = cos(theta1 - theta2)
sin12 = sin(theta1 - theta2)
sin1 = sin(theta1)
sin2 = sin(theta2)
denom = cos12**2*m2 - m1 - m2
ans2 = -( L2*m2*cos12*sin12*w2**2 + L1*(m1 + m2)*sin12*w1**2
+ (m1 + m2)*g*sin1*cos12 - (m1 + m2)*g*sin2 )/(L2*denom)
return ans2
# d0/dt function for theta 1
def funcd0dt1(w0):
return w0
# d0/dt function for theta 2
def funcd0dt2(w0):
return w0
X1= []
X2= []
Y1= []
Y2= []
def func(w1,w2, theta1,theta2):
for i in range(N):
k1a = h * funcd0dt1(w1) # gives theta1
k1b = h * funcdwdt1(theta1,theta2,w1,w2) # gives omega1
k1c = h * funcd0dt2(w2) # gives theta2
k1d = h * funcdwdt2(theta2,theta1,w1,w2) # gives omega2
k2a = h * funcd0dt1(w1 + (0.5 * k1b))
k2b = h * funcdwdt1(theta1 + (0.5 * k1a),theta2,w1,w2)
k2c = h * funcd0dt2(w2 + (0.5 * k1d))
k2d = h * funcdwdt2(theta2 + (0.5 * k1c),theta1,w1,w2)
k3a = h * funcd0dt1(w1 + (0.5 * k2b))
k3b = h * funcdwdt1(theta1 + (0.5 * k2a),theta2,w1,w2)
k3c = h * funcd0dt2(w2 + (0.5 * k2d))
k3d = h * funcdwdt2(theta2 + (0.5 * k2c),theta1,w1,w2)
k4a = h * funcd0dt1(w1 + k3b)
k4b = h * funcdwdt1(theta1 + k3a,theta2,w1,w2)
k4c = h * funcd0dt2(w2 + k3d)
k4d = h * funcdwdt2(theta2 + k3c,theta1,w1,w2)
#addidng the vakue aftyer the iterartions
theta1 += 1 / 6 * (k1a + 2 * k2a + 2 * k3a + k4a)
w1 +=1 / 6 * (k1b + 2 * k2b + 2 * k3b + k4b)
theta2 += + 1 / 6 * (k1c + 2 * k2c + 2 * k3c + k4c)
w2 += 1 / 6 * (k1d + 2 * k2d + 2 * k3d + k4d)
x1 = L1 * sin(theta1)
y1 = -L1 * cos(theta1)
x2 = x1 + L2 * sin(theta2)
y2 = y1 - L2 * cos(theta2)
X1.append(x1)
X2.append(x2)
Y1.append(y1)
Y2.append(y2)
return x1,y1,x2,y2
print(func(w_1, w_2, theta_01, theta_02))
fig, ax = plt.subplots()
l1, = ax.plot([], [])
l2, = ax.plot([],[])
ax.set(xlim=(-3, 3), ylim=(-2,2))
def animate(i):
l1.set_data(X1[:i], Y2[:i])
l2.set_data(X2[:i], Y2[:i])
return l1,l2,
ani = animation.FuncAnimation(fig, animate, interval = 5, frames=len(X1))
# plt.show()
ani.save('save.mp4', writer='ffmpeg')
Just add another line
l3, = ax.plot([],[], '-ob', lw=2, ms=8)
and in the animate function set its values to
l3.set_data([0,X1[i],X2[i]], [0,Y1[i],Y2[i]])
Adapt line-width and marker-size as necessary. This should draw filled circles at the pendulum positions and the origin with lines connecting them.
You should use Y1 in the l1 data. With a total pendulum length of 2.5, the vertical limits are too small. It is sufficient to use
h = 0.005 #the change in runge kutta
N = 5000 # iterations
to get an animation with realistic speed. Or combine several RK4 steps for each frame. For minimum error you can use h=1e-3, smaller step sizes only lead to the accumulation of floating point errors dominating the method error.

Optimizing function parameters

I explain briefly what the attached program code should do. We give a number of passes before runs = 100. and we give I = 10.
For example we set the area_factor = 1. Then the function HH_model(I,area_factor) does the following:
run 100 times with this I and this area_factor and return the number of times the barrier 60 is broken -- this is checked in the if max(v[:]-v_Rest) > 60 query.
Now I want to do the following: Determine that area_factor so that the number of count matches observations as well as possible.
For example, I know from measurements
HH_model(2*I,area_factor) = 70
HH_model(I,area_factor)=50
HH_model(0.5*I,area_factor) = 30
...
how can I find the area_factor for a given I, so that the difference to the observations becomes minimal.
import matplotlib.pyplot as py
import numpy as np
import scipy.optimize as optimize
# HH parameters
v_Rest = -65 # in mV
gNa = 120 # in mS/cm^2
gK = 36 # in mS/cm^2
gL = 0.3 # in mS/cm^2
vNa = 115 # in mV
vK = -12 # in mV
vL = 10.6 # in mV
#Number of runs
runs = 30
c = 1 # in uF/cm^2
#performing bisection-procedure
ROOT = True
def HH_model(I,area_factor):
count = 0
t_end = 10 # in ms
delay = 1 # in ms
duration = 0.3 # in ms
dt = 0.01 # in ms
I = I
area_factor = area_factor
#geometry
d = 2 # diameter in um
r = d/2 # Radius in um
l = 10 # Length of the compartment in um
A = (2 * np.pi * r * l * 1e-8)*area_factor # surface [cm^2]
C = c * A # uF
for j in range(0,runs):
# Introduction of equations and channels
def alphaM(v): return 12 * ((2.5 - 0.1 * (v)) / (np.exp(2.5 - 0.1 * (v)) - 1))
def betaM(v): return 12 * (4 * np.exp(-(v) / 18))
def betaH(v): return 12 * (1 / (np.exp(3 - 0.1 * (v)) + 1))
def alphaH(v): return 12 * (0.07 * np.exp(-(v) / 20))
def alphaN(v): return 12 * ((1 - 0.1 * (v)) / (10 * (np.exp(1 - 0.1 * (v)) - 1)))
def betaN(v): return 12 * (0.125 * np.exp(-(v) / 80))
# compute the timesteps
t_steps= t_end/dt+1
# Compute the initial values
v0 = 0
m0 = alphaM(v0)/(alphaM(v0)+betaM(v0))
h0 = alphaH(v0)/(alphaH(v0)+betaH(v0))
n0 = alphaN(v0)/(alphaN(v0)+betaN(v0))
# Allocate memory for v, m, h, n
v = np.zeros((int(t_steps), 1))
m = np.zeros((int(t_steps), 1))
h = np.zeros((int(t_steps), 1))
n = np.zeros((int(t_steps), 1))
# Set Initial values
v[:, 0] = v0
m[:, 0] = m0
h[:, 0] = h0
n[:, 0] = n0
### Noise component
knoise= 0.003 #uA/(mS)^1/2
### --------- Step3: SOLVE
for i in range(0, int(t_steps)-1, 1):
# Get current states
vT = v[i]
mT = m[i]
hT = h[i]
nT = n[i]
# Stimulus current
IStim = 0
if delay / dt <= i <= (delay + duration) / dt:
IStim = I * A # in uA
else:
IStim = 0
# Compute change of m, h and n
m[i + 1] = (mT + dt * alphaM(vT)) / (1 + dt * (alphaM(vT) + betaM(vT)))
h[i + 1] = (hT + dt * alphaH(vT)) / (1 + dt * (alphaH(vT) + betaH(vT)))
n[i + 1] = (nT + dt * alphaN(vT)) / (1 + dt * (alphaN(vT) + betaN(vT)))
# Ionic currents
iNa = gNa * m[i + 1] ** 3. * h[i + 1] * (vT - vNa)
iK = gK * n[i + 1] ** 4. * (vT - vK)
iL = gL * (vT-vL)
Inoise = (np.random.normal(0, 1) * knoise * np.sqrt(gNa * A))
IIon = ((iNa + iK + iL) * A) + Inoise #
# Compute change of voltage
v[i + 1] = vT + ((-IIon + IStim) / C) * dt # in ((uA / cm ^ 2) / (uF / cm ^ 2)) * ms == mV
# adjust the voltage to the resting potential
v = v + v_Rest
# test if there was a spike
if max(v[:]-v_Rest) > 60:
count += 1
return count
Ich habe folgendes versucht:
I = 30
xdata = np.array([0.92*I,I,1.05*I])
ydata = np.array([28,100,110])
y0=np.array([1,1,1])
def g(y,xdata,ydata):
return ydata - HH_model(xdata,y)
fit = optimize.leastsq(g, y0, args=(xdata, ydata))
File "", line
126, in HH_model
v[i + 1] = vT + ((-IIon + IStim) / C) * dt
ValueError: could not broadcast input array from shape (3) into shape
(1)
how can I get around this and make the input in the correct format?
The result of your line 126 is a three dimensional array with three times the same value. This size-3 array does not fit into an element of v, which has size-1 elements as you initialized them this way.
Therefore, you could add a [0]:
v[i + 1] = (vT + ((-IIon + IStim) / C) * dt)[0]
Furthermore, I think you do not need to allocate memory. You could for example use numpy.append in line 126.

Projectile with air resistance find time when y = 0

I have to find the time when y = 0.
I have this formula
y(t) = m/k(v0sinθ + mkg)(1−e^[−k/m * t])−m/k * (gt)
I isolated the t like that
t = [m/k(v0sinθ + mkg)(1−e^[−k/m * t]) * k] / gm
I already did something similar for x=a(1− e^−x).
Right now I don't see what I'm doing wrong.
m = 0.5
k = 1
v0 = 20
theta = 25
g = 9.8
i = 1
a = ((m/k)*(v0 * np.sin(np.deg2rad(theta)) + (m/k) * g))
tolerance = 0.001
t0 = a
t1 = a * (1 - exp(- (k/m) * a)) * k / (m*g)
error = t0 - t1
while error > tolerance:
t0 = t1
t1 = a * (1 - exp(- (k/m) * t1)) * k / (m*g)
error = t0 - t1
i+=1

Integrate Over Multiple Columns in 1 List to Fill Additional List With Same Number Of Columns

I am intending to take a list of random variables and alter a previous list in each column by said random variables. However, for the purpose of my function, each variable must be used in a Gamma function as well as integrated.
x[t] = c * (1 / (2 ** (v / 2) + test[t - 1]) * (gamma((v / 2) + test[t - 1]))) * integrate.\
quad(lambda h: np.exp(-h / 2) * h ** ((v / 2) + test[t - 1] - 1), 0, np.inf)
x[ t ] is an np.zeros((x , y)) list, and test[t - 1] is an np.zeros((x - 1, y)) list
I have filled test[ ] with the appropriate random variables, but I am unable to pass them through this equation to complete the columns of row [ t ] in x
When I try to run my current code, I receive:
File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\lib\site-packages\scipy\integrate\quadpack.py", line 450, in _quad
return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)
TypeError: only size-1 arrays can be converted to Python scalars
Is there a different special function which allows me to use each column's variable to solve for my desired x[ t ]?
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import stats
import mpmath as mp
import scipy.integrate as integrate
from scipy.special import gamma
T = 1
beta = 0.5
x0 = 0.05
q = 0
mu = x0 - q
alpha = - (2 - beta) * mu
sigma0 = 0.1
sigma = (2 - beta) * sigma0
b = - ((1 - beta) / (2 * mu) * (sigma0 ** 2))
simulations = 100
M = 50
dt = T / M
def srd_sampled_nxc2():
x = np.zeros((M + 1, simulations))
x[0] = x0
test = np.zeros((M, simulations))
for t in range(1, M + 1):
v = 4 * b * alpha / sigma ** 2
c = (sigma ** 2 * (1 - np.exp(-alpha * dt))) / (4 * alpha)
nc = np.exp(-alpha * dt) / c * x[t - 1]
if v > 1:
x[t] = c * ((np.random.standard_normal(simulations) + nc ** 0.5) ** 2 + mp.nsum(
lambda i: np.random.standard_normal(simulations) ** 2, [0, v - 1]))
else:
max_array = []
nc_over_2 = [l / 2 for l in nc]
for p in range(simulations):
sump = []
poisson_start = 0
while poisson_start <= 1:
x_i = sum(-np.log(np.random.uniform(0, 1, simulations)) / nc_over_2)
sump.append(
x_i
)
poisson_start += x_i
x_n = max(sump)
max_array.append(
x_n
)
sump = []
test[t - 1] = max_array
x[t] = c * (1 / (2 ** ((v / 2) + test[t - 1])) * (gamma((v / 2) + test[t - 1]))) * integrate.\
quad(lambda h: np.exp(-h / 2) * h ** ((v / 2) + test[t - 1] - 1), 0, np.inf)
max_array = []
return x
Ultimately ended up finding a workaround which is simple to implement:
else:
max_array = []
for p in range(simulations):
k = nc[t - 1, p]
lam = k / 2
poisson_samp = 0
while poisson_samp <= 1:
x_i = -math.log(np.random.uniform(0, 1)) / lam
max_array.append(
x_i
)
poisson_samp += x_i
test[t - 1, p] = len(max_array) - 1
max_array.clear()
for f in range(simulations):
n = test[t - 1, f]
z = integrate.quad(lambda h: np.exp(-h / 2) * h ** ((v / 2) + n - 1), 0, 1)
new[t - 1, f] = z[0]
x[t] = c * (1 / (2 ** ((v / 2) + test[t - 1]) * (gamma((v / 2) + test[t - 1]))) * new[0])
The only real problem is the shrinkage of x[t] which leads to dividing by zero--just a formula problem.

Categories

Resources