Brownian motion · Synthetic experiment

Each path wanders.
The ensemble tells a story.

Watch the same trial at different times. Separate cancellation of signed displacements from growth of their squares, and see why looking more often does not reveal one intrinsic Brownian speed.

Start with the no-algebra encounter →

Read the argument and open its missing steps →

Pin a trial, compare intervals, and carry D into the spreading lab →

Change one input: compare radius, viscosity, temperature or observation interval →

BM-01 · A reproducible trial

The tracer ensemble

Static worked example

CurrentThese numbers match the current settings.

Model note
  • Primary output temperature: Host calculation (bm01.acceptedInputs). Owner bm01.acceptedInputs.
  • Primary output viscosity: Host calculation (bm01.acceptedInputs). Owner bm01.acceptedInputs.
  • Primary output particleRadius: Host calculation (bm01.acceptedInputs). Owner bm01.acceptedInputs.
  • Primary output observationInterval: Host calculation (bm01.acceptedInputs). Owner bm01.acceptedInputs.
  • Primary output boltzmannConstant: Host calculation (constants.modernSI2019). Owner constants.modernSI2019.
  • Primary output diffusionCoefficient: Host calculation (diffusion.stokesEinsteinD). Owner diffusion.stokesEinsteinD.
  • Primary output rmsDisplacement1d: Host calculation (diffusion.rmsDisplacement). Owner diffusion.rmsDisplacement.
  • Primary output modelSecondMoment: Host calculation (diffusion.moments). Owner diffusion.moments.
  • Primary output modelMeanNorm: Host calculation (diffusion.moments). Owner diffusion.moments.
  • Primary output modelRmsNorm: Host calculation (diffusion.moments). Owner diffusion.moments.
  • Primary output tracerPositions: Host reference calculation (recordTracers). Owner diffusion.recordTracers.
  • Primary output modelApparentSpeed: Host calculation (diffusion.apparentSpeed). Owner diffusion.apparentSpeed.
  • Primary output sampledApparentSpeed: Host calculation (diffusion.ensembleMoments). Owner diffusion.ensembleMoments.
  • Primary output traceCoordinates: Host calculation (diffusion.recordTracers). Owner diffusion.recordTracers.
  • Primary output traceTimes: Host calculation (bm01.measure). Owner bm01.measure.
  • Primary output histogramEdges: Host calculation (diffusion.displacementHistogram). Owner diffusion.displacementHistogram.
  • Primary output histogramCounts: Host calculation (diffusion.displacementHistogram). Owner diffusion.displacementHistogram.
  • Primary output histogramFrequencies: Host calculation (diffusion.displacementHistogram). Owner diffusion.displacementHistogram.
  • Primary output histogramModel: Host calculation (diffusion.intervalProbability). Owner diffusion.intervalProbability.
  • Primary output underflow: Host calculation (diffusion.displacementHistogram). Owner diffusion.displacementHistogram.
  • Primary output overflow: Host calculation (diffusion.displacementHistogram). Owner diffusion.displacementHistogram.
  • Primary output plotTimes: Host calculation (bm01.measure). Owner bm01.measure.
  • Primary output plotSampleMean: Host calculation (bm01.measure). Owner bm01.measure.
  • Primary output plotSampleMsd: Host calculation (bm01.measure). Owner bm01.measure.
  • Primary output plotSampleRms: Host calculation (bm01.measure). Owner bm01.measure.
  • Primary output plotSampleApparent: Host calculation (bm01.measure). Owner bm01.measure.
  • Primary output plotModelMean: Host calculation (bm01.measure). Owner bm01.measure.
  • Primary output plotModelMsd: Host calculation (bm01.measure). Owner bm01.measure.
  • Primary output plotModelRms: Host calculation (bm01.measure). Owner bm01.measure.
  • Primary output plotModelApparent: Host calculation (bm01.measure). Owner bm01.measure.
  • Primary output meanBand: Host calculation (diffusion.ensembleMomentBands). Owner diffusion.ensembleMomentBands.
  • Primary output secondMomentBand: Host calculation (diffusion.ensembleMomentBands). Owner diffusion.ensembleMomentBands.
  • Primary output recordingDraws: Host calculation (diffusion.recordTracers). Owner diffusion.recordTracers.
  • Primary output reusedRecording: Host calculation (bm01.measure). Owner bm01.measure.
  • Primary output ensembleSize: Host calculation (bm01.acceptedInputs). Owner bm01.acceptedInputs.
  • Primary output signedMean: Host calculation (diffusion.ensembleMoments). Owner diffusion.ensembleMoments.
  • Primary output meanSquare: Host calculation (diffusion.ensembleMoments). Owner diffusion.ensembleMoments.
  • Primary output lambdaX1s: Host calculation (diffusion.rmsDisplacement). Owner diffusion.rmsDisplacement.
  • Primary output lambdaX60s: Host calculation (diffusion.rmsDisplacement). Owner diffusion.rmsDisplacement.
  • Primary output signedMeanLowerBand: Host calculation (diffusion.ensembleMomentBands). Owner diffusion.ensembleMomentBands.
  • Primary output signedMeanUpperBand: Host calculation (diffusion.ensembleMomentBands). Owner diffusion.ensembleMomentBands.
  • Primary output meanSquareLowerBand: Host calculation (diffusion.ensembleMomentBands). Owner diffusion.ensembleMomentBands.
  • Primary output meanSquareUpperBand: Host calculation (diffusion.ensembleMomentBands). Owner diffusion.ensembleMomentBands.
  • Primary output kolmogorovDistance: Host calculation (diffusion.displacementHistogram). Owner diffusion.displacementHistogram.
  • Secondary output sampleMean: Host reduction (ensembleMoments). Owner diffusion.ensembleMoments.
  • Secondary output sampleMeanAbsolute: Host reduction (ensembleMoments). Owner diffusion.ensembleMoments.
  • Secondary output sampleMeanSquare: Host reduction (ensembleMoments). Owner diffusion.ensembleMoments.
  • Secondary output sampleRms: Host reduction (ensembleMoments). Owner diffusion.ensembleMoments.
  • Secondary output sampleMeanNorm: Host reduction (ensembleMoments). Owner diffusion.ensembleMoments.
  • Secondary output sampleMeanSquareNorm: Host reduction (ensembleMoments). Owner diffusion.ensembleMoments.
  • Secondary output sampleRmsNorm: Host reduction (ensembleMoments). Owner diffusion.ensembleMoments.
  • Seed 1905.
  • Accepted input revision 1.
  • Snapshot version 1.
  • Not modeled: Molecular collisions (no collision bath owns the displacement).
  • Show the code

