Beyond Point Masses

From particles to fields

Real gravitational anomalies are rarely points — ore bodies, voids, aquifers, anything extended. The same machinery handles them: replace the point-mass forward model with one that integrates the potential over a continuous profile. Here, a Gaussian density with three parameters — center \(\mu\), width \(\sigma\) (the profile’s own width here, not the observation noise from earlier pages), and peak amplitude \(A\) — and the identical particle filter on top.

The density demo. Left: true vs inferred density profile. Center: the clock rates both produce. Right: convergence of all three parameters.

This committed PNG is the current packaged default output from the corrected SMC implementation.

What spreading the mass does to clocks

Code
import matplotlib.pyplot as plt
import numpy as np
from clocks import ClockArray, MassConfig, clock_rates, clock_rates_density_gaussian

xs = np.linspace(-8, 8, 200).reshape(-1, 1)
dense = ClockArray(positions=xs, track_offset=1.0)
total_mass = 0.02

fig, ax = plt.subplots()
point = MassConfig(positions=np.array([[1.5]]), masses=np.array([total_mass]))
ax.plot(xs[:, 0], clock_rates(point, dense), label="point mass", color="black")
for sigma, color in [(0.5, "steelblue"), (2.0, "lightcoral")]:
    amplitude = total_mass / (sigma * np.sqrt(2 * np.pi))
    rates = clock_rates_density_gaussian(
        np.array([1.5, sigma, amplitude]), dense
    )
    ax.plot(xs[:, 0], rates, label=f"Gaussian, σ = {sigma}", color=color)
ax.set_xlabel("clock position")
ax.set_ylabel("tick rate")
ax.legend()
plt.close(fig)
fig

A point mass vs Gaussian profiles of equal total mass at two widths. Spreading the mass flattens and broadens the dip in tick rates.

A new degeneracy

The model admits a ridge where \(\sigma\) and \(A\) trade off: a wider, weaker profile and a narrower, denser one can produce nearly identical potentials at a handful of clock positions. This is the same inverse-problem pattern as the mass–distance degeneracy: different physical profiles map to nearly identical clock-rate data. The library’s rejuvenation move uses a regularized empirical covariance to propose steps along correlated directions. Crucially, Metropolis-Hastings accepts or rejects those symmetric proposals against the current tempered target; covariance geometry improves mixing without redefining the posterior. The density demo samples a uniform box in \((\mu,\sigma,A)\) conditioned on that box and weak-field validity, and uses the same support for its prior density.

NoteWhere this could go

The repo’s someday-maybe list sketches the next steps: a special-relativity velocity term so SR and GR compete the way they do for real GPS satellites, and an in-browser interactive version — the inference engine is pure numpy/scipy, which Pyodide already supports. First, though, one last question: could you feel gravity?