Published
Edited
Nov 25, 2020
29 stars
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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more