mirror of
https://github.com/vale981/neutrino_oscillations
synced 2025-03-04 09:11:39 -05:00
init
This commit is contained in:
commit
1903c3db4e
5 changed files with 375 additions and 0 deletions
88
index.html
Normal file
88
index.html
Normal file
|
@ -0,0 +1,88 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Neutrino Oscillations</title>
|
||||
<link rel="stylesheet" href="main.css" type="text/css" media="screen" />
|
||||
<link rel="stylesheet" href="https://cdn.rawgit.com/Chalarangelo/mini.css/v3.0.1/dist/mini-default.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css" integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" crossorigin="anonymous">
|
||||
|
||||
<!-- The loading of KaTeX is deferred to speed up page rendering -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js" integrity="sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4" crossorigin="anonymous"></script>
|
||||
|
||||
<!-- To automatically render math in text elements, include the auto-render extension: -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/auto-render.min.js" integrity="sha384-mll67QQFJfxn0IYznZYonOWZ644AWYC+Pt2cHqMaRhXVrursRwvLnLaebdGIlYNa" crossorigin="anonymous"
|
||||
onload="renderMathInElement(document.body);"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<a href="#" class="logo">Neutrino Oscillation Playground</a>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div id="neutrinos" class="card fluid">
|
||||
<canvas id="neutrinorender"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="card fluid" id="settings">
|
||||
<h3>Current Settings</h3>
|
||||
<div class="row">
|
||||
<div class="col-sm-6" id="pmns">
|
||||
</div>
|
||||
<div class="col-sm-3" id="sliders_1">
|
||||
</div>
|
||||
<div class="col-sm-3" id="sliders_2">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<form id="controls">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<fieldset>
|
||||
<legend>Mixing Angles in \(^\circ\)</legend>
|
||||
<label for="t12">\(\theta_{12}\)</label>
|
||||
<input type="range" step=".1" min="0" max="90" id="t12" />
|
||||
<br>
|
||||
|
||||
<label for="t13">\(\theta_{13}\)</label>
|
||||
<input type="range" step=".1" max="90" id="t13" />
|
||||
<br>
|
||||
|
||||
<label for="t23">\(\theta_{23}\)</label>
|
||||
<input type="range" step=".1" min="0" max="90" id="t23" />
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Squared Mass Differences \([10^{-4}\text{eV}^{2}]\)</legend>
|
||||
<label for="ms13">\(\Delta m_{13}^2\)</label>
|
||||
<input type="range" step=".1" min="0" max="30" id="ms13" />
|
||||
<br>
|
||||
<label for="ms23">\(\Delta m_{23}^2\)</label>
|
||||
<input type="range" step=".1" min="0" max="30" id="ms23" />
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<fieldset>
|
||||
<legend>Observatory Settings</legend>
|
||||
<label for="L_max">\(L_{\text{max}}\) [km]</label>
|
||||
<input type="range" min="0" max="1000" id="L_max" />
|
||||
<br>
|
||||
|
||||
<label for="energy">\(E\) [MeV]</label>
|
||||
<input type="range" step=".1" min="0" max="1000" id="energy" />
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="lib/chart.min.js"></script>
|
||||
<script src="lib/math.min.js"></script>
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
</html>
|
256
index.js
Normal file
256
index.js
Normal file
|
@ -0,0 +1,256 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Setup/Globals //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const ctx = document.getElementById('neutrinorender').getContext('2d');
|
||||
const render = new Chart(ctx, {
|
||||
type: 'line',
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
tooltips: {
|
||||
mode: 'index',
|
||||
intersect: false,
|
||||
},
|
||||
animation: {
|
||||
duration: 0,
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: "Distance [km]"
|
||||
}
|
||||
},
|
||||
y: {
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: "Survival Probability"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const controls = document.forms.controls;
|
||||
const settings = document.getElementById('settings');
|
||||
|
||||
// Mixing Angle Experimental Values, degrees
|
||||
const t12 = 33.44;
|
||||
const t23 = 49;
|
||||
const t13 = 8.57;
|
||||
|
||||
// squared mass differences, 1e-4 eV^2
|
||||
const ms13 = 25.1;
|
||||
const ms23 = 24.4;
|
||||
|
||||
// default settings
|
||||
const defaultNeutrinoData =
|
||||
{
|
||||
t12,
|
||||
t23,
|
||||
t13,
|
||||
ms13,
|
||||
ms23,
|
||||
L_range: [0, 100],
|
||||
E: 6 // MeV
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Util //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
function deg_to_rad(x) {
|
||||
return (x / 180) * math.pi
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Neutrino Mixing Specifics //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Compute the PMNS Matrix.
|
||||
*
|
||||
* Angle Arguments in Degrees.
|
||||
*/
|
||||
function pmns(t12, t23, t13) {
|
||||
t12 = deg_to_rad(t12);
|
||||
t13 = deg_to_rad(t13);
|
||||
t23 = deg_to_rad(t23);
|
||||
|
||||
// Compute all sines, cosines
|
||||
let c12 = math.cos(t12);
|
||||
let c13 = math.cos(t13);
|
||||
let c23 = math.cos(t23);
|
||||
|
||||
let s12 = math.sin(t12);
|
||||
let s13 = math.sin(t13);
|
||||
let s23 = math.sin(t23);
|
||||
|
||||
return math.matrix([
|
||||
[c12 * c13, s12 * c13, s13],
|
||||
[-s12 * c23 - c12 * s23 * s13, c12 * c23 - s12 * s23 * s13, s23 * c13],
|
||||
[s12 * s23 - c12 * c23 * s13, -c12 * s23 - s12 * c23 * s13, c23 * c13]
|
||||
]);
|
||||
}
|
||||
|
||||
function propagation_step(pmns_matrix, ms13, ms23, dL, E) {
|
||||
E = E / 1000;
|
||||
ms13 = ms13 * 1e-4;
|
||||
ms23 = ms23 * 1e-4;
|
||||
|
||||
const propagator = math.matrix([[math.exp(math.complex(0, -ms13 * 2.54 * dL / E)), 0, 0],
|
||||
[0, math.exp(math.complex(0, -ms23 * 2.54 * dL / E)), 0],
|
||||
[0, 0, 1]]);
|
||||
|
||||
return math.multiply(pmns_matrix, propagator, math.transpose(pmns_matrix));
|
||||
}
|
||||
|
||||
function propagate(initial_state, pmns_matrix, ms13, ms23, L, E) {
|
||||
const propagator = propagation_step(pmns_matrix, ms13, ms23, L, E);
|
||||
|
||||
return math.multiply(propagation_step, initial_state);
|
||||
}
|
||||
|
||||
function state_to_probabilies(state) {
|
||||
return state.map(value => math.multiply(value.conjugate(), value).re);
|
||||
}
|
||||
|
||||
function plot_propagation(state, neutrino_data) {
|
||||
const {t12, t23, t13, ms13, ms23, L_range, E} = neutrino_data;
|
||||
|
||||
pmns_matrix = pmns(t12, t23, t13);
|
||||
|
||||
dL = ((L_range[1] - L_range[0]) / 1000);
|
||||
lengths = math.range(L_range[0], L_range[1], dL);
|
||||
|
||||
common_options = {
|
||||
pointRadius: 0,
|
||||
};
|
||||
|
||||
datasets = [
|
||||
{
|
||||
data: [],
|
||||
borderColor: 'green',
|
||||
label: 'electron',
|
||||
...common_options
|
||||
},
|
||||
{
|
||||
data: [],
|
||||
borderColor: 'blue',
|
||||
label: 'muon',
|
||||
...common_options
|
||||
},
|
||||
{
|
||||
data: [],
|
||||
borderColor: 'red',
|
||||
label: 'tauon',
|
||||
...common_options
|
||||
}
|
||||
];
|
||||
|
||||
propagator = propagation_step(pmns_matrix, ms13, ms23, dL, E)
|
||||
|
||||
for (const length of lengths._data) {
|
||||
state = math.multiply(propagator, state);
|
||||
|
||||
probs = state_to_probabilies(state);
|
||||
probs.forEach((p, index) => {
|
||||
datasets[index[0]].data.push(p);
|
||||
})
|
||||
}
|
||||
|
||||
render.data.labels = lengths.map(l => math.round(l, 2))._data;
|
||||
render.data.datasets = datasets;
|
||||
render.update({
|
||||
duration: 0,
|
||||
easing: 'easeInOutBack'
|
||||
});
|
||||
}
|
||||
|
||||
function initForm() {
|
||||
controls.elements.t13.value = t13;
|
||||
controls.elements.t12.value = t12;
|
||||
controls.elements.t23.value = t23;
|
||||
|
||||
controls.elements.L_max.value = defaultNeutrinoData.L_range[1];
|
||||
controls.elements.energy.value = defaultNeutrinoData.E;
|
||||
|
||||
controls.elements.ms13.value = ms13;
|
||||
controls.elements.ms23.value = ms23;
|
||||
}
|
||||
|
||||
function getNeutrinoData() {
|
||||
return {
|
||||
...defaultNeutrinoData,
|
||||
t13: controls.elements.t13.value,
|
||||
t12: controls.elements.t12.value,
|
||||
t23: controls.elements.t23.value,
|
||||
ms13: controls.elements.ms13.value,
|
||||
ms23: controls.elements.ms23.value,
|
||||
E: controls.elements.energy.value,
|
||||
L_range: [0, controls.elements.L_max.value],
|
||||
};
|
||||
}
|
||||
|
||||
function renderPmnsMatrix(pmns_matrix) {
|
||||
let result = "$$U=\\begin{pmatrix}\n";
|
||||
|
||||
for (let row of pmns_matrix._data) {
|
||||
for (let val of row) {
|
||||
result += `${math.round(val, 3)} &`
|
||||
}
|
||||
result = result.slice(0, -1);
|
||||
result += "\\\\\n";
|
||||
}
|
||||
|
||||
result += "\\end{pmatrix}$$";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function displayCurrentSettings() {
|
||||
const {t12, t23, t13, ms13, ms23, L_range, E} = getNeutrinoData();
|
||||
pmns_matrix = pmns(t12, t23, t13);
|
||||
|
||||
// render pmns
|
||||
settings.querySelector("#pmns").textContent = renderPmnsMatrix(pmns_matrix);
|
||||
|
||||
settings.querySelector("#sliders_1").innerHTML = `
|
||||
\\(\\theta_{12} = ${t12}^\\circ\\)
|
||||
<br>
|
||||
\\(\\theta_{13} = ${t13}^\\circ\\)
|
||||
<br>
|
||||
\\(\\theta_{23} = ${t23}^\\circ\\)
|
||||
`;
|
||||
settings.querySelector("#sliders_2").innerHTML = `
|
||||
\\(\\Delta m_{13}^2 = ${ms13}\\cdot 10^{-4}\\text{GeV}\\)
|
||||
<br>
|
||||
\\(\\Delta m_{23}^2 = ${ms23}\\cdot 10^{-4}\\text{GeV}\\)
|
||||
<br>
|
||||
\\(L_\\text{max} = ${L_range[1]}\\text{km}\\)
|
||||
<br>
|
||||
\\(E = ${E}\\text{MeV}\\)
|
||||
`;
|
||||
|
||||
renderMathInElement(settings);
|
||||
|
||||
};
|
||||
|
||||
document.addEventListener("DOMContentLoaded", (event) => {
|
||||
initForm();
|
||||
displayCurrentSettings();
|
||||
plot_propagation(math.matrix([
|
||||
[1],
|
||||
[0],
|
||||
[0]
|
||||
]), defaultNeutrinoData);
|
||||
});
|
||||
|
||||
controls.addEventListener('input', () => {
|
||||
displayCurrentSettings();
|
||||
plot_propagation(math.matrix([
|
||||
[1],
|
||||
[0],
|
||||
[0]
|
||||
]), getNeutrinoData());
|
||||
});
|
13
lib/chart.min.js
vendored
Normal file
13
lib/chart.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
lib/math.min.js
vendored
Normal file
1
lib/math.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
17
main.css
Normal file
17
main.css
Normal file
|
@ -0,0 +1,17 @@
|
|||
.container {
|
||||
max-width: 1500px !important;
|
||||
}
|
||||
|
||||
#neutrinos {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 20vw;
|
||||
}
|
||||
|
||||
#controls {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#settings {
|
||||
width: 100%;
|
||||
}
|
Loading…
Add table
Reference in a new issue