Compare the movement of individual tracers with the statistics of the whole ensemble. Changing when or how you observe the trial does not generate different paths.

Record and observe

The preview records at most 8 MiB of latent paths. Its default is 400 tracers for 10 seconds at 0.02-second resolution. Larger requests are refused, never silently reduced.

Same-seed viscosity comparisons use common random numbers, not independent trials.

Predict before comparing observation times

The independent-step model predicts four times the mean square, hence twice its square root. Your prediction never locks the explanation or controls.

These buttons use the accepted trial, not unsaved draft edits. The requested time must lie on its recording grid.

Accepted synthetic trial: 400 tracers, 1 seconds, coordinate mean 0.0029237 micrometres and coordinate RMS 0.98602 micrometres.

Accepted trial: seed 1905; 400 tracers; 293.15 K; viscosity 1 mPa·s; radius 0.5 μm. Observe at 1 s in a 10-second recording. Constants: modern SI 2019.

1 μm5 μm+5 μmy displacement
Displacements from a common origin, not a literal microscope image. Lines connect recorded positions and do not supply an instantaneous velocity. 0 / 400 endpoints lie outside this view; none are removed from the ensemble.
t = 1.00 s (true rate (1 s/s))
Natural rate: ~0.8 μm per second Brownian walk (scale bar: 1 μm)Simulation view: accelerated snapshot across 10 s
View only: no calculation or new draws.
Fraction in each bin-4.6338 μm4.6338 μm
Solid bars: the synthetic sample. Dashed line: probabilities of the same bins under the unbounded model, not a density curve. Counts beyond the plotted range: 0 left, 0 right.
Whole-ensemble statistics: signed coordinate x, total over 1 coordinate
Diffusion coefficient (model)0.42944 μm²/s
Signed mean (sample)0.0029237 μm (modern-si-2019)
Mean absolute coordinate displacement0.77808 μm (modern-si-2019)
Mean-square coordinate displacement0.97223 μm²
Coordinate RMS (sample / model)0.98602 / 0.92676 μm (modern-si-2019)
Mean distance (sample / model)0.77808 / 0.73945 μm (modern-si-2019)
Total mean square (sample / model)0.97223 / 0.85888 μm²
Apparent coordinate speed (sample / model)0.98602 / 0.92676 μm/s
Sampling bands under the model

