Available probability functions

This page lists the osc_prob_* functions Magνs ships, grouped by environment and scenario, with the name for each flavor count. Use it when you know what you want (“3-flavor, matter, with NSI”) but not the function’s name; API reference documents each one in full.

Two groups of functions are not listed in the tables. The layers below the wrappers (the scenario functions, osc_prob_energy_baseline and osc_prob) are described in Code architecture. The closed-form functions osc_prob_2nu_vacuum_std, osc_prob_2nu_matter_std and osc_prob_3nu_vacuum_std, which validate the numerical ones, are in magnus.oscprob. Command-line calculator is the command-line calculator that wraps the same functions.

Every function in the tables below returns a full \(d \times d\) probability matrix (\(P[i][j] = P(\nu_i \to \nu_j)\)), or a single channel if nu_i and nu_f are both given. Each of them also accepts nubar=True to compute the antineutrino probability. Standard oscillation parameters left unset default to the NuFIT 6.1 best fit (normal ordering) [EGonzalezGarciaM+24]; sterile-sector parameters (4th/5th flavor) default to zero mixing.

Vacuum

There is no matter potential: the flavor Hamiltonian is the vacuum mass/mixing term, evaluated once and scaled by \(1/E\).

Flavors

Standard

LIV

2

osc_prob_2nu_vacuum()

osc_prob_2nu_vacuum_liv()

3

osc_prob_3nu_vacuum()

osc_prob_3nu_vacuum_liv()

4 (3+1 sterile)

osc_prob_4nu_vacuum()

osc_prob_4nu_vacuum_liv()

5 (3+2 sterile)

osc_prob_5nu_vacuum()

osc_prob_5nu_vacuum_liv()

There is no “vacuum + NSI” family: NSI couplings scale the matter potential, and vacuum has none to scale (the CLI rejects this combination explicitly; see Command-line calculator).

Pseudo-Dirac neutrinos in vacuum, with a sterile partner on any of the three mass states, have their own function, osc_prob_pseudo_dirac_vacuum(). It takes the pairing and the splittings and returns a \((3+n_\text{pairs})\times(3+n_\text{pairs})\) probability matrix. Its average=True forms each pair’s phase from its splitting directly, so it stays exact for splittings too small for the generic route to resolve; see the note on pseudo-Dirac pairs.

Matter, constant density

These functions take a user-supplied matter density, uniform along the trajectory. rho is in natural units, eV4: pass 2.8*gd.UNIT_G_PER_CM3, or pass 2.8 together with density_matter_is_in_g_per_cm3=True, but not both. electron_fraction, the number of electrons per atomic mass unit \(Y_e\) (Conventions), is 0.5 unless given. The command line’s --rho is in g cm-3.

Flavors

Standard

NSI

LIV

2

osc_prob_2nu_matter_constant_density()

osc_prob_2nu_matter_nsi_constant_density()

osc_prob_2nu_matter_liv_constant_density()

3

osc_prob_3nu_matter_constant_density()

osc_prob_3nu_matter_nsi_constant_density()

osc_prob_3nu_matter_liv_constant_density()

4

osc_prob_4nu_matter_constant_density()

osc_prob_4nu_matter_nsi_constant_density()

osc_prob_4nu_matter_liv_constant_density()

5

osc_prob_5nu_matter_constant_density()

osc_prob_5nu_matter_nsi_constant_density()

osc_prob_5nu_matter_liv_constant_density()

Matter, exponential density

These functions take a user-supplied matter density profile \(\rho(l) = \rho_{\rm central}\, e^{-l/l_{\rm scale}}\), with rho_central in the same units as rho above and l_scale in eV-1.

Flavors

Standard

NSI

LIV

2

osc_prob_2nu_matter_exp_density()

osc_prob_2nu_matter_nsi_exp_density()

osc_prob_2nu_matter_liv_exp_density()

3

osc_prob_3nu_matter_exp_density()

osc_prob_3nu_matter_nsi_exp_density()

osc_prob_3nu_matter_liv_exp_density()

4

osc_prob_4nu_matter_exp_density()

osc_prob_4nu_matter_nsi_exp_density()

osc_prob_4nu_matter_liv_exp_density()

5

osc_prob_5nu_matter_exp_density()

osc_prob_5nu_matter_nsi_exp_density()

osc_prob_5nu_matter_liv_exp_density()

Earth

These functions use the Preliminary Reference Earth Model (PREM) density profile along a chord specified either by the cosine of the zenith angle (plus a baseline) or by two named locations (loc_ini/loc_fin; see magnus.earth.loc_coords_dms for the predefined sites). A value of \(\cos\theta_z = -1\) is straight up through the Earth’s center and 0 is horizontal; magnus.earth.distance_traveled_inside_earth() gives the chord length for a zenith angle. The electron fraction \(Y_e\), the number of electrons per atomic mass unit (Conventions), is set per layer (0.4656 in the core, 0.4957 in the mantle). electron_fraction_core, electron_fraction_mantle and the other electron_fraction_* keywords override it.

