Published
Edited
Apr 14, 2021
12 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// The initial temperature distribution
// This can be edited to experiment with its effect on the results,
// though its values should remain between zero and one, as I haven't
// done anything to scale it.

g = r => 1
Insert cell
// The number of terms in the approximating sum
// The number of terms required for a good approximation depends strongly
// on the initial temperature distribution. The primary choice that's
// illustrated here with g(r) = 1 requires a lot of terms, since it's not
// consistent with the boundary condition

N = 100
Insert cell
// The eigenfunctions
function R(n, r) {
return Math.sin(n * Math.PI * r) / r;
}
Insert cell
// This computation checks that the normalized eigenfunctions are,
// indeed, orthogonal with respect to an inner product. The diagonal
// indicates that the squared-norms are all 1/2
d3
.range(1, 9)
.map(i =>
d3
.range(1, 9)
.map(j => integrate(x => x ** 2 * R(i, x) * R(j, x), 1e-12, 1).toFixed(5))
)
Insert cell
// The coeficients in the approximation
c = d3
.range(1, N)
.map(n => integrate(r => 2 * g(r) * R(n, r) * r ** 2, 1e-12, 1))
Insert cell
// The nth approximation to g using a linear combinations of the eigenfunctions:
function g_approx(n, r) {
return d3.sum(d3.range(0, n).map(n => c[n] * R(n + 1, r)));
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// The solution
function u(t, r) {
return d3.sum(
d3
.range(c.length)
.map(n => c[n] * Math.exp(-t * Math.PI ** 2 * (n + 1) ** 2) * R(n + 1, r))
);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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
function integrate(ff, a, b) {
return adaptiveSimpson(ff, a, b, {
tolerance: 1e-11,
maxDepth: 8,
minDepth: 7
});
}
Insert cell
Insert cell
import { adaptiveSimpson } from '@rreusser/integration@3056'
Insert cell
import { funplot } from '@mbostock/funplot'
Insert cell
import { Scrubber } from '@mbostock/scrubber'
Insert cell
import { Range, Radio, Toggle } from '@observablehq/inputs'
Insert cell
d3 = require('d3-selection@2', 'd3-array@2', 'd3-scale-chromatic@2', 'd3-format@2')
Insert cell
x3dom = require('x3dom').catch(() => window['x3dom'])
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