99.9% per comparison, not a simultaneous guarantee across the table or repeated observations. These ranges are calculated from the model variance, not estimated from the observed sample, and are not uncertainties of the model itself.

Signed coordinate mean (μm): -0.15248 to 0.15248

Total mean square (μm²): 0.67299 to 1.0729

Inspect the model behind this trial

These equations describe the same accepted trial as the plots and table. Select a symbol or an operation to see what it means; model predictions are not sample estimates.

Explore the equation · Modern model notation

Why the apparent speed depends on how you watch

vapp:=λxtv_{\mathrm{app}} := \frac{\lambda_x}{t}

The apparent coordinate speed divides the typical coordinate distance by the chosen positive interval.

Select a term or operation. In the formula, Down enters an operation, Up returns to its parent, and Left/Right move between siblings. Escape clears selection. Tab leaves the formula.

Input · Model result · Constant

Static worked example

Values describe this accepted snapshot, not unsaved input edits.

Apparent coordinate speed
0.92676 μm/s
Coordinate RMS displacement
0.92676 μm
Observation interval
1 s
Read the equation aloud in words

Apparent coordinate speed equals the model coordinate root mean square displacement divided by the observation interval.

This quotient depends on the observation interval. It is not instantaneous physical velocity. At zero interval the quotient is undefined, even though the displacement is zero.

Model assumptions and every term’s meaning
  • The same one-coordinate ideal Brownian model as the RMS relation.
  • A positive observation interval is required for the quotient.
  • Lines joining recorded points are a rendering convention, not a velocity measurement.
Define the observable
This defines an interval-dependent comparison. It does not introduce a physical instantaneous Brownian velocity. Read the prerequisite
Apparent coordinate speed
A distance-per-interval statistic. It is not a molecular collision speed. Read the prerequisite
Divide by the same interval
The distance grows as the square root of time, while the denominator grows linearly. The quotient therefore decreases as the interval grows. Read the prerequisite
Model coordinate RMS
The same accepted one-coordinate model displacement used by the neighboring RMS equation. Read the prerequisite
Positive observation interval
A zero interval yields no apparent-speed value. The interface keeps the explanation instead of fabricating zero or infinity. Read the prerequisite

Exact rational SI dimensions were checked at build time. This is a unit check, not a proof of the model. This teaching record is a draft, not a transcription of a printed equation.

Explore the equation · Modern model notation

Resistance to motion controls spreading

D=kBT6πηaD = \frac{k_B\,T}{6\,\pi\,\eta\,a}

The diffusion coefficient is thermal energy divided by the viscous drag coefficient.

Select a term or operation. In the formula, Down enters an operation, Up returns to its parent, and Left/Right move between siblings. Escape clears selection. Tab leaves the formula.

Input · Model result · Constant

Static worked example

Values describe this accepted snapshot, not unsaved input edits.

Diffusion coefficient
0.42944 μm²/s
Boltzmann constant
1.3806e-23 J/K
Absolute temperature
293.15 K
Dynamic viscosity
1 mPa·s
Particle radius
0.5 μm
Read the equation aloud in words

The diffusion coefficient equals the Boltzmann constant times the absolute temperature, divided by six times pi times the dynamic viscosity times the particle radius.

Thermal energy competes with viscous drag. Doubling viscosity halves the diffusion coefficient while reducing RMS displacement only by the square root of two. Radius means radius, not diameter.

Model assumptions and every term’s meaning
  • Dilute, approximately spherical tracers with no-slip Stokes drag in a homogeneous Newtonian liquid.
  • Wall corrections, interactions, inertia, and observation noise are not included.
  • The modern SI 2019 constant set is used; this is not a historical inversion exercise.
