GENIEGenerator
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
HNLDecaySelector.cxx
Go to the documentation of this file.
1 //____________________________________________________________________________
2 /*
3  Copyright (c) 2003-2024, The GENIE Collaboration
4  For the full text of the license visit http://copyright.genie-mc.org
5 
6  Author: John Plows <komninos-john.plows \at physics.ox.ac.uk>
7  University of Oxford
8 */
9 //____________________________________________________________________________
10 
12 
14 
15 using namespace genie::hnl;
16 
17 // Takes parameter space, outputs all available channels + widths
18 std::map< HNLDecayMode_t, double > selector::GetValidChannelWidths( const double M, const double /* Ue42 */, const double /* Umu42 */, const double /* Ut42 */, const bool IsMajorana ){
19 
20  // construct an BRCalculator * object to handle the scalings.
21  const Algorithm * algBRCalc = AlgFactory::Instance()->GetAlgorithm("genie::hnl::BRCalculator", "Default");
22  const BRCalculator * BRCalc = dynamic_cast< const BRCalculator * >( algBRCalc );
23 
24  std::map< HNLDecayMode_t, double > allChannels;
25 
26  // invisible decay is always possible
27  double GINV = 0.0;
28  if( fDecayGammas[0] < 0.0 ){
29  GINV = BRCalc->DecayWidth( kHNLDcyNuNuNu );
30  if( IsMajorana ) GINV *= 2.0;
31  fDecayGammas[0] = GINV;
32  LOG("HNL", pDEBUG)
33  << " Invisible decay gamma = " << fDecayGammas[0];
34  } else GINV = fDecayGammas[0];
35  allChannels.insert( allChannels.begin(), std::pair< HNLDecayMode_t, double >( kHNLDcyNuNuNu, GINV ) );
36 
37  assert( GINV >= 0.0 );
38 
39  // nu-e-e is next lightest
40  if( M < 2.0 * genie::constants::kElectronMass ) return allChannels;
41 
42  double GNEE = 0.0;
43  if( fDecayGammas[1] < 0.0 ){
44  GNEE = BRCalc->DecayWidth( kHNLDcyNuEE );
45  if( IsMajorana ) GNEE *= 2.0;
46  fDecayGammas[1] = GNEE;
47  LOG("HNL", pDEBUG)
48  << " Nu-e-e gamma = " << fDecayGammas[1];
49  } else GNEE = fDecayGammas[1];
50  allChannels.insert( allChannels.begin(), std::pair< HNLDecayMode_t, double >( kHNLDcyNuEE, GNEE ) );
51 
52  assert( GNEE >= 0.0 );
53 
54  // nu-e-mu is next lightest
55  if( M < genie::constants::kElectronMass + genie::constants::kMuonMass ) return allChannels;
56 
57  double GNEM = 0.0;
58  if( fDecayGammas[2] < 0.0 ){
59  GNEM = BRCalc->DecayWidth( kHNLDcyNuMuE );
60  if( IsMajorana ) GNEM *= 2.0;
61  fDecayGammas[2] = GNEM;
62  LOG("HNL", pDEBUG)
63  << " Nu-e-mu gamma = " << fDecayGammas[2];
64  } else GNEM = fDecayGammas[2];
65  allChannels.insert( allChannels.begin(), std::pair< HNLDecayMode_t, double >( kHNLDcyNuMuE, GNEM ) );
66 
67  assert( GNEM >= 0.0 );
68 
69  // pi0-nu is next lightest
70  if( M < genie::constants::kPi0Mass ) return allChannels;
71 
72  double GP0N = 0.0;
73  if( fDecayGammas[3] < 0.0 ){
74  GP0N = BRCalc->DecayWidth( kHNLDcyPi0Nu );
75  if( IsMajorana ) GP0N *= 2.0;
76  fDecayGammas[3] = GP0N;
77  LOG("HNL", pDEBUG)
78  << " Pi0-nu gamma = " << fDecayGammas[3];
79  } else GP0N = fDecayGammas[3];
80  allChannels.insert( allChannels.begin(), std::pair< HNLDecayMode_t, double >( kHNLDcyPi0Nu, GP0N ) );
81 
82  assert( GP0N >= 0.0 );
83 
84  // pi-e is next lightest
85  if( M < genie::constants::kPionMass + genie::constants::kElectronMass ) return allChannels;
86 
87  double GPIE = 0.0;
88  if( fDecayGammas[4] < 0.0 ){
89  GPIE = BRCalc->DecayWidth( kHNLDcyPiE );
90  if( IsMajorana ) GPIE *= 2.0;
91  fDecayGammas[4] = GPIE;
92  LOG("HNL", pDEBUG)
93  << " Pi-e gamma = " << fDecayGammas[4];
94  } else GPIE = fDecayGammas[4];
95  allChannels.insert( allChannels.begin(), std::pair< HNLDecayMode_t, double >( kHNLDcyPiE, GPIE) );
96 
97  assert( GPIE >= 0.0 );
98 
99  // nu-mu-mu is next lightest
100  if( M < 2.0 * genie::constants::kMuonMass ) return allChannels;
101 
102  double GNMM = 0.0;
103  if( fDecayGammas[5] < 0.0 ){
104  GNMM = BRCalc->DecayWidth( kHNLDcyNuMuMu );
105  if( IsMajorana ) GNMM *= 2.0;
106  fDecayGammas[5] = GNMM;
107  LOG("HNL", pDEBUG)
108  << " Nu-mu-mu gamma = " << fDecayGammas[5];
109  } else GNMM = fDecayGammas[5];
110  allChannels.insert( allChannels.begin(), std::pair< HNLDecayMode_t, double >( kHNLDcyNuMuMu, GNMM ) );
111 
112  assert( GNMM >= 0.0 );
113 
114  // pi-mu is next lightest
115  if( M < genie::constants::kPionMass + genie::constants::kMuonMass ) return allChannels;
116 
117  double GPIM = 0.0;
118  if( fDecayGammas[6] < 0.0 ){
119  GPIM = BRCalc->DecayWidth( kHNLDcyPiMu );
120  if( IsMajorana ) GPIM *= 2.0;
121  fDecayGammas[6] = GPIM;
122  LOG("HNL", pDEBUG)
123  << " Pi-mu gamma = " << fDecayGammas[6];
124  } else GPIM = fDecayGammas[6];
125  allChannels.insert( allChannels.begin(), std::pair< HNLDecayMode_t, double >( kHNLDcyPiMu, GPIM ) );
126 
127  assert( GPIM >= 0.0 );
128 
129  // pi0-pi0-nu is next lightest
130  if( M < 2.0 * genie::constants::kPi0Mass ) return allChannels;
131 
132  double GP02 = 0.0;
133  if( fDecayGammas[7] < 0.0 ){
134  GP02 = BRCalc->DecayWidth( kHNLDcyPi0Pi0Nu );
135  if( IsMajorana ) GP02 *= 2.0;
136  fDecayGammas[7] = GP02;
137  LOG("HNL", pDEBUG)
138  << " Pi0-pi0-nu gamma = " << fDecayGammas[7];
139  } else fDecayGammas[7] = GP02;
140  allChannels.insert( allChannels.begin(), std::pair< HNLDecayMode_t, double >( kHNLDcyPi0Pi0Nu, GP02 ) );
141 
142  assert( GP02 >= 0.0 );
143 
144  // pi-pi0-e is next lightest
146 
147  double GP0E = 0.0;
148  if( fDecayGammas[8] < 0.0 ){
149  GP0E = BRCalc->DecayWidth( kHNLDcyPiPi0E );
150  if( IsMajorana ) GP0E *= 2.0;
151  fDecayGammas[8] = GP0E;
152  LOG("HNL", pDEBUG)
153  << " Pi-pi0-e gamma = " << fDecayGammas[8];
154  } else GP0E = fDecayGammas[8];
155  allChannels.insert( allChannels.begin(), std::pair< HNLDecayMode_t, double >( kHNLDcyPiPi0E, GP0E ) );
156 
157  assert( GP0E >= 0.0 );
158 
159  // pi-pi0-mu is next lightest
161 
162  double GP0M = 0.0;
163  if( fDecayGammas[9] < 0.0 ){
164  GP0M = BRCalc->DecayWidth( kHNLDcyPiPi0Mu );
165  if( IsMajorana ) GP0M *= 2.0;
166  fDecayGammas[9] = GP0M;
167  LOG("HNL", pDEBUG)
168  << " Pi-pi0-mu gamma = " << fDecayGammas[9];
169  } else GP0M = fDecayGammas[9];
170  allChannels.insert( allChannels.begin(), std::pair< HNLDecayMode_t, double >( kHNLDcyPiPi0Mu, GP0M ) );
171 
172  assert( GP0M >= 0.0 );
173 
174  //all done! Return
175  return allChannels;
176 }
177 
178 // Calculates the *total* decay width from all the valid channels
179 double selector::GetTotalDecayWidth( std::map< HNLDecayMode_t, double > gammaMap ) {
180 
181  double totGamma = 0.0;
182 
183  for( std::map< HNLDecayMode_t, double >::iterator it = gammaMap.begin(); it != gammaMap.end(); ++it ){ totGamma += (*it).second; }
184 
185  LOG("HNL", pDEBUG)
186  << " Total gamma from N_channels = " << gammaMap.size()
187  << " is = " << totGamma << " [GeV]"
188  << " or = " << totGamma * genie::units::GeV * genie::units::ns << " [ns^{-1}]";
189 
190  return totGamma;
191 }
192 
193 // Returns lifetime of particle with mass and couplings
194 double selector::CalcCoMLifetime( const double M, const double Ue42, const double Umu42, const double Ut42, const bool IsMajorana ){
195 
196  std::map< HNLDecayMode_t, double > allChannels = selector::GetValidChannelWidths( M, Ue42, Umu42, Ut42, IsMajorana );
197  double totGamma = selector::GetTotalDecayWidth( allChannels );
198  return 1.0 / totGamma; // GeV^{-1}
199 }
200 
201 // let's pick the interesting channels
202 std::map< HNLDecayMode_t, double > selector::SetInterestingChannels( std::vector< HNLDecayMode_t > intChannels, std::map< HNLDecayMode_t, double > gammaMap ){
203 
204  std::map< HNLDecayMode_t, double > interestingMap;
205 
206  for( std::vector< HNLDecayMode_t >::iterator it = intChannels.begin(); it != intChannels.end(); ++it ){
207  HNLDecayMode_t decType = (*it);
208  double gamma = gammaMap.find( (*it) )->second;
209  interestingMap.insert( std::pair< HNLDecayMode_t, double >( decType, gamma ) );
210  }
211  return interestingMap;
212 } // this is now a reduced map with only the channels we want to decay HNL to
213 
214 // and transform decay widths to branching ratios (probabilities)
215 std::map< HNLDecayMode_t, double > selector::GetProbabilities( std::map< HNLDecayMode_t, double > gammaMap ){
216 
217  double totGamma = GetTotalDecayWidth( gammaMap );
218  std::map< HNLDecayMode_t, double > Pmap;
219 
220  // P = Gamma(channel)/Gamma(tot)
221  for( std::map< HNLDecayMode_t, double >::iterator it = gammaMap.begin(); it != gammaMap.end(); ++it ){
222  Pmap.insert( std::pair< HNLDecayMode_t, double >( (*it).first, (*it).second / totGamma ) );
223  }
224  return Pmap;
225 }
226 
227 // choose a particular channel to decay to
228 HNLDecayMode_t selector::SelectChannelInclusive( std::map< HNLDecayMode_t, double > Pmap, double ranThrow ){
229 
230  // in inclusive method, decay is factorised in three parts:
231  // a) Decay vertex placement
232  // b) Decay product selection: construct
233  // c) Decay product kinematics
234  // This method does only b)
235 
236  // first get P(all interesting channels)
237  double PInt = 0.0, all_before = 0.0;
238  HNLDecayMode_t selectedChannel = kHNLDcyNull;
239 
240  for( std::map< HNLDecayMode_t, double >::iterator it = Pmap.begin(); it != Pmap.end(); ++it ){ PInt += (*it).second; }
241 
242  // compare ranThrow to P(channel)/PInt + all_before
243  // if all_before + P(channel)/PInt >= ranThrow then select this channel
244  // don't break, check if scores add up to 1!
245  for( std::map< HNLDecayMode_t, double >::iterator it = Pmap.begin(); it != Pmap.end(); ++it ){
246  double modP = (*it).second / PInt;
247  if( all_before < ranThrow &&
248  all_before + modP >= ranThrow ) selectedChannel = (*it).first;
249  all_before += modP;
250  }
251 
252  return selectedChannel;
253 }
Manages HNL BR (prod and decay)
double GetTotalDecayWidth(std::map< genie::hnl::HNLDecayMode_t, double > gammaMap)
Algorithm abstract base class.
Definition: Algorithm.h:54
static constexpr double ns
Definition: Units.h:98
static const double kElectronMass
std::map< genie::hnl::HNLDecayMode_t, double > SetInterestingChannels(std::vector< genie::hnl::HNLDecayMode_t > intChannels, std::map< genie::hnl::HNLDecayMode_t, double > gammaMap)
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
Definition: Messenger.h:96
static constexpr double GeV
Definition: Units.h:28
const Algorithm * GetAlgorithm(const AlgId &algid)
Definition: AlgFactory.cxx:75
enum genie::hnl::EHNLDecayMode HNLDecayMode_t
static AlgFactory * Instance()
Definition: AlgFactory.cxx:64
double DecayWidth(genie::hnl::HNLDecayMode_t hnldm) const
std::map< genie::hnl::HNLDecayMode_t, double > GetProbabilities(std::map< genie::hnl::HNLDecayMode_t, double > gammaMap)
double CalcCoMLifetime(const double M, const double Ue42, const double Umu42, const double Ut42, const bool IsMajorana=false)
genie::hnl::HNLDecayMode_t SelectChannelInclusive(std::map< genie::hnl::HNLDecayMode_t, double > Pmap, double ranThrow)
std::map< genie::hnl::HNLDecayMode_t, double > GetValidChannelWidths(const double M, const double Ue42, const double Umu42, const double Ut42, const bool IsMajorana=false)
#define pDEBUG
Definition: Messenger.h:63