All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Classes | Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
evgen::ldm::HNLMakeDecay Class Reference

HNLMakeDecay class definiton. More...

Inheritance diagram for evgen::ldm::HNLMakeDecay:
evgen::ldm::IMeVPrtlDecay evgen::ldm::IMeVPrtlStage

Classes

struct  DecayFinalState
 
struct  ThreebodyMomentum
 

Public Member Functions

 HNLMakeDecay (fhicl::ParameterSet const &pset)
 Constructor. More...
 
 ~HNLMakeDecay ()
 Destructor. More...
 
void configure (fhicl::ParameterSet const &pset) override
 Interface for configuring the particular algorithm tool. More...
 
bool Decay (const MeVPrtlFlux &flux, const TVector3 &in, const TVector3 &out, MeVPrtlDecay &decay, double &weight) override
 
double MaxWeight () override
 
- Public Member Functions inherited from evgen::ldm::IMeVPrtlDecay
virtual ~IMeVPrtlDecay () noexcept=default
 Virtual Destructor. More...
 
- Public Member Functions inherited from evgen::ldm::IMeVPrtlStage
virtual ~IMeVPrtlStage () noexcept
 Virtual Destructor. More...
 
 IMeVPrtlStage (const char *name)
 
TVector3 RandomUnitVector ()
 
double GetRandom ()
 
const char * Name ()
 

Private Types

typedef DecayFinalState(HNLMakeDecay::* HNLDecayFunction )(const MeVPrtlFlux &flux)
 

Private Member Functions

double CalculateMaxWeight ()
 
double CalculateKDARDecayLength ()
 
ThreebodyMomentum isotropic_threebody_momentum (double parent_mass, double childA_mass, double childB_mass, double childC_mass)
 
double I1 (double x, double y, double z)
 
double I2 (double x, double y, double z)
 
double NuDiLepDecayWidth (double hnl_mass, double ue4, double um4, bool nu_is_muon, bool lep_is_muon)
 
DecayFinalState NuMupMum (const MeVPrtlFlux &flux)
 
DecayFinalState LepPi (const MeVPrtlFlux &flux, bool is_muon)
 
DecayFinalState EPi (const MeVPrtlFlux &flux)
 
DecayFinalState MuPi (const MeVPrtlFlux &flux)
 

Private Attributes

double fMaxWeight
 
gsl_integration_workspace * fIntegrator
 
unsigned fIntegratorSize
 
double fReferenceUE4
 
double fReferenceUM4
 
double fReferenceHNLMass
 
double fReferenceRayLength
 
double fReferenceHNLEnergy
 
double fReferenceHNLKaonEnergy
 
double fMinDetectorDistance
 
bool fMajorana
 
std::map< std::string,
HNLDecayFunction
fAvailableDecays
 
std::map< std::string, double > fAvailableDecayMasses
 
std::vector< std::string > fDecayConfig
 
std::vector< HNLDecayFunctionfSelectedDecays
 

Additional Inherited Members

- Protected Member Functions inherited from evgen::ldm::IMeVPrtlDecay
double TimeOfFlight (const MeVPrtlFlux &flux, TVector3 decay)
 
- Protected Attributes inherited from evgen::ldm::IMeVPrtlStage
CLHEP::HepRandomEngine * fEngine
 
const char * fName
 

Detailed Description

HNLMakeDecay class definiton.

Implementation of HNL decay ->mupi taken from: https://arxiv.org/abs/1610.08512

Definition at line 55 of file HNLMakeDecay_tool.cc.

Member Typedef Documentation

typedef DecayFinalState(HNLMakeDecay::* evgen::ldm::HNLMakeDecay::HNLDecayFunction)(const MeVPrtlFlux &flux)
private

Definition at line 111 of file HNLMakeDecay_tool.cc.

Constructor & Destructor Documentation

evgen::ldm::HNLMakeDecay::HNLMakeDecay ( fhicl::ParameterSet const &  pset)

Constructor.

Definition at line 489 of file HNLMakeDecay_tool.cc.

489  :
490  IMeVPrtlStage("HNLMakeDecay")
491 {
492  this->configure(pset);
493 }
void configure(fhicl::ParameterSet const &pset) override
Interface for configuring the particular algorithm tool.
IMeVPrtlStage(const char *name)
Definition: IMeVPrtlStage.h:46
evgen::ldm::HNLMakeDecay::~HNLMakeDecay ( )

Destructor.

Definition at line 497 of file HNLMakeDecay_tool.cc.

498 {
499  gsl_integration_workspace_free(fIntegrator);
500 }
gsl_integration_workspace * fIntegrator

