/***************************************************************************** * Copyright (C) 2009-2010 this file is part of the NPTool Project * * * * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * * For the list of contributors see $NPTOOL/Licence/Contributors * *****************************************************************************/ /***************************************************************************** * * * Original Author : Adrien MATTA contact address: matta@ipno.in2p3.fr * * * * Creation Date : March 2009 * * Last update : January 2011 * *---------------------------------------------------------------------------* * Decription: * * This class deal with Two Body transfert Reaction * * Physical parameter (Nuclei mass) are loaded from the nubtab03.asc file * * (2003 nuclear table of isotopes mass). * * * * KineRelativistic: Used in NPSimulation * * A relativistic calculation is made to compute Light and Heavy nuclei * * angle given the Theta CM angle. * * * * ReconstructRelativistic: Used in NPAnalysis * * A relativistic calculation is made to compute Excitation energy given the* * light angle and energy in Lab frame. * * * *---------------------------------------------------------------------------* * Comment: * * + 20/01/2011: Add support for excitation energy for light ejectile * * (N. de Sereville) * * Based on previous work by N.de Sereville * * * *****************************************************************************/ #include <iostream> #include <fstream> #include <string> #include <cstdlib> #include <sstream> //#include <stdlib.h> #include <cmath> #include <vector> #include "NPReaction.h" // Use CLHEP System of unit and Physical Constant #include "CLHEP/Units/GlobalSystemOfUnits.h" #include "CLHEP/Units/PhysicalConstants.h" using namespace NPL; //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... Reaction::Reaction() { //------------- Default Constructor ------------- fNuclei1 = new Nucleus() ; fNuclei2 = new Nucleus() ; fNuclei3 = new Nucleus() ; fNuclei4 = new Nucleus() ; fBeamEnergy = 0 ; fThetaCM = 0 ; fExcitationLight = 0 ; fExcitationHeavy = 0 ; fQValue = 0 ; initializePrecomputeVariable() ; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... Reaction::Reaction(string name1, string name2, string name3, string name4, double BeamEnergy, double ExcitationEnergyLight, double ExcitationEnergyHeavy ,string Path) { SetEveryThing( name1, name2, name3, name4, BeamEnergy, ExcitationEnergyLight, ExcitationEnergyHeavy, Path) ; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Reaction::SetEveryThing(string name1, string name2, string name3, string name4, double BeamEnergy, double ExcitationEnergyLight, double ExcitationEnergyHeavy, string Path) { //------------- Constructor with nuclei names and beam energy ------------ fNuclei1 = new Nucleus(name1); fNuclei2 = new Nucleus(name2); fNuclei3 = new Nucleus(name3); fNuclei4 = new Nucleus(name4); fBeamEnergy = BeamEnergy; fThetaCM = 0; fExcitationLight = ExcitationEnergyLight; fExcitationHeavy = ExcitationEnergyHeavy; fQValue = (fNuclei1->GetMassExcess() + fNuclei2->GetMassExcess() - fNuclei3->GetMassExcess() - fNuclei4->GetMassExcess()) / 1000; int masse = fNuclei1->GetA() + fNuclei2->GetA() - fNuclei3->GetA() - fNuclei4->GetA(); int charge = fNuclei1->GetZ() + fNuclei2->GetZ() - fNuclei3->GetZ() - fNuclei4->GetZ(); if (masse || charge) { cout << endl; cout << "********************************** Error **********************************" << endl; cout << "* NPReaction: charge of mass not conserved. Check you event generator file *" << endl; cout << "***************************************************************************************" << endl; exit(1); } ///Read the differential cross section string GlobalPath = getenv("NPTOOL"); string StandardPath = GlobalPath + "/Inputs/CrossSection/" + Path; ifstream CSFile; CSFile.open( StandardPath.c_str() ); if(CSFile.is_open()) cout << "Reading Cross Section File " << Path << endl; // In case the file is not found in the standard path, the programm try to interpret the file name as an absolute or relative file path. else { CSFile.open( Path.c_str() ); if(CSFile.is_open()) { cout << "Reading Cross Section File " << Path << endl;} else {cout << "Cross Section File " << Path << " not found" << endl;return;} } double CSBuffer,AngleBuffer; vector<double> CrossSectionBuffer ; while(!CSFile.eof()) { CSFile >> AngleBuffer; CSFile >> CSBuffer; double CSFinal = CSBuffer*sin(AngleBuffer*deg); CrossSectionBuffer.push_back(CSFinal); } CSFile.close(); CrossSectionSize = CrossSectionBuffer.size(); CrossSection = new double[CrossSectionSize] ; for(int i = 0 ; i <CrossSectionSize ; i++ ) CrossSection[i] = CrossSectionBuffer[i]; initializePrecomputeVariable(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... Reaction::~Reaction() { //------------- Default Destructor ------------ delete fNuclei1; delete fNuclei2; delete fNuclei3; delete fNuclei4; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... bool Reaction::CheckKinematic() { // Check if kinematics is allowed // case of inverse kinematics double theta = fThetaCM; if (m1 > m2) theta = M_PI - fThetaCM; // total and kinetic energies in the lab double W3lab = W3cm * G * (1 + B*beta3cm*cos(theta)); double W4lab = W4cm * G * (1 + B*beta4cm*cos(theta + M_PI)); // test for total energy conversion if (fabs(WtotLab - (W3lab+W4lab)) > 1e-6) return false; else return true; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Reaction::KineRelativistic(double &ThetaLab3, double &EnergieLab3, double &ThetaLab4, double &EnergieLab4) const { // 2-body relativistic kinematics: direct + inverse // EnergieLab3,4 : lab energy in MeV of the 2 ejectiles // ThetaLab3,4 : angles in rad // case of inverse kinematics double theta = fThetaCM; if (m1 > m2) theta = M_PI - fThetaCM; // lab angles ThetaLab3 = atan(sin(theta) / (cos(theta) + K3) / G); if (ThetaLab3 < 0) ThetaLab3 += M_PI; ThetaLab4 = atan(sin(M_PI + theta) / (cos(M_PI + theta) + K4) / G); if (fabs(ThetaLab3) < 1e-6) ThetaLab3 = 0; ThetaLab4 = fabs(ThetaLab4); if (fabs(ThetaLab4) < 1e-6) ThetaLab4 = 0; // total and kinetic energies in the lab double W3lab = W3cm * G * (1 + B*beta3cm*cos(theta)); double W4lab = W4cm * G * (1 + B*beta4cm*cos(theta + M_PI)); // test for total energy conversion if (fabs(WtotLab - (W3lab+W4lab)) > 1e-6) cout << "Problem for energy conservation" << endl; EnergieLab3 = W3lab - m3; EnergieLab4 = W4lab - m4; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... double Reaction::ReconstructRelativistic(double EnergyLab, double ThetaLab) const { // EnergyLab in MeV // ThetaLab in rad double P1 = sqrt(2*m1*fBeamEnergy+(fBeamEnergy*fBeamEnergy)); double P3 = sqrt(2*m3*EnergyLab+(EnergyLab*EnergyLab)); double P4 = sqrt(P1*P1+P3*P3-(2*P1*P3*cos(ThetaLab))); double E4 = fBeamEnergy+m1+m2-(EnergyLab+m3); double m4e = sqrt((E4*E4)-(P4*P4)); double Eex= m4e-fNuclei4->Mass(); return Eex; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... //Return ThetaCM double Reaction::EnergyLabToThetaCM( double EnergyLab , double ExcitationEnergy ) const { if(ExcitationEnergy == -500) ExcitationEnergy = fExcitationHeavy; double E1 = (fBeamEnergy+m1) ; double E3 = (EnergyLab+m3) ; // Compute Mandelstan variable double s = 2*m2*E1 + m1*m1 + m2*m2 ; double u = -2*m2*E3 + m2*m2 + m3*m3 ; // Compute CM impulsion: //before reaction double P2CM = ( sqrt( ( s-(m1-m2)*(m1-m2) )*( s-(m1+m2)*(m1+m2) ) ) ) / (2*sqrt(s)) ; // after reaction double P3CM = ( sqrt( ( s-(m3-m4)*(m3-m4) )*( s-(m3+m4)*(m3+m4) ) ) ) / (2*sqrt(s)) ; // Compute CM Energy double E2CM = (s + m2*m2 -m1*m1)/(2*sqrt(s)) ; double E3CM = (s + m3*m3 -m4*m4)/(2*sqrt(s)) ; double u0 = m2*m2 + m3*m3 - 2*(E2CM*E3CM + P2CM*P3CM) ; double Pi = 3.141592654 ; double ThetaCM = Pi - acos ( 1-(u-u0)/(2*P2CM*P3CM) ) ; return(ThetaCM); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Reaction::Print() const { // Print informations concerning the reaction cout << "Reaction : " << fNuclei2->GetName() << "(" << fNuclei1->GetName() << "," << fNuclei3->GetName() << ")" << fNuclei4->GetName() << " @ " << fBeamEnergy << " MeV" << endl ; cout << "Exc Light = " << fExcitationLight << " MeV" << endl; cout << "Exc Heavy = " << fExcitationHeavy << " MeV" << endl; cout << "Qgg = " << fQValue << " MeV" << endl; } void Reaction::ReadConfigurationFile(string Path) { ////////General Reading needs//////// string LineBuffer; string DataBuffer; ////////Reaction Setting needs/////// string Beam, Target, Heavy, Light, CrossSectionPath ; double BeamEnergy = 0 , ExcitationEnergyLight = 0, ExcitationEnergyHeavy = 0; bool ReadingStatus = false ; bool check_Beam = false ; bool check_Target = false ; bool check_Light = false ; bool check_Heavy = false ; bool check_ExcitationEnergyLight = false ; bool check_ExcitationEnergyHeavy = false ; bool check_BeamEnergy = false ; bool check_CrossSectionPath = false ; ////////////////////////////////////////////////////////////////////////////////////////// ifstream ReactionFile; string GlobalPath = getenv("NPTOOL"); string StandardPath = GlobalPath + "/Inputs/EventGenerator/" + Path; ReactionFile.open(StandardPath.c_str()); if (ReactionFile.is_open()) {cout << "Reading Reaction File " << Path << endl ;} // In case the file is not found in the standard path, the programm try to interpret the file name as an absolute or relative file path. else { ReactionFile.open( Path.c_str() ); if(ReactionFile.is_open()) { cout << "Reading Reaction File " << Path << endl;} else {cout << "Reaction File " << Path << " not found" << endl;return;} } while (!ReactionFile.eof()) { //Pick-up next line getline(ReactionFile, LineBuffer); if (LineBuffer.compare(0, 9, "Transfert") == 0) { ReadingStatus = true ;} while(ReadingStatus){ ReactionFile >> DataBuffer; //Search for comment Symbol % if (LineBuffer.compare(0, 1, "%") == 0) {/* Do Nothing */;} else if (DataBuffer=="Beam=") { check_Beam = true ; ReactionFile >> DataBuffer; Beam = DataBuffer; cout << "Beam " << Beam << endl; } else if (DataBuffer=="Target=") { check_Target = true ; ReactionFile >> DataBuffer; Target = DataBuffer; cout << "Target " << Target << endl; } else if (DataBuffer=="Light=") { check_Light = true ; ReactionFile >> DataBuffer; Light = DataBuffer; cout << "Light " << Light << endl; } else if (DataBuffer== "Heavy=") { check_Heavy = true ; ReactionFile >> DataBuffer; Heavy = DataBuffer; cout << "Heavy " << Heavy << endl; } else if (DataBuffer=="ExcitationEnergyLight=") { check_ExcitationEnergyLight = true ; ReactionFile >> DataBuffer; ExcitationEnergyLight = atof(DataBuffer.c_str()) * MeV; cout << "Excitation Energy Light" << ExcitationEnergyLight / MeV << " MeV" << endl; } else if (DataBuffer=="ExcitationEnergyHeavy=") { check_ExcitationEnergyHeavy = true ; ReactionFile >> DataBuffer; ExcitationEnergyHeavy = atof(DataBuffer.c_str()) * MeV; cout << "Excitation Energy Heavy" << ExcitationEnergyHeavy / MeV << " MeV" << endl; } else if (DataBuffer=="BeamEnergy=") { check_BeamEnergy = true ; ReactionFile >> DataBuffer; BeamEnergy = atof(DataBuffer.c_str()) * MeV; cout << "Beam Energy " << BeamEnergy / MeV << " MeV" << endl; } else if (DataBuffer== "CrossSectionPath=") { check_CrossSectionPath = true ; ReactionFile >> CrossSectionPath; cout << "Cross Section File: " << CrossSectionPath << endl ; } /////////////////////////////////////////////////// // If no Transfert Token and no comment, toggle out else {/*Ignore Token used by G4*/} /////////////////////////////////////////////////// // If all Token found toggle out if (check_Beam && check_Target && check_Light && check_Heavy && check_ExcitationEnergyLight && check_ExcitationEnergyHeavy && check_BeamEnergy && check_CrossSectionPath) ReadingStatus = false; } } SetEveryThing(Beam, Target, Light, Heavy,BeamEnergy,ExcitationEnergyLight, ExcitationEnergyHeavy,CrossSectionPath); ReactionFile.close(); } void Reaction::initializePrecomputeVariable() { m1 = fNuclei1->Mass(); m2 = fNuclei2->Mass(); m3 = fNuclei3->Mass() + fExcitationLight; m4 = fNuclei4->Mass() + fExcitationHeavy; // center-of-mass velocity WtotLab = (fBeamEnergy + m1) + m2; P1 = sqrt(pow(fBeamEnergy,2) + 2*m1*fBeamEnergy); B = P1 / WtotLab; G = 1 / sqrt(1 - pow(B,2)); // total energy of the ejectiles in the center-of-mass W3cm = (pow(WtotLab,2) + pow(G,2)*(pow(m3,2) - pow(m4,2))) / (2 * G * WtotLab); W4cm = (pow(WtotLab,2) + pow(G,2)*(pow(m4,2) - pow(m3,2))) / (2 * G * WtotLab); // velocity of the ejectiles in the center-of-mass beta3cm = sqrt(1 - pow(m3,2)/pow(W3cm,2)); beta4cm = sqrt(1 - pow(m4,2)/pow(W4cm,2)); // Constants of the kinematics K3 = B / beta3cm; K4 = B / beta4cm; }