Wave Packets

Physics
  import {fullWidth as fullWidth, fullHeight as fullHeight} from "./tools/Globals.js"
defaults = Object {tau: 1, w0: 1, k0: 5, k1: 1}
Code
chart = {
  const margin = { top: 20, right: 10, bottom: 20, left: 10 };
  const width = fullWidth - margin.left - margin.right,
        height = fullHeight - margin.top - margin.bottom;

  const window = d3.create("svg")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("viewBox", `0 0 ${fullWidth} ${fullHeight}`)
    .attr("preserveAspectRatio", "xMidYMid meet");

  const svg = window.append("g")
    .attr("class", "pulse")
    .attr("transform", `translate(${margin.left},${margin.top})`);

  const envelope = svg.append("path")
    .attr("class", "envelope")
    .attr("opacity", 0.2)
    .style("fill", "#1f77b4");

  const signal = svg.append("path")
    .attr("class", "signal")
    .style("fill", "none")
    .style("stroke", "#d62728")
    .style("stroke-width", 3);

  const range = d3.range(-10, 10.1, 0.05);

  const x = d3.scaleLinear().domain(d3.extent(range)).range([0, width]),
        y = d3.scaleLinear().domain([-1, 1]).range([height, 0]);

  const re = d3.line()
    .x(d => x(d.x))
    .y(d => y(d.re))
    .curve(d3.curveBasis);

  const abs = d3.area()
    .x(d => x(d.x))
    .y0(d => y(-d.abs))
    .y1(d => y(d.abs))
    .curve(d3.curveBasis);

  function f(x) {
    const f0 = tau;
    return {
      r: f0 / Math.sqrt(Math.PI) / tau
        * Math.exp(-(t - k1 * x) * (t - k1 * x) / (2 * tau * tau)),
      phi: w0 * t - k0 * x,
    };
  }

  let t = 0, // animation time
      dt = 0.05; // time step

  let tau = defaults.tau,
      w0 = defaults.w0,
      k0 = defaults.k0,
      k1 = defaults.k1;

  function tick() {
    t += dt;

    if (t > k1 * 10 || t < -k1 * 10) {
      dt *= -1; // reverse the direction of motion
    }

    const data = range.map(x => {
      const y = f(x);
      return {
        x: x,
        re: y.r * Math.cos(y.phi),
        abs: y.r
      };
    });

    envelope
      .datum(data)
      .attr("d", abs);

    signal
      .datum(data)
      .attr("d", re);
  }

  const timer = d3.interval(tick, 20);

  invalidation.then(() => {
    timer.stop();
  });

  return Object.assign(window.node(), {
    update(values) {
      tau = values.tau;
      w0 = values.w0;
      k0 = values.k0;
      t *= values.k1 / k1;
      k1 = values.k1;
    },
  });
}
_tau = 1
_w0 = 1
_k0 = 5
_k1 = 1

This pulse is described by the following equation, where τ is the pulse width, ω0 is the frequency, k0 is the first wavenumber, and k is the second wavenumber:

E(x,t)=E0πτe(tkx)22τ2eiω0tik0x

The phase propagates at velocity vph=ω0k0 and the envelope at vgr=1k.

Resources