Member Function Documentation

double evgen::ldm::HNLMakeDecay::CalculateKDARDecayLength ( )
private

Definition at line 405 of file HNLMakeDecay_tool.cc.

405  {
406  double ue4 = fReferenceUE4;
407  double um4 = fReferenceUM4;
408  double hnl_mass = fReferenceHNLMass;
409  // If the muon coupling is turned on, the lower energy / lower decay length HNL would have a muon
410  // secondary
411  double lep_mass = (um4 > 0.) ? Constants::Instance().muon_mass : Constants::Instance().elec_mass;
412  double P = twobody_momentum(Constants::Instance().kplus_mass, lep_mass, hnl_mass);
413  double E = sqrt(P*P + hnl_mass * hnl_mass);
414 
415  // make a fake HNL flux with these parameters
416  MeVPrtlFlux hnl;
417  hnl.C1 = ue4;
418  hnl.C2 = um4;
419  hnl.mass = hnl_mass;
420  hnl.mom = TLorentzVector(P * TVector3(1, 0, 0), E);
421  hnl.secondary_pdg = -1; // doesn't affect the end width, just make it viable
422 
423  // Mock up the secondary momenta -- this shouldn't affect width and just
424  // is there to make sure the decay functions work correctly
425  hnl.kmom = TLorentzVector(TVector3(0, 0, 0), Constants::Instance().kplus_mass);
426  hnl.sec = TLorentzVector(-P * TVector3(1, 0, 0), sqrt(P*P + lep_mass*lep_mass));
427 
428  double width = 0.;
430  width += ((*this.*F)(hnl)).width;
431  }
432 
433  double lifetime_ns = Constants::Instance().hbar / width;
434  double mean_dist = lifetime_ns * hnl.mom.Gamma() * hnl.mom.Beta() * Constants::Instance().c_cm_per_ns;
435 
436  return mean_dist;
437 }
double twobody_momentum(double parent_mass, double childA_mass, double childB_mass)
Definition: Constants.cpp:73
process_name E
std::vector< HNLDecayFunction > fSelectedDecays
DecayFinalState(HNLMakeDecay::* HNLDecayFunction)(const MeVPrtlFlux &flux)
static const Constants & Instance()
Definition: Constants.h:68
double evgen::ldm::HNLMakeDecay::CalculateMaxWeight ( )
private

Definition at line 439 of file HNLMakeDecay_tool.cc.

439  {
440  double ue4 = fReferenceUE4;
441  double um4 = fReferenceUM4;
442  double hnl_mass = fReferenceHNLMass;
443  double length = fReferenceRayLength;
444  double E = fReferenceHNLEnergy;
445  double P = sqrt(E*E - hnl_mass * hnl_mass);
446 
447  // Compute the boost to get the HNL with the correct energy
448  double lep_mass = (um4 > 0) ? Constants::Instance().muon_mass : Constants::Instance().elec_mass;
449  double p0 = twobody_momentum(Constants::Instance().kplus_mass, lep_mass, hnl_mass);
450  double e0 = sqrt(p0*p0 + hnl_mass*hnl_mass);
451  double beta = (-e0*p0 + E*P) / (E*E + p0*p0);
452  TVector3 boost(beta, 0, 0);
453 
454  // make a fake HNL flux with these parameters
455  MeVPrtlFlux hnl;
456  hnl.C1 = ue4;
457  hnl.C2 = um4;
458  hnl.mass = hnl_mass;
459  hnl.mom = TLorentzVector(p0 * TVector3(1, 0, 0), e0);
460  hnl.mom.Boost(boost);
461  hnl.secondary_pdg = -1; // doesn't affect the end width, just make it viable
462 
463  std::cout << "Reference Energy: " << E << std::endl;
464  std::cout << "HNL 4P: " << hnl.mom.E() << " " << hnl.mom.Px() << std::endl;
465 
466  // Mock up the secondary momenta -- this shouldn't affect width and just
467  // is there to make sure the decay functions work correctly
468  hnl.kmom = TLorentzVector(TVector3(0, 0, 0), Constants::Instance().kplus_mass);
469  hnl.kmom.Boost(boost);
470  hnl.sec = TLorentzVector(-p0 * TVector3(1, 0, 0), sqrt(p0*p0 + lep_mass*lep_mass));
471  hnl.sec.Boost(boost);
472 
473  double width = 0.;
475  width += ((*this.*F)(hnl)).width;
476  }
477 
478  std::cout << "REFERENCE WIDTH: " << width << std::endl;
479 
480  double lifetime_ns = Constants::Instance().hbar / width;
481  double mean_dist = lifetime_ns * hnl.mom.Gamma() * hnl.mom.Beta() * Constants::Instance().c_cm_per_ns;
482 
483  std::cout << "REFERENCE DECAY LENGTH: " << mean_dist << std::endl;
484 
485  return length / mean_dist;
486 }
double twobody_momentum(double parent_mass, double childA_mass, double childB_mass)
Definition: Constants.cpp:73
process_name E
std::vector< HNLDecayFunction > fSelectedDecays
DecayFinalState(HNLMakeDecay::* HNLDecayFunction)(const MeVPrtlFlux &flux)
static const Constants & Instance()
Definition: Constants.h:68
BEGIN_PROLOG could also be cout
void evgen::ldm::HNLMakeDecay::configure ( fhicl::ParameterSet const &  )
overridevirtual

