Public
Edited
Nov 17, 2022
Importers
9 stars
Insert cell
Insert cell
orbit = rk4(([x, y], t) => [-y - x / t, x - y / 2], [1, 1], 1, 0.5, 100, 1000)
Insert cell
Insert cell
{
let w = 0.8 * width;
let h = 0.6 * w;
let plot = plotter({
xDomain: [-1, 3],
yDomain: [1.5, -0.5],
width: w,
height: h
});
plot.polyline(orbit.map(([x, y]) => ({ x: x, y: y })));
return plot.node;
}
Insert cell
Insert cell
// Run RK4 forwards and backwards over the time interval [a,b] where t0 is in [a,b], like
// rk4(([x]) => [x], [1], 0, -5, 5, 100)
function rk4(f, y0, t0, a, b, n) {
let dt = (b - a) / n;
if (t0 == a) {
// Just go forward
return rk4_multi_step(f, y0, a, dt, n);
} else if (b == t0) {
// Just go backward
let result = rk4_multi_step(f, y0, b, -dt, n);
result.reverse();
return result;
} else if (a < t0 && t0 < b) {
// Go forward and backward and concatenate
let i = Math.floor((t0 - a) / dt);
let backward = rk4_multi_step(f, y0, t0, -dt, i);
backward.reverse();
let forward = rk4_multi_step(f, y0, t0, dt, n - i).slice(1);
return backward.concat(forward);
}
}
Insert cell
// Take a bunch of RK4 steps, like
// rk4_multi_step(([x]) => [x], [1], 0, 0.1, 10)
function rk4_multi_step(f, y0, t0, dt, n) {
let y = y0;
y.t = t0;
let ys = [y];
for (let i = 0; i < n; i++) {
y = rk4_single_step(f, y, t0 + i * dt, dt);
y.t = t0 + (i + 1) * dt;
// Implement an overly simple bailout
// ys.push(y);
if (d3.sum(y.map((x) => x ** 2)) < 10 ** 8 && y.filter(isNaN).length == 0) {
ys.push(y);
} else {
return ys;
}
}
return ys;
}
Insert cell
// Take a single RK4 step from t0 to t0+dt, like
// rk4_single_step(([x]) => [x], [1], 0, 0.1)
function rk4_single_step(f, y0, t0, dt) {
let dt2 = dt / 2;
let k1 = f(y0, t0);
let k2 = f(add(y0, mul(dt2, k1)), t0 + dt2);
let k3 = f(add(y0, mul(dt2, k2)), t0 + dt2);
let k4 = f(add(y0, mul(dt, k3)), t0 + dt);
let s1 = add(k1, mul(2, k2));
let s2 = add(s1, mul(2, k3));
let s3 = add(s2, k4);
return add(y0, mul(dt / 6, s3));
}
Insert cell
// Multiply a vector by a scalar, like
// mul(2,[3,4])
function mul(r, a) {
return a.map(x => r * x);
}
Insert cell
// add two vectors, like
// add([1, 2], [3, 4])
function add(a1, a2) {
return a1.map((a, i) => a + a2[i]);
}
Insert cell
Insert cell
d3 = require('d3-array@2')
Insert cell
// Fork of '@kjerandp/plotter'
import { plotter } from '50dadfdec01c15a8'
Insert cell
n = 4
Insert cell
init = d3.range(0, 1 + 1 / n, 1 / n).map(x => 4 * (x - x ** 2))
Insert cell
d3.range(0, 1 + 1 / n, 1 / n)
Insert cell
function F(u, t) {
let v = Array.from({ length: n });
v[0] = 0;
v[n] = 0;
for (let i = 1; i < n; i++) {
v[i] = n ** 2 * (u[i + 1] - 2 * u[i] + u[i - 1]);
}
return v;
}
Insert cell
// rk4_multi_step(f, y0, t0, dt, n)
// rk4(f, y0, t0, a, b, n)
// orbit = rk4(([x, y], t) => [-y - x / t, x - y / 2], [1, 1], 1, 0.5, 100, 1000)
result = rk4(F, init, 0, 0, 1, 10)
Insert cell
import { odeRK4 } from '@rreusser/integration'
Insert cell
odeRK4
Insert cell
init
Insert cell
yy = d3.range(n + 1)
Insert cell
yy
Insert cell
init
Insert cell
rresult = {
let y = d3.range(0, 1 + 1 / n, 1 / n).map(x => 4 * (x - x ** 2));
for (let i = 0; i < 1000; i++) {
odeRK4(y, y, f, 0.001);
}
return y;
}
Insert cell
function f(_, u) {
let v = Array.from({ length: n });
v[0] = 0;
v[n] = 0;
for (let i = 1; i < n; i++) {
v[i] = n ** 2 * (u[i + 1] - 2 * u[i] + u[i - 1]);
}
return v;
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more