An ideal model
This equation assumes the dilute spherical tracer and Stokes-drag model; dimensional consistency alone does not establish those assumptions. Read the prerequisite
Diffusion coefficient
A squared-distance-per-time coefficient. This value comes from the accepted model calculation. Read the prerequisite
Why divide by drag?
Increasing the denominator reduces diffusivity at fixed thermal energy. This is a model dependence, not a rule that every larger quantity must reduce motion. Read the prerequisite
Thermal energy scale
Boltzmann constant times absolute temperature supplies energy per particle. Read the prerequisite
A known modern constant
The SI 2019 constant set supplies this value. It must not be treated as independent historical evidence when trying to infer molecular number. Read the prerequisite
Absolute temperature
Use kelvin. The laboratory holds viscosity as an independently supplied parameter. Read the prerequisite
The drag coefficient
Six pi times viscosity times radius is Stokes drag per speed for an isolated sphere in the assumed low-Reynolds regime. Read the prerequisite
Dynamic viscosity
Viscosity is in the denominator. Doubling it at fixed temperature and radius halves D, not the RMS displacement. Read the prerequisite
Particle radius
The input is a radius, not a diameter. Confusing them changes the predicted coefficient by a factor of two. Read the prerequisite

Exact rational SI dimensions were checked at build time. This is a unit check, not a proof of the model. This teaching record is a draft, not a transcription of a printed equation.

Explore the equation · Modern model notation

From spreading to a measurable distance

λx=2Dt\lambda_x = \sqrt{2\,D\,t}

The typical coordinate distance is the positive square root of twice the diffusion coefficient times the observation interval.

Select a term or operation. In the formula, Down enters an operation, Up returns to its parent, and Left/Right move between siblings. Escape clears selection. Tab leaves the formula.

Input · Model result · Constant

Static worked example

Values describe this accepted snapshot, not unsaved input edits.

Coordinate RMS displacement
0.92676 μm
Diffusion coefficient
0.42944 μm²/s
Observation interval
1 s
Read the equation aloud in words

The model coordinate root mean square displacement equals the square root of two times the diffusion coefficient times the observation interval.

Squaring measures spread without cancellation between directions. Taking the positive square root turns squared distance back into a distance. Four times the observation interval gives twice the model RMS, not four times.

Model assumptions and every term’s meaning
  • Independent, zero-mean Gaussian displacement increments in a homogeneous liquid.
  • One-coordinate model statistic, not a measured speed or a sample estimate.
  • The overdamped regime is assumed rather than established from additional particle and fluid measurements.
A model relation
This equality concerns the ideal model. A finite synthetic ensemble fluctuates around it; its sample RMS is displayed separately. Read the prerequisite
Coordinate RMS
One coordinate, not the total three-dimensional distance. Model RMS and sample RMS have different meanings. Read the prerequisite
Why a square root?
Two D t has units of squared length. Its positive square root has units of length and defines the typical displacement. Read the prerequisite
Build the mean square
Independent zero-mean increments add their variances. The definition of D makes the coordinate mean square equal to 2 D t. Read the prerequisite
Diffusion coefficient
This is the accepted model diffusivity, not a rate inferred from the synthetic data. Read the prerequisite
Observation interval
This is the interval used for the displayed displacement, not the simulation frame rate. Re-observing the trial preserves its paths. Read the prerequisite

Exact rational SI dimensions were checked at build time. This is a unit check, not a proof of the model. This teaching record is a draft, not a transcription of a printed equation.

RMS distance over recorded time

μm · log scale0.02 s10 s
Solid: this sample. Dashed: the model. The time axis is logarithmic. Zero sample values, if any, remain in the table but cannot appear on a log scale. All times refer to the same recorded paths.
Read the comparison as a table
RMS distance (μm)
Time (s)SampleModel
0.020.130380.13106
0.040.185560.18535
0.10.303680.29307
0.20.404160.41446
0.40.613880.58613
10.986020.92676
21.34951.3106
41.90351.8535
102.87232.9307

What is, and is not, being simulated

These synthetic paths are Gaussian independent increments for dilute spherical tracers in a homogeneous Newtonian liquid. They do not simulate individual molecular collisions, inertia, interactions, sedimentation, walls, localization error or motion blur.

Low Reynolds number and observation times long compared with momentum relaxation are assumed, not verified from fluid and particle data. Lines between samples are a drawing convention; they do not define an instantaneous Brownian speed.

The three latent coordinates are recorded together. Axis, dimension, observation and statistic changes reuse those coordinates. The histogram and statistics use every tracer, including those outside the view.

No FrankenSim WASM artifact is used. Integer random draws follow the pinned Philox mapping; Gaussian conversion uses this host’s math functions and is not claimed bitwise identical across browser engines.

Logical recording draws: 1200000. This result was assembled from a newly generated deterministic recording.

