All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Kaon2HNLFlux_tool.cc
Go to the documentation of this file.
1 /**
2  *
3  */
4 
5 // Framework Includes
6 #include "art/Framework/Core/EDProducer.h"
7 #include "art/Framework/Principal/Event.h"
8 #include "art/Framework/Principal/Handle.h"
9 #include "art/Framework/Services/Registry/ServiceHandle.h"
10 #include "art/Persistency/Common/PtrMaker.h"
11 #include "art/Utilities/ToolMacros.h"
12 #include "cetlib/cpu_timer.h"
13 #include "fhiclcpp/ParameterSet.h"
14 #include "messagefacility/MessageLogger/MessageLogger.h"
15 #include "CLHEP/Random/RandFlat.h"
16 
17 // local includes
20 
23 
24 // ROOT
25 #include "TVector3.h"
26 
27 // std includes
28 #include <string>
29 #include <iostream>
30 #include <memory>
31 
32 #include "TDatabasePDG.h"
33 
34 //------------------------------------------------------------------------------------------------------------------------------------------
35 // implementation follows
36 
37 namespace evgen {
38 namespace ldm {
39 /**
40  * @brief Kaon2HNLFlux class definiton
41  *
42  * Implementation of Kaon->HNL branching ratio taken from:
43  * arXiv:1912.07622
44  */
45 class Kaon2HNLFlux : public IMeVPrtlFlux
46 {
47 public:
48  /**
49  * @brief Constructor
50  */
51  Kaon2HNLFlux(fhicl::ParameterSet const &pset);
52 
53  /**
54  * @brief Destructor
55  */
56  ~Kaon2HNLFlux();
57 
58  bool MakeFlux(const simb::MCFlux &flux, MeVPrtlFlux &hnl, double &weight) override;
59  void configure(const fhicl::ParameterSet&) override;
60 
61  double MaxWeight() override;
62 
63 private:
64  // config
65  double fM; //!< Mass of HNL [GeV]
66  double fMagUe4;
67  double fMagUm4;
68  bool fKDAROnly;
69 };
70 
71 Kaon2HNLFlux::Kaon2HNLFlux(fhicl::ParameterSet const &pset):
72  IMeVPrtlStage("Kaon2HNLFlux"),
73  IMeVPrtlFlux(pset)
74 {
75  this->configure(pset);
76 
77 }
78 
79 //------------------------------------------------------------------------------------------------------------------------------------------
80 
82 {
83 }
84 
85 // helper functions
86 //
87 // kaon -> leption + HNL
88 double hnl_momentum(double kaon_mass, double lep_mass, double hnl_mass) {
89  if (kaon_mass - lep_mass < hnl_mass) return -1.;
90 
91  return sqrt(kaon_mass * kaon_mass * kaon_mass * kaon_mass
92  -2 * kaon_mass * kaon_mass * lep_mass * lep_mass
93  -2 * kaon_mass * kaon_mass * hnl_mass * hnl_mass
94  + lep_mass * lep_mass * lep_mass * lep_mass
95  + hnl_mass * hnl_mass * hnl_mass * hnl_mass
96  -2 * lep_mass * lep_mass * hnl_mass * hnl_mass) / ( 2 * kaon_mass );
97 }
98 
99 double SMKaonBR(int kaon_pdg) {
100  // The Kaons in Dk2nu file only include those that decay to neutrinos.
101  //
102  // We want all kaons -- in order to account for this, we divide by the
103  // branching-ratio of kaons to neutrinos
104  //
105  // Taken from:
106  // /cvmfs/minerva.opensciencegrid.org/minerva/beamsim/x86_64/geant4/source/particles/hadrons/mesons/src/G4KaonPlus.cc
107  // /cvmfs/minerva.opensciencegrid.org/minerva/beamsim/x86_64/geant4/source/particles/hadrons/mesons/src/G4KaonZerLong.cc
108  switch (kaon_pdg) {
109  case 321:
110  return 0.6339 /* 5 */ + 0.0559 /* 6 */ + 0.0330 /* 7 */;
111  case -321:
112  return 0.6339 /* 8 */ + 0.0559 /* 9 */ + 0.0330 /* 10 */;
113  case 130:
114  return 0.2020 /* 1 */ + 0.2020 /* 2 */ + 0.1348 /* 3 */ + 0.1348 /* 4 */;
115  default:
116  return -1;
117  }
118 }
119 
120 double BranchingRatio(double hnl_mass, double u4, bool is_muon) {
121  double lep_mass = is_muon ? Constants::Instance().muon_mass : Constants::Instance().elec_mass;
122  double kplus_mass = Constants::Instance().kplus_mass;
123 
124  if (hnl_mass > kplus_mass - lep_mass) return 0.;
125 
127  double lep_ratio = (lep_mass * lep_mass) / (kplus_mass * kplus_mass);
128  double hnl_ratio = (hnl_mass * hnl_mass) / (kplus_mass * kplus_mass);
129  double kinematic_factor = (lep_ratio + hnl_ratio - (lep_ratio - hnl_ratio) * (lep_ratio - hnl_ratio)) \
130  * sqrt(1 + hnl_ratio * hnl_ratio + lep_ratio * lep_ratio - 2*(hnl_ratio + lep_ratio + hnl_ratio*lep_ratio)) \
131  / (lep_ratio * (1. - lep_ratio) * (1. - lep_ratio));
132 
133  // scale the branching ratio
134  return smbr * (u4 / (1. - u4)) * kinematic_factor;
135 }
136 
137 std::pair<double, bool> Branch(double hnl_mass, double ue4, double um4, double rand) {
138  double kplus_mass = Constants::Instance().kplus_mass;
139 
140  double br_muon = (um4 > 0. && hnl_mass < kplus_mass - Constants::Instance().muon_mass) ? BranchingRatio(hnl_mass, um4, true) : 0.;
141  double br_elec = (ue4 > 0. && hnl_mass < kplus_mass - Constants::Instance().elec_mass) ? BranchingRatio(hnl_mass, ue4, false): 0.;
142  if (br_muon == 0. && br_elec == 0.) return {0., false};
143 
144  double br_weight = br_muon + br_elec;
145 
146  bool is_muon = rand < (br_muon / br_weight);
147 
148  return {br_weight, is_muon};
149 }
150 
151 
152 //------------------------------------------------------------------------------------------------------------------------------------------
153 void Kaon2HNLFlux::configure(fhicl::ParameterSet const &pset)
154 {
155  fM = pset.get<double>("M");
156  fMagUm4 = pset.get<double>("MagUm4");
157  fMagUe4 = pset.get<double>("MagUe4");
158 
159  fKDAROnly = pset.get<bool>("KDAROnly", false);
160 
161  double max_mass = (fMagUe4 > 0.) ? (Constants::Instance().kplus_mass - Constants::Instance().elec_mass) :
163 
164  if (fM > max_mass) {
165  throw cet::exception("Kaon2HNLFlux Tool: BAD MASS. Configured mass (" + std::to_string(fM) +
166  ") is larger than maximum allowed by enabled couplings (" + std::to_string(max_mass) + ").");
167  }
168 
169 }
170 
172  // Weight comes from the NuMi importance weight -- max is 100 (add in an epsilon)
173  // Scale by the branching ratios here
174  return 100.0001 * std::max(BranchingRatio(fM, fMagUe4, false) / SMKaonBR(321), BranchingRatio(fM, fMagUm4, true) / SMKaonBR(321));
175 }
176 
177 bool Kaon2HNLFlux::MakeFlux(const simb::MCFlux &flux, evgen::ldm::MeVPrtlFlux &hnl, double &weight) {
178  // make the kaon parent
179  evgen::ldm::KaonParent kaon(flux);
180  if (abs(kaon.kaon_pdg) != 321) return false; // Only take charged kaons
181 
182  // select on the kaon
183  if (fKDAROnly && (kaon.mom.P() > 1e-3 || kaon.pos.Z() < 72000.)) return false;
184  if (fKDAROnly) std::cout << "FOUND KDAR\n";
185 
186  TLorentzVector Beam4 = BeamOrigin();
187 
188  // get position in detector frame
189  hnl.pos_beamcoord = kaon.pos;
190  hnl.pos = kaon.pos;
191  hnl.pos.Transform(fBeam2Det);
192  hnl.pos += Beam4;
193 
194  // Branch the parent Kaon Decay
195  double hnl_mass = fM;
196  std::pair<double, bool> decay = Branch(hnl_mass, fMagUe4, fMagUm4, GetRandom());
197  double br = decay.first;
198  bool is_muon = decay.second;
199  double lep_mass = is_muon ? Constants::Instance().muon_mass : Constants::Instance().elec_mass;
200 
201  std::cout << "BR: " << br << std::endl;
202 
203  // ignore if we can't make this hnl
204  // Ignore if branching ratio is exactly 0.
205  if (br == 0.) return false;
206 
207  // get the momentum direction in the kaon parent rest frame
208  double p = hnl_momentum(Constants::Instance().kplus_mass, lep_mass, hnl_mass);
209  double e = sqrt(p*p + hnl_mass * hnl_mass);
210  // Two-body decays are isotropic
211  hnl.mom = TLorentzVector(p*RandomUnitVector(), e);
212 
213  // boost to lab frame
214  TLorentzVector mom = hnl.mom;
215  mom.Boost(kaon.mom.BoostVector());
216 
217  hnl.mom_beamcoord = mom;
218  // rotate to detector frame
219  hnl.mom = mom;
220  hnl.mom.Transform(fBeam2Det);
221 
222  hnl.kmom_beamcoord = kaon.mom;
223  // also save the kaon momentum in the detector frame
224  hnl.kmom = kaon.mom;
225  hnl.kmom.Transform(fBeam2Det);
226 
227  // and save the secondary momentum
228  hnl.sec = hnl.kmom - hnl.mom;
230 
231  // The weight is the importance weight times the branching-ratio weight
232  weight = kaon.weight * br / SMKaonBR(kaon.kaon_pdg);
233 
234  // set the mixing
235  hnl.C1 = fMagUe4;
236  hnl.C2 = fMagUm4;
237  hnl.mass = fM;
238 
239  hnl.kaon_pdg = kaon.kaon_pdg;
240  hnl.secondary_pdg = (is_muon ? 11 : 13) * (kaon.kaon_pdg > 0 ? 1 : -1);
241  hnl.generator = 1; // kHNL
242 
243  // equivalent neutrino energy
244  hnl.equiv_enu = EnuLab(flux.fnecm, hnl.kmom, hnl.pos);
245 
246  return true;
247 }
248 
249 DEFINE_ART_CLASS_TOOL(Kaon2HNLFlux)
250 
251 } // namespace ldm
252 } // namespace evgen
TLorentzVector pos_beamcoord
Definition: MeVPrtlFlux.h:10
TLorentzVector sec_beamcoord
Definition: MeVPrtlFlux.h:17
TLorentzVector mom
Definition: MeVPrtlFlux.h:14
TLorentzVector mom_beamcoord
Definition: MeVPrtlFlux.h:15
pdgs p
Definition: selectors.fcl:22
std::pair< double, bool > Branch(double hnl_mass, double ue4, double um4, double rand)
double fM
Mass of HNL [GeV].
Kaon2HNLFlux class definiton.
Kaon2HNLFlux(fhicl::ParameterSet const &pset)
Constructor.
T abs(T value)
TLorentzVector kmom
Definition: MeVPrtlFlux.h:13
TLorentzVector pos
Definition: KaonParent.h:12
double BranchingRatio(double hnl_mass, double u4, bool is_muon)
IMeVPrtlStage interface class definiton. General interface behind each stage. Provides random number ...
Definition: IMeVPrtlStage.h:36
TLorentzVector mom
Definition: KaonParent.h:13
static const Constants & Instance()
Definition: Constants.h:68
bool MakeFlux(const simb::MCFlux &flux, MeVPrtlFlux &hnl, double &weight) override
double SMKaonBR(int kaon_pdg)
double hnl_momentum(double kaon_mass, double lep_mass, double hnl_mass)
void configure(const fhicl::ParameterSet &) override
Interface for configuring the particular algorithm tool.
TLorentzVector BeamOrigin()
Definition: IMeVPrtlFlux.h:107
std::string to_string(WindowPattern const &pattern)
TLorentzVector pos
Definition: MeVPrtlFlux.h:11
do i e
This is an interface for an art Tool which turns MCFlux objects (which is a meson decay to neutrinos)...
double EnuLab(double enucm, TLorentzVector meson_mom, TLorentzVector meson_pos)
Definition: IMeVPrtlFlux.h:119
IMeVPrtlFlux interface class definiton.
Definition: IMeVPrtlFlux.h:39
TLorentzVector kmom_beamcoord
Definition: MeVPrtlFlux.h:12
BEGIN_PROLOG could also be cout
TLorentzVector sec
Definition: MeVPrtlFlux.h:16