Interface for configuring the particular algorithm tool.

Parameters
ParameterSetThe input set of parameters for configuration

Implements evgen::ldm::IMeVPrtlStage.

Definition at line 503 of file HNLMakeDecay_tool.cc.

504 {
505  fIntegratorSize = 1000;
506 
507  fIntegrator = gsl_integration_workspace_alloc(fIntegratorSize);
508 
509  // Setup available decays
514  // TODO: make available
515  // fAvailableDecays["nu_mu_mu"] = &HNLMakeDecay::NuMupMum;
516 
517  // Select which ones are configued
518  fDecayConfig = pset.get<std::vector<std::string>>("Decays");
519 
520  for (const std::string &d: fDecayConfig) {
521  if (fAvailableDecays.count(d)) {
522  fSelectedDecays.push_back(fAvailableDecays.at(d));
523  }
524  else {
525  std::cerr << "ERROR: Selected unavailable decay (" << d << ")" << std::endl;
526  }
527  }
528  fReferenceUE4 = pset.get<double>("ReferenceUE4");
529  fReferenceUM4 = pset.get<double>("ReferenceUM4");
530  fReferenceHNLMass = pset.get<double>("ReferenceHNLMass");
531  fReferenceRayLength = pset.get<double>("ReferenceRayLength");
532 
533  fReferenceHNLEnergy = pset.get<double>("ReferenceHNLEnergy", -1);
534  fReferenceHNLKaonEnergy = pset.get<double>("ReferenceHNLEnergyFromKaonEnergy", -1.);
535  if (fReferenceHNLEnergy < 0. && fReferenceHNLKaonEnergy > 0.) {
538  }
539 
540  fMinDetectorDistance = pset.get<double>("MinDetectorDistance", 100e2); // 100m for NuMI -> SBN/ICARUS
541 
542  fMajorana = pset.get<bool>("Majorana");
543 
545 
546  // Guard against bad couplings that will mess with decay weighting approximations
547  double kdar_decay_length = CalculateKDARDecayLength();
548  if (kdar_decay_length < fMinDetectorDistance) {
549  throw cet::exception("HNLMakeDecay Tool: BAD CONFIG. Existing configuration results in a KDAR-flux partial decay length (" +
550  std::to_string(kdar_decay_length) + ") that is smaller than the configured min distance to the detector (" + std::to_string(fMinDetectorDistance) + ").");
551  }
552 }
BEGIN_PROLOG could also be cerr
std::map< std::string, double > fAvailableDecayMasses
DecayFinalState EPi(const MeVPrtlFlux &flux)
gsl_integration_workspace * fIntegrator
std::vector< HNLDecayFunction > fSelectedDecays
std::map< std::string, HNLDecayFunction > fAvailableDecays
static const Constants & Instance()
Definition: Constants.h:68
std::vector< std::string > fDecayConfig
std::string to_string(WindowPattern const &pattern)
double forwardPrtlEnergy(double parentM, double secM, double prtlM, double parentE)
Definition: Constants.cpp:212
DecayFinalState MuPi(const MeVPrtlFlux &flux)
bool evgen::ldm::HNLMakeDecay::Decay ( const MeVPrtlFlux flux,
const TVector3 &  in,
const TVector3 &  out,
MeVPrtlDecay decay,
double &  weight 
)
overridevirtual

Implements evgen::ldm::IMeVPrtlDecay.

Definition at line 554 of file HNLMakeDecay_tool.cc.

554  {
555  // Check that the mass/decay configuration is allowed
556  bool has_allowed_decay = false;
557  for (const std::string &d: fDecayConfig) {
559  has_allowed_decay = true;
560  break;
561  }
562  }
563 
564  if (!has_allowed_decay) {
565  throw cet::exception("HNLMakeDecay Tool: BAD MASS. Configured mass (" + std::to_string(flux.mass) +
566  ") is smaller than any configured decay.");
567  }
568 
569  // Run the selected decay channels
570  std::vector<HNLMakeDecay::DecayFinalState> decays;
571  double total_width = 0.;
573  decays.push_back((*this.*F)(flux));
574  total_width += decays.back().width;
575  }
576 
577  std::cout << "TOTAL DECAY WIDTH: " << total_width << std::endl;
578  if (total_width == 0.) return false;
579 
580  // pick one
581  double sum_width = 0.;
582  int idecay = decays.size()-1;
583  double rand = GetRandom();
584  for (unsigned i = 0; i < decays.size()-1; i++) {
585  sum_width += decays[i].width;
586  if (rand < sum_width / total_width) {
587  idecay = i;
588  break;
589  }
590  }
591 
592  // Pick a random decay position -- assumes it is uniform across the detector
593  TVector3 decay_pos = in + GetRandom() * (out - in);
594 
595  // Get the decay probability
596 
597  // total lifetime
598  double lifetime_ns = Constants::Instance().hbar / total_width;
599 
600  // multiply by gamma*v to get the length
601  double mean_dist = lifetime_ns * flux.mom.Gamma() * flux.mom.Beta() * Constants::Instance().c_cm_per_ns;
602 
603  // Get the weight (NOTE: this negelects the probability that the HNL decays before the detector)
604  // I.e. it is only valid in the limit mean_dist >> 100m (distance from beam to SBN)
605  if (mean_dist < fMinDetectorDistance) {
606  std::cerr << "ERROR: bad mean_dist value (" << mean_dist << "). Decay weighting approximations invalid. Ignoring event." << std::endl;
607  std::cout << "ERROR: bad mean_dist value (" << mean_dist << "). Decay weighting approximations invalid. Ignoring event." << std::endl;
608  return false;
609  }
610 
611  // saves the weight
612  weight = (out - in).Mag() / mean_dist;
613 
614  // Save the decay info
615  decay.pos = TLorentzVector(decay_pos, TimeOfFlight(flux, decay_pos));
616  for (const TLorentzVector &p: decays[idecay].mom) {
617  decay.daughter_mom.push_back(p.Vect());
618  decay.daughter_e.push_back(p.E());
619  }
620  decay.daughter_pdg = decays[idecay].pdg;
621  decay.decay_width = total_width;
622  decay.mean_lifetime = lifetime_ns;
623  decay.mean_distance = mean_dist;
624 
625  return true;
626 }
BEGIN_PROLOG could also be cerr
std::map< std::string, double > fAvailableDecayMasses
pdgs p
Definition: selectors.fcl:22
std::vector< HNLDecayFunction > fSelectedDecays
DecayFinalState(HNLMakeDecay::* HNLDecayFunction)(const MeVPrtlFlux &flux)
static const Constants & Instance()
Definition: Constants.h:68
if &&[-z"$BASH_VERSION"] then echo Attempting to switch to bash bash shellSwitch exit fi &&["$1"= 'shellSwitch'] shift declare a IncludeDirectives for Dir in
std::vector< std::string > fDecayConfig
std::string to_string(WindowPattern const &pattern)
double TimeOfFlight(const MeVPrtlFlux &flux, TVector3 decay)
Definition: IMeVPrtlDecay.h:47
BEGIN_PROLOG could also be cout
DecayFinalState evgen::ldm::HNLMakeDecay::EPi ( const MeVPrtlFlux flux)
inlineprivate

Definition at line 129 of file HNLMakeDecay_tool.cc.

129 { return LepPi(flux, false); }
DecayFinalState LepPi(const MeVPrtlFlux &flux, bool is_muon)
double evgen::ldm::HNLMakeDecay::I1 ( double  x,
double  y,
double  z 
)
private

Definition at line 221 of file HNLMakeDecay_tool.cc.

221  {
222  gsl_function F;
223  double xyz[3];
224  xyz[0] = x;
225  xyz[1] = y;
226  xyz[2] = z;
227  F.function = &I1_integrand;
228  F.params = xyz;
229 
230  double result, error;
231  gsl_integration_qags(&F, (x+y)*(x+y), (1.-z)*(1.-z), 0., 1e-7, fIntegratorSize, fIntegrator, &result, &error);
232 
233  return result;
234 }
process_name opflash particleana ie ie ie z
process_name opflash particleana ie x
gsl_integration_workspace * fIntegrator
process_name opflash particleana ie ie y
double I1_integrand(double s, void *param)
do i e
double evgen::ldm::HNLMakeDecay::I2 ( double  x,
double  y,
double  z 
)
private

