求解python中的colebrook(非线性)方程

时间:2013-09-18 18:55:39

标签: python numpy scipy nonlinear-functions

我想在MATLAB中使用python what this guy did

我已经安装了anaconda,所以我有numpy和sympy库。到目前为止,我已尝试使用numpy nsolve,但这不起作用。我应该说我是python的新手,而且我知道如何在MATLAB中做到这一点:P。

The equation

-2*log(( 2.51/(331428*sqrt(x)) ) + ( 0.0002 /(3.71*0.26)) ) = 1/sqrt(x)

通常,我会迭代地解决这个问题,只是在左边猜测x而不是在右边求解x。将解决方案放在左侧,再次解决。重复,直到左边x接近右边。我知道应该是什么解决方案。

所以我可以做到,但那不是很酷。我想用数字做。 我的15欧元卡西欧计算器可以解决它,所以我认为不应该复杂吗?

感谢您的帮助,

编辑:所以我尝试了以下内容:

from scipy.optimize import brentq

w=10;
d=0.22;
rho=1.18;
ni=18.2e-6;

Re=(w*d*rho)/ni
k=0.2e-3;
d=0.26;

def f(x,Re,k,d):
    return (
        -2*log((2.51/(Re*sqrt(x)))+(k/(3.71*d)),10)*sqrt(x)+1
            );

print(
    scipy.optimize.brentq
        (
        f,0.0,1.0,xtol=4.44e-12,maxiter=100,args=(),full_output=True,disp=True
        )
    );

我得到了这个结果:

    r = _zeros._brentq(f,a,b,xtol,maxiter,args,full_output,disp)
TypeError: f() takes exactly 4 arguments (1 given)

是因为我在解决常数问题吗?

EDIT2: 所以我想我必须通过args =()关键字分配常量,所以我改变了:

f,0.0,1.0,xtol=4.44e-12,maxiter=100,args=(Re,k,d),full_output=True,disp=True

但现在我明白了:

-2*log((2.51/(Re*sqrt(x)))+(k/(3.71*d)),10)*sqrt(x)+1
TypeError: return arrays must be of ArrayType

无论如何,当我输入不同的等式时;让我们说2*x*Re+(k*d)/(x+5)它有效,所以我想我必须改变这个等式。

所以它死在这里:log(x,10)..

edit4:正确的语法是log10(x)......现在它可以工作,但结果是零

3 个答案:

答案 0 :(得分:1)

这很好用。我在这里做了一些事情。首先,我使用了你定义的全局变量来更简单地定义函数。我发现这比将args =传递给求解器要好一些,如果你需要这样的东西,它还可以更容易地使用你自己的自定义解算器。我使用泛型root函数作为入口点而不是使用特定算法 - 这很好,因为您可以稍后传递不同的方法。我还修改了你的间距,使其符合PEP 8的建议,并修正了你对等式的错误重写。我发现只是简单地编写LHS - RHS而不是像你那样操纵它。另外,请注意我已经用1.0或其他任何内容替换了所有整数文字以避免整数除法的问题。 0.02被认为是摩擦系数的一个非常标准的起点。

import numpy
from scipy.optimize import root

w = 10.0
d = 0.22
rho = 1.18
ni = 18.2e-6

Re = w*d*rho/ni
k = 0.2e-3

def f(x):
    return (-2*numpy.log10((2.51/(Re*numpy.sqrt(x))) + (k/(3.71*d))) - 1.0/numpy.sqrt(x))

print root(f, 0.02)

我还必须提到,对于这个问题,定点迭代实际上甚至比牛顿的方法更快。您可以通过定义f2来使用内置定点迭代例程,如下所示:

def f2(x):
    LHS = -2*numpy.log10((2.51/(Re*numpy.sqrt(x))) + (k/(3.71*d)))
    return 1/LHS**2

计时(从根开始进一步显示收敛速度):

%timeit root(f, 0.2)
1000 loops, best of 3: 428 µs per loop

%timeit fixed_point(f2, 0.2)
10000 loops, best of 3: 148 µs per loop

答案 1 :(得分:0)

您的代码有点偏差:您将其标记为sympy,这是符号计算的库,但是您说要以数字方式解决它。如果后者是你的实际意图,这里是相关的scipy文档:

http://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html#root-finding

答案 2 :(得分:0)

带有 fixed_point 的 Scipy 也是首选,因为 root 不会收敛于远处的猜测值,例如@chthonicdaemon %timeit 示例中的 0.2。