Conventions

These are the conventions Magνs follows: the parametrization, signs, units and indexing that another code may choose differently. A convention applied wrongly but consistently passes every internal test, so each one is stated here.

At a glance

What

Convention

Probability matrix

P[i][f] is \(P(\nu_i \to \nu_f)\), initial flavor first; flavors in the order \((e, \mu, \tau, s_1, s_2)\); a batched call puts the point index first, (n_points, d, d)

Mixing matrix

The PDG parametrization,

\[\mathbb{R} = \mathbb{R}_{23}(\theta_{23})\,\mathbb{R}_{13}(\theta_{13},\delta_{\rm CP})\, \mathbb{R}_{12}(\theta_{12}),\]

with \(\mathbb{R}_{e3} = \sin\theta_{13}\,e^{-i\delta_{\rm CP}}\)

Mixing angles

Given as sines by default; angles='sin2', 'rad' or 'deg' changes that

CP phases

Radians (degrees under angles='deg')

Mass splittings

D21 \(= m_2^2 - m_1^2\), D31 \(= m_3^2 - m_1^2\), in eV2; the ordering is the sign of D31

Inverted ordering from NuFIT

NuFIT quotes \(\Delta m^2_{32}\); load_nufit_params(..., 'IO') returns D31 \(= \Delta m^2_{32} + \Delta m^2_{21}\)

Antineutrinos

nubar=True conjugates the mixing matrix and flips the sign of the matter potential. A Lorentz-violating term is conjugated too, and changes sign when n_liv is even: an operator of dimension n_liv + 3 is CPT-odd when n_liv + 3 is odd, as in the Standard-Model Extension (Kostelecký & Mewes, Phys. Rev. D 85, 096005 (2012))

Matter potential

\(V_{\rm CC} = +\sqrt{2} G_F n_e\) on the \(\nu_e\) entry; \(Y_e = 0.5\) by default, and one value per layer in the Earth (0.4656 core, 0.4957 mantle)

Units

Natural units: energies in eV, distances in eV-1, densities in eV4; see Units

The Hamiltonian and the probability

The state of \(n\) flavors evolves under an \(n \times n\) Hermitian Hamiltonian \(\mathbb{H}\). The solution of the Schrödinger equation defines the evolution operator \(\mathbb{U}(l_1, l_0)\), and the probability that a neutrino born as \(\nu_\alpha\) is detected as \(\nu_\beta\) is

(1)\[P_{\nu_\alpha \to \nu_\beta}(l_1, l_0) = \left\lvert \left[\mathbb{U}(l_1,l_0)\right]_{\beta\alpha} \right\rvert^2 .\]

In vacuum,

(2)\[\mathbb{H}^{\rm vac}(E) = \frac{1}{2E}\, \mathbb{R}\, \mathbb{M}^2\, \mathbb{R}^\dagger , \qquad \mathbb{M}^2 = {\rm diag}(0, \Delta m^2_{21}, \Delta m^2_{31}, \ldots) ,\]

with the mixing matrix \(\mathbb{R}\) a product of rotations. Each \(\mathbb{R}_{ij}\) rotates by \(\theta_{ij}\) in the \((i,j)\) plane, with \(\sin\theta_{ij}\,e^{-i\delta_{ij}}\) in entry \((i,j)\):

(3)\[\begin{split}\mathbb{R} = \begin{cases} \mathbb{R}_{12} , & n = 2 , \\ \mathbb{R}_{23}\, \mathbb{R}_{13}\, \mathbb{R}_{12} , & n = 3 , \\ \mathbb{R}_{34}\, \mathbb{R}_{24}\, \mathbb{R}_{14}\, \mathbb{R}_{23}\, \mathbb{R}_{13}\, \mathbb{R}_{12} , & n = 4 , \\ \mathbb{R}_{35}\, \mathbb{R}_{25}\, \mathbb{R}_{15}\, \mathbb{R}_{34}\, \mathbb{R}_{24}\, \mathbb{R}_{14}\, \mathbb{R}_{23}\, \mathbb{R}_{13}\, \mathbb{R}_{12} , & n = 5 . \end{cases}\end{split}\]

At three flavors, this is the PMNS matrix, and the phase of \(\mathbb{R}_{13}\) is \(\delta_{\rm CP}\). Of the sterile rotations, only \(\mathbb{R}_{14}\), \(\mathbb{R}_{24}\), \(\mathbb{R}_{15}\) and \(\mathbb{R}_{35}\) carry a phase.

In matter, the charged-current potential enters through a diagonal projector \(\mathbb{P}\):

(4)\[\mathbb{H}(E, l) = \mathbb{H}^{\rm vac}(E) + V_{\rm CC}(l)\, \mathbb{P}(l) , \qquad V_{\rm CC} = \sqrt{2}\, G_F\, n_e(l) .\]

At three flavors, \(\mathbb{P} = {\rm diag}(1, 0, 0)\). With sterile states, \(\mathbb{P} = {\rm diag}(1, 0, 0, r/2, \ldots)\), with \(r = n_n/n_p\) (ratio_number_neutrons_to_protons): the neutral-current potential, common to the active flavors, is subtracted from the whole diagonal, and what it leaves on a sterile state is \((r/2)\,V_{\rm CC}\). magnus.matter.matter_potential_projector() builds \(\mathbb{P}\) for every flavor count.

Ordering of the probabilities

Every osc_prob_* function returns the probability matrix indexed initial flavor first:

\[P[\nu_i][\nu_f] \;=\; P(\nu_i \to \nu_f) .\]

For example, P[1][0] is \(P(\nu_\mu \to \nu_e)\), not the reverse. Flavors are in the standard order \((e, \mu, \tau, s_1, s_2)\), so index 0 is always \(\nu_e\).

