Published
Edited
Nov 25, 2020
29 stars
Also listed in…
Math
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Perform Euler's method with n steps over the interval [a,b]
// for y' = f(y,t) with y(t0) = y0.
function euler(f, y0, a, b, n) {
let dt = (b - a) / n;
let ti = a;
let yi = y0;
let pts = [[ti, yi]];
for (let i = 0; i < n; i++) {
yi = yi + f(yi, ti) * dt;
ti = ti + dt;
pts.push([ti, yi]);
}
return pts;
}
Insert cell
Insert cell
pts = euler((y, t) => y, 1, 0, 1, 10)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Apply the Runge-Kutta method with n steps over an interval
// [a,b] containing t0.
function rk4_1d(f, y0, t0, a, b, n) {
let dt = (b - a) / n;
if (t0 == a) { // Just go forward
return rk4_multi_step_1d(f, y0, a, dt, n);
} else if (b == t0) { // Just go backward
let result = rk4_multi_step_1d(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_1d(f, y0, t0, -dt, i);
backward.reverse();
let forward = rk4_multi_step_1d(f, y0, t0, dt, n - i).slice(1);
return backward.concat(forward);
}
}
Insert cell
function rk4_multi_step_1d(f, y0, t0, dt, n) {
let result = [[t0, y0]];
for (let i = 0; i < n; i++) {
y0 = rk4_single_step_1d(f, y0, t0, dt);
t0 = t0 + dt;
if (Math.abs(y0) < 1000) {
result.push([t0, y0]);
} else {
break;
}
}
return result;
}
Insert cell
function rk4_single_step_1d(f, y0, t0, dt) {
let dt2 = dt / 2;
let k1 = f(y0, t0);
let k2 = f(y0 + k1 * dt2, t0 + dt2);
let k3 = f(y0 + k2 * dt2, t0 + dt2);
let k4 = f(y0 + k3 * dt, t0 + dt);

return y0 + ((k1 + 2 * k2 + 2 * k3 + k4) * dt) / 6;
}
Insert cell
Insert cell
md`Euler's method with 10 steps:`
Insert cell
euler_approx10 = euler(y => y, 1, 0, 1, 10).slice(-1)[0][1]
Insert cell
Insert cell
rk4_approx = rk4_1d(y => y, 1, 0, 0, 1, 10).slice(-1)[0][1]
Insert cell
Insert cell
euler_approx100000 = euler(y => y, 1, 0, 1, 100000).slice(-1)[0][1]
Insert cell
Insert cell
[Math.E - euler_approx100000, Math.E - rk4_approx]
Insert cell
Insert cell
Insert cell
// d3 = require('d3@6')
d3 = require('d3-selection@2', 'd3-scale@3', 'd3-shape@2', 'd3-array@2', 'd3-axis@2')
Insert cell
math = require('mathjs@7.6.0')
Insert cell
import { slider, text, select } from "@jashkenas/inputs"
Insert cell
import { plotter } from '@kjerandp/plotter'
Insert cell
Insert cell
// Store the values of t0 and y0 in this external object so
// they don't get rewritten when we resize R.
inits = ({
t0: null,
y0: null
})
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