1

在我的模型中,每个代理在每个滴答声中求解一个 ODE 系统。我采用了欧拉方法(类似于 NetLogo 中的系统动力学建模器)来求解这些一阶 ODE。但是,为了获得稳定的解决方案,我不得不使用非常小的时间步 (dt),这意味着使用这种方法进行的模拟非常缓慢。我很好奇是否有人对更快地解决 ODE 的方法有建议?我正在考虑像这里(http://academic.evergreen.edu/m/mcavityd/netlogo/Bouncing_Ball.html )那样实施Runge-Kutta(时间步长更大? )。我还会考虑使用 R 扩展并在 R 中使用 ODE 求解器。但同样,ODE 由每个代理求解,所以我不知道这是否是一种有效的方法。

我希望有人对这些方法的性能有所了解,并可以提供一些建议。如果没有,我会尝试分享我的发现。

4

1 回答 1

1

总的来说,您的想法是正确的。对于在长度的积分区间上p达到全局误差水平的顺序方法,您将需要幅度范围内的步长tolT

h=pow(tol/T,1.0/p). 

然而,不仅离散化误差会随着N=T/h步骤累积,而且浮点误差也会累积。这给出了有用步长大小的下限h=pow(T*mu,1.0/(p+1))

示例:对于T=1,mu=1e-15tol=1e-6

  • 1 阶的欧拉方法需要大约的步长,h=1e-6因此需要步长N=1e+6和函数评估。可以预期合理结果的步长范围以 为界h=3e-8

  • 改进的 Euler 或 Heun 方法具有 2 阶,这意味着步长1e-3N=1000步长和2N=2000函数评估,有用步长的下限是1e-3

  • 经典的 Runge-Kutta 方法的阶数为 4,它给出了所需的步长大约为h=3e-2大约N=30步长和4N=120函数评估。下界是1e-3

因此,使用高阶方法可以获得显着的收益。同时,步长减小导致全局误差较低的范围也随着阶数的增加而显着变窄。但与此同时,可实现的精度也会提高。因此,一个人必须有意识地关心何时达到这一点,以便独自离开。


球示例中 RK4 的实现,通常用于 ODE 的数值积分,适用于 ODE 系统x'=f(t,x),其中x是可能非常大的状态向量


通过使速度成为状态向量的成员,将二阶 ODE(系统)转换为一阶系统。x''=a(x,x')变成[x',v']=[v, a(x,v)]. 然后,代理系统的大向量由对的集合组成,[x,v]或者,如果需要,作为所有组件的集合和所有x组件的集合的串联v


在基于代理的系统中,将属于代理的状态向量的分量存储为代理的内部变量是合理的。然后通过迭代代理集合并计算适合内部变量的操作来执行向量操作。


考虑到在LOGO语言中函数调用没有显式参数,所以求值dotx = f(t,x)需要先确定正确的值,t然后x再调用函数求值f

 save t0=t, x0=x
 evaluate k1 = f_of_t_x

 set t=t0+h/2, x=x0+h/2*k1
 evaluate k2=f_of_t_x

 set x=x0+h/2*k2
 evaluate k3=f_of_t_x

 set t=t+h, x=x0+h*k3
 evaluate k4=f_of_t_x

 set x=x0+h/6*(k1+2*(k2+k3)+k4)
于 2015-04-10T18:27:22.683 回答