Repository navigation
Releases: mbustama/Magnus
Release list
v1.2.0
Magνs 1.2.0.
Magνs 1.2.0 fixes three physics errors, so some results change. It also validates inputs more strictly and adds a few features.
Results that change
- Electron density from mass density. A density in g/cm³ is now converted with the atomic mass unit, ρ N_A Y_e, as in nuSQuIDS, GLoBES, Prob3++, NuFast, OscProb, and nuCraft. Before, it was 0.8% too low. Probabilities through the Earth's core change by up to 0.065 at 1–20 GeV (#168).
- Lorentz violation for antineutrinos. The Lorentz-violating term now changes sign for antineutrinos when
n_livis even, including the defaultn_liv=0. Neutrinos, and oddn_liv, are unchanged (#162). average=True. It now returns the phase average over an energy spread set by the new keywordaverage_spread(default 0.1). Before, it kept or dropped each interference term outright (#64).
Fixed
- Calls from several threads no longer interfere (#153).
- A tight tolerance on the Sun no longer gives a worse answer than the default.
- Undeclared jumps and narrow spikes in a profile no longer end the refinement on a wrong answer.
Changed
- Arguments are checked once per call, by one set of rules, at every entry point. Values that used to be ignored or misread now raise an error that names the argument (#160).
- The 1-3 CP phase is
dCP, and the Lorentz-violating onedxiCP, at every number of flavors. The old namesd13anddxi13still work, with aFutureWarning(#121). - Every Hamiltonian builder accepts an array for its varying argument (#155).
Added
osc_prob_pseudo_dirac_vacuum, whose phase average stays exact even for very small splittings (#165).- Oscillograms with non-standard interactions and Lorentz violation (#146), and
nubar=on the probability plots (#145). - On the command line,
probis optional (#138).
Install or upgrade with pip install -U magnuspy. The full list of changes is in the changelog.
v1.0.0
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 magnuspyPython 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
rtoland 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_nsibuilt the standard part of its matter Hamiltonian as a literaldiag(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.5to 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
- Documentation — https://mbustama.github.io/Magnus/
- Quick start — https://mbustama.github.io/Magnus/quickstart.html
- Notebooks — https://mbustama.github.io/Magnus/tutorials.html
- Against other codes — https://mbustama.github.io/Magnus/comparison.html
GPL-3.0-only. Mauricio Bustamante (mbustamante@gmail.com).