我正在尝试为研究项目创建一个自定义太阳能系统,以测试不同的数值方法并查看它们之间的区别。
我们制造自己的太阳系而不是试图模拟地球/太阳,因为这似乎更难。
现在我们有一个太阳M1和地球M2。
当我们计算它的重力时,它应该是,F = 8.75或-8.75(F = GM1M2 / r ^ 2)
当我们计算恒定速度时,地球应绕地球运行,我们发现v = 2(v = sqrt(G(M1 + M2)/ r))
要计算力的vec2,我们使用以下代码
static double GravitationalConstant = 0.2f;//6.674e-11;
static public Vector2f GravitationalForce(SolarObject onObj, SolarObject fromObj)
{
Vector2f result = fromObj.OldPosition - onObj.OldPosition;
float distance = result.Lenght();
Console.WriteLine(distance);
result = new Vector2f(result.X / distance, result.Y / distance); // Normalized, but I've the lenght al ready so
result *= (float)((GravitationalConstant * onObj.Mass * fromObj.Mass) / (distance * distance));
return result;
}
要更新位置/速度,我们使用此
public void Update(float dt, List<SolarObject> objects)
{
foreach(SolarObject s in objects.Skip(1))
{
Vector2f f = Utility.GravitationalForce(s, objects[0]);
Vector2f a = f / s.Mass;
s.OldPosition = s.NewPosition;
s.NewPosition += dt * s.Velocity
s.Velocity += dt * a;
}
}
物体围绕太阳飞行,但它根本不是轨道。 M1 / M2之间的距离不是恒定的&lt; - &gt;。力也不总是等于8.75f。我们知道欧拉有一个“错误”,但这似乎很大,因为即使在一个圆周轨道上,25%的距离也准备增加。所以某处必须有一个错误。
答案 0 :(得分:3)
不幸的是,这种行为是欧拉积分所固有的 - 你总是会在某种程度上超越弯曲的路径。使用较小的时间步长可以抑制此效果,即使没有double
s:
正如您所看到的,Euler方法的准确性随着时间步长的减少而提高。内行星(较小的轨道半径=较大的曲率=更多的超调)开始更加一致地跟随它们的投射轨道(绿色)。对于dt = 0.0001
的最内层行星,过冲变为仅,而dt = 0.00001
则完全不可见。
为了改进欧拉方法而不必采用可笑的小时间步长,可以使用例如 Runge-Kutta 集成(4阶变体很受欢迎)。
此外,轨道速度应该是v = sqrt(G*Msun/r))
而不是v = sqrt(G(M1+M2)/r))
,但对于大的星限,这不应该造成太多问题。
(如果您想要我的测试代码,请告诉我 - 虽然编写得非常糟糕,核心功能与您的相同。)