Python fmin using lambda expression

163 views Asked by At

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():

1

There are 1 answers

1
Thierry Lathuille On BEST ANSWER

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]