首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Runge-Kutta N体实现不起作用

Runge-Kutta N体实现不起作用
EN

Stack Overflow用户
提问于 2017-03-17 02:26:52
回答 2查看 465关注 0票数 1

我已经用Java实现了Runge 4算法,正如本文所描述的。http://spiff.rit.edu/richmond/nbody/OrbitRungeKutta4.pdf

然而,这些变化是不稳定的。即使只有两具身体,也没有周期性的运动。

代码语言:javascript
复制
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的一阶张量。

所有静态方法Vectors2.*都返回向量的副本。

调用Vector2实例的所有非静态方法都修改了向量,对于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的一个属性,这些函数是该类的一部分。它是一个PointBody[]数组。

为了确保它不是其他bug,我通过删除、k3和k4,将RK4算法简化为一个显式的欧拉算法。这个按预期工作。

代码语言:javascript
复制
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)));
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-03-17 07:25:59

你在设置

代码语言:javascript
复制
rk1 = v0
pos2 = pos0 + rk1*h/2
vk2 = acc(pos2)

这是正确的。但接着你继续

代码语言:javascript
复制
rk2 = vk1*h/2

它应该在哪里

代码语言:javascript
复制
rk2 = v0 + vk1*h/2

诸若此类。当然,累积位置更新也是错误的。

票数 2
EN

Stack Overflow用户

发布于 2017-03-17 09:11:45

这不是RK集成的好实现。

您正在使用共享的、可变的数据。这可不是安全的线索。

我见过的任何适当的数值积分实现都会将要集成的函数抽象为传递到集成方案中的方法。您应该能够通过将函数传递到一个新例程来更改集成方案。

从一个以函数和初始条件作为参数的集成接口开始。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42848155

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档