繁体   English   中英

在python中求解科尔布鲁克(非线性)方程

[英]solving colebrook (nonlinear) equation in python

我想在 python 中做这家伙在 MATLAB 中所做的事情

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

方程

-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)... 现在它可以工作了,但结果我得到了零

这工作正常。 我在这里做了几件事。 首先,我使用您无论如何定义的全局变量对函数进行了更简单的定义。 我发现这比将 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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM