【问题标题】:solving colebrook (nonlinear) equation in python在python中求解科尔布鲁克(非线性)方程
【发布时间】:2013-09-18 18:55:38
【问题描述】:

我想在 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)

是因为我也在求解常量吗?

编辑2: 所以我想我必须通过 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)... 现在它可以工作了,但结果我得到了零

【问题讨论】:

    标签: python numpy scipy nonlinear-functions


    【解决方案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
    

    【讨论】:

    • 您好 chthonicdeamon,感谢您的意见。我有一些疑问。 1.您能否详细说明一下“我使用通用根函数作为入口点,而不是使用特定算法 - 这很好,因为您稍后可以简单地传递不同的方法。” 2. 是的,谢谢,我的方程式很愚蠢。 3.所以如果我理解正确,定点法几乎就是我会手动做的,就像我在第一篇文章中所说的那样? 4.如果我有更多,我会编辑。你帮了大忙。谢谢
    • 1.如果您查看the documentation for scipy.optimize.root,您将看到可以从参数中选择各种算法,而不必更改实际的函数名称。 3. 差不多,但是函数包含了收敛过程。
    【解决方案2】:

    您的标签有点偏离:您将其标记为sympy,这是一个用于符号 计算的库,但说您想用数值解决它。如果后者是您的实际意图,这里是相关的 scipy 文档:

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

    【讨论】:

    • 谢谢,我选择了brentq,稍后我会测试。再次Tnx
    【解决方案3】:

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

    【讨论】:

    • 欢迎来到 SO,请使用 cmets 部分为 cmets。
    • @blondelg,如果我有足够的声誉,我会拥有的。
    • 好点。也就是说,将行为与声誉联系起来是为了改善行为。绕过规则不会最终提高您的声誉,而尊重正确提问和回答问题的规则会增加您的代表点数。
    猜你喜欢
    • 2020-05-06
    • 1970-01-01
    • 2019-10-02
    • 2013-12-22
    • 1970-01-01
    • 1970-01-01
    • 2014-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多