SPSPlot_web/spsSim.js
2023-07-30 15:14:19 -04:00

498 lines
14 KiB
JavaScript

var beam = [];
var target = [];
var recoil = [];
var residual = [];
var ExB; //excitation energy of residual
var reactionName;
var angle;
var BField;
var parity;
function checkParity(){
parity = 0;
if( document.getElementById('pos').checked == true ) parity += 1;
if( document.getElementById('neg').checked == true ) parity += 2;
if( document.getElementById('unk').checked == true ) parity += 4;
//console.log(parity);
}
function addStates(){
let AZ = residual[3];
let maxEx = document.getElementById('maxEx').value;
checkParity();
let str = 'get_nuclear_data.py?isotopes_name=' + AZ + '&maxEx='+maxEx;
let table = document.getElementById("ExTable");
const client = new XMLHttpRequest();
client.addEventListener('loadstart',
function(e){
document.getElementById('waiting').innerHTML = "wait....retrieving data from IAEA..";
}
);
client.addEventListener('error',
function(e){
document.getElementById('waiting').innerHTML = "Error.";
}
);
client.addEventListener('loadend',
function(e){
let result = client.responseText.split(/\r?\n/);
//clear table
let nRow = table.rows.length;
for( let j = nRow; j > 2; j--){
table.deleteRow(j - 2);
}
document.getElementById('waiting').innerHTML = "";
let count = 0;
for( let i = 0; i < result.length; i++){
if( i < 17 ) continue;
if( result[i] == "</table>" ) break;
let kaka = result[i].split(' ').filter(n => n);
let ex = parseFloat(kaka[3])/1000.;
let jpi = kaka[7]?.replace('(', '')?.replace(')', '');
//console.log(ex + ", " + jpi);
//check parity
if( (((parity >> 2) & 1) != 1) && kaka[7].slice(-1) == ")" ) continue;
if( (((parity >> 2) & 1) != 1) && jpi == "," ) continue;
if( (((parity) & 1) != 1) && jpi.slice(-1) == "+" ) continue;
if( (((parity >> 1) & 1) != 1) && jpi.slice(-1) == "-" ) continue;
count ++;
nRow = table.rows.length;
let row = table.insertRow(nRow-1);
row.innerHTML = '<td><input type="text" name="Ex" size="5" value="' + ex.toFixed(3) + '"/></td> \
<td><button type="button" onclick="addRow(this)">Insert Ex</button></td> \
<td><button type="button" onclick="deleteRow(this)">Remove Ex</button></td> \
<td>'+ kaka[7] +'</td>';
}
if( count == 0 ){
document.getElementById('waiting').innerHTML = "no states found.";
nRow = table.rows.length;
let row = table.insertRow(nRow-1);
row.innerHTML = '<td><input type="text" name="Ex" size="5" value="0"/></td> \
<td><button type="button" onclick="addRow(this)">Insert Ex</button></td> \
<td><button type="button" onclick="deleteRow(this)">Remove Ex</button></td>';
}
}
);
client.open('GET', str);
client.send();
}
function addRow(ele) {
let iRow = ele.closest('tr').sectionRowIndex;
let table = document.getElementById("ExTable");
let row = table.insertRow(iRow+1);
row.innerHTML = '<td><input type="text" name="Ex" size="5" /></td> \
<td><button type="button" onclick="addRow(this)">Insert Ex</button></td> \
<td><button type="button" onclick="deleteRow(this)">Remove Ex</button></td>';
}
function deleteRow(ele){
let table = document.getElementById("ExTable");
let nRow = table.rows.length;
let iRow = ele.closest('tr').sectionRowIndex;
if ( nRow > 2){
table.deleteRow(iRow);
}
}
function GetMassData(Name, id){
let str = 'https://fsunuc.physics.fsu.edu/SOLARIS/massProxy.py?AZ=' + Name;
let client = new XMLHttpRequest();
client.onreadystatechange = function() {
let mass = client.responseText.split(",");
if( id == 0 ){ //Beam
beam[0] = parseInt(mass[0]); // A
beam[1] = parseInt(mass[1]); // Z
beam[2] = parseFloat(mass[2]); // mass
beam[3] = Name; // Sym
}
if( id == 1 ){ // target
target[0] = parseInt(mass[0]);
target[1] = parseInt(mass[1]);
target[2] = parseFloat(mass[2]);
target[3] = Name;
target[4] = parseFloat(mass[4]); //Sp
target[5] = parseFloat(mass[5]); //Sn
target[6] = parseFloat(mass[6]); //Sa
}
if( id == 2 ){ // Recoil
recoil[0] = parseInt(mass[0]);
recoil[1] = parseInt(mass[1]);
recoil[2] = parseFloat(mass[2]);
recoil[3] = Name;
}
}
client.open('GET', str, false);
client.send();
}
function GetMassFromAZ(A,Z){
let str = 'https://fsunuc.physics.fsu.edu/SOLARIS/massProxy.py?A=' + A + '&Z=' + Z;
let client = new XMLHttpRequest();
client.onreadystatechange = function() {
let mass = client.responseText.split(",");
residual[2] = parseFloat(mass[2]);
residual[3] = mass[3]?.trim();
residual[4] = parseFloat(mass[4]); //Sp
residual[5] = parseFloat(mass[5]); //Sn
residual[6] = parseFloat(mass[6]); //Sa
}
client.open('GET', str, false);
client.send();
}
function UpdateReaction(){
residual[0] = beam[0] + target[0] - recoil[0];
residual[1] = beam[1] + target[1] - recoil[1];
GetMassFromAZ( residual[0], residual[1]);
var Qvalue = beam[2] + target[2] - recoil[2] - residual[2];
document.getElementById('residual').innerHTML = residual[3];
document.getElementById('residualSp').innerHTML = residual[4].toFixed(3);
document.getElementById('residualSn').innerHTML = residual[5].toFixed(3);
document.getElementById('residualSa').innerHTML = residual[6].toFixed(3);
document.getElementById('Q-value').innerHTML = Qvalue.toFixed(3);
CalTransferConstant();
}
var Etot; // CM frame total energy
var k; //Lab frame momentum of beam
var beta, gamma; // Lorentz boost
var p; // CM frame exist channel momentum
function CalTransferConstant(){
let ma = beam[2];
let mA = target[2];
let KE = parseFloat(document.getElementById('KEA').value) * beam[0];
k = Math.sqrt( Math.pow(ma + KE, 2 ) -ma * ma);
beta = k / (ma + KE + mA);
gamma = 1 / Math.sqrt(1 - beta * beta);
Etot = Math.sqrt(Math.pow(ma + KE + mA,2) - k * k);
reactionName = target[3] + "(" + beam[3] + "," + recoil[3] + ")" + residual[3] + " @ " + KE/beam[0] + " MeV/u";
// console.log("Etot : " + Etot);
// console.log("k : " + k);
// console.log("beta : " + beta);
// console.log("gamma : " + gamma);
// console.log(reactionName);
}
function CalCMMomentum(ExB){
let mb = recoil[2];
let mB = residual[2];
ExB = parseFloat(ExB);
p = Math.sqrt( (Etot*Etot - Math.pow(mb + mB + ExB, 2)) * (Etot*Etot - Math.pow(mb - mB - ExB,2)) ) / 2 / Etot;
// console.log("p : " + p);
}
var ExList = [];
var EnergyLab = [];
var data = [];
function PlotKinematic(){
// plot recoil Lab energy vs Lab angle;
Plotly.purge("Plot_Kinematics");
ExList = Array.from(document.getElementsByName("Ex"));
// for( let i = 0; i < ExList.length; i++){ console.log(ExList[i].value);}
let mb = recoil[2];
//console.log("Plot--------------");
data = [];
for( let i = 0; i < ExList.length; i++){
let yList = []; // lab energy;
let xList = []; // lab angle in degree;
let ExB = parseFloat(ExList[i].value).toFixed(3);
CalCMMomentum(ExB);
// console.log("ExB : " + ExB + ", p : " + p);
for( let thetaCM = 0; thetaCM <= 120; thetaCM ++){
let thetaRad = thetaCM * Math.PI/ 180.;
let EE = gamma * Math.sqrt(mb*mb + p*p) + gamma * beta * p * Math.cos(thetaRad);
let pz = gamma * beta * Math.sqrt(mb*mb + p*p) + gamma * p * Math.cos(thetaRad);
let pxy = p * Math.sin(thetaRad);
let thetaLab = Math.atan2(pxy, pz) * 180. / Math.PI;
xList.push(thetaLab);
yList.push((EE-mb));
}
let newData = {
x : xList,
y : yList,
mode : "lines",
type: "scatter",
name : ("Ex=" + ExB)
}
data.push(newData);
};
let layout = {
xaxis: {range: [0, 90], title: { text : "Angle Lab [degree]", standoff : 1}, mirror : "allticks", linewidth : "1"},
yaxis: {range: [0, 20], title: "Kinematic Energy [MeV]" , mirror : "allticks", linewidth : "1"},
title: reactionName,
dragmode : "pan",
margin: { l: 40, r: 40, b : 60, t : 40},
legend: {yanchor:"bottom", xanchor:"left", x:"0.01",y:"0.01" }
};
Plotly.newPlot( "Plot_Kinematics", data, layout, {responsive: false});
ChangeSPSAnglePlotKinematics();
}
function SearchForRecoilEnergy(){
EnergyLab = [];
angle = parseFloat(document.getElementById("angle").value);
for( let i = 0; i < data.length; i++){
let low = 0, high = 180;
let elow, ehigh;
for(let j = 0; j < data[i].x.length; j++ ){
let thetaLab = data[i].x[j];
let energy = data[i].y[j];
if( angle >= thetaLab && thetaLab > low) {low = thetaLab; elow = energy; }
if( high > thetaLab && thetaLab >= angle) {high = thetaLab; ehigh = energy;}
}
EnergyLab.push((ehigh - elow )/ (high - low) * (angle - low) + elow);
// console.log("angle low : " + low + ", " + elow);
// console.log("angle low : " + high + ", " + ehigh);
// console.log("E : " + EnergyLab);
}
}
function ChangeSPSAnglePlotKinematics(){
angle = parseFloat(document.getElementById("angle").value);
let shapeArray = [
{
type: 'rect',
xref: 'x',
yref: 'paper',
x0 : angle - 0.5,
x1 : angle + 0.5,
y0 : 0,
y1 : 1,
fillcolor : '#782F40',
opacity : 0.5,
line : { width : 0}
}
];
var update = {
'shapes' : shapeArray
}
Plotly.relayout("Plot_Kinematics", update);
SearchForRecoilEnergy();
}
//################################### SPS functions
function recoilRho(KE){
let mass = parseFloat(recoil[2]);
let charge = parseFloat(recoil[1]);
let momt = Math.sqrt( 2*mass*KE + KE*KE );
let field = parseFloat(document.getElementById('BField').value);
return momt/ 299.792458 / charge / field * 100; // unit??
}
function PlotSPS(){
Plotly.purge("Plot_SPS");
let spsData = [];
for(let i = 0; i < EnergyLab.length; i++){
let rho = recoilRho(EnergyLab[i]);
let newData = {
x : [rho, rho],
y : [0, 1],
mode : "lines",
type: "scatter",
name : ("Ex=" + parseFloat(ExList[i].value).toFixed(3))
}
spsData.push(newData);
//console.log(rho);
}
let layout = {
xaxis: {range: [65, 82], title: { text : "rho [cm]", standoff : 1}, mirror : "allticks", linewidth : "1"},
yaxis: {range: [0, 1], title: "state" , mirror : "allticks", linewidth : "1"},
title: reactionName,
dragmode : "pan",
margin: { l: 40, r: 40, b : 60, t : 40},
legend: {yanchor:"top", xanchor:"left", x:"0.01",y:"0.99" }
};
Plotly.newPlot( "Plot_SPS", spsData, layout, {responsive: false});
}
function PlotAll(){
PlotKinematic();
PlotSPS();
}
//######################################## Add reaction
var reactionCount = 1;
function addReaction(){
document.getElementById('msg').innerHTML = "not working yet";
var table = document.getElementById('ReactionTable');
var rowCount = table.rows.length;
if(reactionCount >= 3 ){
document.getElementById('msg').innerHTML = "maximum # of reaction reached.";
return;
}
for (var i = 0; i < rowCount; i++) {
var row = table.rows[i];
var cell = row.insertCell(-1); // -1 means insert at the end
if( i == 0 ) cell.innerHTML = '<Input type="text" style="text-align: center; width:90px" value="d" id="beam1" enterkeyhint="done"/>';
if( i == 1 ) cell.innerHTML = '<Input type="text" style="text-align: center; width:90px" value="12C" id="target1" enterkeyhint="done"/>';
if( i == 2 ) cell.innerHTML = '<Input type="text" style="text-align: center; width:90px" value="p" id="recoil1" enterkeyhint="done"/>';
if( i == 3 ) {
cell.innerHTML = '13C';
cell.style.textAlign = 'center';
}
if( i == 4 ) cell.innerHTML = '4.946';
if( i == 5 ) cell.innerHTML = '17.533';
if( i == 6 ) cell.innerHTML = '10.648';
if( i == 7 ) cell.innerHTML = '2.722';
if( i >= 4) {
cell.style.textAlign = 'right';
}
}
reactionCount ++;
}
function removeRactiion(ele){
document.getElementById('msg').innerHTML = "not working yet";
}
//######################################### when load
GetMassData( document.getElementById('beam').value, 0);
GetMassData( document.getElementById('target').value, 1);
GetMassData( document.getElementById('recoil').value, 2);
UpdateReaction();
PlotAll();
//########################################## UI control
document.getElementById('beam').addEventListener('keypress',
function(e){
if(e.keyCode == 13){
GetMassData( document.getElementById('beam').value, 0);
UpdateReaction();
PlotAll();
}
}, false
);
document.getElementById('target').addEventListener('keypress',
function(e){
if(e.keyCode == 13){
GetMassData( document.getElementById('target').value, 1);
UpdateReaction();
PlotAll();
}
}, false
);
document.getElementById('recoil').addEventListener('keypress',
function(e){
if(e.keyCode == 13){
GetMassData( document.getElementById('recoil').value, 2);
UpdateReaction();
PlotAll();
}
}, false
);
document.getElementById('KEA').addEventListener('keypress',
function(e){
if(e.keyCode == 13){
document.getElementById('KEARange').value = this.value;
CalTransferConstant();
PlotAll();
}
}, false
);
document.getElementById('KEARange').oninput = function(){
document.getElementById('KEA').value = this.value;
CalTransferConstant();
PlotAll();
};
document.getElementById('angle').addEventListener('keypress',
function(e){
if(e.keyCode == 13){
document.getElementById('angleRange').value = this.value;
angle = this.value;
PlotSPS();
}
}, false
);
document.getElementById('angleRange').oninput = function(){
document.getElementById('angle').value = this.value;
angle = this.value;
ChangeSPSAnglePlotKinematics();
PlotSPS();
};
document.getElementById('BField').addEventListener('keypress',
function(e){
if(e.keyCode == 13){
document.getElementById('BRange').value = this.value;
BField - this.value;
ChangeSPSAnglePlotKinematics();
PlotSPS();
}
}, false
);
document.getElementById('BRange').oninput = function(){
document.getElementById('BField').value = this.value;
BField - this.value;
PlotSPS();
};