我不确定你是否可以按照自己的意願去做,但是可以做很多事情。 首先,這聽起來像首次通過時間 (又名第一次)的某種數值計算。 如果這些“粒子”是随機的, ode45停下來,不要使用ode45 ,而要使用ode45方法。
據我所知,你可以有多less個事件函數沒有限制 – 或者說事件函數的維數(類似于ODE函數的維數) – 而且它們的數量并不與你擁有多less個ODE方程有關。 事件函數接收目前時間和目前狀态向量。 您可以創build每個事件的任何或所有元素。 你是正确的,更多的事件function和更複雜的事件将減緩整合。 性能還取決于檢測事件的頻率。 如果你的每一個粒子到達“屋頂”,就像你所說的那樣,隻觸發一個事件,那就不會太糟糕。
在實作方面,這裡隻是一個簡單的例子,基于Matlab的ballode例子,它模拟ballode垂直的N個彈道粒子。 有N個非終止事件來捕獲每個粒子穿過y = 0時的時間和速度。一個額外的終止事件被添加來檢查是否所有的粒子已經通過y = 0(如果我們知道哪個粒子是這樣的就像我們在這裡所做的那樣,我們可以讓這個事件結束)。
function eventsdemo % Initial conditions for n balls n = 10; y0(2*n,1) = 0; y0(n+1:end) = linspace(20,40,n); % Specify events function options = odeset('Events',@(t,y)efun(t,y,n)); % Integrate [t,y,te,ye,ie] = ode45(@(t,y)f(t,y,n),[0 10],y0,options); figure; plot(t,y(:,1:n),'b',te(1:n),ye(sub2ind(size(ye),ie(1:n),(1:n).')),'r.'); function dydt = f(t,y,n) % Differential equations for ballistic motion dydt = [y(n+1:end);zeros(n,1)-9.8]; function [value,isterminal,direction] = efun(t,y,n) % Last event checks that all balls have hit ground and terminates integration yn = y(1:n); value = [yn;all(yn < 0)]; zn = zeros(n,1); isterminal = [zn;1]; direction = [zn-1;1];
在某些方面,這是低效率的,因為我們繼續模拟所有N個系統,即使它們中的一些已經通過了y = 0。但是,它很簡單,輸出數組是矩形的而不是不齊的。
我并不清楚你的意思是什麼“聯結在一起”,需要粒子“停止”。 如果您不僅需要logging事件資料,例如更改系統參數或以其他方式更改微分方程,則需要在每個事件之後終止并重新開始內建。 看看ballode例子(在Matlab指令視窗中鍵入edit ballode )來看看一些build議,以提高效率。