wifi-densepose/v2/crates/nvsim
ruv 177624174e feat(nvsim): sensor.rs NV ensemble [nvsim:pass4]
Pass 4 of the implementation plan — the load-bearing physics module.
Linear-readout proxy for ODMR ensemble magnetometry per Barry et al.
*Rev. Mod. Phys.* 92, 015004 (2020) §III.A. Full Hamiltonian + Lindblad
dynamics is *out of scope* (plan §6); the leading-order formulae below
are validated as adequate for ensemble magnetometers in the linear
regime.

Public API (re-exported from lib.rs):

- NvSensorConfig — gamma_fwhm_hz / t1_s / t2_s / t2_star_s / contrast /
  n_spins / shot_noise_disabled. Defaults match Barry 2020 Table III
  for COTS bulk diamond.
- NvSensor::cots_defaults() / new(config)
- NvSensor::lorentzian(δν) — normalised Lorentzian, 1.0 on resonance,
  0.5 at half-width
- NvSensor::t2_envelope(t) — exp(-t/T2)
- NvSensor::shot_noise_floor_t_sqrt_hz(t) — δB ∝ 1/(γ_e·C·√(N·t·T2*))
- NvSensor::sample(B_in, dt, seed) -> NvReading — projects B onto 4 NV
  axes, adds shot noise, recovers via LSQ inversion, returns:
    b_recovered, sigma_per_axis, noise_floor_t_sqrt_hz, odmr_nu_plus_hz
- nv_axes() — 4 〈111〉 crystallographic axes (Doherty 2013 §3)

LSQ inversion uses the closed-form (AᵀA) = (4/3) I for the regular
tetrahedron — verified by `nv_axes_form_orthogonal_set_in_aggregate`.

Determinism (plan §5): shot noise is sampled from a ChaCha20 PRNG
seeded explicitly per `sample` call. Same (B_in, dt, seed) ⇒
byte-identical NvReading. New rand + rand_chacha deps, both
crates.io-pinned.

8 new tests:
- lorentzian_fwhm_within_5_percent (FWHM = 1.0 ± 0.05 MHz)
- shot_noise_scales_as_one_over_sqrt_t_over_5_decades
  (Barry 2020 Eq. 35; 5 decades from 1 µs to 100 ms)
- t2_envelope_is_exp_minus_t_over_t2
- lsq_recovery_residual_below_one_percent_with_noise_off
  (4-axis LSQ inversion exactness)
- zero_input_with_noise_yields_approximately_zero_mean
  (n=1024 sample mean ≤ σ_mean of zero per axis)
- shot_noise_floor_within_4x_of_wolf_2015_reference
  (Pass-4 acceptance gate per plan §3 / §7-2)
- determinism_same_seed_produces_byte_identical_reading
- nv_axes_form_orthogonal_set_in_aggregate
  ((AᵀA) = (4/3)I tetrahedron property)

Pass 4 acceptance gate: shot-noise floor at t=1s lands within 4× of
Wolf 2015's 0.9 pT/√Hz bulk-diamond reference. Gate PASSED — no
abort under §7-2.

Validated:
- cargo test -p nvsim → 34 passed (was 26; +8).
- cargo test --workspace --no-default-features → 1,609 passed,
  0 failed, 8 ignored (was 1,601; +8).
- ESP32-S3 on COM7 unaffected.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-26 16:40:49 -04:00
..
src feat(nvsim): sensor.rs NV ensemble [nvsim:pass4] 2026-04-26 16:40:49 -04:00
Cargo.toml feat(nvsim): sensor.rs NV ensemble [nvsim:pass4] 2026-04-26 16:40:49 -04:00
README.md feat(nvsim): scaffold + scene + frame [nvsim:pass1] 2026-04-26 15:57:58 -04:00

README.md

nvsim

Deterministic Rust simulator for NV-diamond ensemble magnetometer pipelines.

nvsim models a forward-only magnetic sensing path:

scene
  → magnetic source synthesis
  → material attenuation
  → NV-ensemble response
  → digitisation
  → binary magnetic feature frames
  → deterministic SHA-256 witness

It is designed for ferrous-anomaly modeling, eddy-current sanity checks, synthetic magnetic traces, sensor education, and regression testing.

It is not a hardware-control stack, microscope simulator, full Hamiltonian solver, or claim of fT-level sensitivity. This crate does not control lasers, microwave sources, ADC hardware, or real NV sensors.

Deterministic in the strong sense: a simulator with explicit physics approximations, conjectural propagation defaults that are documented as such, a linear NV-ensemble readout proxy validated by Barry et al. Rev. Mod. Phys. 92, 015004 (2020) §III.A, and no hidden mocks.

Quick start

use nvsim::scene::{Scene, DipoleSource};
use nvsim::frame::{MagFrame, MAG_FRAME_MAGIC};

let mut scene = Scene::new();
scene.add_dipole(DipoleSource::new([0.0, 0.0, 0.5], [0.0, 0.0, 1e-6]));
scene.add_sensor([0.0, 0.0, 0.0]);

// Pass 2+ adds source synthesis, propagation, sensor, digitiser, pipeline.

Acceptance commitments (per implementation plan §5)

  • Pipeline throughput: ≥ 1 kHz simulated samples per second of wall-clock on a Cortex-A53-class CPU.
  • Determinism: same (scene, seed) produces byte-identical proof-bundle output across runs and machines.
  • Noise floor reproduction: simulator with shot-noise OFF reproduces the analytical BiotSavart result to ≤ 0.1% RMS.
  • Lockin SNR floor: 1 nT @ 1 kHz vs 100 pT/√Hz floor → SNR ≥ 10 in 1 s.

Pass 1 (this build) ships only the scaffold + scene types + binary frame shape; the four acceptance numbers come online over Passes 26 per the plan.

Physics primary sources

  • Jackson, Classical Electrodynamics 3e (1999), §5.45.8 — BiotSavart, dipole field.
  • Doherty et al., Phys. Rep. 528, 1 (2013) — NV ground-state Hamiltonian, ODMR transition.
  • Barry et al., Rev. Mod. Phys. 92, 015004 (2020) — NV-ensemble sensitivity, Lorentzian lineshape.
  • Wolf et al., Phys. Rev. X 5, 041001 (2015) — bulk-diamond pT/√Hz reference floor.
  • Ortner & Bandeira, SoftwareX 11, 100466 (2020) — Magpylib reference implementation.

See docs/research/quantum-sensing/14-nv-diamond-sensor-simulator.md for context and 15-nvsim-implementation-plan.md for the build spec.

Optional integrations

nvsim is a standalone leaf crate. RuView ecosystem integrations (wifi-densepose-core frame alignment, ruvector-core trace compression, etc.) land behind feature flags in follow-up passes once the core simulator ships. None are required to use this crate.

License

MIT OR Apache-2.0 (matches workspace default).