36 for (
int i = 0; i < 5; i++) {
43 fThetaLabVsThetaCM[i] =
nullptr;
44 fELabVsThetaCM[i] =
nullptr;
45 fELabVsThetaLab[i] =
nullptr;
47 fKoxReactionXSec =
nullptr;
48 fEqbmChargeState =
nullptr;
49 fEqbmChargeStateShSol =
nullptr;
50 fEqbmChargeStateShGas =
nullptr;
53 SetIntegralPrecision(1
e-10);
113 bool beam_in_mev =
false;
120 scouple = syst.
Next();
157 SetTitle(
Form(
"%s + %s %.1f MeV/A", fNuclei[1].GetSymbol(), fNuclei[2].GetSymbol(), ee));
170 Obsolete(
"KV2Body(KVNucleus*, KVNucleus*, KVNucleus*, Double_t)",
"1.11",
"1.12");
173 Info(
"KV2Body",
"Use constructor KV2Body(const KVNucleus& compound) to simulate binary decay of compound");
175 else if (!proj_out) {
176 Info(
"KV2Body",
"Use constructor KV2Body(const KVNucleus& proj, const KVNucleus& targ) to define entrance channel");
179 Info(
"KV2Body",
"Use constructor KV2Body(const KVNucleus& proj, const KVNucleus& targ, const KVNucleus& outgoing) to define entrance & exit channels");
211 : fNuclei(5), fEDiss(-Exx)
238 if (fEDiss == 0) fEDiss =
compound.GetExcitEnergy();
257 fNuclei(5), fEDiss(Ediss)
274 SetTitle(
Form(
"%s + %s %.1f MeV/A", fNuclei[1].GetSymbol(), fNuclei[2].GetSymbol(), fNuclei[1].GetAMeV()));
297 fNuclei(5), fEDiss(Ediss)
320 SetTitle(
Form(
"%s + %s %.1f MeV/A", fNuclei[1].GetSymbol(), fNuclei[2].GetSymbol(), fNuclei[1].GetAMeV()));
344 fNuclei[2].SetZandA(z,
a);
368 fNuclei[1].SetZandA(z,
a);
378 if (fKoxReactionXSec)
delete fKoxReactionXSec;
379 if (fEqbmChargeState)
delete fEqbmChargeState;
380 for (
int i = 0; i < 5; i++) {
381 if (fThetaLabVsThetaCM[i])
delete fThetaLabVsThetaCM[i];
382 if (fELabVsThetaCM[i])
delete fELabVsThetaCM[i];
383 if (fELabVsThetaLab[i])
delete fELabVsThetaLab[i];
417 SetTitle(
Form(
"%s + %s %.1f MeV/A", fNuclei[1].GetSymbol(), fNuclei[2].GetSymbol(), fNuclei[1].GetAMeV()));
418 fSetOutgoing =
kTRUE;
419 fNuclei[3] = proj_out;
422 for (
unsigned i = 1; i <= 4; ++i)
if (fNuclei[i].IsDefined()) fNuclei[i].SetExcitEnergy(0);
436 void KV2Body::Set4thNucleus()
453 if (fEDiss == 0) fEDiss =
sum.GetExcitEnergy();
477 if (fNuclei[i].IsDefined())
return (
KVNucleus*) &fNuclei[i];
480 KVError::Warning(
this,
"GetNucleus(nucleus_of_interest i)",
"Index i out of bounds, i=%d", i);
495 KVError::Warning(
this,
"GetQReaction",
"Parameters for outgoing nuclei not set");
515 "Parameters for outgoing nuclei not set");
553 "Returns maximum scattering angle in lab for projectile_like or target_like nuclei");
571 "Returns minimum scattering angle in lab for projectile_like or target_like nuclei");
618 if (i < projectile || i >
target) {
620 "i should be projectile or target");
625 "No target defined for reaction");
634 Double_t RINT = CP + CT + 4.49 - (CT + CP) / 6.35;
708 if (!Nuc2 && !fSetOutgoing) {
709 KVError::Error(
this,
"CalculateKinematics",
"Set outgoing (decay) product first");
717 WLT = WCT = BCM = 0.;
718 for (
int i = 0; i < 5; i++) {
738 BCM = VCM.
Mag() / WLT;
755 K[1] = VCM.
Mag() / VC[1];
760 K[2] = VCM.
Mag() / VC[2];
766 WC[3] = (WCT -
GetEDiss()) / 2. + (AM3 - AM4) * (AM3 + AM4)
771 if (VC[3] > 0.) K[3] = VCM.
Mag() / VC[3];
789 if (VC[4] > 0.) K[4] = VCM.
Mag() / VC[4];
828 eqn.
Form(
"%s(%s,%s)%s",
832 eqn.
Form(
"%s(%s,%s)",
836 eqn.
Form(
"(%s,%s)%s",
840 eqn.
Form(
"%s(%s,%s)%s",
890 cout <<
" ******" << endl;
899 cout <<
" ==> Q-REACTION = " <<
GetQReaction() <<
" MEV";
902 cout <<
" AVAILABLE ENERGY IN C.M. : ECM = " <<
GetCMEnergy() <<
905 GetA() : 0.)) <<
" MEV/A)" << endl;
909 Mag() <<
" CM/NS" << endl;
911 for (
int i=1; i<=4; ++i) {
913 cout <<
" ENERGY - VELOCITY OF NUCLEUS " << i <<
" IN CM : " <<
918 cout <<
" MAXIMUM SCATTERING ANGLE IN LABORATORY" << endl;
926 cout <<
" GRAZING ANGLE IN LABORATORY : PROJECTILE " <<
928 cout <<
" GRAZING ANGLE IN LABORATORY : TARGET " <<
935 if (!strcmp(opt,
"lab") || !strcmp(opt,
"LAB")
936 || !strcmp(opt,
"Lab")) {
939 " LABORATORY ANGULAR DISTRIBUTION" << endl
942 "Th-PLF [deg.] E-PLF [MeV] V-PLF [cm/ns] Th-TLF [deg.] E-TLF [MeV] Th-PLF [deg.]"
945 " (LAB) (LAB) (LAB) (LAB) (LAB) (C.M)"
948 for (
int step = 0; step <= nsteps; step++) {
959 (
" %6.2f %7.2f /%7.2f %5.2f /%5.2f %6.2f /%6.2f %7.2f /%7.2f %6.2f/%6.2f\n",
960 theta, *elabP->first(), *elabP->second(), *vP->first(), *vP->second(),
961 *tlT->first(), *tlT->second(), *elabT->first(), *elabT->second(), *tcmP->first(), *tcmP->second());
964 (
" %6.2f %7.2f %5.2f %6.2f %7.2f %6.2f\n",
965 theta, *elabP->first(), *vP->first(), *tlT->first(), *elabT->first(), *tcmP->first());
969 || !strcmp(opt,
"Ruth"))) {
972 " RUTHERFORD LABORATORY ANGULAR DISTRIBUTION" <<
975 " TETA 3 TETA 3 EN.DIF.3 SIG.RUT. SIG.RUT."
978 " (LAB) (CM) (LAB) (LAB) (b/sr) (CM) (b/sr)"
982 for (
int step = 0; step < nsteps; step++) {
983 Double_t theta = dtheta * (step + 1);
989 (
" %6.2f %6.2f %7.2f %10.4g %10.4g\n",
990 theta, *tcm->first(), *elabP->first(),
1011 AngleNucleus = OfNucleus;
1012 auto AN_theta_cm =
GetThetaCM(ThetaLab, *AngleNucleus);
1015 KinematicSolutions ON_theta_cm;
1017 AN_theta_cm->iterate_solutions([&](
double x){ON_theta_cm.solutions[i++] =
GetThetaCM(OfNucleus,
x, *AngleNucleus);});
1019 KinematicSolutions energies;
1021 ON_theta_cm.iterate_solutions([&](
double x){energies.solutions[i++] =
GetELab(
x, OfNucleus);});
1063 return FindRoots(fonc,ThetaLab);
1080 if(kine_sol == kinematic_solution::low_E_branch)
1081 return kine->second();
1082 return kine->first();
1101 if(elab && elab->second() && ((
kinematic_solution)par[1])==kinematic_solution::low_E_branch)
1102 return *elab->second();
1103 return elab ? *elab->first() : 0;
1146 else if(K[OfNucleus]<1){
1155 if (ThetaL < 0.) ThetaL += 180.;
1172 if (!fELabVsThetaCM[OfNucleus]) {
1173 fELabVsThetaCM[OfNucleus] =
new TF1(
Form(
"KV2Body:ELabVsThetaCM:%d", OfNucleus),
1174 const_cast<KV2Body*
>(
this), &KV2Body::ELabVsThetaCM, 0, 180, 1,
"KV2Body",
"ELabVsThetaCM");
1175 fELabVsThetaCM[OfNucleus]->
SetNpx(1000);
1178 return fELabVsThetaCM[OfNucleus];
1213 if (!fELabVsThetaLab[OfNucleus]) {
1214 fELabVsThetaLab[OfNucleus] =
new TF1(
Form(
"KV2Body:ELabVsThetaLab:%d", OfNucleus),
1215 const_cast<KV2Body*
>(
this), &KV2Body::ELabVsThetaLab, 0, 180, 2,
"KV2Body",
"ELabVsThetaLab");
1216 fELabVsThetaLab[OfNucleus]->
SetNpx(1000);
1217 fELabVsThetaLab[OfNucleus]->
SetParameter(0, OfNucleus);
1220 return fELabVsThetaLab[OfNucleus];
1235 auto elab =
GetELab(OfNucleus, ThetaLab, AngleNucleus);
1239 KinematicSolutions velo;
1255 if (ThetaLab > TETAMAX[AngleNucleus])
return {};
1256 if (!(
TMath::Abs(OfNucleus - AngleNucleus) % 2)) {
1258 return {{ThetaLab,{}}};
1261 auto TCM =
GetThetaCM(ThetaLab, AngleNucleus);
1265 KinematicSolutions tcm;
1267 TCM->iterate_solutions([&](
double T){ tcm.solutions[i++] =
GetThetaCM(OfNucleus,
T, AngleNucleus); });
1270 KinematicSolutions tlab;
1271 tcm.iterate_solutions([&](
double t){ tlab.solutions[i++] =
GetThetaLab(t, OfNucleus); });
1288 if (!fThetaLabVsThetaCM[OfNucleus]) {
1289 fThetaLabVsThetaCM[OfNucleus] =
new TF1(
Form(
"KV2Body:ThetaLabVsThetaCM:%d", OfNucleus),
1290 const_cast<KV2Body*
>(
this), &KV2Body::ThetaLabVsThetaCM, 0, 180, 1,
"KV2Body",
"ThetaLabVsThetaCM");
1291 fThetaLabVsThetaCM[OfNucleus]->
SetNpx(1000);
1292 fThetaLabVsThetaCM[OfNucleus]->
SetParameter(0, OfNucleus);
1294 return fThetaLabVsThetaCM[OfNucleus];
1342 double dth = 180. / (npoints - 1.);
1344 while (i < npoints) {
1345 auto thcm = i * dth;
1396 else name +=
"(target)";
1397 TF1* fXSecRuthCM = (
TF1*)
gROOT->GetListOfFunctions()->FindObject(
name.Data());
1399 fXSecRuthCM =
new TF1(
name.Data(),
1400 const_cast<KV2Body*
>(
this), &KV2Body::XSecRuthCMVsThetaCM,
1401 theta_cm_min, theta_cm_max, 1,
"KV2Body",
"XSecRuthCMVsThetaCM");
1403 fXSecRuthCM->
SetNpx(1000);
1405 fXSecRuthCM->
SetRange(theta_cm_min, theta_cm_max);
1441 auto theta = *tcm->second();
1442 return XSecRuthCMVsThetaCM(&theta, par);
1448 auto theta = *tcm->first();
1449 return XSecRuthCMVsThetaCM(&theta, par);
1470 std::array<double,2> par = { (double)OfNucleus, (
double)kineSol };
1471 return const_cast<KV2Body*
>(
this)->XSecRuthCM(&ThetaLab, par.data());
1501 Double_t DSIDTB = XSecRuthCM(x, par);
1505 auto T3CM = *T3CM_v;
1531 std::vector<double> par = { (double)OfNucleus, (
double)kineSol };
1532 return const_cast<KV2Body*
>(
this)->XSecRuthLab(&ThetaLab, par.data());
1619 if (phi1 == -1 || phi2 == -1) dphi = 2 *
TMath::Pi();
1620 else if (phi1 == phi2) dphi = 1;
1627 if (
th1 < theta_min) theta_min =
th1;
1628 if (
th2 > theta_max) theta_max =
th2;
1630 #if ROOT_VERSION_CODE > ROOT_VERSION(5,99,01)
1657 Double_t R12 = r0 * (A1third + A2third);
1660 - 2.9 * A1third * A2third / (A1third + A2third);
1695 Double_t BC = proj->
GetZ() * targ->
GetZ() * e2 / (rc * (A1third + A2third));
1699 pow((A1third + A2third +
a * A1third * A2third / (A1third + A2third) -
c), 2) *
1721 pow(A1third + A2third, 2);
1778 if (!fKoxReactionXSec) {
1782 fKoxReactionXSec =
new TF1(
name.Data(),
1784 fKoxReactionXSec->
SetNpx(1000);
1786 return fKoxReactionXSec;
1893 if (!fEqbmChargeState) {
1898 fEqbmChargeState =
new TF1(
name.Data(),
1900 fEqbmChargeState->
SetNpx(1000);
1902 return fEqbmChargeState;
1924 x = Vp / V0 *
pow(Zp, -0.52) *
pow(Zt,
x) / 1.68;
1925 x =
pow(
x, 1. + 1.8 / Zp);
1927 q = (Zp * (12 *
x +
pow(
x, 4.))) /
q;
1953 if (!fEqbmChargeStateShSol) {
1957 name +=
" SHIWIETZ-SOLID";
1958 fEqbmChargeStateShSol =
new TF1(
name.Data(),
1960 fEqbmChargeStateShSol->
SetNpx(1000);
1962 return fEqbmChargeStateShSol;
1984 x = Vp / V0 *
pow(Zp, -0.52) *
pow(Zt,
x);
1985 x =
pow(
x, 1. + 0.4 / Zp);
1987 q = (Zp * (376.*
x +
pow(
x, 6.))) /
q;
2014 if (!fEqbmChargeStateShGas) {
2018 name +=
" SHIWIETZ-GAS";
2019 fEqbmChargeStateShGas =
new TF1(
name.Data(),
2021 fEqbmChargeStateShGas->
SetNpx(1000);
2023 return fEqbmChargeStateShGas;
2044 Info(
"GetXSecRuthLabFunc",
"Maximum angle set to %lf degrees", theta_max);
2055 else name +=
"(target)";
2057 TF1* fXSecRuthLab = (
TF1*)
gROOT->GetListOfFunctions()->FindObject(
name.Data());
2058 if (!fXSecRuthLab) {
2059 fXSecRuthLab =
new TF1(
name.Data(),
2060 const_cast<KV2Body*
>(
this), &KV2Body::XSecRuthLab, theta_min, theta_max, 2,
"KV2Body",
"XSecRuthLab");
2063 fXSecRuthLab->
SetNpx(1000);
2065 fXSecRuthLab->
SetRange(theta_min, theta_max);
2066 return fXSecRuthLab;
2106 else name +=
"(target)";
2108 TF1* fXSecRuthLab = (
TF1*)
gROOT->GetListOfFunctions()->FindObject(
name.Data());
2109 if (!fXSecRuthLab) {
2110 fXSecRuthLab =
new TF1(
name.Data(),
2111 const_cast<KV2Body*
>(
this), &KV2Body::XSecRuthLabInt, theta_min, theta_max, 2,
"KV2Body",
"XSecRuthLabInt");
2114 fXSecRuthLab->
SetNpx(1000);
2116 fXSecRuthLab->
SetRange(theta_min, theta_max);
2117 return fXSecRuthLab;
2150 KV2Body::KinematicSolutions_v KV2Body::FindRoots(
TF1* fonc,
Double_t val)
const
2186 if(fonc->
Eval(xmax)==0)
2192 if (val > max)
return {};
2200 if (fonc->
Eval(xmax) == 0) nRoots = 2;
2202 auto x1 = fonc->
GetX(val, xmin, xmax1);
2205 auto x2 = fonc->
GetX(val, maxX, xmax);
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t g
char * Form(const char *fmt,...)
Relativistic binary kinematics calculator.
Double_t eqbm_charge_state_shiwietz_gas(Double_t *t, Double_t *)
void SetTarget(const KVNucleus &)
Set target for reaction.
TString GetReactionEquation() const
KVDrawable< TF1 > GetELabVsThetaLabFunc(nucleus_of_interest OfNucleus, kinematic_solution kine_sol=kinematic_solution::high_E_branch) const
Double_t GetSphereDureReactionXSec(Double_t r0=1.05)
Double_t GetMaxAngleLab(nucleus_of_interest i) const
KinematicSolutions_v GetThetaCM(Double_t ThetaLab, nucleus_of_interest OfNucleus) const
void SetProjectile(const KVNucleus &)
Set projectile for reaction.
KVDrawable< TF1 > GetXSecRuthCMFunc(nucleus_of_interest OfNucleus=projectile_like, Double_t theta_cm_min=1., Double_t theta_cm_max=179.) const
Double_t GetXSecRuthLab(Double_t ThetaLab, nucleus_of_interest OfNucleus=projectile_like, kinematic_solution kineSol=high_E_branch) const
Double_t GetQReaction() const
Calculate Q-value for reaction, including dissipated (excitation) energy.
Double_t EqbmChargeState(Double_t *t, Double_t *)
KVDrawable< TF1 > GetShiwietzEqbmChargeStateFuncForSolidTargets() const
void SetOutgoing(const KVNucleus &proj_out)
Double_t GetELab(Double_t ThetaCM, nucleus_of_interest OfNucleus) const
KVDrawable< TGraph > GetGraphELabVsThetaLab(nucleus_of_interest OfNucleus=projectile_like, int npoints=50) const
Double_t GetThetaLab(Double_t ThetaCM, nucleus_of_interest OfNucleus) const
KVDrawable< TF1 > GetELabVsThetaCMFunc(nucleus_of_interest OfNucleus) const
Double_t GetEDiss() const
KinematicSolutions_v GetVLab(nucleus_of_interest OfNucleus, Double_t ThetaLab, std::optional< nucleus_of_interest > AngleNucleus={}) const
static Double_t GetVelocity(Double_t mass, Double_t E)
KVDrawable< TF1 > GetEqbmChargeStateFunc() const
KVDrawable< TF1 > GetXSecRuthLabFunc(nucleus_of_interest OfNucleus=projectile_like, kinematic_solution kineSol=high_E_branch, Double_t theta_min=1., Double_t theta_max=179.) const
Double_t GetBmaxFromReactionXSec(Double_t ReacXsec)
Double_t GetLabGrazingAngle(nucleus_of_interest i=projectile) const
KVDrawable< TF1 > GetShiwietzEqbmChargeStateFuncForGasTargets() const
Double_t KoxReactionXSec(Double_t *, Double_t *)
Double_t GetCMGamma() const
Double_t GetMinAngleLab(nucleus_of_interest i) const
Double_t GetExcitEnergy() const
Double_t BassIntBarrier()
TVector3 GetCMVelocity() const
Return vector velocity of centre of mass of reaction (units: cm/ns)
void CalculateKinematics()
void Print(Option_t *opt="") const override
void init()
Default initialisations.
KVDrawable< TF1 > GetKoxReactionXSecFunc() const
Double_t GetIntegratedXsec(Double_t b1, Double_t b2)
Double_t GetQGroundStates() const
Calculate Q-value for reaction, assuming all nuclei in ground state.
KVDrawable< TF1 > GetThetaLabVsThetaCMFunc(nucleus_of_interest OfNucleus) const
Double_t GetXSecRuthCM(Double_t ThetaLab, nucleus_of_interest OfNucleus=projectile_like, kinematic_solution kineSol=high_E_branch) const
Double_t GetCMEnergy() const
Return available kinetic energy in centre of mass.
Double_t eqbm_charge_state_shiwietz_solid(Double_t *t, Double_t *)
KVNucleus * GetNucleus(nucleus_of_interest i) const
KVDrawable< TF1 > GetXSecRuthLabIntegralFunc(nucleus_of_interest OfNucleus=projectile_like, Double_t theta_min=1., Double_t theta_max=179., kinematic_solution kineSol=high_E_branch) const
Double_t GetIntegratedXSecRuthLab(Float_t th1, Float_t th2, Float_t phi1=-1, Float_t phi2=-1, nucleus_of_interest OfNucleus=projectile_like)
Simple wrapper for objects which can be drawn (graphs, histograms)
Description of properties and kinematics of atomic nuclei.
const Char_t * GetSymbol(Option_t *opt="") const
Double_t GetExcitEnergy() const
Double_t GetMassExcess(Int_t z=-1, Int_t a=-1) const
Int_t GetZ() const
Return the number of proton / atomic number.
TVector3 GetMomentum() const
Double_t GetEnergy() const
void SetFrame(const Char_t *frame, const KVFrameTransform &)
KVParticle const * GetFrame(const Char_t *frame, Bool_t warn_and_return_null_if_unknown=kTRUE) const
void SetEnergy(Double_t e)
TVector3 GetVelocity() const
returns velocity vector in cm/ns units
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
void Begin(TString delim) const
KVString Next(Bool_t strip_whitespace=kFALSE) const
virtual void SetRange(Double_t xmin, Double_t xmax)
virtual void SetNpx(Int_t npx=100)
virtual Double_t GetX(Double_t y, Double_t xmin=0, Double_t xmax=0, Double_t epsilon=1.E-10, Int_t maxiter=100, Bool_t logx=false) const
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
virtual Double_t GetMaximum(Double_t xmin=0, Double_t xmax=0, Double_t epsilon=1.E-10, Int_t maxiter=100, Bool_t logx=false) const
virtual void SetParameter(const TString &name, Double_t value)
virtual Double_t GetMaximumX(Double_t xmin=0, Double_t xmax=0, Double_t epsilon=1.E-10, Int_t maxiter=100, Bool_t logx=false) const
virtual void AddPoint(Double_t x, Double_t y)
void SetTitle(const char *title="") override
virtual void SetTitle(const char *title="")
R__ALWAYS_INLINE Bool_t IsZombie() const
virtual void Info(const char *method, const char *msgfmt,...) const
void Obsolete(const char *method, const char *asOfVers, const char *removedFromVers) const
TString & Append(char c, Ssiz_t rep=1)
void Form(const char *fmt,...)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
TString & ReplaceAll(const char *s1, const char *s2)
void SetXYZ(Double_t x, Double_t y, Double_t z)
double beta(double x, double y)
T Mag(const SVector< T, D > &rhs)
RVec< PromoteTypes< T0, T1 > > pow(const T0 &x, const RVec< T1 > &v)
void Error(UserClass p, const char *location, const char *va_(fmt),...)
void Warning(UserClass p, const char *location, const char *va_(fmt),...)
double max(double x, double y)
Double_t Landau(Double_t x, Double_t mpv=0, Double_t sigma=1, Bool_t norm=kFALSE)
constexpr Double_t PiOver2()
Double_t ATan2(Double_t y, Double_t x)
Double_t Power(Double_t x, Double_t y)
constexpr Double_t DegToRad()
Double_t Sqrt(Double_t x)
Bool_t AreEqualAbs(Double_t af, Double_t bf, Double_t epsilon)
constexpr Double_t RadToDeg()
Double_t Log10(Double_t x)