簡體   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