Published
Edited
Jun 15, 2021
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Initial distribution
// You can change this and the results below should change along with it,
// as should the picture at the top.
g = r => 1 - r ** 2
Insert cell
Insert cell
// The eigenfunction. Note that that the Bessel function j0 is
// imported below, j0_zero(n) represents the nth zero and that
// sqrt(lambda_n) = j0_zero(n).
function R(n, x) {
return j0(x * j0_zero(n));
}
Insert cell
Insert cell
// The norms of the eigenfunctions
norms = {
function norm(ff) {
return Math.sqrt(integrate(x => x * ff(x) * ff(x), 0, 1));
}
return d3.range(1, N).map(n => norm(x => R(n, x)));
}
Insert cell
Insert cell
// The normalized eigenfunctions
// Since we divide by the norm, these each have norm 1.
function F(n, x) {
return R(n, x) / norms[n - 1];
}
Insert cell
Insert cell
// This computation checks that the normalized eigenfunctions are,
// indeed, orhonormal.
d3
.range(1, 9)
.map(i =>
d3
.range(1, 9)
.map(j => integrate(x => x * F(i, x) * F(j, x), 0, 1).toFixed(5))
)
Insert cell
Insert cell
// The coefficients to approximat g(r)
c = d3.range(1, N).map(n => integrate(r => g(r) * F(n, r) * r, 0, 1))
Insert cell
Insert cell
Insert cell
Insert cell
// The nth approximation to g using linear comination of the eigenfunctions:
function g_approx(n, r) {
return d3.sum(d3.range(0, n).map(n => c[n] * F(n + 1, r)));
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function u(t, r) {
return d3.sum(
d3
.range(c.length)
.map(n => c[n] * Math.exp(-(j0_zero(n + 1) ** 2) * t) * F(n + 1, r))
);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
N = 10
Insert cell
Insert cell
u(0.2, 0)
Insert cell
Insert cell
function norm(ff) {
return Math.sqrt(integrate(x => x * ff(x) * ff(x), 0, 1));
}
Insert cell
function rgb_to_r_g_b(rgb_string) {
return String(
rgb_string
.split('(')[1]
.split(')')[0]
.split(',')
.map(x => String(parseFloat(x) / 255))
).replace(/,/g, ' ');
}
Insert cell
j0_zero = function j0_zero(n) {
let table = [
2.404825557695773,
5.5200781102863115,
8.653727912911013,
11.791534439014281,
14.930917708487787,
18.071063967910924,
21.21163662987926,
24.352471530749302,
27.493479132040253,
30.634606468431976
];
if (n < 11) {
return table[n - 1];
} else {
let z = table[9] + (n - 10) * Math.PI;
for (let i = 0; i < 5; i++) {
z = z + j0(z) / j1(z);
}
return z;
}
}
Insert cell
function integrate(ff, a, b) {
return adaptiveSimpson(ff, a, b, {
tolerance: 1e-11,
maxDepth: 8,
minDepth: 7
});
}
Insert cell
Insert cell
j1 = (await import("https://cdn.jsdelivr.net/npm/@stdlib/esm@0.0.3/math/base/special/besselj1.js"))
.default
Insert cell
j0 = (await import("https://cdn.jsdelivr.net/npm/@stdlib/esm@0.0.3/math/base/special/besselj0.js"))
.default
Insert cell
import {
create_indexedLineSet,
create_indexedFaceSet
} from "@mcmcclur/x3dom-primitives"
Insert cell
import { pt_list_to_coordString } from "ba6b3d20e94e294f"
Insert cell
import { adaptiveSimpson } from '@rreusser/integration@3056'
Insert cell
import { funplot } from '@mbostock/funplot'
Insert cell
import { Range } from "@observablehq/inputs"
Insert cell
x3dom = require('x3dom').catch(() => window['x3dom'])
Insert cell
d3 = require('d3@6')
Insert cell
html`
<style>
canvas {
outline: none
}
</style>`
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