学有所思值得鼓励,但是有必要指出的是楼主对于数值分析还要学习一个。欧拉法是最简单的数值模拟方法,精度是比较低的,如何改进以及更高精度的算法可参照相关教材或wikipedia。
物理课上老师用物理模拟软件给大家做了演示,觉得挺有意思。就开始想物理模拟究竟是怎么实现的。想来想去有点东西,拿c++写出来也挺好玩,就来给大家分享一下。
物体的运动(只考虑平动的质点,二维空间内)我们最关心加速度,速度,和位移三个量,即a,v,x。如果知道能每一时刻t的这三个矢量,那就能很好的描述物体的运动了。这三个量的关系也容易感受得到:v是a在时间上的累加,同样x也是v在时间上的累积,也正因如此如果给出某个量和时间的函数,也就能用积分或微分求的其余关于t的函数。
以上,也就是高中课本里带有朴素微积分思想的微元法,就是物理模拟的重要基础。
所以给定一个物体,在某一时刻t外界约束(一般是受力)首先给予了它确定的加速度,在t附近a可以看作恒定不变的,即匀加速,由此可以用匀加速公式求出这一下段时间里v的变化量,同理在t附近v也可以视作不变,可以用匀速公式求出x的变化量。
即dv=adt dx=vdt 的离散版,在每个离散的时间点同样成立,只要你的delta t足够小。这就是高中课本里所谓的微元法,也可以看作离散函数的积分了。
所以就可以用开始模拟了,给一个模拟对象,设置时间间隔值dt,先通过外部条件(一般是受力分析)求出加速度矢量(x y两轴分别分析,互相独立),然后用它来更新速度矢量xy分量,即v+=a dt,同理再更新位移x,每做完一遍就能解算出下一时刻物体的状态,重复迭代,就能模拟出物体的行为辣!多物体,空间里,其实也都是同理,拓展更新对象和矢量维度即可。也许《三体》里徒手计算三体问题用的“时间断面法”就是这样的吧。
让理论指导实践吧!用IDE是devcpp,绘图用的opengl库(devcpp原本没有,得自己装),然后就可以模拟各种好玩的物理模型了。
wx_camera_1696086582271.mp4 点击下载
VID_20231021_231648.mp4 点击下载
wx_camera_1696139106301.mp4 点击下载
可以轻松模拟弹簧摆,三体问题,天体环绕模型等等,一般的物理场景都可以用微元法这个思路模拟出来,而且结果十分精准。
可以考虑把设计一个可以描述物理模拟初态参数的格式化语言(就跟脚本语言一样),模拟前依照格式把初态数据写进文件,我们的物理模拟程序就只用读取,解释,执行就好了。这样就不用为每个物理场景都单独写一个程序了。
当然,这种思路故有其弊端。就是在物体碰撞,擦肩而过,或者平衡等临界状态时可能会使误差无限放大,并产生奇奇怪怪的结果,比如因为距离过近导致碰撞异常等,,,
VID_20231021_233231.mp4 点击下载
总之这个思路还算比较普适,而且也十分轻量化,甚至还可以运行在51单片机上(stc8h平台),来模拟三体运动。
VID_20231021_234331.mp4 点击下载
希望我的分享能对大家有帮助
学有所思值得鼓励,但是有必要指出的是楼主对于数值分析还要学习一个。欧拉法是最简单的数值模拟方法,精度是比较低的,如何改进以及更高精度的算法可参照相关教材或wikipedia。
时段 | 个数 |
---|---|
{{f.startingTime}}点 - {{f.endTime}}点 | {{f.fileCount}} |
200字以内,仅用于支线交流,主线讨论请采用回复功能。