Я пытаюсь реализовать реализацию Runge-Kutta для массы на пружине в Javascript и визуализировать ее с помощью D3. Цель состоит в том, чтобы сравнить его с Forward Euler и прокомментировать различия. Моя FE работает отлично, и сюжеты прекрасны, но Рунге-Кутта стреляет в отрицательном направлении и никогда не обматывает.Проблемы с Runge Kutta в JS
Вот plunkr с изображением и кодом, но я добавлю JS (только для решателей ODE).
// *** 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);
Это работало отлично, спасибо. Я беру класс числовых методов, не взяв класс ODE, поэтому процессы немного чужды. –
Чтобы быть справедливым, следует учитывать, что 100 шагов RK4 - это 400 оценок функций. Призыв Эйлера для аналогичных усилий за тот же промежуток времени будет «forwardEuler (1, 0, 0.025, 400)», который выглядит немного менее катастрофическим – LutzL