I'm using scipy's optimize.fsolve function for the first time to find the roots to an equation. The problem is that whatever number I use as the guess/estimate value is what I get back as my answer (to within about 8 decimal places). When using full_output=True, I get the exitflag to be '1', which is supposed to mean that 'The solution converged', which to the best of my understanding should mean that the output is indeed a root of the equation.
I know there are a finite number of distinct roots (that are spaced out), as when I graph the equation I can see them. Also, fsolve fails (gives error exitflags) when I input the starting point to be in a range which should return a undefined values (divide by zero, square root of a negative value). But besides that it always return the starting point as the root.
I tested fsolve with a very simple equation and it worked fine, so I know that I'm importing everything I need and should be using fsolve correctly. I also tried messing around with some of the input arguments, but I don't understand them very well and nothing seemed to change).
Below is the relevant code (E is the only variable, everything else has a non-zero value):
def func(E):
s = sqrt(c_sqr * (1 - E / V_0))
f = s / tan(s) + sqrt(c_sqr - s**2)
return f
guess = 3
fsolve(func, guess)
which just outputs '3' and says 'The solution converged.', even though the closest solutions should be at about 2.8 and 4.7.
Does anyone have any idea how to fix this and get a correct answer (using fsolve)?
I think your equation doesn't do what you think it does. For one thing, when I try it, it doesn't return the guess; it returns a number close to the guess. It's very unstable and that seems to be confusing fsolve
. For example:
>>> V_0 = 100
>>> c_sqr = 3e8 ** 2
>>> guess = 5
>>> fsolve(func, guess)
array([ 5.00000079])
This is not 5. It is not even 5 within machine precision. It is also not a root of the equation:
>>> func(5.00000079)
2114979.3239706755
But the behavior of the equation is pretty unpredictable anyway:
>>> func(5.0000008)
6821403.0196130127
>>> func(5.0000006)
-96874198.203683496
So obviously there's a zero crossing somewhere around there. I'd say take a good look at your equation. Make sure you are specifying tan
's argument in radians, for instance.
Did you try changing your function to something really trivial? Like this:
#!/usr/bin/python
from scipy.optimize import fsolve
def func(E):
# s = sqrt(c_sqr * (1 - E / V_0))
# f = s / tan(s) + sqrt(c_sqr - s**2)
f = E**2 -3.
return f
guess = 9
sol=fsolve(func, guess)
print sol, func(sol)
For me the code above does converge to where it should.
Also, in the code you've provided --- what are c_str
and V_0
? If in fact your function depends on more than one variable, and you're treating all of them but one as constant parameters, then use the args
argument of the fsolve, like this:
#!/usr/bin/python
from scipy.optimize import fsolve
from numpy import sqrt
def func(E,V_0):
#s = sqrt(c_sqr * (1 - E / V_0))
#f = s / tan(s) + sqrt(c_sqr - s**2)
f = E**2 -V_0
return f
VV=4.
guess = 9
sol=fsolve(func, guess, args=(VV))
print sol, func(sol,VV)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With