498 lines
14 KiB
JavaScript
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();
|
||
|
};
|