Definition at line 236 of file HNLMakeDecay_tool.cc.

236  {
237  gsl_function F;
238  double xyz[3];
239  xyz[0] = x;
240  xyz[1] = y;
241  xyz[2] = z;
242  F.function = &I2_integrand;
243  F.params = xyz;
244 
245  double result, error;
246  gsl_integration_qags(&F, (y+z)*(y+z), (1.-x)*(1.-x), 0., 1e-7, fIntegratorSize, fIntegrator, &result, &error);
247 
248  return result;
249 }
process_name opflash particleana ie ie ie z
process_name opflash particleana ie x
gsl_integration_workspace * fIntegrator
process_name opflash particleana ie ie y
double I2_integrand(double s, void *param)
do i e
HNLMakeDecay::ThreebodyMomentum evgen::ldm::HNLMakeDecay::isotropic_threebody_momentum ( double  parent_mass,
double  childA_mass,
double  childB_mass,
double  childC_mass 
)
private

Definition at line 140 of file HNLMakeDecay_tool.cc.

140  {
141  ThreebodyMomentum ret;
142  double sumofdaughtermass = childA_mass + childB_mass + childC_mass;
143  if (parent_mass < sumofdaughtermass) { // shouldn't happen
144  return ret;
145  }
146 
147  double E_A, E_B, E_C;
148  double P_A, P_B, P_C;
149  double P_max, P_sum;
150  // Kinetic Energy is distributed uniformly to daughters, with the constraint that
151  // total momentum is conserved. Randomly allocate energy until a possible such configuration
152  // is found
153  do {
154  double r1 = GetRandom();
155  double r2 = GetRandom();
156 
157  E_A = childA_mass + (parent_mass - sumofdaughtermass) * std::min(r1, r2);
158  E_B = childB_mass + (parent_mass - sumofdaughtermass) * std::min(1-r1,1-r2);
159  E_C = childC_mass + (parent_mass - sumofdaughtermass) * abs(r1-r2);
160 
161  P_A = sqrt(E_A*E_A - childA_mass*childA_mass);
162  P_B = sqrt(E_B*E_B - childB_mass*childB_mass);
163  P_C = sqrt(E_C*E_C - childC_mass*childC_mass);
164 
165  P_max = std::max(std::max(P_A,P_B),P_C);
166  P_sum = P_A + P_B + P_C;
167 
168  } while(P_max > P_sum - P_max);
169 
170  // Found a valid momentum allocation!
171 
172  // Pick a random direction for A, have the direction of B, C work to conserve momentum
173  TVector3 dirA = RandomUnitVector();
174 
175  // daughter particles B and C have the same momentum perpindicular to the direction of A
176  // Solving for the direction along the axis of particle A gives:
177  double cos_thAB = (P_C*P_C - P_B*P_B - P_A*P_A) / (2. * P_A * P_B);
178  double sin_thAB = sqrt(1. - cos_thAB * cos_thAB);
179  double cos_thAC = (P_B*P_B - P_C*P_C - P_A*P_A) / (2. * P_A * P_C);
180  double sin_thAC = sqrt(1. - cos_thAC * cos_thAC);
181 
182  // The azimuthal angle of B and C about A is distributed uniformly
183  double gammaB = (2*GetRandom() - 1.) * M_PI;
184  double gammaC = -gammaB;
185 
186  TVector3 dirB(
187  sin_thAB*cos(gammaB)*dirA.CosTheta()*sin(dirA.Phi()) - sin_thAB*sin(gammaB)*sin(dirA.Phi()) + cos_thAB*sqrt(1.-dirA.CosTheta()*dirA.CosTheta()) * cos(dirA.Phi()),
188  sin_thAB*cos(gammaB)*dirA.CosTheta()*cos(dirA.Phi()) - sin_thAB*sin(gammaB)*cos(dirA.Phi()) + cos_thAB*sqrt(1.-dirA.CosTheta()*dirA.CosTheta()) * sin(dirA.Phi()),
189  -sin_thAB*cos(gammaB)*sqrt(1. - dirA.CosTheta() * dirA.CosTheta()) + cos_thAB*dirA.CosTheta());
190 
191  TVector3 dirC(
192  sin_thAC*cos(gammaC)*dirA.CosTheta()*sin(dirA.Phi()) - sin_thAC*sin(gammaC)*sin(dirA.Phi()) + cos_thAC*sqrt(1.-dirA.CosTheta()*dirA.CosTheta()) * cos(dirA.Phi()),
193  sin_thAC*cos(gammaC)*dirA.CosTheta()*cos(dirA.Phi()) - sin_thAC*sin(gammaC)*cos(dirA.Phi()) + cos_thAC*sqrt(1.-dirA.CosTheta()*dirA.CosTheta()) * sin(dirA.Phi()),
194  -sin_thAC*cos(gammaC)*sqrt(1. - dirA.CosTheta() * dirA.CosTheta()) + cos_thAC*dirA.CosTheta());
195 
196  ret.A = TLorentzVector(P_A*dirA, E_A);
197  ret.B = TLorentzVector(P_B*dirB, E_B);
198  ret.C = TLorentzVector(P_C*dirC, E_C);
199 
200  return ret;
201 }
T abs(T value)
HNLMakeDecay::DecayFinalState evgen::ldm::HNLMakeDecay::LepPi ( const MeVPrtlFlux flux,
bool  is_muon 
)
private

