11#include " AnisotropicThreeBodyDecay.h"
2- #include " sbncode/EventGenerator/MeVPrtl/Tools/Constants.h"
32
4- #include " TLorentzVector.h"
5- #include " TRandom3.h"
3+ double evgen::ldm::AnThreeBD::GetRandom (CLHEP::HepRandomEngine* fEngine ) {
4+ return CLHEP::RandFlat::shoot (fEngine );
5+ }
6+
7+
68
79/* Implementation of HNL Three Body Decays Anisotropies
810 Valid as long as the HNL is decaying into a neutrino and identical final-state charged leptons
@@ -178,7 +180,7 @@ double evgen::ldm::AnThreeBD::MSqDM(double (&C)[6], double z2_num, double z2_ll,
178180 Currently optimized for electrons and muons for m_HNl<388 MeV
179181 This function returns values of the maximum previously calculated using multiple iterations of MSqDM function, as the maximum is not trivial to estimate, mainly because the allowed Dalitz region restricts the use of some algorithms.
180182 */
181- double evgen::ldm::AnThreeBD::MaxMSqDM (double m_HNL, int LeptonPDG, double Ue4, double Umu4, double Ut4, double m_p, double m_m, double Pol, double (&C)[6], bool Majorana)
183+ double evgen::ldm::AnThreeBD::MaxMSqDM (double m_HNL, int LeptonPDG, double Ue4, double Umu4, double Ut4, double m_p, double m_m, double Pol, double (&C)[6], bool Majorana, CLHEP::HepRandomEngine* fEngine )
182184{
183185 double Ce4 = 0 ;
184186 double Cmu4 = 0 ;
@@ -293,15 +295,14 @@ in the rejection sampling method used in AnisotropicThreeBodyDist. If the theor
293295 // Use 10e6 as a good aproximation of the maximum, if more precision is required the number can be increased
294296 int N_iter = pow (10 ,6 );
295297 double MSqMax = 0 ;
296- TRandom3 *rand = new TRandom3 (0 );
297298 for (int i=0 ;i<N_iter;i++) {
298299 double MSq = 0 ;
299- do {
300- // Generate a position in the Dalitz Plot randomly
301- double r1 = rand-> Rndm ( );
302- double r2 = rand-> Rndm ( );
303- double r3 = rand-> Rndm ( );
304- double r4 = rand-> Rndm ( );
300+ do {
301+ // Generate a position in the Dalitz Plot randomly
302+ double r1 = evgen::ldm::AnThreeBD::GetRandom ( fEngine );
303+ double r2 = evgen::ldm::AnThreeBD::GetRandom ( fEngine );
304+ double r3 = evgen::ldm::AnThreeBD::GetRandom ( fEngine );
305+ double r4 = evgen::ldm::AnThreeBD::GetRandom ( fEngine );
305306
306307 z2_ll = ((m_HNL * m_HNL - (m_m + m_p) * (m_m + m_p)) * r1 + (m_m + m_p) * (m_m + m_p)) / (m_HNL * m_HNL);
307308 z2_num = (((m_HNL - m_p) * (m_HNL - m_p) - m_m * m_m) * r2 + m_m * m_m) / (m_HNL * m_HNL);
@@ -331,15 +332,14 @@ in the rejection sampling method used in AnisotropicThreeBodyDist. If the theor
331332 ctll: cosine of the angle between the charged-lepton-pair (sum of the four-vectors) and the z-axis
332333 gamll: rotation angle about the direction of the charged-lepton pair
333334 masses: [mN, mm, mp] the HNL and daughter charged-lepton masses (mm: negatively-charged, mp: positively-charged) */
334- void evgen::ldm::AnThreeBD::RF4vecs (TLorentzVector &pnu, TLorentzVector &pm, TLorentzVector &pp, double z2_num, double z2_ll, double ct_ll, double gam_ll, double m_HNL, double m_p, double m_m)
335+ void evgen::ldm::AnThreeBD::RF4vecs (TLorentzVector &pnu, TLorentzVector &pm, TLorentzVector &pp, double z2_num, double z2_ll, double ct_ll, double gam_ll, double m_HNL, double m_p, double m_m, CLHEP::HepRandomEngine* fEngine )
335336{
336337 double PnuRF[4 ], PmRF[4 ], PpRF[4 ];
337338
338339 double m2_ll = z2_ll * m_HNL * m_HNL;
339340 double m2_num = z2_num * m_HNL * m_HNL;
340341
341- TRandom3 *rand1 = new TRandom3 (0 );
342- double r1 = rand1->Rndm ();
342+ double r1 = evgen::ldm::AnThreeBD::GetRandom (fEngine );
343343
344344 // Calculate some useful kinematical cuantities
345345 double E_m = (m2_ll + m2_num - m_p * m_p) / (2.0 * m_HNL);
@@ -352,7 +352,6 @@ void evgen::ldm::AnThreeBD::RF4vecs(TLorentzVector &pnu, TLorentzVector &pm, TLo
352352
353353 // Select the phi angle randomly as it doesnt affect the anisotropies
354354 double phi = r1 * 2.0 * TMath::Pi ();
355- phi = 1 ;
356355
357356 PnuRF[0 ] = E_nu;
358357 PnuRF[1 ] = -E_nu * st_ll * sin (phi);
@@ -385,14 +384,12 @@ void evgen::ldm::AnThreeBD::RF4vecs(TLorentzVector &pnu, TLorentzVector &pm, TLo
385384 AntiHNL: Wether the HNL is a AntiHNL or a HNL (Only relevant in Dirac case)
386385 Pol: Polarization of the HNL
387386 See arXiv:2104.05719 for more details */
388- void evgen::ldm::AnThreeBD::AnisotropicThreeBodyDist (TLorentzVector &pnu, TLorentzVector &pm, TLorentzVector& pp, double m_HNL, double Ue4, double Umu4, double Ut4, int LeptonPDG, bool Majorana, bool AntiHNL, double Pol)
387+ void evgen::ldm::AnThreeBD::AnisotropicThreeBodyDist (TLorentzVector pHNL, TLorentzVector &pnu, TLorentzVector &pm, TLorentzVector& pp, double m_HNL, double Ue4, double Umu4, double Ut4, int LeptonPDG, bool Majorana, bool AntiHNL, double Pol, CLHEP::HepRandomEngine* fEngine )
389388{
390389 // By default select the electron as the lepton pair
391390 double m_p = evgen::ldm::Constants::Instance ().elec_mass ;
392391 double m_m = evgen::ldm::Constants::Instance ().elec_mass ;
393392
394- TRandom3 *rand = new TRandom3 (0 );
395-
396393 // Select wether the final leptons are electrons or muons
397394 if (LeptonPDG == 13 ) {
398395 m_p = evgen::ldm::Constants::Instance ().muon_mass ;
@@ -418,7 +415,7 @@ void evgen::ldm::AnThreeBD::AnisotropicThreeBodyDist(TLorentzVector &pnu, TLoren
418415 double gam_ll = 0 ;
419416
420417 // Get the Maximum of the Matrix-element squared and use rejection sampling to get the anisotropic final states distribution
421- double MSqMax = evgen::ldm::AnThreeBD::MaxMSqDM (m_HNL, LeptonPDG, Ue4, Umu4, Ut4, m_p, m_m, Pol, C, Majorana);
418+ double MSqMax = evgen::ldm::AnThreeBD::MaxMSqDM (m_HNL, LeptonPDG, Ue4, Umu4, Ut4, m_p, m_m, Pol, C, Majorana, fEngine );
422419
423420 double MSq = 0 ;
424421 bool IsW = false ;
@@ -430,23 +427,68 @@ void evgen::ldm::AnThreeBD::AnisotropicThreeBodyDist(TLorentzVector &pnu, TLoren
430427 ctll: cosine of the angle between the charged-lepton-pair (sum of the four-vectors) and the z-axis
431428 gamll: rotation angle about the direction of the charged-lepton pair
432429 */
433- double r1 = rand-> Rndm ( );
434- double r2 = rand-> Rndm ( );
435- double r3 = rand-> Rndm ( );
436- double r4 = rand-> Rndm ( );
430+ double r1 = evgen::ldm::AnThreeBD::GetRandom ( fEngine );
431+ double r2 = evgen::ldm::AnThreeBD::GetRandom ( fEngine );
432+ double r3 = evgen::ldm::AnThreeBD::GetRandom ( fEngine );
433+ double r4 = evgen::ldm::AnThreeBD::GetRandom ( fEngine );
437434
438435 z2_ll = ((m_HNL * m_HNL - (m_m + m_p) * (m_m + m_p)) * r1 + (m_m + m_p) * (m_m + m_p))/(m_HNL * m_HNL);
439436 z2_num = (((m_HNL - m_p) * (m_HNL - m_p) - m_m * m_m) * r2 + m_m * m_m) / (m_HNL * m_HNL);
440437 ct_ll = r3 * 2 - 1 ;
441438 gam_ll = 2 * TMath::Pi () * r4;
442439 MSq = evgen::ldm::AnThreeBD::MSqDM (C, z2_num, z2_ll, ct_ll, gam_ll, m_HNL, m_p, m_m, Pol);
443440 }while (MSq==0 );// Check if the randomly selected kinematical quantities where allowed in the Dalitz
444- double r5 = rand-> Rndm ( );
441+ double r5 = evgen::ldm::AnThreeBD::GetRandom ( fEngine );
445442 if (r5 < MSq/MSqMax) IsW = true ;
446443 }while (!IsW); // Use rejection-sampling to select each final state given its probability to happen
447444
448445 // Change from the generated kinematical quantities to 4 Vectors that can be used by the generator
449- evgen::ldm::AnThreeBD::RF4vecs (pnu, pm, pp, z2_num, z2_ll, ct_ll, gam_ll, m_HNL, m_p, m_m);
450-
446+ evgen::ldm::AnThreeBD::RF4vecs (pnu, pm, pp, z2_num, z2_ll, ct_ll, gam_ll, m_HNL, m_p, m_m, fEngine );
447+ evgen::ldm::AnThreeBD::RotateToHNLPolFrame (pHNL, pnu, pm, pp);
448+
451449 return ;
452450}
451+
452+ /*
453+ Function to apply a rotation to the calculated vector to match the HNL Pol direction.
454+ Formulas in arXiv:2104.05719 are defined with an HNL with the spin in the z direction.
455+ A rotation must be applied to the decay products to change the z direction to the beam direction (or HNL direction)
456+ in order for the results to be consistent, as per the reference arXiv:2104.05719
457+ p_HNL: HNL momentum vector
458+ pnu: neutrino momentum vector
459+ pl: positive charge momentum vector
460+ pm: negative charge lepton momentum vector (3D)
461+ */
462+ void evgen::ldm::AnThreeBD::RotateToHNLPolFrame (TLorentzVector pHNL, TLorentzVector &pnu, TLorentzVector &pm, TLorentzVector &pp) {
463+ // Define the HNL direction
464+ TVector3 HNL_dir = TVector3 (pHNL.X (), pHNL.Y (), pHNL.Z ()).Unit ();
465+
466+ // Define the direction of the polarized HNL in which formulas are calculated (In this case z)
467+ TVector3 z (0 , 0 , 1 );
468+
469+ // Calculate the axis of rotation (cross product of z and hnl direction)
470+ TVector3 rotation_axis = z.Cross (HNL_dir);
471+
472+ // Calculate the angle of rotation
473+ double angle = z.Angle (HNL_dir);
474+
475+ TVector3 pnu3D = TVector3 (pnu.X (), pnu.Y (), pnu.Z ());
476+ TVector3 pm3D = TVector3 (pm.X (), pm.Y (), pm.Z ());
477+ TVector3 pp3D = TVector3 (pp.X (), pp.Y (), pp.Z ());
478+
479+ // Apply the rotation
480+ if (rotation_axis.Mag () != 0 ) {
481+ pnu3D.Rotate (angle, rotation_axis);
482+ pm3D.Rotate (angle, rotation_axis);
483+ pp3D.Rotate (angle, rotation_axis);
484+ } else if (angle == M_PI) {
485+ pnu3D = -pnu3D;
486+ pm3D = -pm3D;
487+ pp3D = -pp3D;
488+ }
489+ pnu.SetXYZT (pnu3D.X (), pnu3D.Y (), pnu3D.Z (), pnu.T ());
490+ pm.SetXYZT (pm3D.X (), pm3D.Y (), pm3D.Z (), pm.T ());
491+ pp.SetXYZT (pp3D.X (), pp3D.Y (), pp3D.Z (), pp.T ());
492+
493+ return ;
494+ }
0 commit comments