Both named locations lie on the surface. Either end of the trajectory can instead be put underground with source_depth and detector_depth, which every function below accepts. The zenith angle is measured at the detector, so a buried detector also sees downward-going neutrinos (\(\cos\theta_z > 0\)), which cross its overburden; a detector on the surface does not. Naming detector_depth fixes where the trajectory ends, so the baseline is computed rather than given. A third keyword, density_matter_ocean, replaces the density of PREM’s outermost shell, a global-average ocean that does not describe a detector under rock or ice, and electron_fraction_ocean sets its composition.

Flavors

Standard

NSI

LIV

2

osc_prob_2nu_earth()

osc_prob_2nu_earth_nsi()

osc_prob_2nu_earth_liv()

3

osc_prob_3nu_earth()

osc_prob_3nu_earth_nsi()

osc_prob_3nu_earth_liv()

4

osc_prob_4nu_earth()

osc_prob_4nu_earth_nsi()

osc_prob_4nu_earth_liv()

5

osc_prob_5nu_earth()

osc_prob_5nu_earth_nsi()

osc_prob_5nu_earth_liv()

Sun

These functions use the built-in exponentially falling solar electron-density profile (see magnus.oscprob.osc_prob_sun()), from an initial radial position L0 (0 is the center) to a final radial position L, both in eV-1; gd.SUN_RADIUS*gd.UNIT_KM is the surface. A solar-neutrino measurement is the phase-averaged probability: pass average=True. Every function in the table below takes density_profile to use one of twelve tabulated standard solar models instead (see Standard solar models).

Flavors

Standard

NSI

LIV

2

osc_prob_2nu_sun()

osc_prob_2nu_sun_nsi()

osc_prob_2nu_sun_liv()

3

osc_prob_3nu_sun()

osc_prob_3nu_sun_nsi()

osc_prob_3nu_sun_liv()

4

osc_prob_4nu_sun()

osc_prob_4nu_sun_nsi()

osc_prob_4nu_sun_liv()

5

osc_prob_5nu_sun()

osc_prob_5nu_sun_nsi()

osc_prob_5nu_sun_liv()

Generic entry points

For anything the tables above do not cover — any other number of flavors, or a Hamiltonian that does not fit the vacuum/matter/NSI/LIV mold — four functions accept an arbitrary user-supplied Hamiltonian directly:

  • osc_prob() — the general Magnus ladder, the base layer: any Hamiltonian, any dimension, any environment you build yourself.

  • osc_prob_energy_baseline() — like osc_prob, but takes an energy and a baseline and accepts arrays of either.

  • osc_prob_earth() — like osc_prob, but handles the Earth-crossing geometry and PREM potential for you.

  • osc_prob_sun() — like osc_prob, but handles the solar density profile for you.

The osc_prob_{N}nu_* functions above are built on osc_prob_energy_baseline and osc_prob; see Code architecture.

Returning the evolution operator

Every function above returns probabilities. Observables built from amplitudes, such as the mass-eigenstate content of the state that leaves a star, need the evolution operator. For those, pass return_evolution_operator=True to any of the functions, and the call returns the pair (P, U) instead of P alone; The evolution operator, for observables built from amplitudes shows a worked example.

P is exactly what the call returns without the keyword, so nu_i, nu_f and the batching over arrays keep their meaning. U is the complex, unitary evolution operator over the same interval, in the flavor basis. U[final, initial] is the amplitude from the initial to the final flavor, so P == (abs(U)**2).T. For arrays of points it has shape (n, d, d), and P == np.swapaxes(abs(U)**2, -1, -2).

The operator comes from the general Magnus ladder, the only engine that forms it. With the keyword set, the ladder compares the operator itself between refinement levels, at the same rtol and atol, so its phases converge as well as its moduli. The specialized engines of Engines and dispatch are skipped for the call, and a baseline scan is computed point by point. Two combinations raise an error because neither forms an operator: average=True and strategy='hybrid'.

The phase average is also available when you pass your own Hamiltonian. average=True on osc_prob_energy_baseline, osc_prob_earth and osc_prob_sun behaves as it does on a wrapper and uses the same three routes: closed form, adiabatic transport or an energy-window average across declared discontinuities. The same keywords apply: average_spread sets the spread, average_n_samples the number of energies in a window average, and average_initial_state the starting state, the flavor state by default. A Hamiltonian given as a matrix, or as a function of position alone, does not depend on energy, so no spread acts on it; pairs of levels with a large phase are averaged and the others stay coherent (see Phase-averaged probabilities). osc_prob computes a single point, so it refuses average, as it refuses cumulative.