SOLARIS_Analysis/Cleopatra/knockoutSim.C

508 lines
16 KiB
C++
Raw Normal View History

#include "ClassHelio.h"
2023-04-03 16:03:48 -04:00
#include "TROOT.h"
#include "TBenchmark.h"
#include "TLorentzVector.h"
#include "TMath.h"
#include "TFile.h"
#include "TF1.h"
#include "TTree.h"
#include "TRandom.h"
#include "TClonesArray.h"
#include <vector>
#include <fstream>
//----------- usage
// $root sim.C+ | tee output.txt
// this will same the massage to output.txt
void knockout(){
//================================================= User Setting
//---- reaction
int AA = 23, ZA = 9;
int Aa = 1, Za = 1;
int A2 = 1, Z2 = 1;
bool isNormalKinematics = false;
bool isOverRideExNegative = true;
double maxkb = 200.;
//---- beam
double KEAmean = 100; // MeV/u
const int nKEA = 1;
double KEAList[nKEA] = {300};
double KEAsigma = 0; //KEAmean*0.001; // MeV/u , assume Guassian
double thetaMean = 0.; // mrad
double thetaSigma = 0.; // mrad , assume Guassian due to small angle
int numEvent = 100000;
//---- HELIOS detector geometry
string heliosDetGeoFile = "";//"detectorGeo_upstream.txt";
double BField = 4.0; // if not detector, must set B-field, else, this value is not used.
double BFieldTheta = 0.; // direction of B-field
double eSigma = 0.0001 ; // detector energy sigma MeV
double zSigma = 0.1 ; // detector position sigma mm
//---- excitation of Beam
int nExA = 1;
double ExAList[nExA];
ExAList[0] = 0.000; // MeV
//ExAList[1] = 1.567;
//---- Separation energy
string separationFile = "separation_energies.txt";
//---- save root file name
TString saveFileName = "knockout.root";
//---- Auxiliary setting
bool isTargetScattering = false;
bool isDecay = false;
bool isReDo = false; // redo calculation until detected.
//---- target
double density = 0.913; // 0.913 g/cm3
double targetThickness = 2./2. * 2.2e-4; // 2.2 um = 201 ug/cm2
string stoppingPowerForA = "208Pb_in_CD2.txt"; // generated by SRIM
string stoppingPowerForb = "1H_in_CD2.txt";
string stoppingPowerForB = "209Pb_in_CD2.txt";
//=============================================================
//=============================================================
//=============================================================
//===== Set Reaction
Knockout reaction;
int AB = AA-A2, ZB = ZA-Z2;
int A1 = Aa , Z1 = Za;
reaction.SetA(AA,ZA);
reaction.Seta(Aa,Za);
reaction.Set2(A2,Z2);
reaction.SetIncidentEnergyAngle(KEAmean, 0, 0);
reaction.OverRideExNegative(isOverRideExNegative);
printf("===================================================\n");
printf("=========== %s ===========\n", reaction.GetReactionName().Data());
printf("=========== KE: %9.4f +- %5.4f MeV/u, dp/p = %5.2f %% \n", KEAmean, KEAsigma, KEAsigma/KEAmean * 50.);
printf("======== theta: %9.4f +- %5.4f MeV/u \n", thetaMean, thetaSigma);
printf("===================================================\n");
//======== Set HELIOS
printf("############################################## HELIOS configuration\n");
HELIOS helios1; // for particle-1
HELIOS helios2; // for particle-2
helios1.SetMagneticFieldDirection(BFieldTheta);
helios2.SetMagneticFieldDirection(BFieldTheta);
bool sethelios1 = helios1.SetDetectorGeometry(heliosDetGeoFile);
bool sethelios2 = helios2.SetDetectorGeometry(heliosDetGeoFile);
if( sethelios1 && sethelios2 ) {
int mDet = helios1.GetNumberOfDetectorsInSamePos();
printf("========== energy resol.: %f MeV\n", eSigma);
printf("=========== pos-Z resol.: %f mm \n", zSigma);
}else{
helios1.SetMagneticField(BField);
helios2.SetMagneticField(BField);
printf("======== B-field : %5.2f T, Theta: %5.2f deg\n", BField, BFieldTheta);
}
//==== Target scattering, only energy loss
if(isTargetScattering) printf("############################################## Target Scattering\n");
TargetScattering msA;
TargetScattering msB;
TargetScattering msb;
if(isTargetScattering) printf("======== Target : (thickness : %6.2f um) x (density : %6.2f g/cm3) = %6.2f ug/cm2\n",
targetThickness * 1e+4,
density,
targetThickness * density * 1e+6);
if( isTargetScattering ){
msA.LoadStoppingPower(stoppingPowerForA);
msb.LoadStoppingPower(stoppingPowerForb);
msB.LoadStoppingPower(stoppingPowerForB);
}
//======= Decay of particle-B
Decay decay;
decay.SetMotherDaugther(AB, ZB, AB-1,ZB); //neutron decay
//======= loading excitation energy
printf("############################################## excitation energies\n");
vector<double> SpList;
printf("----- loading separation energies.");
ifstream file;
file.open(separationFile.c_str());
string isotopeName;
if( file.is_open() ){
string line;
int i = 0;
while( file >> line){
//printf("%d, %s \n", i, line.c_str());
if( line.substr(0,2) == "//" ) continue;
if( i == 0 ) isotopeName = line;
if ( i >= 1 ){
SpList.push_back(atof(line.c_str()));
}
i = i + 1;
}
file.close();
printf("... done.\n");
printf("========== %s\n", isotopeName.c_str());
int n = SpList.size();
for(int i = 0; i < n ; i++){
if( isDecay ) {
TLorentzVector temp(0,0,0,0);
int decayID = decay.CalDecay(temp, SpList[i], 0);
if( decayID == 1) {
printf("%d, Sp: %6.2f MeV --> Decay. \n", i, SpList[i]);
}else{
printf("%d, Sp: %6.2f MeV\n", i, SpList[i]);
}
}else{
printf("%d, Sp: %6.2f MeV \n", i, SpList[i]);
}
}
}else{
printf("... fail\n");
return;
}
//====================== build tree
TFile * saveFile = new TFile(saveFileName, "recreate");
TTree * tree = new TTree("tree", "tree");
double thetaNN, phiNN;
double theta1, phi1, T1;
double theta2, phi2, T2;
double thetaB, TB;
double Sp, kb, thetab, phib;
int SpID;
double ExA;
int ExAID;
double KEA, KEAscattered, theta, phi;
double mB,mb;
tree->Branch("theta1", &theta1, "theta1/D");
tree->Branch("phi1", &phi1, "phi1/D");
tree->Branch("T1", &T1, "T1/D");
tree->Branch("theta2", &theta2, "theta2/D");
tree->Branch("phi2", &phi2, "phi2/D");
tree->Branch("T2", &T2, "T2/D");
tree->Branch("thetaB", &thetaB, "thetaB/D");
tree->Branch("TB", &TB, "TB/D");
tree->Branch("thetaNN", &thetaNN, "thetaNN/D");
tree->Branch("phiNN", &phiNN, "phiNN/D");
tree->Branch("Sp", &Sp, "Sp/D");
tree->Branch("kb", &kb, "kb/D");
tree->Branch("thetab", &thetab, "thetab/D");
tree->Branch("phib", &phib, "phib/D");
tree->Branch("SpID", &SpID, "SpID/I");
tree->Branch("ExAID", &ExAID, "ExAID/I");
tree->Branch("KEA", &KEA, "KEA/D");
if(isTargetScattering) tree->Branch("KEAscattered", &KEAscattered, "KEAscattered/D");
tree->Branch("theta", &theta, "theta/D");
tree->Branch("phi", &phi, "phi/D");
tree->Branch("mB", &mB, "mB/D");
tree->Branch("mb", &mb, "mb/D");
tree->Branch("Bfield", &BField, "Bfield/D");
TClonesArray * arr = new TClonesArray("TLorentzVector");
tree->Branch("fV", arr, 256000);
arr->BypassStreamer();
TClonesArray * arrN = new TClonesArray("TLorentzVector");
tree->Branch("fVN", arrN, 256000);
arrN->BypassStreamer();
TLorentzVector* fourVector = NULL;
// the output of Helios.CalHit
double e1, z1, t1, rho1, x1h, y1h, r1h;
double e2, z2, t2, rho2, x2h, y2h, r2h;
tree->Branch("e1", &e1, "e1/D");
tree->Branch("z1", &z1, "z1/D");
tree->Branch("t1", &t1, "t1/D");
tree->Branch("x1h", &x1h, "x1h/D"); //at 200 mm downstream
tree->Branch("y1h", &y1h, "y1h/D");
tree->Branch("r1h", &r1h, "r1h/D");
tree->Branch("rho1", &rho1, "rho1/D");
tree->Branch("e2", &e2, "e2/D");
tree->Branch("z2", &z2, "z2/D");
tree->Branch("t2", &t2, "t2/D");
tree->Branch("x2h", &x2h, "x2h/D"); //at 200 mm downstream
tree->Branch("y2h", &y2h, "y2h/D");
tree->Branch("r2h", &r2h, "r2h/D");
tree->Branch("rho2", &rho2, "rho2/D");
double Sp2;
tree->Branch("Sp2", &Sp2, "Sp2/D");
//different coordinate
double a0, a1, a2; // in k1-k2 coordinate
tree->Branch("a0", &a0, "a0/D");
tree->Branch("a1", &a1, "a1/D");
tree->Branch("a2", &a2, "a2/D");
double b; // in THREEDEE coordinate
tree->Branch("b", &b, "b/D");
//========timer
TBenchmark clock;
bool shown ;
clock.Reset();
clock.Start("timer");
shown = false;
printf("############################################## generating %d events \n", numEvent);
//====================================================== calculate
int count = 0;
for( int i = 0; i < numEvent; i++){
bool redoFlag = true;
if( !isReDo ) redoFlag = false;
do{
//==== Set Ex of A
ExAID = gRandom->Integer(nExA);
ExA = ExAList[ExAID];
reaction.SetExA(ExA);
//==== Set Sp of B
SpID = gRandom->Integer(SpList.size());
Sp = SpList[SpID];
//==== Set incident beam
if( KEAsigma == 0 ){
KEA = KEAmean;
}else{
KEA = gRandom->Gaus(KEAmean, KEAsigma);
}
if( thetaSigma == 0 ){
theta = thetaMean;
}else{
theta = gRandom->Gaus(thetaMean, thetaSigma);
}
int rKEA = gRandom->Integer(nKEA);
KEA = KEAList[rKEA];
/*
KEA = 300*gRandom->Rndm();
BField = 4*gRandom->Rndm();
helios1.SetMagneticField(BField);
helios2.SetMagneticField(BField);
*/
reaction.SetIncidentEnergyAngle(KEA, theta, 0.);
/*
//For target scattering
reaction.CalIncidentChannel(isNormalKinematics); // but only need is PA
TLorentzVector PA = reaction.GetPA();
double depth = 0;
if( isTargetScattering ){
//==== Target scattering, only energy loss
depth = targetThickness * gRandom->Rndm();
msA.SetTarget(density, depth);
TLorentzVector PAnew = msA.Scattering(PA);
KEAscattered = msA.GetKE()/AA;
reaction.SetIncidentEnergyAngle(KEAscattered, theta, phi);
}*/
//==== Calculate reaction
thetaNN = TMath::ACos(2 * gRandom->Rndm() - 1) ;
phiNN = TMath::TwoPi() * gRandom->Rndm();
kb = maxkb * gRandom->Rndm();
thetab = TMath::ACos(2 * gRandom->Rndm() - 1);
phib = TMath::TwoPi() * gRandom->Rndm();
reaction.SetBSpk(Sp, kb, thetab, phib);
reaction.CalReactionConstant(isNormalKinematics);
reaction.Event(thetaNN, phiNN);
TLorentzVector PA = reaction.GetPA();
TLorentzVector Pa = reaction.GetPa();
TLorentzVector P1 = reaction.GetP1();
TLorentzVector P2 = reaction.GetP2();
TLorentzVector Pb = reaction.GetPb();
TLorentzVector PB = reaction.GetPB();
/*
//==== Calculate energy loss of scattered and recoil in target
if( isTargetScattering ){
if( Pb.Theta() < TMath::PiOver2() ){
msb.SetTarget(density, targetThickness - depth);
}else{
msb.SetTarget(density, depth);
}
Pb = msb.Scattering(Pb);
TbLoss = msb.GetKELoss();
msB.SetTarget(density, targetThickness - depth);
PB = msB.Scattering(PB);
}else{
TbLoss = 0;
}
//======= Decay of particle-B
if( isDecay){
int decayID = decay.CalDecay(PB, Sp, 0); // decay to ground state
if( decayID == 1 ){
PB = decay.GetDaugther_D();
decayTheta = decay.GetAngleChange();
}else{
decayTheta = TMath::QuietNaN();
}
}
*/
//################################### tree branches
//===== reaction
theta1 = P1.Theta() * TMath::RadToDeg();
theta2 = P2.Theta() * TMath::RadToDeg();
thetaB = PB.Theta() * TMath::RadToDeg();
T1 = P1.E() - P1.M();
T2 = P2.E() - P2.M();
TB = PB.E() - PB.M();
phi1 = P1.Phi() * TMath::RadToDeg();
phi2 = P2.Phi() * TMath::RadToDeg();
//--------- diff coordinate
b = TMath::ASin( TMath::Sin(P2.Theta()) * TMath::Sin(P1.Phi() - P2.Phi() )) * TMath::RadToDeg();
TVector3 kA = (PA.Vect()).Unit();
TVector3 k1 = (P1.Vect()).Unit();
TVector3 k2 = (P2.Vect()).Unit();
TVector3 n = (k1.Cross(k2)).Unit();
TVector3 j = (kA - (kA.Dot(n))*n).Unit();
a0 = TMath::ASin(n.Dot(kA)) * TMath::RadToDeg();
a1 = TMath::ACos(k1.Dot(j)) * TMath::RadToDeg();
a2 = TMath::ACos(k2.Dot(j)) * TMath::RadToDeg();
//----------- mass
mB = PB.M();
mb = Pb.M();
TVector3 bA = PA.BoostVector();
for(int i = 0; i < 6 ; i++){
TLorentzVector temp;
double xyzt[4];
switch(i){
case 0: temp = PA; break;
case 1: temp = Pa; break;
case 2: temp = P1; break;
case 3: temp = P2; break;
case 4: temp = PB; break;
case 5: temp = Pb; break;
}
temp.GetXYZT(xyzt);
fourVector = (TLorentzVector*) arr->ConstructedAt(i);
fourVector->SetXYZT(xyzt[0], xyzt[1], xyzt[2], xyzt[3]);
//into normal kinematic
temp.Boost(-bA);
temp.GetXYZT(xyzt);
fourVector = (TLorentzVector*) arrN->ConstructedAt(i);
fourVector->SetXYZT(xyzt[0], xyzt[1], xyzt[2], xyzt[3]);
}
//==== Helios
int hit1 = helios1.CalHit(P1, Z1, PB, ZB);
int hit2 = helios2.CalHit(P2, Z2, PB, ZB);
double recoilZ = 1000;
e1 = helios1.GetEnergy() + gRandom->Gaus(0, eSigma);
z1 = helios1.GetZ() ;
t1 = helios1.GetTime();
rho1 = helios1.GetRho();
x1h = helios1.GetXPos(recoilZ);
y1h = helios1.GetYPos(recoilZ);
r1h = helios1.GetR(recoilZ);
e2 = helios2.GetEnergy() + gRandom->Gaus(0, eSigma);
z2 = helios2.GetZ() ;
t2 = helios2.GetTime();
rho2 = helios2.GetRho();
x2h = helios2.GetXPos(recoilZ);
y2h = helios2.GetYPos(recoilZ);
r2h = helios2.GetR(recoilZ);
double gammaA = PA.Gamma();
double betaA = PA.Beta();
Sp2 = (1-gammaA)* 938.272 - gammaA*(e1+e2) + betaA*gammaA*(P1.Pz() + P2.Pz()) ;
//printf("%f, %f | %f, %f \n", e1, z1, e2, z2);
//change thetaNN into deg
thetaNN = thetaNN * TMath::RadToDeg();
if( hit1 == 1) {
count ++;
}
if( isReDo ){
if( hit1 == 1) {
redoFlag = false;
}else{
redoFlag = true;
//printf("%d, %2d, thetaNN : %f, theta : %f, z0: %f \n", i, hit, thetaNN * TMath::RadToDeg(), thetab, helios.GetZ0());
}
}else{
redoFlag = false;
}
}while( redoFlag );
tree->Fill();
//#################################################################### Timer
clock.Stop("timer");
Double_t time = clock.GetRealTime("timer");
clock.Start("timer");
if ( !shown ) {
if (fmod(time, 10) < 1 ){
printf( "%10d[%2d%%]| %8.2f sec | expect: %5.1f min \n", i, TMath::Nint((i+1)*100./numEvent), time , numEvent*time/(i+1)/60);
shown = 1;
}
}else{
if (fmod(time, 10) > 9 ){
shown = 0;
}
}
}
saveFile->Write();
saveFile->Close();
printf("=============== done. saved as %s. count(hit==1) : %d\n", saveFileName.Data(), count);
gROOT->ProcessLine(".q");
/**/
}