2013-04-13 94 views
1

我已經求解了初始值微分方程並繪製了由ODE45給出的Y值。從陰謀我可以隱約地告訴根本應該在哪裏,但在給定的任務,我需要非常準確地找到它。Matlab:找到由微分方程給出的y值的根

我的第一個猜測是將一個多項式調整爲我的X和Y值,然後求解多項式方程。但是我使用了polyfit,並有69個知道的值給我一個我無法解決的68級多項式。那麼,有沒有人知道如何在不知道實際方程的情況下找到一組給定Y值的「根」?它寫在任務中,應該使用插值!

在此先感謝!

回答

2

給定一個Y值向量(從相應的X值穩步增加的意義上來說是有序的),可以很容易地發現根在哪個X值附近。根可以是Y值爲零的地方,也可以是改變符號的兩個連續的Y值之間。的想法是在此代碼段中所示:

X = -1:0.1:1; 
Y = X.*X - 0.4; 

root_exact_pos = find(Y==0); 
root_approx_pos = find(diff(sign(Y))~=0); 

根是在X值,無論是在X(root_exact_pos(k)),或X(root_approx_pos(k))X(root_approx_pos(k)+1)之間,k從1將各自的根位置陣列的元件的數量。

從這裏開始,你可以應用任何插值你想找到一個更好的根的近似值(我會用線性的,在2點之間)。

+0

非常感謝!掙扎着無數小時,你救了我! – Nekroz

1

你說你需要找到根「非常準確」。上面的@ CST-Link的答案並不是如何做到這一點,如果你用ODE45數值求解微分方程。實際上這是一個壞主意。它需要以高分辨率輸出解決方案點,並引入誤差,如果方程的積分保守(即,您將有效地從能量應始終保持不變的解決方案中增加或減少能量),這可能尤其不利。您需要使用Matlab的ODE求解器的事件檢測(過零點)功能。這通常能夠以接近機器epsilon的精確度找到您的根,eps。雖然@ CST-Link給出的技術只能給出ODE45的步長大小的準確性,這可能會非常大(插值可以用來幫助改善這一點,但除非您接近eps,否則不會接近eps你使用微小的步長)。

看着Matlab的幫助ODE45,這些事件的功能似乎混亂,所以我會嘗試使用基於ballodehelp ballodeedit ballode更多信息)的代碼給一個簡單的例子,一個例子Matlab的還包含了事件。

function eventsdemo 

options = odeset('Events',@efun); % specify name of events function 
[t,y,te,ye,ie] = ode45(@f,[0 10],[0;20],options); % integrate 
figure 
plot(t,y(:,1),'b',te,ye(:,1),'r.') 

function dydt = f(t,y) 
dydt = [y(2);-9.8]; % differential equation for ballistic motion 

function [value,isterminal,direction] = efun(t,y) 
value = y(1); 
isterminal = 1; 
direction = -1; 

的例子是在垂直方向上的球的只是簡單的彈道運動:函數f。目標是準確地檢測球在穿過地平面時的速度,即負向的y(1) == 0線。如果你太快檢測到接觸,球的速度將低於現實,能量將會消失;太晚了,能量會被注入。 efunvalue輸出定義了必須等於交叉點的零的方程。這可以根據需要簡單或複雜,可以取決於所有狀態變量和時間,並且可以通過指定矢量來檢測多個交叉點。就你而言,這聽起來像你對x軸的根感興趣,所以我想象你可能有一個相同的定義value。如果您只需要第一個根目錄或者只有一個根目錄,那麼isterminal將在找到時停止集成。最後,如果你不知道你的函數在根上的斜率/斜率,你可以設置direction爲零。嘗試與上面的代碼此事件功能(ie可以用來判斷哪些三個事件在teye輸出觸發):

function [value,isterminal,direction] = efun(t,y) 
value = [y(2) y(1)-10 y(1)]; 
isterminal = [0 0 1]; 
direction = [-1 0 -1]; 

一些小的警告。您需要將最終積分時間設置爲足夠長。換句話說,該事件必須發生在t0tf之間(如果您不知道事件發生的時間,請參見ballode,以便將呼叫迭代到ODE45)。如果您將isterminal設置爲零,則輸出t矢量和y矩陣將被修剪到終端事件發生時結束。最後,如果您指定固定的步長輸出,例如TSPAN = t0:dt:tf,則最後的輸出點可能具有更小的步長。

+0

這是一個非常翔實的解決方案,它教會了我很多關於'ode45'的選項,我不知道的東西,我感謝你。但是,爲了保護我的帖子,:-)我想再次提出被問到的最終問題(並且,經您的許可,我會引用):*那麼,有沒有人知道我怎麼能找到一個「根」到一組給定的Y值,而不知道實際的方程?* – 2013-04-17 03:10:36

+0

我假設你至少有微分方程,並且你自己模擬它們?我解釋了你的問題,因爲你沒有微分方程的解析解(你稱之爲「Y值的實際方程」),因此使用'ode45'獲得數值解的原因。如果不是這樣,你需要重寫你的問題,並刪除對「ode45」的引用 - 獲取數據的手段是無關緊要的。我的解決方案是找到無法找到解析解的微分方程根的數值求解方法。 – horchler

+0

說到ODE解算器選項,如果在數值積分函數中使用單輸出參數形式,那麼在插入解決方案之後,您會得到一個可用於deval函數的結構。由於ODE解算器的[內插多項式](http://en.wikipedia.org/wiki/Polynomial_interpolation)被使用('編輯private/ntrp45'),插值是「最優」的。這不一定會給出與事件一樣好的結果,但如果您在應用某種形式的@CST-Link解決方案後需要更細粒度的輸出,那麼這是最好的選擇。 – horchler