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
Related
I'm having some trouble using odeint function from scipy. I'm translating a discrete system into a continuous one, but some equation in the discrete model requires that I access the previous value of a variable that I'm currently integrating. How could I translate this behaviour?
import numpy as np
days_of_prediction = 15
N = 100
discrete_S0 = np.zeros((days_of_prediction, 1))
discrete_I0 = np.zeros((days_of_prediction, 1))
discrete_Q0 = np.zeros((days_of_prediction, 1))
discrete_H0 = np.zeros((days_of_prediction, 1))
discrete_D0 = np.zeros((days_of_prediction, 1))
discrete_S0[0] = 99
discrete_I0[0] = 1
discrete_Q0[0] = 0
discrete_H0[0] = 0
discrete_D0[0] = 0
v=0.1
alpha = 0.3
gamma = 1/21
psi = 0.2
k_h=0.1
k_q=0.1
eta_h=0.3
eta_q=0.3
for t in range(days_of_prediction - 1):
discrete_S0[t + 1] = discrete_S0[t] - v * discrete_S0[t] *
discrete_I0[t] / (N - discrete_Q0[t] - discrete_H0[t] - discrete_D0[t])
discrete_I0[t + 1] = discrete_I0[t] + v * discrete_S0[t] * discrete_I0[t] / (N - discrete_Q0[t] - discrete_H0[t] - discrete_D0[t]) - gamma * discrete_I0[t] - alpha * discrete_I0[t] - psi * discrete_I0[t]
discrete_Q0[t + 1] = discrete_Q0[t] + alpha * discrete_I0[t] - eta_q * discrete_Q0[t] - k_h *discrete_Q0[t] + k_q * discrete_H0[t]
discrete_H0[t + 1] = discrete_H0[t] + psi * discrete_I0[t] - eta_h * discrete_H0[t] + k_h * discrete_Q0[t] - k_q * discrete_H0[t] - zeta * discrete_H0[t]
discrete_R0[t + 1] = discrete_R0[t] + eta_q * discrete_Q0[t] + eta_h * discrete_H0[t]
I've posted a snippet of the code, the problem is with the denominator of the first two equations.
Thanks in advance.
In such an equation system, where the previous values of some variables are required in the evolution equation of other variables, you could define your function as follows:
import numpy as np
def fun(RHS, t):
# get initial boundary condition values
discrete_S0 = RHS[0]
discrete_I0 = RHS[1]
discrete_Q0 = RHS[2]
discrete_H0 = RHS[3]
discrete_D0 = RHS[4]
# calculte rate of respective variables
discrete_S0dt = - v * discrete_S0 * discrete_I0 / (N - discrete_Q0 - discrete_H0 - discrete_D0)
discrete_I0dt = v * discrete_S0 * discrete_I0 / (N - discrete_Q0 - discrete_H0 - discrete_D0) - gamma * discrete_I0 - alpha * discrete_I0 - psi * discrete_I0
discrete_Q0dt = alpha * discrete_I0 - eta_q * discrete_Q0 - k_h *discrete_Q0 + k_q * discrete_H0
discrete_H0dt = psi * discrete_I0 - eta_h * discrete_H0 + k_h * discrete_Q0 - k_q * discrete_H0 - zeta * discrete_H0
discrete_D0dt = eta_q * discrete_Q0 + eta_h * discrete_H0
# Left-hand side of ODE
LHS = np.zeros([5,])
LHS[0] = discrete_S0dt
LHS[1] = discrete_I0dt
LHS[2] = discrete_Q0dt
LHS[3] = discrete_H0dt
LHS[4] = discrete_D0dt
return LHS
Afterward, you can solve it (according to your boundary conditions) as follows:
from scipy.integrate import odeint
v=0.1
alpha = 0.3
gamma = 1/21
psi = 0.2
k_h=0.1
k_q=0.1
eta_h=0.3
eta_q=0.3
y0 = [99, 1, 0, 0, 0]
t = np.linspace(0,13,14)
res = odeint(fun, y0, t)
Here y0 is the initial boundary condition for all the variables defined in the function fun at t=0. That's why the variable t starts from 0.
Also, you can get the result of all the variables as follows:
print(res[:,0])
print(res[:,1])
print(res[:,2])
print(res[:,3])
print(res[:,4])
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.
I am trying to solve the differential equation using solve_ivp, but I am not getting the right solution. However, I obtained the right solution using ideint. Do I have some problems with the solve_ipv program?
ODEINT program :
# Arhenius Function
def Arhenius(a, T):
dadT = np.exp(lnA)/v * np.exp(- E / (8.3144 * T)) * c * np.abs(a) ** m * np.abs((1 - np.abs(a))) ** n
return dadT
# Initial data
pt = 100000
T0 = 273
Tf = 1500
a0 = 0.0000000001
T = np.linspace(T0, Tf, pt)
a_sol = np.zeros(pt)
dadt = np.zeros(pt)
# ODE solve
a_t = odeint(Arhenius, a0, T)
# For removing errored values and have maximum at 1
search1 = np.where(np.isclose(a_t, 1))
try:
ia_1 = search1[0][0]
a_sol[0,:] = a_t[:,0]
a_sol[0,ia_1+1:pt] = 1
except:
a_sol = a_t[:,0]
# Calculate the new derivative
dadt = np.exp(lnA) * np.exp(- E / (8.3144 * T)) * c * np.abs(a_sol) ** m * np.abs((1 - a_sol)) ** n
PROGRAM with solve_ivp :
# Arhenius Function
def Arhenius(a, T):
dadT = np.exp(lnA) * np.exp(- E / (8.3144 * T)) * c * np.abs(a) ** m * np.abs((1 - np.abs(a))) ** n
return dadT
# Initial data
pt = 100000
T0 = 273
Tf = 1500
a0 = 0.0000000001
T = np.linspace(T0, Tf, pt)
a_sol = np.zeros(pt)
dadt = np.zeros(pt)
# ODE solve
a_t = solve_ivp(Arhenius, t_span = (T0, Tf), y0 = (a0,), t_eval = T, method = 'RK45')
a_sol= a_t.y
# Calculate the new derivative
dadt = np.exp(lnA) * np.exp(- E / (8.3144 * T)) * c * np.abs(a_sol) ** m * np.abs((1 - a_sol)) ** n
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.
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()