I have the following problem:
I need to run the following code, but it always throws an error:
import sympy as sp
import numpy as np
import scipy.constants as const
g, t, theta, t_max, v, x_0, y_0, y_f = sp.symbols("g t theta t_max v x_0 y_0 y_f")
# Bahnkurve
x = x_0 v*sp.cos(theta)*t
y = y_0 v*sp.sin(theta)*t sp.Rational(1,2)*g*t**2
t_end = sp.solve(sp.Eq(y,0),t)[1] # Verwerfen der ersten Möglichkeit, da diese eine negative Zeit liefert
t_end_func = sp.lambdify([y_0,v, theta], t_end.subs(g,const.g), modules="numpy")
x_func = sp.lambdify([x_0, v, theta, t], x, modules=np)
y_func = sp.lambdify([y_0, v, theta, t], y.subs(g, -const.g), modules=np)
fig1, ax1 = plt.subplots()
ax1.set_title(f"Bahnkurven mit normalverteilten $\\Theta$ und $v$")
ax1.set_xlabel("$x$")
ax1.set_ylabel("$y$")
anz_kurven = int(1e2)
for i in range(anz_kurven):
rand_v = np.random.normal(v_0, sigma_v)
rand_theta = np.random.normal(theta_0, sigma_theta)
zeitpunkte = np.linspace(0, t_end_func(rand_v, rand_theta, float(50)))
ax1.plot(x_func(100, rand_v, rand_theta, zeitpunkte), y_func(50, rand_v, rand_theta, zeitpunkte), color="#0000FF50")
Which throws the error "loop of ufunc does not support argument 0 of type Mul which has no callable sin method"
This is a problem that I encountered a few times over the last exercises I needed to solve, but sometimes it went away without doing something I remember. The same problem occurs at other points in this script I write, but there I was able to just write the function by hand, here I really want to do it the correct way.
Because @David_sd asked, here are the values I have given:
v_0 , sigma_v = 200, 1 # m/s
theta_0, sigma_theta = 45*sp.pi/180, 1*sp.pi/180 # Degrees converted to radians
CodePudding user response:
I'm still not getting any error, but I got a warning from inside the for loop:
<lambdifygenerated-22>:2: RuntimeWarning: invalid value encountered in sqrt
return -0.101971621297793*v*sin(theta) - 0.451600755751787*sqrt(0.0509858106488964*v**2*sin(theta)**2 - y_0)
The line raising the warning is this one:
zeitpunkte = np.linspace(0, t_end_func(rand_v, rand_theta, float(50)))
Looking at how you created t_end_func
, this is a function which requires the following arguments: y_0, v, theta
(with this order). Looking at what you wrote, it appears you switched the arguments to v, theta, y_0
.
If I modify that line of code with:
zeitpunkte = np.linspace(0, t_end_func(float(50), rand_v, rand_theta))
The warning goes away, and the plot comes out.
CodePudding user response:
The 3 lambdify create functions with this python code:
In [48]: help(t_end_func)
...
def _lambdifygenerated(y_0, v, theta):
return -0.101971621297793*v*sin(theta) - 0.451600755751787*sqrt(0.0509858106488964*v**2*sin(theta)**2 - y_0)
In [49]: help(x_func)
...
def _lambdifygenerated(x_0, v, theta, t):
return t*v*cos(theta) x_0
In [50]: help(y_func)
...
def _lambdifygenerated(y_0, v, theta, t):
return -4.903325*t**2 t*v*sin(theta) y_0
All have a sin(theta)
call.
Called with all number arguments:
In [51]: y_func(0, 1,2, 3)
Out[51]: -41.4020327
But called with a symbol
:
In [52]: y_func(0, 1,theta, 3)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
AttributeError: 'Symbol' object has no attribute 'sin'
The above exception was the direct cause of the following exception:
TypeError Traceback (most recent call last)
Input In [52], in <cell line: 1>()
----> 1 y_func(0, 1,theta, 3)
File <lambdifygenerated-3>:2, in _lambdifygenerated(y_0, v, theta, t)
1 def _lambdifygenerated(y_0, v, theta, t):
----> 2 return -4.903325*t**2 t*v*sin(theta) y_0
TypeError: loop of ufunc does not support argument 0 of type Symbol which has no callable sin method
Or with a sympy expression:
In [53]: y_func(0, 1,2*theta, 3)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
AttributeError: 'Mul' object has no attribute 'sin'
The above exception was the direct cause of the following exception:
TypeError Traceback (most recent call last)
Input In [53], in <cell line: 1>()
----> 1 y_func(0, 1,2*theta, 3)
File <lambdifygenerated-3>:2, in _lambdifygenerated(y_0, v, theta, t)
1 def _lambdifygenerated(y_0, v, theta, t):
----> 2 return -4.903325*t**2 t*v*sin(theta) y_0
TypeError: loop of ufunc does not support argument 0 of type Mul which has no callable sin method
Just using np.sin
:
In [55]: np.sin(2*theta)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
AttributeError: 'Mul' object has no attribute 'sin'
When np.sin
is given a non-array, it first converts the input to array:
In [56]: np.array(2*theta)
Out[56]: array(2*theta, dtype=object)
Math on object dtype arrays is performed iteratively, applying the appropriate operator or method to each element. In the case of ufunc like this, it tries obj.sin()
, which almost never works. You have to make sure lambdified
functions are called with numbers or numeric dtype arrays, never sympy objects (or arrays containing such).