Evaluator source digest: source:sha256:06f140ad57b373415f0056e72c0a61cee543139245eb0f242333675672ccd7b2

Show the code

Audited TypeScript reference evaluator: the owner on this device, or the host fallback for a FrankenSim capability.

stokesEinsteinD · src/physics/reference/diffusion/distributions.ts · revision workspace · sha256:a41fa1ff39026dbed9a701b368028012995d1835d9acebb2e32d5010f47404ec

This is the function that produced the current snapshot.

In words

Take the temperature and the gas constant, divide by the number of molecules in a mole to get the energy scale of one molecule, then divide by the drag on a sphere of this radius in a liquid of this viscosity.

Mathematics

Implementation

/** SI: temperature K, viscosity Pa s, radius m, output m2/s. No ambient constants. */
export function stokesEinsteinD(
  {
    T,
    eta,
    a,
    medium = "liquid",
  }: { T: number; eta: number; a: number; medium?: "liquid" | "gas" },
  set: ConstantSet,
): Evaluation {
  if (![T, eta, a].every((v) => Number.isFinite(v) && v > 0))
    return outside(
      "diffusionCoefficient",
      "stokesEinsteinD",
      "T > 0, eta > 0, a > 0",
      "Enter positive finite temperature, viscosity, and particle radius.",
      "input",
      set,
    );
  if (medium !== "liquid")
    return outside(
      "diffusionCoefficient",
      "stokesEinsteinD",
      "stokes-gas-medium",
      "The liquid Stokes-drag model does not include the slip correction needed in a gas.",
      "model",
      set,
    );
  const k = thermalConstant(set);
  return number(
    "diffusionCoefficient",
    "stokesEinsteinD",
    (k.value * T) / (6 * Math.PI * eta * a),
    set,
    undefined,
    true,
  );
}
One worked example of this calculation. Constant set: Declared 1905-plan inputs (source review pending).
StepExpressionValueUnit
The gas constant in SIR = 8.31e7 erg mol^{-1} K^{-1}8.31J mol^{-1} K^{-1}
Thermal energy per moleRT2411.1465J mol^{-1}
Drag on one sphere6 π η a1.2723450247038662e-8kg s^{-1}
Drag on a mole of spheresN 6 π η a7634070148223197kg s^{-1} mol^{-1}
Diffusion coefficientRT / (N 6 π η a)3.158402337396894e-13m^2 s^{-1}
Coordinate RMS at 1 sλ_x = √(2 D t) at t = 1 s7.947832833416785e-7m
Coordinate RMS at 60 sλ_x = √(2 D t) at t = 60 s0.000006156364840452743m

Audited TypeScript reference evaluator: the owner on this device, or the host fallback for a FrankenSim capability.

rmsDisplacement · src/physics/reference/diffusion/distributions.ts · revision workspace · sha256:6d2d381222179a43397683f83d95eecf9dab253844f72dfcaa1eaab1302222eb

This function computes the listed outputs when it runs.

In words

The typical one-dimensional displacement is the square root of twice the diffusion coefficient times the observation interval.

Mathematics

Implementation

export function rmsDisplacement(D: number, t: number): Evaluation {
  if (!validDt(D, t))
    return outside(
      "rmsDisplacement1d",
      "rmsDisplacement",
      "D >= 0 and t >= 0",
      "Diffusivity and elapsed time must be finite and nonnegative.",
    );
  return number(
    "rmsDisplacement1d",
    "rmsDisplacement",
    scale(D, t),
    undefined,
    undefined,
    D > 0 && t > 0,
  );
}

Audited TypeScript reference evaluator: the owner on this device, or the host fallback for a FrankenSim capability.

apparentSpeed · src/physics/reference/diffusion/distributions.ts · revision workspace · sha256:1f2137435fdc15b0a9b5c91cc4dafba680e8d52b0f5143fdbefdfa9945f6baec

This function computes the listed outputs when it runs.

In words

Divide the model RMS displacement by the observation interval. The quotient depends on how long you watch.

Mathematics

Implementation

export function apparentSpeed(D: number, tau: number): Evaluation {
  if (!validDt(D, tau) || tau === 0)
    return outside(
      "apparentSpeed",
      "apparentSpeed",
      "D >= 0 and tau > 0",
      "An apparent speed needs a positive observation interval.",
    );
  return number(
    "apparentSpeed",
    "apparentSpeed",
    (Math.SQRT2 * Math.sqrt(D)) / Math.sqrt(tau),
    undefined,
    undefined,
    D > 0,
  );
}

