Skip to content
Snippets Groups Projects
NPReaction.cxx 16.44 KiB
/*****************************************************************************
 * 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;
   }