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 |
||
3 |
||
4 (3+1 sterile) |
||
5 (3+2 sterile) |
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 |
|||
3 |
|||
4 |
|||
5 |
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 |
|||
3 |
|||
4 |
|||
5 |
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 |
|||
3 |
|||
4 |
|||
5 |
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 |
|||
3 |
|||
4 |
|||
5 |
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()— likeosc_prob, but takes an energy and a baseline and accepts arrays of either.osc_prob_earth()— likeosc_prob, but handles the Earth-crossing geometry and PREM potential for you.osc_prob_sun()— likeosc_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.