Definition at line 322 of file HNLMakeDecay_tool.cc.

322  {
323  HNLMakeDecay::DecayFinalState ret;
324  double lep_mass = is_muon ? Constants::Instance().muon_mass : Constants::Instance().elec_mass;
325  int lep_pdg = is_muon ? 13 : 11;
326 
327  double piplus_mass = Constants::Instance().piplus_mass;
328  double Gfermi = Constants::Instance().Gfermi;
329  double fpion = Constants::Instance().fpion;
330  double abs_Vud_squared = Constants::Instance().abs_Vud_squared;
331 
332  // Decay not kinematically allowed
333  if (lep_mass + piplus_mass > flux.mass) {
334  ret.width = 0.;
335  return ret;
336  }
337 
338  double u4 = is_muon ? flux.C2 : flux.C1;
339  double lep_ratio = (lep_mass * lep_mass) / (flux.mass * flux.mass);
340  double pion_ratio = (piplus_mass * piplus_mass) / (flux.mass * flux.mass);
341  double Ifunc = ((1 + lep_ratio + pion_ratio)*(1.+lep_ratio) - 4*lep_ratio) * sqrt(lambda(1., lep_ratio, pion_ratio));
342  ret.width = u4 * (Gfermi * Gfermi *fpion * fpion * abs_Vud_squared * flux.mass * flux.mass * flux.mass * Ifunc) / (16 * M_PI);
343 
344  // Majorana gets an extra factor b.c. it can go to pi+l- and pi-l+
345  if (fMajorana) ret.width *= 2;
346 
347  // Majorana decays don't conserve lepton number, Dirac decay's do
348  int lep_pdg_sign;
349  if (fMajorana) {
350  lep_pdg_sign = (GetRandom() > 0.5) ? 1 : -1;
351  }
352  else {
353  // Dirac HNL caries opposite lepton number to production lepton
354  lep_pdg_sign = (flux.secondary_pdg > 0) ? -1 : 1;
355  }
356 
357  // Use rejection sampling to draw a direction for the child particles
358  //
359  // Work in the lab frame
360  double dalitz_max = HNLLepPiDalitzMax(Constants::Instance().kplus_mass, flux.sec.M(), flux.mass, piplus_mass, lep_mass);
361  double this_dalitz = 0.;
362  double p = evgen::ldm::twobody_momentum(flux.mass, lep_mass, piplus_mass);
363  TLorentzVector LB;
364  TLorentzVector PI;
365  do {
366  TVector3 dir = RandomUnitVector();
367  LB = TLorentzVector(p*dir, sqrt(p*p + lep_mass*lep_mass));
368  PI = TLorentzVector(-p*dir, sqrt(p*p + piplus_mass*piplus_mass));
369  LB.Boost(flux.mom.BoostVector());
370  PI.Boost(flux.mom.BoostVector());
371 
372  this_dalitz = ((flux.secondary_pdg > 0 ) != (lep_pdg_sign > 0)) ? \
373  evgen::ldm::HNLLepPiLNCDalitz(flux.kmom, flux.sec, flux.mom, PI, LB):
374  evgen::ldm::HNLLepPiLNVDalitz(flux.kmom, flux.sec, flux.mom, PI, LB);
375 
376  assert(this_dalitz < dalitz_max);
377  if (this_dalitz > dalitz_max) {
378  std::cerr << "VERY VERY BAD!!!! Incorrect dalitz max!!!\n";
379  std::cout << "VERY VERY BAD!!!! Incorrect dalitz max!!!\n";
380  std::cout << "PK: " << flux.kmom.E() << " " << flux.kmom.Px() << " " << flux.kmom.Py() << " " << flux.kmom.Pz() << std::endl;
381  std::cout << "PA: " << flux.sec.E() << " " << flux.sec.Px() << " " << flux.sec.Py() << " " << flux.sec.Pz() << std::endl;
382  std::cout << "PN: " << flux.mom.E() << " " << flux.mom.Px() << " " << flux.mom.Py() << " " << flux.mom.Pz() << std::endl;
383  std::cout << "PP: " << PI.E() << " " << PI.Px() << " " << PI.Py() << " " << PI.Pz() << std::endl;
384  std::cout << "PB: " << LB.E() << " " << LB.Px() << " " << LB.Py() << " " << LB.Pz() << std::endl;
385 
386  std::cout << "This Dalitz: " << this_dalitz << std::endl;
387  std::cout << "Max Dalitz: " << dalitz_max << std::endl;
388  std::cout << "LNC: " << ((flux.secondary_pdg > 0 ) != (lep_pdg_sign > 0)) << std::endl;
389 
390  exit(1);
391  }
392  } while (GetRandom() > this_dalitz / dalitz_max);
393 
394  // lepton
395  ret.mom.push_back(LB);
396  ret.pdg.push_back(lep_pdg*lep_pdg_sign);
397 
398  // pion
399  ret.mom.emplace_back(PI);
400  ret.pdg.push_back(211*lep_pdg_sign); // negative of lepton-charge has same-sign-PDG code
401 
402  return ret;
403 }
BEGIN_PROLOG could also be cerr
double lambda(double a, double b, double c)
pdgs p
Definition: selectors.fcl:22
double twobody_momentum(double parent_mass, double childA_mass, double childB_mass)
Definition: Constants.cpp:73
constexpr double PI
double HNLLepPiLNVDalitz(TLorentzVector K, TLorentzVector LA, TLorentzVector N, TLorentzVector PI, TLorentzVector LB)
tuple dir
Definition: dropbox.py:28
static const Constants & Instance()
Definition: Constants.h:68
double HNLLepPiDalitzMax(double mK, double mA, double mN, double mP, double mB)
BEGIN_PROLOG could also be cout
double HNLLepPiLNCDalitz(TLorentzVector K, TLorentzVector LA, TLorentzVector N, TLorentzVector PI, TLorentzVector LB)
double evgen::ldm::HNLMakeDecay::MaxWeight ( )
inlineoverridevirtual

