我已经用java实现了本文描述的runge-kutta 4算法。
http://spiff.rit.edu/richmond/nbody/OrbitRungeKutta4.pdf
然而,这些运动是不稳定的。即使只有两个物体,也没有周期性的运动。

protected void integrateRK4(double time) {

    final double H = time;
    final double HO2 = H/2;
    final double HO6 = H/6;

    Vector2[] currentVelocities = new Vector2[objects.length];
    Vector2[] currentPositions = new Vector2[objects.length];
    Vector2[] vk1 = new Vector2[objects.length];
    Vector2[] vk2 = new Vector2[objects.length];
    Vector2[] vk3 = new Vector2[objects.length];
    Vector2[] vk4 = new Vector2[objects.length];
    Vector2[] rk1 = new Vector2[objects.length];
    Vector2[] rk2 = new Vector2[objects.length];
    Vector2[] rk3 = new Vector2[objects.length];
    Vector2[] rk4 = new Vector2[objects.length];


    for (int i=0; i<objects.length; i++) {
        currentVelocities[i] = objects[i].velocity().clone();
        currentPositions[i] = objects[i].position().clone();
    }

        vk1 = computeAccelerations(objects);
    for (int i=0; i<objects.length; i++) {
        rk1[i] = currentVelocities[i].clone();
    }

    for (int i=0; i<objects.length; i++) {
        objects[i].setPosition(Vectors2.add(currentPositions[i], Vectors2.prod(rk1[i], HO2)));
    }
        vk2 = computeAccelerations(objects);

    for (int i=0; i<objects.length; i++) {
        rk2[i] = Vectors2.prod(vk1[i], HO2);
    }


    for (int i=0; i<objects.length; i++) {
        objects[i].setPosition(Vectors2.add(currentPositions[i], Vectors2.prod(rk2[i], HO2)));
    }
        vk3 = computeAccelerations(objects);

    for (int i=0; i<objects.length; i++) {
        rk3[i] = Vectors2.prod(vk2[i], HO2);
    }


    for (int i=0; i<objects.length; i++) {
        objects[i].setPosition(Vectors2.add(currentPositions[i], Vectors2.prod(rk3[i], H)));
    }
        vk4 = computeAccelerations(objects);

    for (int i=0; i<objects.length; i++) {
        rk4[i] = Vectors2.prod(vk3[i], H);
    }


    for (int i=0; i<objects.length; i++) {
        objects[i].setVelocity(Vectors2.add(currentVelocities[i], Vectors2.prod(Vectors2.add(vk1[i], Vectors2.prod(vk2[i], 2), Vectors2.prod(vk3[i], 2), vk4[i]), HO6)));
        objects[i].setPosition(Vectors2.add(currentPositions[i], Vectors2.prod(Vectors2.add(rk1[i], Vectors2.prod(rk2[i], 2), Vectors2.prod(rk3[i], 2), rk4[i]), HO6)));
    }
}

我的实现是不是有点不正确?
注:
Vectors2是我自己实现的向量,它是大小为2的一阶张量。
所有静态方法都返回向量的副本。
在Vector2实例上调用的所有非静态方法都会修改向量,对于Vectors2.*objects[i].addVelocity()
objects[i].addPosition()按元素添加。
Vectors2.add(Vector2... vectors2)按元素进行乘法运算。
Vectors2.prod(Vector2... vectors2)按元素进行乘法运算。
Vectors2.prod(Vector2 vector2, double c)返回加速度向量数组。
变量computeAccelerations(PointBody[] objects)是类objects的一个属性,这些函数是该类的一部分。它是一个NBodyIntegrator数组。
为了确保它不是其他错误,我通过删除k2、k3和k4将rk4算法简化为显式euler算法。
这一个按预期工作。
protected void integrateRK1(double time) {
    final double H = time;
    final double HO2 = H/2;

    Vector2[] currentVelocities = new Vector2[objects.length];
    Vector2[] currentPositions = new Vector2[objects.length];
    Vector2[] vk1;
    Vector2[] rk1 = new Vector2[objects.length];


    for (int i=0; i<objects.length; i++) {
        currentVelocities[i] = objects[i].velocity().clone();
        currentPositions[i] = objects[i].position().clone();
    }


        vk1 = computeAccelerations(objects);
    for (int i=0; i<objects.length; i++) {
        rk1[i] = currentVelocities[i].clone();
    }


    for (int i=0; i<objects.length; i++) {
        objects[i].setVelocity(Vectors2.add(currentVelocities[i], Vectors2.prod(Vectors2.add(vk1[i]), H)));
        objects[i].setPosition(Vectors2.add(currentPositions[i], Vectors2.prod(Vectors2.add(rk1[i]), H)));
    }
}

最佳答案

你在设置

rk1 = v0
pos2 = pos0 + rk1*h/2
vk2 = acc(pos2)

这是正确的。但是你继续
rk2 = vk1*h/2

应该在哪里
rk2 = v0 + vk1*h/2

等等当然,累积位置更新也是错误的。

关于java - Runge-Kutta N-Body实现不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42848155/

10-11 06:27