Skip to content

v1.0.0

Choose a tag to compare

@mbustama mbustama released this 13 Aug 09:27
· 628 commits to main since this release
f49eeff

The first public release of Magνs — a Python package for neutrino oscillation probabilities between an arbitrary number of flavors, for any Hamiltonian, time-dependent or not.

It works by the Magnus expansion: instead of integrating the Schrödinger equation step by step, it exponentiates truncated time-ordered integrals of the Hamiltonian over a chain of position slabs. Any truncation of the series lives in the Lie algebra, so the evolution operator is exactly unitary by construction — probabilities are non-negative and sum to one at machine precision, at every accuracy setting.

Install

pip install magnuspy

Python 3.10 or newer. The distribution is magnuspy; the import package is magnus.

import magnus.oscprob as oscprob
import magnus.globaldefs as gd

# Three-flavor vacuum probability at 1 GeV over 1000 km
P = oscprob.osc_prob_3nu_vacuum(1.0*gd.UNIT_GEV, 1000.0*gd.UNIT_KM)
print(P[gd.NUMU][gd.NUE])

Oscillation parameters left unset default to the current global fit, so that call is complete as it stands.

What it computes

  • Two to five flavors, in vacuum and in matter, with a dedicated named function for every combination of flavor count, environment and scenario.
  • Environments: constant density, exponential profiles, the Earth through PREM, the Sun, a tabulated model from disk, or any density profile or Hamiltonian you supply.
  • Beyond the Standard Model: non-standard interactions, Lorentz-invariance violation, sterile states (3+1 and 3+2).
  • Phase-averaged probabilities — the quantity a solar experiment actually measures — evaluated in closed form and returned directly, rather than estimated by averaging a scan over a window.
  • An accuracy, not a slab count: ask for rtol and the refinement ladder finds the resolution.
  • An adiabatic + Magnus hybrid for trajectories carrying extreme accumulated phase.
  • A command-line calculator — magnus prob ... — for one probability without writing Python.

Why you might trust it

  • 1207 tests, run on Python 3.10 through 3.13, at 93% coverage, including a clean-room install of the built wheel.
  • Unitarity is structural, not checked afterwards — a property of the truncation, at any order.
  • Measured against other codes rather than asserted: a documented comparison against NuOscProbExact and nuSQuIDS, every case refereed by a third method, with the boundary stated plainly — where a closed form exists and the accumulated phase is large, use the closed form.
  • 27 example notebooks, executed in CI so their numbers cannot drift from the code.
  • Constants are documented where they live, each with the measurement that set it.

A known limitation, stated rather than hidden

On an Earth chord with a sterile state, the matter potential's density is resolved per PREM layer, while the sterile states' entry in the projector takes a single scalar for the whole chord — no single value is right for a chord crossing iron and rock. The Earth entry points warn when the two disagree by more than 2%, naming the path-averaged ratio to pass. No number changes unless you act on the warning. The position-dependent fix is tracked as #47.

If you have been running this from a git checkout

Everything above is new to PyPI, but the repository has been usable for a while. Four changes move numbers, so results produced from an earlier checkout should be re-run:

Two wrong-answer bugs, both in published entry points:

  • Sterile states felt no matter at all on the NSI route. osc_prob_matter_nsi built the standard part of its matter Hamiltonian as a literal diag(1, 0, 0, 0), so sterile states carried zero where they carry −V_NC = (r/2)V_CC. With every coupling set to zero the route must reproduce the standard one, and did not: 5.2e-02 at four flavors, 5.1e-02 at five. Three flavors agreed throughout, which is why nothing caught it.
  • The solar LIV routes read the Sun's electron number density as a mass density, forwarding a flag that defaulted to False. Off by up to 0.69 in probability.

Two deliberate defaults that change results:

  • The Earth's electron fraction is now resolved per PREM layer — iron core 0.4656, peridotite mantle 0.4957, granitic crust 0.4952, seawater ocean 0.5551 — with the neutron-to-proton ratio derived from it. Up to a factor of four on core-crossing chords. Pass electron_fraction=0.5 to reproduce the old uniform composition.
  • The default oscillation parameters are NuFIT 6.1, derived from load_nufit_params() so the implicit values cannot drift from the loader again. 4.0e-03 in probability.

The changelog carries the full list, with the measurement behind each entry.

Links

GPL-3.0-only. Mauricio Bustamante (mbustamante@gmail.com).