我最近有這個問題,我的一些代碼。在「簡單」的解決方案是做到以下幾點,首先,一旦溶液達到0,你必須保持在0, 從而改變
dx = 1/(1+y*z) - x;
來(注意一下這裏x == 0
情況評價)
if x > 0
dx = 1/(1+y*z) - x;
else % if x <= 0
dx = 0;
end
或也許向(取決於爲什麼它可能永遠不會爲0)
dxTmp = 1/(1+y*z) - x;
if x > 0
dx = dxTmp;
elseif dxTmp > 0
% x becomes positive again
dx = dxTmp;
else
dx = 0;
end
注意然而,這會在第一衍生物的跳躍不連續,WHI當DDE求解器到達接近這個點的位置時,它不能很好地解決它,除非它知道這個不連續點的確切位置(通常你使用一個額外的選項來告訴Matlab它在哪裏,但是如果你按照下面的步驟,那麼將不需要)。
要確定此中斷的地方,你需要使用的events(DDE選項向下滾動到「活動地點屬性」,你也可以看看這些examples,其中的一個例子其實有類似的系統,其中負交易值在ODE中是不允許的 - ODE和DDE的事件幾乎是相同的)。基本上,一個事件是帶有向量輸出的Matlab函數,向量的每個條目都是對變量的一些或其他評估;在每一步Matlab都檢查它們中的一個是否爲eqauls 0,當其中一個等於0時,DDE停止並返回到該點的解決方案,從中必須重新啓動具有該部分解決方案的DDE作爲歷史記錄,即不是運行
sol = dde23(ddefun, lags, history, [t0 tEnd], options);
運行(注意sol
和t0
改變)
sol = dde23(ddefun, lags, sol, [tCurrent tEnd], options);
在這種情況下,矢量的條目之一將是x
(只要你想的DDE停止時x
等於0)。此外,代碼行elseif dxTmp <= 0
會產生另一個不連續性,因此您需要一個事件,當dxTmp
變爲0時,即1/(1+y*z) - x
將成爲矢量輸出的另一個組件。
現在,當您重新啓動ODE時,Matlab會自動假定在該點存在不連續性,因此您不必擔心告訴Matlab該處有一個。
接下來的問題是,Matlab的從未完全達到其權,x
,y
,z
和X
值會略有下降。因此,如果要創建一個問題,你會希望在計算衍生品之前
if x < 0
x = 0;
end
糾正x
值(和類似的其它值)。但這隻會在本地更改x
的值。因此,您可能需要將最終解決方案中x
的所有負值更改爲0。我建議你在輸入sol = dde23(ddefun, lags, sol, [tCurrent tEnd], options);
之前不要試圖更改sol
,因爲我在這方面做了很多嘗試,但無法使其工作。
是可以簡單地使用ODE45然後延遲組件添加到所產生的時間向量...這是可能的,如果你可以從非延遲輸入 – Rasman
分開延遲投入?我不這麼認爲。使用'dde23'的全部原因是因爲存在着相互依存關係......像X一樣取決於一小時前Y的值。 – dumbmatter
你可以發佈你的方程嗎? – Rasman