JS中的Runge Kutta问题 [英] Runge Kutta problems in JS

查看:87
本文介绍了JS中的Runge Kutta问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Javascript中的弹簧上的质量Runge-Kutta实现并使用D3将其可视化。目的是将它与Forward Euler进行比较并对差异进行评论。我的FE工作正常,情节很好,但Runge-Kutta正朝着负面方向射击而且从未缠绕过。

I'm attempting a Runge-Kutta implementation for a mass on a spring in Javascript and visualizing it with D3. The purpose is to compare it to Forward Euler and comment on the differences. My FE works fine and plots fine, but the Runge-Kutta is shooting off in a negative direction and never wrapping around.

这是 plunkr vis和代码,但我也会添加JS(仅适用于ODE求解器)。

Here's a plunkr with the vis and the code, but I'll add the JS (only for the ODE solvers) too.

// *** Functions for ODE Solvers *** //

function FEx (x, v, h)
{
    return x + h*v;
}

function FEv (x, v, h)
{
    var k = 1; var m = 0.5; var g = 0;

    return v + h*( (-k/m)*x + g );
}

function RKx (x, v, h)
{
    var k1 = FEx(x, v, h);
    var k2 = FEx(x+h/2*k1, v+h/2, h);
    var k3 = FEx(x+h/2*k2, v+h/2, h);
    var k4 = FEx(x+h*k3, v+h, h);

    return x + h/6*(k1 + 2*k2 + 2*k3 + k4);
}

function RKy (x, v, h)
{
    var k1 = FEv(x, v, h);
    var k2 = FEv(x+h/2, v+h/2*k1, h);
    var k3 = FEv(x+h/2, v+h/2*k2, h);
    var k4 = FEv(x+h, v+h*k3, h);

    return v + h/6*(k1 + 2*k2 + 2*k3 + k4);
}

// FORWARD EULER
function forewardEuler (x, v, h, n)
{
    // Initialize an array to hold the values
    // JS doesn't really support multi-dimensional arrays
    // so this is a "jagged" nested array
    var values = new Array(n);
    for(i = 0; i < values.length; i++)
        values[i] = new Array(2);

    // Initial conditions
    values[0] = [x, v];

    for (i = 1; i < n; ++i)
    {
        values[i][0] = FEx(values[i-1][0], values[i-1][1], h);
        values[i][1] = FEv(values[i-1][0], values[i-1][1], h);
    }

    return values;
}

// 4TH ORDER RUNGE-KUTTA 
function RK4 (x, v, h, n)
{
    // Initialize an array to hold the values
    var values = new Array(n);
    for(i = 0; i < values.length; i++)
        values[i] = new Array(2);

    // Initial conditions
    values[0] = [x, v];

    for (i = 1; i < n; ++i)
    {
        values[i][0] = RKx(values[i-1][0], values[i-1][1], h);
        values[i][1] = RKy(values[i-1][0], values[i-1][1], h);
    }

    return values;
}

// *** Setting up the data *** //

var rkValues = RK4(1, 0, 0.1, 100);
var feValues = forewardEuler(1, 0, 0.1, 100);


推荐答案

这有一些非常基本的概念问题。对于耦合系统,您必须同时评估所有操作。也就是说,在 y'(t)= f(y(t))函数 y(t)是向量值, f 将向量作为输入,向量作为输出。然后可以将欧拉方法概括为

This has some very basic conceptual problems. For a coupled system you have to evaluate all operations simultaneously. That is, in y'(t)=f(y(t)) the function y(t) is vector valued, f has vectors as inputs and vectors as outputs. The Euler method can then be summarized as

k = f(y[i]);
y[i+1] = y[i] + h*k;

允许灵活地了解 f 的组件被评估。 RK4接着是一个类似的方案,斜率 k0,...,k3 都是函数 f 的值各种修改点。

allowing flexibility in how the components of f are evaluated. RK4 follows then a similar scheme, the slopes k0,...,k3 are all values of the function f at various modified points.

欧拉步骤当然不是RK4步骤的一部分,也不应该与ODE的系统功能混淆。

The Euler step certainly is not a part of the RK4 step and should also not be mixed up with the system function of the ODE.

所以你应该使用方向

function odefuncX(x,v) {return v;}

function odefuncV(x,v) { 
    var k = 1; var m = 0.5; var g = 0;
    return (-k/m)*x + g;
}

function EulerStep(x,v,h) {
    var kx = odefuncX(x,v);
    var kv = odefuncV(x,v);
    return [ x+h*kx, v+h*kv ];
}

function RK4Step(x,v,h) {
    var kx0 = odefuncX(x,v);
    var kv0 = odefuncV(x,v);

    var kx1 = odefuncX(x+0.5*h*kx0,v+0.5*h*kv0);
    var kv1 = odefuncV(x+0.5*h*kx0,v+0.5*h*kv0);

    var kx2 = odefuncX(x+0.5*h*kx1,v+0.5*h*kv1);
    var kv2 = odefuncV(x+0.5*h*kx1,v+0.5*h*kv1);

    var kx3 = odefuncX(x+    h*kx2,v+    h*kv2);
    var kv3 = odefuncV(x+    h*kx2,v+    h*kv2);

    return [ x+h/6*(kx0+2*(kx1+kx2)+kx3),
             v+h/6*(kv0+2*(kv1+kv2)+kv3) ];
}

// 4TH ORDER RUNGE-KUTTA 
function RK4 (x, v, h, n) {
    // Initialize an array to hold the values
    var values = new Array(n);

    // Initial conditions
    values[0] = [x, v];
    for (i = 1; i < n; ++i) {
        values[i] = RK4Step(values[i-1][0], values[i-1][1], h); 
    }
    return values;
}

参见分叉的Plunker

这篇关于JS中的Runge Kutta问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