Implements evgen::ldm::IMeVPrtlStage.

Definition at line 72 of file HNLMakeDecay_tool.cc.

72  {
73  return fMaxWeight;
74  }
DecayFinalState evgen::ldm::HNLMakeDecay::MuPi ( const MeVPrtlFlux flux)
inlineprivate

Definition at line 130 of file HNLMakeDecay_tool.cc.

130 { return LepPi(flux, true); }
DecayFinalState LepPi(const MeVPrtlFlux &flux, bool is_muon)
double evgen::ldm::HNLMakeDecay::NuDiLepDecayWidth ( double  hnl_mass,
double  ue4,
double  um4,
bool  nu_is_muon,
bool  lep_is_muon 
)
private

Definition at line 252 of file HNLMakeDecay_tool.cc.

252  {
253  double hnl_mass_pow5 = hnl_mass*hnl_mass*hnl_mass*hnl_mass*hnl_mass;
254  double u4 = nu_is_muon ? um4 : ue4;
255  double lep_mass = lep_is_muon ? Constants::Instance().muon_mass : Constants::Instance().elec_mass;
256 
257  double Gfermi = Constants::Instance().Gfermi;
258  double gL = Constants::Instance().gL;
259  double gR = Constants::Instance().gR;
260 
261  if (hnl_mass < lep_mass * 2.) return 0.;
262 
263  int CC = (lep_is_muon == nu_is_muon);
264 
265  double I1val = I1(0., lep_mass / hnl_mass, lep_mass / hnl_mass);
266  double I2val = I2(0., lep_mass / hnl_mass, lep_mass / hnl_mass);
267 
268  double width = (Gfermi*Gfermi*hnl_mass_pow5) * u4 * ((gL*gR/*NC*/ + CC*gR/*CC*/)*I1val + (gL*gL+gR*gR+CC*(1+2.*gL))*I2val);
269 
270  return width;
271 }
static const Constants & Instance()
Definition: Constants.h:68
process_name showerreco Particles Coinciding wih the Vertex services ScanOptions nu_mu CC
double I2(double x, double y, double z)
double I1(double x, double y, double z)
HNLMakeDecay::DecayFinalState evgen::ldm::HNLMakeDecay::NuMupMum ( const MeVPrtlFlux flux)
private