Each row sums to one — a neutrino that started as \(\nu_i\) ends as something. Each column also sums to one; both sums follow from unitarity. Passing nu_i and nu_f returns that one entry instead of the matrix.

For a batched call, the point index comes first: the shape is (n_points, d, d), so P[:, 1, 0] is \(P_{\mu e}\) along a scan.

Sign of the matter potential

The charged-current potential enters the electron-flavor diagonal entry,

\[\mathbb{H} \;=\; \mathbb{H}^{\rm vac} \;+\; \mathrm{diag}(V_{\rm CC},\, 0,\, \ldots) , \qquad V_{\rm CC} = +\sqrt{2}\, G_F n_e ,\]

and for antineutrinos it changes sign. That flip is applied once, inside magnus.matter.vcc_func_from_rho_func(), so a user passing nubar=True gets it automatically, and code downstream must not apply it again. Applied twice, it would give antineutrinos a positive potential, and the resulting probabilities would still look plausible.

Mass ordering

The ordering is carried by the sign of \(\Delta m^2_{31}\), not by a flag: positive is normal, negative is inverted. The default parameter set, OSC_PARAMS_PREDEFINED['OSC_PARAMS_DEFAULT'], is the normal ordering, with \(\Delta m^2_{31} = +2.511 \times 10^{-3}\) eV2. It is NuFIT 6.1 with Super-Kamiokande atmospheric data, the release load_nufit_params() returns by default. To name a fit explicitly, magnus.globaldefs.OSC_PARAMS_PREDEFINED holds every NuFIT release from 1.0 on, in both orderings and, from 4.0 on, with and without that atmospheric data. Its names are generated from gd.NUFIT_GLOBAL_FITS, the table that load_nufit_params() reads.

For two flavors, the same rule applies to \(\Delta m^2\), which is what makes the two-flavor case easy to get backwards: flipping its sign moves the MSW resonance into the other channel, and the result still looks like an ordinary probability.

Mixing parameters

Angles are given as sines by default (angles='sin'): s12 is \(\sin\theta_{12}\), not the angle and not \(\sin^2\theta_{12}\). Setting angles='sin2', 'rad' or 'deg' selects the other forms. Under 'rad' and 'deg', an angle beyond \(\pm 90^\circ\) is refused, because the cosine is taken as \(+\sqrt{1 - s^2}\). Fits usually quote \(\sin^2\theta\); pass those with angles='sin2', or take the square root, e.g., s12 = np.sqrt(0.309). Phases are in radians; the default \(\delta_{\rm CP}\) is 3.7001 rad, i.e., 212°.

Two flavors take sth and Dm2 rather than s12 and D21. A mistake here cannot pass unnoticed: unrecognized keywords are refused by name, so a two-flavor call written with the three-flavor names raises an error instead of returning a probability computed from the defaults.

Units

Magνs uses natural units throughout: energies in eV, baselines and positions in eV-1, so that \(\mathbb{H} L\) is dimensionless. magnus.globaldefs supplies the conversions — multiply by UNIT_KM, UNIT_MEV, UNIT_GEV, UNIT_G_PER_CM3 — and Units lists them.

Coming from GLoBES, Prob3++ or nuSQuIDS

The physics is the same; the bookkeeping differs. Each entry for the other codes is what the drivers behind Against other codes pass them (resources/benchmarks/external_drivers, in a source checkout).

Magνs

GLoBES

Prob3++

nuSQuIDS

Energy

eV: multiply GeV by gd.UNIT_GEV

GeV

GeV

its own units: E*units.GeV, with units = nuSQuIDS.Const()

Baseline

eV-1: multiply km by gd.UNIT_KM

km

km, or a zenith cosine through the Earth

its own units: L*units.km

Density

natural units, or g cm-3 with density_matter_is_in_g_per_cm3=True

g cm-3

g cm-3

g cm-3

\(Y_e\)

electron_fraction, 0.5 by default; per layer through the Earth

fixed at 0.5 inside the code

from the profile file on the Earth path

an argument of the body, e.g., ConstantDensity(rho, 0.5)

Flavor indices

0, 1, 2 = e, μ, τ; P[initial][final]

1, 2, 3; (initial, final, …)

1, 2, 3; GetProb(initial, final)

0, 1, 2; initial state set, then EvalFlavor(final)

Antineutrinos

nubar=True

cp_sign = -1

a negative neutrino type

NeutrinoType.antineutrino

Angles

sines by default; angles='sin2', 'rad' or 'deg'

radians, in the order θ12, θ13, θ23

\(\sin^2\theta\) (kSquared=true) or \(\sin^2 2\theta\), in the order θ12, θ13, θ23

radians, Set_MixingAngle(i, j, θ)

Splittings and ordering

D21, D31; the sign of D31 is the ordering

Δm²21, Δm²31

Δm²21 and Δm²32, not Δm²31

Set_SquareMassDifference(1, Δm²21), (2, Δm²31)

\(\delta_{\rm CP}\)

radians (degrees under angles='deg')

radians

radians

radians, Set_CPPhase(0, 2, δ)

Two differences matter at the level of the comparison itself:

  • The matter potential for a given density. Every code converts g cm-3 to an electron density as \(\rho N_A Y_e\), but with its own rounding of the constant \(\sqrt{2} G_F N_A\): Prob3++’s value is 0.04% below Magνs’s, and the comparison drivers correct for the difference. The stored benchmark data predate the potential correction in version 1.2.0, which raised the Magνs potential by 0.8%; their rescaling factors (0.992 for GLoBES) include that difference.

  • Prob3++ takes Δm²32. Passing Δm²31 in its place changes probabilities by up to 0.26.