Audited TypeScript reference evaluator: the owner on this device, or the host fallback for a FrankenSim capability.

ensembleMoments · src/physics/reference/diffusion/tracers.ts · revision workspace · sha256:1d87c8e69590b8871bcc7a6390089003f59d0b80bfc7eb1919a57dec661743e6

This function computes the listed outputs when it runs.

In words

Average the recorded displacements of every tracer, not a viewport subset.

Mathematics

Implementation

/** Compensated sums over ALL members, never a viewport-selected subset. Row-major M by d. */
export function ensembleMoments({
  displacements,
  d,
  dt,
  viewport,
}: {
  displacements: Float64Array;
  d: number;
  dt?: number;
  viewport?: ViewportBounds;
}): Computation<EnsembleMoments> {
  if (
    !(displacements instanceof Float64Array) ||
    ![1, 2, 3].includes(d) ||
    displacements.length === 0 ||
    displacements.length % d !== 0 ||
    displacements.length > 30000 ||
    !displacements.every(Number.isFinite)
  )
    return invalid(
      ["displacements", "d"],
      "Provide finite, row-major displacements with one, two or three coordinates per tracer.",
    );
  const M = displacements.length / d,
    sums = new Float64Array(d * 3 + 1),
    corrections = new Float64Array(d * 3 + 1);
  function add(i: number, v: number) {
    const corr = corrections[i] ?? 0,
      sum = sums[i] ?? 0,
      y = v - corr,
      t = sum + y;
    corrections[i] = t - sum - y;
    sums[i] = t;
  }
  for (let i = 0; i < M; i++) {
    let norm = 0;
    for (let j = 0; j < d; j++) {
      const v = displacements[i * d + j];
      if (v === undefined) return failure("A required displacement coordinate was undefined.");
      if (v !== 0 && v * v === 0)
        return failure("A nonzero squared displacement is below the representable range.");
      add(j * 3, v);
      add(j * 3 + 1, Math.abs(v));
      add(j * 3 + 2, v * v);
      norm = Math.hypot(norm, v);
    }
    add(d * 3, norm);
  }
  const axes = Array.from({ length: d }, (_, j) => {
    const mean = (sums[j * 3] ?? 0) / M;
    const meanAbsolute = (sums[j * 3 + 1] ?? 0) / M;
    const meanSquare = (sums[j * 3 + 2] ?? 0) / M;
    return {
      mean,
      meanAbsolute,
      meanSquare,
      rms: Math.sqrt(meanSquare),
    };
  });
  const meanSquareNorm = axes.reduce((s, a) => s + a.meanSquare, 0);
  if (![...sums, meanSquareNorm].every(Number.isFinite))
    return failure("The moment reduction exceeded the numerical range.");
  const rmsNorm = Math.sqrt(meanSquareNorm);
  let insideCount: number | undefined;
  let outsideCount: number | undefined;
  if (viewport) {
    let inc = 0;
    let outc = 0;
    for (let i = 0; i < M; i++) {
      let isInside = true;
      for (let j = 0; j < d; j++) {
        const v = displacements[i * d + j] ?? 0;
        const minVal = viewport.min[j] ?? -Infinity;
        const maxVal = viewport.max[j] ?? Infinity;
        if (v < minVal || v > maxVal) {
          isInside = false;
          break;
        }
      }
      if (isInside) inc++;
      else outc++;
    }
    insideCount = inc;
    outsideCount = outc;
  }
  const apparentSpeed =
    dt !== undefined && Number.isFinite(dt) && dt > 0
      ? (d === 1 ? (axes[0]?.rms ?? 0) : rmsNorm) / dt
      : undefined;
  return {
    kind: "accepted",
    data: {
      M,
      axes,
      meanNorm: (sums[d * 3] ?? 0) / M,
      meanSquareNorm,
      rmsNorm,
      ...(apparentSpeed !== undefined ? { apparentSpeed } : {}),
      ...(insideCount !== undefined && outsideCount !== undefined ? { insideCount, outsideCount } : {}),
    },
  };
}

Audited TypeScript reference evaluator: the owner on this device, or the host fallback for a FrankenSim capability.

