Search code examples
pythonscipy

Trying to fit data to a curve and getting "OptimizeWarning: Covariance of the parameters could not be estimated " scipy


I have some experimental data from a wind tunnel and I'm trying to fit a curve to this data and determine the x-intercept from it but cannot seem to get it to fit properly.

Plot of my experimental data:

Plot of my experimental data

Desired plot:

Desired plot

My Arrays for x and y are as follows below:

x = [0.05068111 0.04818916 0.04882654 0.05214874 0.05944521 0.07145887 0.0815519  0.09417571 0.11834393]

y = [0.0963202  0.22971568 0.36601308 0.50110841 0.63746987 0.77172614 0.85511004 0.90326404 0.94890827]

x = CD[3:12]
y = CL[3:12]

print(x)
print(y)

def fit_func(x, Cdmin, k1, Clmind):
    return ((x-Cdmin)/k1)**0.5 + Clmind

params = curve_fit(fit_func, x, y)

[Cdmin, k1, Clmind] = params[0]

print([Cdmin, k1, Clmind])

Solution

  • The main issue is that you tried to fit a non-function, as one x-value here has two y-values. If you however invert the relation and calculate Cd as function of Cl, it works.

    Also, the fit is not very good when including all the data points. I suspect some non-ideal conditions towards the end. You get a much better fit when leaving out the last two points.

    from matplotlib import pylab
    from scipy.optimize import curve_fit
    
    x = [0.05068111, 0.04818916, 0.04882654, 0.05214874, 0.05944521, 0.07145887, 0.0815519,  0.09417571, 0.11834393]
    y = [0.0963202,  0.22971568, 0.36601308, 0.50110841, 0.63746987, 0.77172614, 0.85511004, 0.90326404, 0.94890827]
    
    x2 = x[:-2]  # removing last two data points
    y2 = y[:-2]
    
    def cd_calc(cl, Cdmin, k1, Clmind):
        return k1 * (cl - Clmind) ** 2 + Cdmin
    
    
    params, cov_param = curve_fit(cd_calc, y2, x2)
    print(params)
    
    x_hat = [cd_calc(y_i, *params) for y_i in y]
    print(x_hat)
    
    pylab.plot(x, y, "b.")
    pylab.plot(x_hat, y, "k-")
    pylab.xlabel("Cd")
    pylab.xlabel("Cl")
    pylab.grid()
    pylab.show()
    

    Resulting plot:

    resulting plot

    But I get k1=0.1 not 0.7 to 0.85 as you wish. The curvature would then be much stronger as in your data points.