#ifndef Transfer_h #define Transfer_h #include "utility" #include "ClassIsotope.h" #include "../Armory/AnalysisLib.h" #include "../Armory/ClassReactionConfig.h" #include "TLorentzVector.h" #include "TMath.h" //======================================================= //####################################################### // Class for Transfer Reaction // reaction notation A(a,b)B // A = incident particle // a = target // b = light scattered particle // B = heavy scattered particle //======================================================= class TransferReaction { public: TransferReaction(); ~TransferReaction(); void SetA(int A, int Z, double Ex); void Seta(int A, int Z); void Setb(int A, int Z); void SetB(int A, int Z); void SetIncidentEnergyAngle(double KEA, double theta, double phi); void SetReactionSimple(int beamA, int beamZ, int targetA, int targetZ, int recoilA, int recoilZ, float beamEnergy_AMeV); void SetExA(double Ex); void SetExB(double Ex); void SetReactionFromFile(string settingFile); TString GetReactionName(); TString GetReactionName_Latex(); ReactionConfig GetRectionConfig() { return reaction;} double GetMass_A() const {return mA + ExA;} double GetMass_a() const {return ma;} double GetMass_b() const {return mb;} double GetMass_B() const {return mB + ExB;} int GetCharge_b() const {return reaction.recoilLightZ;} double GetCMTotalKE() {return Etot - mA - ma;} double GetQValue() {return mA + ExA + ma - mb - mB - ExB;} double GetMaxExB() {return Etot - mb - mB;} TLorentzVector GetPA(){return PA;} TLorentzVector GetPa(){return Pa;} TLorentzVector GetPb(){return Pb;} TLorentzVector GetPB(){return PB;} void CalReactionConstant(); void Event(double thetaCM_rad, double phiCM_rad); double GetMomentumbCM() {return p;} double GetReactionBeta() {return beta;} double GetReactionGamma() {return gamma;} double GetCMTotalEnergy() {return Etot;} std::pair CalExThetaCM(double e, double z, double Bfield, double a); private: ReactionConfig reaction; string nameA, namea, nameb, nameB; double thetaIN, phiIN; double mA, ma, mb, mB; double TA, T; // TA = KE of A pre u, T = total energy double ExA, ExB; bool isReady; bool isBSet; double k; // CM Boost momentum double beta, gamma; //CM boost beta double Etot; double p; // CM frame momentum of b, B TLorentzVector PA, Pa, Pb, PB; TString format(TString name); }; TransferReaction::TransferReaction(){ thetaIN = 0.; phiIN = 0.; SetA(12, 6, 0); Seta(2,1); Setb(1,1); SetB(13,6); TA = 6; T = TA * reaction.beamA; ExA = 0; ExB = 0; CalReactionConstant(); TLorentzVector temp (0,0,0,0); PA = temp; Pa = temp; Pb = temp; PB = temp; } TransferReaction::~TransferReaction(){ } void TransferReaction::SetA(int A, int Z, double Ex = 0){ Isotope temp (A, Z); mA = temp.Mass; reaction.beamA = A; reaction.beamZ = Z; ExA = Ex; nameA = temp.Name; isReady = false; isBSet = true; } void TransferReaction::Seta(int A, int Z){ Isotope temp (A, Z); ma = temp.Mass; reaction.targetA = A; reaction.targetZ = Z; namea = temp.Name; isReady = false; isBSet = false; } void TransferReaction::Setb(int A, int Z){ Isotope temp (A, Z); mb = temp.Mass; reaction.recoilLightA = A; reaction.recoilLightZ = Z; nameb = temp.Name; isReady = false; isBSet = false; } void TransferReaction::SetB(int A, int Z){ Isotope temp (A, Z); mB = temp.Mass; reaction.recoilHeavyA = A; reaction.recoilHeavyZ = Z; nameB = temp.Name; isReady = false; isBSet = true; } void TransferReaction::SetIncidentEnergyAngle(double KEA, double theta, double phi){ this->TA = KEA; this->T = TA * reaction.beamA; this->thetaIN = theta; this->phiIN = phi; isReady = false; } void TransferReaction::SetReactionSimple(int beamA, int beamZ, int targetA, int targetZ, int recoilA, int recoilZ, float beamEnergy_AMeV){ reaction.SetReactionSimple(beamA, beamZ, targetA, targetZ, recoilA, recoilZ, beamEnergy_AMeV); SetA(reaction.beamA, reaction.beamZ); Seta(reaction.targetA, reaction.targetZ); Setb(reaction.recoilLightA, reaction.recoilLightZ); SetB(reaction.recoilHeavyA, reaction.recoilHeavyZ); SetIncidentEnergyAngle(reaction.beamEnergy, 0, 0); CalReactionConstant(); } void TransferReaction::SetExA(double Ex){ this->ExA = Ex; isReady = false; } void TransferReaction::SetExB(double Ex){ this->ExB = Ex; isReady = false; } void TransferReaction::SetReactionFromFile(string settingFile){ if( reaction.LoadReactionConfig(settingFile) ){ SetA(reaction.beamA, reaction.beamZ); Seta(reaction.targetA, reaction.targetZ); Setb(reaction.recoilLightA, reaction.recoilLightZ); SetB(reaction.recoilHeavyA, reaction.recoilHeavyZ); SetIncidentEnergyAngle(reaction.beamEnergy, 0, 0); CalReactionConstant(); }else{ printf("cannot read file %s.\n", settingFile.c_str()); isReady = false; } } TString TransferReaction::GetReactionName(){ TString rName; rName.Form("%s(%s,%s)%s", nameA.c_str(), namea.c_str(), nameb.c_str(), nameB.c_str()); return rName; } TString TransferReaction::format(TString name){ if( name.IsAlpha() ) return name; int len = name.Length(); TString temp = name; TString temp2 = name; if( temp.Remove(0, len-2).IsAlpha()){ temp2.Remove(len-2); }else{ temp = name; temp.Remove(0, len-1); temp2.Remove(len-1); } return "^{"+temp2+"}"+temp; } TString TransferReaction::GetReactionName_Latex(){ TString rName; rName.Form("%s(%s,%s)%s", format(nameA).Data(), format(namea).Data(), format(nameb).Data(), format(nameB).Data()); return rName; } void TransferReaction::CalReactionConstant(){ if( !isBSet){ reaction.recoilHeavyA = reaction.beamA + reaction.targetA - reaction.recoilLightA; reaction.recoilHeavyZ = reaction.beamZ + reaction.targetZ - reaction.recoilLightZ; Isotope temp (reaction.recoilHeavyA, reaction.recoilHeavyZ); mB = temp.Mass; isBSet = true; } k = TMath::Sqrt(TMath::Power(mA + ExA + T, 2) - (mA + ExA) * (mA + ExA)); beta = k / (mA + ExA + ma + T); gamma = 1 / TMath::Sqrt(1- beta * beta); Etot = TMath::Sqrt(TMath::Power(mA + ExA + ma + T,2) - k * k); p = TMath::Sqrt( (Etot*Etot - TMath::Power(mb + mB + ExB,2)) * (Etot*Etot - TMath::Power(mb - mB - ExB,2)) ) / 2 / Etot; PA.SetXYZM(0, 0, k, mA + ExA); PA.RotateY(thetaIN); PA.RotateZ(phiIN); Pa.SetXYZM(0,0,0,ma); isReady = true; } void TransferReaction::Event(double thetaCM_rad, double phiCM_rad){ if( isReady == false ){ CalReactionConstant(); } //---- to CM frame TLorentzVector Pc = PA + Pa; TVector3 b = Pc.BoostVector(); TVector3 vb(0,0,0); if( b.Mag() > 0 ){ TVector3 v0 (0,0,0); TVector3 nb = v0 - b; TLorentzVector PAc = PA; PAc.Boost(nb); TVector3 vA = PAc.Vect(); TLorentzVector Pac = Pa; Pac.Boost(nb); TVector3 va = Pac.Vect(); //--- construct vb vb = va; vb.SetMag(p); TVector3 ub = vb.Orthogonal(); vb.Rotate(thetaCM_rad, ub); vb.Rotate(phiCM_rad + TMath::PiOver2(), va); // somehow, the calculation turn the vector 90 degree. //vb.Rotate(phiCM , va); // somehow, the calculation turn the vector 90 degree. } //--- from Pb TLorentzVector Pbc; Pbc.SetVectM(vb, mb); //--- from PB TLorentzVector PBc; //PBc.SetVectM(vB, mB + ExB); PBc.SetVectM(-vb, mB + ExB); //---- to Lab Frame Pb = Pbc; Pb.Boost(b); PB = PBc; PB.Boost(b); } std::pair TransferReaction::CalExThetaCM(double e, double z, double Bfield, double perpDist){ double Ex = TMath::QuietNaN(); double thetaCM = TMath::QuietNaN(); double mass = mb; double massB = mB; double y = e + mass; double slope = 299.792458 * reaction.recoilLightZ * abs(Bfield) / TMath::TwoPi() * beta / 1000.; // MeV/mm; double alpha = slope/beta; double G = alpha * gamma * beta * perpDist ; double Z = alpha * gamma * beta * z; double H = TMath::Sqrt(TMath::Power(gamma * beta,2) * (y*y - mass * mass) ) ; double Et = Etot; if( TMath::Abs(Z) < H ) { //using Newton's method to solve 0 == H * sin(phi) - G * tan(phi) - Z = f(phi) double tolerrence = 0.001; double phi = 0; //initial phi = 0 -> ensure the solution has f'(phi) > 0 double nPhi = 0; // new phi int iter = 0; do{ phi = nPhi; nPhi = phi - (H * TMath::Sin(phi) - G * TMath::Tan(phi) - Z) / (H * TMath::Cos(phi) - G /TMath::Power( TMath::Cos(phi), 2)); iter ++; if( iter > 10 || TMath::Abs(nPhi) > TMath::PiOver2()) break; }while( TMath::Abs(phi - nPhi ) > tolerrence); phi = nPhi; // check f'(phi) > 0 double Df = H * TMath::Cos(phi) - G / TMath::Power( TMath::Cos(phi),2); if( Df > 0 && TMath::Abs(phi) < TMath::PiOver2() ){ double K = H * TMath::Sin(phi); double x = TMath::ACos( mass / ( y * gamma - K)); double k = mass * TMath::Tan(x); // momentum of particel b or B in CM frame double EB = TMath::Sqrt(mass*mass + Et*Et - 2*Et*TMath::Sqrt(k*k + mass * mass)); Ex = EB - massB; double hahaha1 = gamma* TMath::Sqrt(mass * mass + k * k) - y; double hahaha2 = gamma* beta * k; thetaCM = TMath::ACos(hahaha1/hahaha2) * TMath::RadToDeg(); //double pt = k * TMath::Sin(thetaCM * TMath::DegToRad()); //double pp = gamma*beta*TMath::Sqrt(mass*mass + k*k) - gamma * k * TMath::Cos(thetaCM * TMath::DegToRad()); //thetaLab = TMath::ATan(pt/pp) * TMath::RadToDeg(); }else{ Ex = TMath::QuietNaN(); thetaCM = TMath::QuietNaN(); //thetaLab = TMath::QuietNaN(); } }else{ Ex = TMath::QuietNaN(); thetaCM = TMath::QuietNaN(); //thetaLab = TMath::QuietNaN(); } return std::make_pair(Ex, thetaCM); } #endif