displacementHistogram · src/physics/reference/diffusion/tracers.ts · revision workspace · sha256:746f24cee7b8573b8a986cd8e072b4786549eba47dffca106dbd38582d670c7b

This function computes the listed outputs when it runs.

In words

Count how many recorded displacements fall in each interval of the histogram.

Mathematics

Implementation

export function displacementHistogram(
  values: Float64Array,
  edges: Float64Array,
): Computation<{ counts: Float64Array; underflow: number; overflow: number; total: number }> {
  if (
    values.length === 0 ||
    values.length > 10000 ||
    edges.length < 2 ||
    edges.length > 1001 ||
    !values.every(Number.isFinite) ||
    !edges.every((v, i) => {
      if (!Number.isFinite(v)) return false;
      if (i === 0) return true;
      const prev = edges[i - 1];
      return prev !== undefined && v > prev;
    })
  )
    return invalid(
      ["values", "edges"],
      "Use finite samples and strictly increasing histogram edges.",
    );
  const counts = new Float64Array(edges.length - 1);
  let underflow = 0,
    overflow = 0;
  const firstEdge = edges[0];
  const lastEdge = edges[edges.length - 1];
  if (firstEdge === undefined || lastEdge === undefined)
    return invalid(["edges"], "Histogram edges array must contain at least two finite bounds.");
  for (const value of values) {
    if (value < firstEdge) {
      underflow++;
      continue;
    }
    if (value > lastEdge) {
      overflow++;
      continue;
    }
    let lo = 0,
      hi = edges.length - 1;
    while (hi - lo > 1) {
      const mid = (lo + hi) >>> 1;
      const edgeMid = edges[mid];
      if (edgeMid !== undefined && value < edgeMid) hi = mid;
      else lo = mid;
    }
    const bin = Math.min(lo, counts.length - 1);
    const prevCount = counts[bin];
    if (prevCount !== undefined) {
      counts[bin] = prevCount + 1;
    }
  }
  return { kind: "accepted", data: { counts, underflow, overflow, total: values.length } };
}
Every histogram count, including tails
Coordinate intervals in μm; half-open bins, with the final endpoint included
IntervalCount
Below the plotted range0
-4.6338 to -4.40210
-4.4021 to -4.17040
-4.1704 to -3.93870
-3.9387 to -3.7070
-3.707 to -3.47530
-3.4753 to -3.24370
-3.2437 to -3.0120
-3.012 to -2.78031
-2.7803 to -2.54861
-2.5486 to -2.31690
-2.3169 to -2.08527
-2.0852 to -1.85357
-1.8535 to -1.62186
-1.6218 to -1.390116
-1.3901 to -1.158412
-1.1584 to -0.9267615
-0.92676 to -0.6950728
-0.69507 to -0.4633824
-0.46338 to -0.2316939
-0.23169 to 039
0 to 0.2316943
0.23169 to 0.4633837
0.46338 to 0.6950726
0.69507 to 0.9267632
0.92676 to 1.158423
1.1584 to 1.390117
1.3901 to 1.62188
1.6218 to 1.85356
1.8535 to 2.08526
2.0852 to 2.31693
2.3169 to 2.54861
2.5486 to 2.78031
2.7803 to 3.0121
3.012 to 3.24371
3.2437 to 3.47530
3.4753 to 3.7070
3.707 to 3.93870
3.9387 to 4.17040
4.1704 to 4.40210
4.4021 to 4.63380
Above the plotted range0
Total, including both tails400

Separate controls and workers; both start with the same worked-example seed. Choose a new trial to compare independently seeded realizations.

A mean near zero does not mean no motion.

x=0,x2=2Dt,λx=2Dt\langle x\rangle=0,\qquad\langle x^2\rangle=2Dt,\qquad\lambda_x=\sqrt{2Dt}

The model’s signed mean is zero; a finite synthetic sample fluctuates around it. The mean square remains positive as the cloud spreads. Four times the observation interval gives twice the model RMS displacement, not four times the RMS.

The apparent-speed trap

λxτ=2Dτ\frac{\lambda_x}{\tau}=\sqrt{\frac{2D}{\tau}}

Dividing the typical displacement by the observation interval produces a quantity that grows as the interval shrinks. It is an interval-dependent apparent speed, not an instantaneous velocity of a tracer. At zero elapsed time it is not defined.

The accepted sample and the model curves are not experimental evidence. The source-aligned critical edition and reviewed historical constants remain in preparation.