Definition at line 273 of file HNLMakeDecay_tool.cc.

273  {
274  HNLMakeDecay::DecayFinalState ret;
275 
276  double muon_mass = Constants::Instance().muon_mass;
277 
278  // Decay not kinematically allowed
279  if (2*muon_mass > flux.mass) {
280  ret.width = 0.;
281  return ret;
282  }
283 
284  double ue4 = flux.C1;
285  double um4 = flux.C2;
286  double nue_width = NuDiLepDecayWidth(flux.mass, ue4, um4, false, true);
287  double numu_width = NuDiLepDecayWidth(flux.mass, ue4, um4, true, true);
288 
289  ret.width = nue_width + numu_width;
290 
291  if (ret.width == 0.) return ret;
292 
293  // Majorana gets an extra factor b.c. it can go to nu and nubar
294  if (fMajorana) ret.width *= 2;
295 
296  // Three body decay
297  //
298  // TODO: account for anisotropies in decay
299  ThreebodyMomentum momenta = isotropic_threebody_momentum(flux.mass, 0., muon_mass, muon_mass);
300 
301  // pick whether the neutrino is nue or numu
302  int nu_pdg_sign;
303  if (fMajorana) {
304  nu_pdg_sign = (GetRandom() > 0.5) ? 1:-1;
305  }
306  else {
307  // same as the HNL
308  nu_pdg_sign = (flux.secondary_pdg > 0) ? -1 : 1;
309  }
310  int nu_pdg = nu_pdg_sign * ((GetRandom() > numu_width / (numu_width + nue_width)) ? 14 : 12);
311  ret.pdg.push_back(nu_pdg);
312  ret.mom.push_back(momenta.A);
313 
314  ret.pdg.push_back(13);
315  ret.mom.push_back(momenta.B);
316  ret.pdg.push_back(-13);
317  ret.mom.push_back(momenta.C);
318 
319  return ret;
320 }
ThreebodyMomentum isotropic_threebody_momentum(double parent_mass, double childA_mass, double childB_mass, double childC_mass)
double NuDiLepDecayWidth(double hnl_mass, double ue4, double um4, bool nu_is_muon, bool lep_is_muon)
static const Constants & Instance()
Definition: Constants.h:68

Member Data Documentation

std::map<std::string, double> evgen::ldm::HNLMakeDecay::fAvailableDecayMasses
private

Definition at line 114 of file HNLMakeDecay_tool.cc.

std::map<std::string, HNLDecayFunction> evgen::ldm::HNLMakeDecay::fAvailableDecays
private

Definition at line 113 of file HNLMakeDecay_tool.cc.

std::vector<std::string> evgen::ldm::HNLMakeDecay::fDecayConfig
private

Definition at line 115 of file HNLMakeDecay_tool.cc.

gsl_integration_workspace* evgen::ldm::HNLMakeDecay::fIntegrator
private

Definition at line 79 of file HNLMakeDecay_tool.cc.

unsigned evgen::ldm::HNLMakeDecay::fIntegratorSize
private

Definition at line 80 of file HNLMakeDecay_tool.cc.

bool evgen::ldm::HNLMakeDecay::fMajorana
private

Definition at line 94 of file HNLMakeDecay_tool.cc.

double evgen::ldm::HNLMakeDecay::fMaxWeight
private

Definition at line 78 of file HNLMakeDecay_tool.cc.

double evgen::ldm::HNLMakeDecay::fMinDetectorDistance
private

Definition at line 91 of file HNLMakeDecay_tool.cc.

double evgen::ldm::HNLMakeDecay::fReferenceHNLEnergy
private

Definition at line 87 of file HNLMakeDecay_tool.cc.

double evgen::ldm::HNLMakeDecay::fReferenceHNLKaonEnergy
private

Definition at line 88 of file HNLMakeDecay_tool.cc.

double evgen::ldm::HNLMakeDecay::fReferenceHNLMass
private

Definition at line 85 of file HNLMakeDecay_tool.cc.

double evgen::ldm::HNLMakeDecay::fReferenceRayLength
private

Definition at line 86 of file HNLMakeDecay_tool.cc.

double evgen::ldm::HNLMakeDecay::fReferenceUE4
private

Definition at line 83 of file HNLMakeDecay_tool.cc.

double evgen::ldm::HNLMakeDecay::fReferenceUM4
private

Definition at line 84 of file HNLMakeDecay_tool.cc.

std::vector<HNLDecayFunction> evgen::ldm::HNLMakeDecay::fSelectedDecays
private

Definition at line 116 of file HNLMakeDecay_tool.cc.


The documentation for this class was generated from the following file: