我已經求解了初始值微分方程並繪製了由ODE45給出的Y值。從陰謀我可以隱約地告訴根本應該在哪裏,但在給定的任務,我需要非常準確地找到它。Matlab:找到由微分方程給出的y值的根
我的第一個猜測是將一個多項式調整爲我的X和Y值,然後求解多項式方程。但是我使用了polyfit,並有69個知道的值給我一個我無法解決的68級多項式。那麼,有沒有人知道如何在不知道實際方程的情況下找到一組給定Y值的「根」?它寫在任務中,應該使用插值!
在此先感謝!
我已經求解了初始值微分方程並繪製了由ODE45給出的Y值。從陰謀我可以隱約地告訴根本應該在哪裏,但在給定的任務,我需要非常準確地找到它。Matlab:找到由微分方程給出的y值的根
我的第一個猜測是將一個多項式調整爲我的X和Y值,然後求解多項式方程。但是我使用了polyfit,並有69個知道的值給我一個我無法解決的68級多項式。那麼,有沒有人知道如何在不知道實際方程的情況下找到一組給定Y值的「根」?它寫在任務中,應該使用插值!
在此先感謝!
給定一個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點之間)。
你說你需要找到根「非常準確」。上面的@ CST-Link的答案並不是如何做到這一點,如果你用ODE45
數值求解微分方程。實際上這是一個壞主意。它需要以高分辨率輸出解決方案點,並引入誤差,如果方程的積分保守(即,您將有效地從能量應始終保持不變的解決方案中增加或減少能量),這可能尤其不利。您需要使用Matlab的ODE求解器的事件檢測(過零點)功能。這通常能夠以接近機器epsilon的精確度找到您的根,eps
。雖然@ CST-Link給出的技術只能給出ODE45的步長大小的準確性,這可能會非常大(插值可以用來幫助改善這一點,但除非您接近eps
,否則不會接近eps
你使用微小的步長)。
看着Matlab的幫助ODE45
,這些事件的功能似乎混亂,所以我會嘗試使用基於ballode
(help ballode
和edit 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
線。如果你太快檢測到接觸,球的速度將低於現實,能量將會消失;太晚了,能量會被注入。 efun
的value
輸出定義了必須等於交叉點的零的方程。這可以根據需要簡單或複雜,可以取決於所有狀態變量和時間,並且可以通過指定矢量來檢測多個交叉點。就你而言,這聽起來像你對x軸的根感興趣,所以我想象你可能有一個相同的定義value
。如果您只需要第一個根目錄或者只有一個根目錄,那麼isterminal
將在找到時停止集成。最後,如果你不知道你的函數在根上的斜率/斜率,你可以設置direction
爲零。嘗試與上面的代碼此事件功能(ie
可以用來判斷哪些三個事件在te
和ye
輸出觸發):
function [value,isterminal,direction] = efun(t,y)
value = [y(2) y(1)-10 y(1)];
isterminal = [0 0 1];
direction = [-1 0 -1];
一些小的警告。您需要將最終積分時間設置爲足夠長。換句話說,該事件必須發生在t0
和tf
之間(如果您不知道事件發生的時間,請參見ballode
,以便將呼叫迭代到ODE45
)。如果您將isterminal
設置爲零,則輸出t
矢量和y
矩陣將被修剪到終端事件發生時結束。最後,如果您指定固定的步長輸出,例如TSPAN = t0:dt:tf
,則最後的輸出點可能具有更小的步長。
這是一個非常翔實的解決方案,它教會了我很多關於'ode45'的選項,我不知道的東西,我感謝你。但是,爲了保護我的帖子,:-)我想再次提出被問到的最終問題(並且,經您的許可,我會引用):*那麼,有沒有人知道我怎麼能找到一個「根」到一組給定的Y值,而不知道實際的方程?* – 2013-04-17 03:10:36
我假設你至少有微分方程,並且你自己模擬它們?我解釋了你的問題,因爲你沒有微分方程的解析解(你稱之爲「Y值的實際方程」),因此使用'ode45'獲得數值解的原因。如果不是這樣,你需要重寫你的問題,並刪除對「ode45」的引用 - 獲取數據的手段是無關緊要的。我的解決方案是找到無法找到解析解的微分方程根的數值求解方法。 – horchler
說到ODE解算器選項,如果在數值積分函數中使用單輸出參數形式,那麼在插入解決方案之後,您會得到一個可用於deval函數的結構。由於ODE解算器的[內插多項式](http://en.wikipedia.org/wiki/Polynomial_interpolation)被使用('編輯private/ntrp45'),插值是「最優」的。這不一定會給出與事件一樣好的結果,但如果您在應用某種形式的@CST-Link解決方案後需要更細粒度的輸出,那麼這是最好的選擇。 – horchler
非常感謝!掙扎着無數小時,你救了我! – Nekroz