Hey guys I'm receiving an error and I'm not 100% sure why it's happening. I'm trying to perform both the eulers and heun's methods and plot them against one another. Any help or suggestions would be awesome! I'm pretty novice with python so this is a bit new to me.
import numpy
#eulers
yi = 0
h = 0.2
te = [0.0,2.0,0.2]
def euler(f, y0, t):
n = len(t)
y = numpy.array([y0] * n)
for i in range(n - 1):
y[i+1] = y[i] + (t[i+1] - t[i]) * f(y[i], t[i])
return y
fy = (y*t**3) - 1.5*y
y1 = euler(fy, yi, te)
#heun
def heun(f, y0, t):
n = len(t)
y = numpy.array( [y0] * n )
for i in range(n - 1):
h = t[i+1] - t[i]
k1 = h * f( y[i], t[i])
k2 = h * f( y[i] + k1, t[i+1])
y[i+1] = y[i] + (k1 + k2) / 2.0
return y
y2 = heun(fy, 1, te)
tp = numpy.linspace(0.0, 2.0, 0.2)
plt.plot(tp, y1,'r-',linewidth=2,label='Eulers')
plt.plot(tp, y2,'b--',linewidth=2,label='Heun')
plt.xlabel('time')
plt.ylabel('y(t)')
plt.legend()
plt.show()
This is my error code:
TypeError Traceback (most recent call last)
<ipython-input-152-395afeefc50a> in <module>()
11 return y
12 fy = (y*t**3) - 1.5*y
---> 13 y1 = euler(fy, yi, te)
14
15 #heun
<ipython-input-152-395afeefc50a> in euler(f, y0, t)
8 y = numpy.array([y0] * n)
9 for i in range(n - 1):
---> 10 y[i+1] = y[i] + (t[i+1] - t[i]) * f(y[i], t[i])
11 return y
12 fy = (y*t**3) - 1.5*y
TypeError: 'numpy.ndarray' object is not callable
My guess is that you're trying to define a function f(y,t) in the line
fy = (y*t**3) - 1.5*y
as your differential equation. However, that is not how you define a function in python.
Try
def f(y,t):
return y*t**3 - 1.5*y
You are getting an error because on line
---> 10 y[i+1] = y[i] + (t[i+1] - t[i]) * f(y[i], t[i])
f is a NumPy array, but you are treating it as a function.
Related
I have to analyse a mass with variable acceleration. The first function defines acceleration. The second return arrays for respectively place, speed and acceleration at time t. (t goes from 0-10 with increments of 0.1)
import numpy as np
import matplotlib.pyplot as plt
dt = 0.1
t0 = 0.0
t1 = 10.0
x0 = 0.0
v0 = 0.0
m = 5.0
t = np.linspace(0, 10, 101)
def versnelling(t):
return (0.7 * np.sin(3 * t)) / m
def numeriek(x0, v0, a_func, t):
x = np.zeros(len(t))
v = np.zeros(len(t))
a = np.zeros(len(t))
x[0] = x0
v[0] = v0
a[0] = a_func(t[0])
for i in range(len(t) - 1):
dt = t[i + 1] - t[i]
a[i + 1] = a0 + a_func(i)
v[i + 1] = v[i] + a[i] * dt
x[i + 1] = x[i] + v[i] * dt
return x, v, a
But when I call it:
numeriek(x0, v0, versnelling(t), t)
I get:
TypeError: 'numpy.ndarray' object is not callable
I tried just a 0 in a_function(), as well as a t
How do I fix it but most of all why does my code not work??
The parameter a_func seems to be a function, so when you call the numeriek it should be passed as versnelling and not versnelling(t) that is in fact a function invocation resulting in a value.
import numpy as np
import matplotlib.pyplot as plt
dt = 0.1
t0 = 0.0
t1 = 10.0
x0 = 0.0
v0 = 0.0
m = 5.0
t = np.linspace(0, 10, 101)
def versnelling(t):
return (0.7 * np.sin(3 * t)) / m
def numeriek(x0, v0, a_func, t):
x = np.zeros(len(t))
v = np.zeros(len(t))
a = np.zeros(len(t))
x[0] = x0
v[0] = v0
a[0] = a_func(t[0])
for i in range(len(t) - 1):
dt = t[i + 1] - t[i]
a[i + 1] = a[0] + a_func(i)
v[i + 1] = v[i] + a[i] * dt
x[i + 1] = x[i] + v[i] * dt
return x, v, a
if __name__ == "__main__":
print(numeriek(x0, v0, versnelling, t))
I am desperately trying to use the scipy ODE integrator, but I keep getting the following error :
Y[0] = (1/I3) * T_z(INP[0], INP[1], INP[2], INP[3], INP[4])
TypeError: 'float' object is not subscriptable
My code is the following :
import scipy.integrate as spi
import numpy as np
import pylab as pl
from time import time
#Constants
I3 = 0.00396
lamb = 1
L = 5*10**-1
mu = 1
m = 0.1
Cz = 0.5
rho = 1.2
S = 0.03*0.4
K_z = 1/2*rho*S*Cz
g = 9.81
#Initial conditions
omega0 = 10*2*np.pi
V0 = 25
theta0 =np.pi/2
phi0 = 0
psi0 = -np.pi/9
X0 = 0
Y0 = 0
Z0 = 1.8
#for integration
t_start = 0.0
t_end = 5
t_step = 0.1
t_range = np.arange(t_start, t_end+t_step, t_step)
INPUT = omega0, V0, theta0, phi0, psi0, X0, Y0, Z0 #initial conditions
def diff_eqs(INP,t):
def M(v_G, w_z):
return L*K_z*(v_G**2 + v_G*L*w_z*np.sin(w_z*t_step)+(L*w_z)**2)
def F_x(w_z, v_G, theta, phi, psi):
return K_z*(v_G**2+(L*w_z)**2)*np.sin(theta)*np.sin(phi) + lamb*v_G*(np.cos(psi)*np.cos(phi) - np.cos(theta)*np.sin(phi)*np.sin(psi))
def F_y(w_z, v_G, theta, phi, psi):
return -K_z*(v_G**2+(L*w_z)**2)*np.sin(theta)*np.cos(phi) + lamb*v_G*(np.cos(psi)*np.sin(phi) + np.cos(theta)*np.cos(phi)*np.sin(psi))
def F_z(w_z, v_G, theta, phi, psi):
return -K_z*(v_G**2+(L*w_z)**2)*np.cos(theta) + lamb*v_G*np.sin(theta)*np.sin(psi) - m*g
def T_x(w_z, v_G, theta, phi, psi):
return M(v_G, w_z)*(-np.sin(w_z*t_step)*(np.cos(psi)*np.cos(phi) - np.cos(theta)*np.sin(phi)*np.sin(psi)) \
+ np.cos(w_z*t_step)*(-np.sin(psi)*np.cos(phi) - np.cos(theta)*np.sin(phi)*np.cos(psi))) \
- mu * w_z * (np.sin(theta)*np.sin(phi))
def T_y(w_z, v_G, theta, phi, psi):
return M(v_G, w_z)*(-np.sin(w_z*t_step)*(np.cos(psi)*np.sin(phi) + np.cos(theta)*np.cos(phi)*np.sin(psi)) \
+ np.cos(w_z*t_step)*(-np.sin(psi)*np.sin(phi) - np.cos(theta)*np.cos(phi)*np.cos(psi)))
- mu * w_z * (np.sin(theta)*np.cos(phi))
def T_z(w_z, v_G, theta, phi, psi):
return M(v_G, w_z)*(-np.sin(w_z*t_step)*np.sin(theta)*np.sin(psi) + np.cos(w_z*t_step)*np.sin(theta)*np.cos(psi)) \
- mu * w_z * np.cos(theta)
Y = np.zeros(8)
Y[0] = (1/I3) * T_z(INP[0], INP[1], INP[2], INP[3], INP[4])
Y[1] = -(lamb/m)*F_x(INP[0], INP[1], INP[2], INP[3], INP[4])
Y[2] = (1/(I3*INP[0]))*(-T_y(INP[0], INP[1], INP[2], INP[3], INP[4])*np.cos(INP[4]) - T_x(INP[0], INP[1], INP[2], INP[3], INP[4])*np.sin(INP[4]))
Y[3] = (1/(I3*INP[0]*np.cos(INP[3]))) * (-T_y(INP[0], INP[1], INP[2], INP[3], INP[4])*np.sin(INP[4]) + T_x(INP[0], INP[1], INP[2], INP[3], INP[4])*np.cos(INP[4]))
Y[4] = -(1/(m*INP[1]))*F_y(INP[0], INP[1], INP[2], INP[3], INP[4])
Y[5] = INP[1]*(-np.cos(INP[4])*np.cos(INP[3]) + np.sin(INP[4])*np.sin(INP[3])*np.cos(INP[2]))
Y[6] = INP[1]*(-np.cos(INP[4])*np.sin(INP[3]) - np.sin(INP[4])*np.cos(INP[3])*np.cos(INP[2]))
Y[7] = INP[1]*(-np.sin(INP[4])*np.sin(INP[2]))
return Y
ode = spi.ode(diff_eqs)
# BDF method suited to stiff systems of ODEs
ode.set_integrator('vode',nsteps=500,method='bdf')
ode.set_initial_value(INPUT,t_start)
ts = []
ys = []
while ode.successful() and ode.t < t_end:
ode.integrate(ode.t + t_step)
ts.append(ode.t)
ys.append(ode.y)
t = np.vstack(ts)
I have a set of 8 differentials equations I want to numerically solve. Therefore I have 8 initial values stored in "INPUT". But when I use this variable in ode.set_initial_value(INPUT,t_start), it keeps repeating that the variable is a float ! It has been bugging me for hours and the answer is maybe obvious but I can't see where I made a mistake. And I don't think the equations themselves, even though they are pretty messy, are involved here.
Thanks in advance for your help.
Your argument order is the one required in the ODE function for odeint. For ode you need the order (t, INP).
Try to use the more recent solve_ivp interface, it has about the same functionality of the ode class and about the same compact call structure as odeint.
I have written the following code for a chemical reaction kinetics assignment. The problem actually involves rabbits being born and leaving a farm instead of reactions. I'm asked to develop an Explicit Euler method program to model the rabbit population.
My program was running fine (i.e. I wasn't receiving any errors but wasn't getting the results I wanted) until just recently where I've been getting the ValueError (ValueError: setting an array element with a sequence.) message. I'm unsure of what I did to my code to prompt the error.
Any help would be appreciated.
def explicit_euler(df, x0, h, n):
# df - ODE that you wish to solve numerically
# x0 - initials values for ODE
# h - step size
# n - number of steps
for i in range(0, len(x0)):
N = np.zeros((len(x0), n))
t = 0
N[i, 0] = x0[i]
for j in range(0, n - 1):
N[i, j + 1] = N[i, j] + h * df(t, N[i, j])
t += h
return N
def df(t, N):
return [(k2 - k5) * t * N,
(k3 - k4) * t * N,
(k1 - k2 - k3 - (k6 * N)) * t * N]
N0 = [2., 10., 0.] # initial number of rabbits [Male, Female, Baby]
# "Reaction rate" coefficients
k1 = 3.5 # [events/rabbits month]
k2 = k3 = 0.15 # [events/rabbits month]
k4 = 0.1 # [events/rabbits month]
k5 = 0.5 # [events/rabbits month]
k6 = 0.1 # [events/rabbits^2 month]
h = 1 # time steps [month]
tspan = 120 # length of time [month]
n = int(tspan / h) # number of time steps
N = explicit_euler(df, N0, h, n)
t = np.linspace(0, tspan, n)
plot1, = plt.plot(t, N[0, :])
plot2, = plt.plot(t, N[1, :])
plot3, = plt.plot(t, N[2, :])
plt.xlabel('Time [months]')
plt.ylabel('Rabbits')
plt.legend((plot1, plot2, plot3), ('Male', 'Female', 'Babies'))
plt.show()
print(N)
EDIT: Forgot to include the error traceback.
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-d31ce8d859bf> in <module>()
39 n = int(tspan / h) # number of time steps
40
---> 41 N = explicit_euler(df, N0, h, n)
42 t = np.linspace(0, tspan, n)
43
<ipython-input-4-d31ce8d859bf> in explicit_euler(df, x0, h, n)
14 for j in range(0, n - 1):
15
---> 16 N[i, j + 1] = N[i, j] + h * df(t, N[i, j])
17 t += h
18
ValueError: setting an array element with a sequence.
I'd like to use an implementation of RK4 I found online for something, but I'm having a bit of difficulty wrapping my head around the implementations I have found online.
For example:
def rk4(f, x0, y0, x1, n):
vx = [0] * (n + 1)
vy = [0] * (n + 1)
h = (x1 - x0) / float(n)
vx[0] = x = x0
vy[0] = y = y0
for i in range(1, n + 1):
k1 = h * f(x, y)
k2 = h * f(x + 0.5 * h, y + 0.5 * k1)
k3 = h * f(x + 0.5 * h, y + 0.5 * k2)
k4 = h * f(x + h, y + k3)
vx[i] = x = x0 + i * h
vy[i] = y = y + (k1 + k2 + k2 + k3 + k3 + k4) / 6
return vx, vy
Could someone please help me understand what exactly the parameters are? If possible, I'd like a more general explanation, but, if being more specific makes it easier to explain, I'm going to be using it specifically for an ideal spring system.
You are asking for the parameters here:
def rk4(f, x0, y0, x1, n):
...
return vx, vy
f is the ODE function, declared as def f(x,y) for the differential equation y'(x)=f(x,y(x)),
(x0,y0) is the initial point and value,
x1 is the end of the integration interval [x0,x1]
n is the number of sub-intervals or integration steps
vx,vx are the computed sample points, vy[k] approximates y(vx[k]).
You can not use this for the spring system, as that code only works for a scalar v. You would need to change it to work with numpy for vector operations.
def rk4(func, x0, y0, x1, n):
y0 = np.array(y0)
f = lambda x,y: np.array(func(x,y))
vx = [0] * (n + 1)
vy = np.zeros( (n + 1,)+y0.shape)
h = (x1 - x0) / float(n)
vx[0] = x = x0
vy[0] = y = y0[:]
for i in range(1, n + 1):
k1 = h * f(x, y)
k2 = h * f(x + 0.5 * h, y + 0.5 * k1)
k3 = h * f(x + 0.5 * h, y + 0.5 * k2)
k4 = h * f(x + h, y + k3)
vx[i] = x = x0 + i * h
vy[i] = y = y + (k1 + 2*(k2 + k3) + k4) / 6
return vx, vy
It's uncomfortable code, I know, and sorry. Especially, if it's a stupid question.
Here is an error with list, and I don't know why (I'm beginner). Can someone, please, tell me, how to fix it?
This is the output:
Traceback (most recent call last):
File "C:/Users/milom/PycharmProjects/ChislM/method.py", line 77, in <module>
vx, vy = rk3(diff1, 0, U0, 10, 100)
File "C:/Users/milom/PycharmProjects/ChislM/method.py", line 39, in rk3
x,v=step(f, h, i, x0, U0)
File "C:/Users/milom/PycharmProjects/ChislM/method.py", line 11, in step
k2 = f(x[i] + (1 / 3) * h[i], v[i] + (1 / 3) * k1)
IndexError: list index out of range
Code:
import matplotlib.pyplot as plt
import math as m
import pandas as pd
x =[0]*101
v =[0]*101
def step(f, h, i, x0, U0):
x[0] = x0
v[0] = U0
k1 = f(x[i], v[i])
k2 = f(x[i] + (1 / 3) * h[i], v[i] + (1 / 3) * k1)
k3 = f(x[i] + (2 / 3) * h[i], v[i] + (2 / 3) * h[i] * k2)
x[i] = x[i - 1] + h[i]
v[i] = v[i - 1] + (h[i]) * ((1 / 4) * k1 + (3 / 4) * k3)
return x, v
def rk3(f, x0, U0, x1, n):
h = [(x1 - x0) / float(n)]
for i in range(1, n+1):
x,v=step(f, h, i, x0, U0)
###h= control(f, h[i], i, v[i], x0, U0)
return x, v
def diff1(x, U):
return 0.1
def diff(x, U):
return -(m.cos(10 * x) + ((m.log(1 + x ** 2)) / (1 + x)) * (U ** 2) + U)
def exact_path():
plt.grid()
plt.plot(vx, vy)
plt.show()
def table():
mytable = pd.DataFrame({
'Xn': vx,
'Vn': vy,
}, index=[i for i in range(0, 101)])
mytable.index.name = 'number'
pd.set_option('display.max_rows', None)
print(mytable)
task = int(input("Task:"))
U0 = float(input("First value- U0:"))
if task == 2:
vx, vy = rk3(diff, 0, U0, 10, 100)
table()
exact_path()
if task == 1:
vx, vy = rk3(diff1, 0, U0, 10, 100)
table()
exact_path()
P.S. It's a simple 3th order Runge-Kutta method, but mostly problem with synthax. I tried to implement method with Python.
In the rk3() function you have h = [(x1 - x0) / float(n)] which creates an list with only a single element in it. This means that the only valid non-negative index that can be used with it would be h[0]—and an attempt to use any other index value, as is likely in the step() function in the for loop, will cause an IndexError.