2017-07-02 66 views
2

我有一個3個微分方程組(從我認爲的代碼中可以看出)具有3個邊界條件。我設法在MATLAB中用一個循環來解決這個問題,如果它要返回一個錯誤,那麼一點一點地改變最初的猜測而不終止程序。不過,在scipysolve_bvp,我總是得到一些的答案,雖然是錯的。所以我一直在改變我的猜測(它不斷改變答案),並且對我從實際解決方案中得到的數據給出了非常接近的數字,但它仍然不起作用。也許還有其他一些代碼問題,由於它不起作用?我剛剛編輯了他們的文檔代碼。用scipy解決一個BVP solve_bvp

import numpy as np 
def fun(x, y): 
    return np.vstack((3.769911184e12*np.exp(-19846/y[1])*(1-y[0]), 0.2056315191*(y[2]-y[1])+6.511664773e14*np.exp(-19846/y[1])*(1-y[0]), 1.696460033*(y[2]-y[1]))) 
def bc(ya, yb): 
    return np.array([ya[0], ya[1]-673, yb[2]-200]) 
x = np.linspace(0, 1, 5) 
#y = np.ones((3, x.size)) 
y = np.array([[1, 1, 1, 1, 1], [670, 670, 670, 670, 670], [670, 670, 670, 670, 670] ]) 
from scipy.integrate import solve_bvp 
sol = solve_bvp(fun, bc, x, y) 

實際的解決方案如下圖所示。

MATLAB解法BVP

回答

1

顯然,你需要一個更好的初始猜測,否則solve_bvp使用迭代方法可以y[1],使表達exp(-19846/y[1])溢出創造價值。發生這種情況時,算法可能會失敗。該表達式中的溢出意味着y[1]中的某個值爲負值;即解算器在雜草中如此之遠以至於它很少有機會收斂到正確的解決方案。你會看到警告,有時候這個函數仍然會返回一個合理的解決方案,但是通常當溢出發生時它會返回垃圾。

您可以通過檢查sol.status來確定solve_bvp是否收斂失敗。如果它不是0,則失敗。 sol.message包含描述狀態的文本消息。

我能夠用它來創建最初的猜測得到了Matlab的解決方案:的n

n = 25 
x = np.linspace(0, 1, n) 
y = np.array([x, np.full_like(x, 673), np.linspace(800, 200, n)]) 

較小的值也行,但是當n太小,溢出的警告可能會出現。

這裏是我的腳本的修改版本,之後的情節,它產生:

import numpy as np 
from scipy.integrate import solve_bvp 
import matplotlib.pyplot as plt 


def fun(x, y): 
    t1 = np.exp(-19846/y[1])*(1 - y[0]) 
    dy21 = y[2] - y[1] 
    return np.vstack((3.769911184e12*t1, 
         0.2056315191*dy21 + 6.511664773e14*t1, 
         1.696460033*dy21)) 

def bc(ya, yb): 
    return np.array([ya[0], ya[1] - 673, yb[2] - 200]) 


n = 25 
x = np.linspace(0, 1, n) 
y = np.array([x, np.full_like(x, 673), np.linspace(800, 200, n)]) 

sol = solve_bvp(fun, bc, x, y) 

if sol.status != 0: 
    print("WARNING: sol.status is %d" % sol.status) 
print(sol.message) 

plt.subplot(2, 1, 1) 
plt.plot(sol.x, sol.y[0], color='#801010', label='$y_0(x)$') 
plt.grid(alpha=0.5) 
plt.legend(framealpha=1, shadow=True) 
plt.subplot(2, 1, 2) 
plt.plot(sol.x, sol.y[1], '-', color='C0', label='$y_1(x)$') 
plt.plot(sol.x, sol.y[2], '--', color='C0', label='$y_2(x)$') 
plt.xlabel('$x$') 
plt.grid(alpha=0.5) 
plt.legend(framealpha=1, shadow=True) 
plt.show() 

plot

+1

有沒有辦法知道,如果這是真正的* *的答案嗎?就像在MATLAB中,如果我有錯誤的開始猜測,我會得到一個錯誤,但在這裏一切都給了我*一些*答案。所以我現在才知道如何驗證我的解決方案在Python中是對還是錯。我假設沒有錯誤消息,如溢出警告意味着它的工作。我只是用'np.linspace(700,400,n)])'嘗試過,它似乎也失敗了。我想我需要把變量的範圍有些封閉? –

+0

*「我剛剛嘗試過使用np.linspace(700,400,n)])」*這不是必需的,它當然不能保證收斂,但傳遞滿足的初始猜測似乎是個好主意邊界條件。 –

+0

謝謝。這是驗證它的好方法。 你使用'y [2]'初始猜測作爲一個從800到200的空間數組,而不是相反的方向,因爲這是怎麼回事,對嗎?你爲什麼不爲'y [1]'做一個600以上的空間,而只是使用'full_like'呢? 'y [2]'更敏感,你是如何知道的? –

相關問題