I have the following function for which I try to solve Vcr for given S,h,g:
Vcr/np.sqrt(g*h)=((2/3)*(1-S+ (Vcr**2)/(2*g*h)))**(3/2)
I do as follows:
from scipy.optimize import fsolve
import numpy as np
S = 0.06
h = 15.14
g = 9.8
def eqn(Vcr,g,h,S):
return (Vcr/np.sqrt(g*h)-((2/3)*(1-S+ (Vcr**2)/(2*g*h)))**(3/2))
ans = fsolve(lambda Vcr,g,h,S: eqn(Vcr,g,h,S), x0=5, args=(S,h,g))
print(eqn(ans,g,h,S))
The answer prints 4.9109. This answer is NOT correct. I checked this in Matlab:
fun = @(Vcr) Vcr./sqrt(g*h)-((2/3)*(1-S+ (Vcr.^2)./(2*g*h))).^(3/2);
sol = fzero(fun, 5); % solution critical speed;
# sol = 8.5970
The solution is then substituted in the Python equation and gives me: print(eqn(8.5970,g,h,S))=0
So indeed it should be 8.5970.
How can I solve this in Python with an expression close to the given matlab expression (with anonymous function)? If it is possible I don't want to define a function as def():
The extra arguments to the function must be passed in the order the function expects, you reversed them (args=(S,h,g)
while your function declares them in the opposite order: lambda Vcr,g,h,S:
).
Putting them in the right order gives you the expected solution:
from scipy.optimize import fsolve
import numpy as np
S = 0.06
h = 15.14
g = 9.8
def eqn(Vcr,g,h,S):
return (Vcr/np.sqrt(g*h)-((2/3)*(1-S+ (Vcr**2)/(2*g*h)))**(3/2))
ans = fsolve(lambda Vcr,g,h,S: eqn(Vcr,g,h,S), x0=5, args=(g, h, S))
print(ans, eqn(ans,g,h,S))
# [8.5970162] [1.11022302e-16]