35 #include "Math/GSLMinimizer.h"
36 #include <Math/WrappedParamFunction.h>
38 using namespace genie;
39 using namespace genie::controls;
40 using namespace genie::constants;
63 <<
"Running dark sector decayer ";
66 TObjArrayIter piter(event);
72 LOG(
"DarkSectorDecayer",
pDEBUG) <<
"Checking: " << p->
Name();
77 std::vector<DarkSectorDecayer::DecayChannel> dcs;
78 int pdg_code = mother.
Pdg();
87 for (
const auto & dc : dcs ) {
88 std::stringstream amplitudes_msg;
89 amplitudes_msg <<
"Decay amplitude: " << dc.second <<
" GeV "
90 <<
" -> " << 1. / dc.second /
units::second <<
"s for channel [" ;
91 for (
const auto & pdgc : dc.first ) {
92 amplitudes_msg << pdgc <<
" " ;
94 amplitudes_msg <<
"]";
95 LOG(
"DarkSectorDecayer",
pDEBUG) << amplitudes_msg.str();
98 double total_amplitude = std::accumulate(dcs.begin(), dcs.end(), 0.,
101 {
return total + dc.second;});
104 std::vector<GHepParticle> daughters =
Decay(mother, dcs[dcid].first);
107 for(
auto & daughter: daughters){
108 daughter.SetFirstMother(ipos);
109 event->AddParticle(daughter);
114 <<
"Done finding & decaying dark sector particles";
120 const std::vector<int> & pdg_daughters)
const
122 TLorentzVector mother_p4 = *(mother.
P4());
124 <<
"Decaying a " << mother.
Name()
127 unsigned int nd = pdg_daughters.size();
128 std::vector<double> mass(nd, 0.);
130 for(
unsigned int iparticle = 0; iparticle < nd; iparticle++) {
134 mass[iparticle] = daughter->Mass();
137 <<
"+ daughter[" << iparticle <<
"]: "
138 << daughter->GetName() <<
" (pdg-code = "
139 << pdg_daughters[iparticle] <<
", mass = " << mass[iparticle] <<
")";
143 assert(is_permitted);
147 for(
int i=0; i<50; i++) {
149 wmax = TMath::Max(wmax,w);
153 <<
"Max phase space gen. weight for current decay: " << wmax;
158 bool accept_decay=
false;
161 while(!accept_decay){
166 double gw = wmax * rnd->
RndDec().Rndm();
170 <<
"Current decay weight = " << w <<
" > wmax = " << wmax;
173 <<
"Current decay weight = " << w <<
" / R = " << gw;
175 accept_decay = (gw<=w);
179 std::vector<GHepParticle> particles;
181 for(
unsigned int id = 0;
id < nd;
id++) {
184 <<
"Adding daughter particle with PDG code = " << pdg_daughters[id]
187 <<
"Particle Gun Kinematics: "
188 <<
"PDG : " << pdg_daughters[id] <<
", "
192 particles.push_back(
GHepParticle(pdg_daughters[
id], daughter_status_code,
194 *daughter_p4, TLorentzVector()));
201 const std::vector<DarkSectorDecayer::DecayChannel> & dcs,
202 const double total_amplitude)
const
205 unsigned int ich = 0, sel_ich;
207 double x = total_amplitude * rnd->
RndDec().Rndm();
208 double partial_sum = 0. ;
211 partial_sum += dcs.at(ich++).second;
212 }
while (x > partial_sum );
222 std::vector<DarkSectorDecayer::DecayChannel> dcs;
224 for(
size_t i=0; i<neutrinos.size(); ++i){
225 for(
size_t j=0; j<antineutrinos.size(); ++j){
227 dcs.push_back(
DecayChannel{{neutrinos[i], antineutrinos[j]}, decay_width});
234 double phase_space_correction = sqrt(1. - ratio*ratio ) ;
242 double phase_space_correction = sqrt(1. - ratio*ratio ) ;
255 std::vector<DarkSectorDecayer::DecayChannel> dcs;
258 for(
size_t i=0; i<neutrinos.size(); ++i){
262 const double p2 = 1 - mass2ratio;
263 const double p3 = 1 + mass2ratio - 2*mass2ratio*mass2ratio;
264 const double decay_width = p0 * p1 * p2 * p3;
278 std::vector<GHepParticle> & pp,
280 double total_amplitude)
const {
286 double t = rnd->
RndDec().Exp(lifetime);
290 t *= mother.
P4() -> Gamma() ;
293 const TLorentzVector & mother_X4 = *(mother.
X4());
294 TVector3 mother_boost = mother.
P4()->BoostVector();
298 TVector3 daughter_position = mother_X4.Vect() + mother_boost * (speed_of_light * t * 1
e-9);
299 TLorentzVector daughter_X4 = TLorentzVector(daughter_position, (mother_X4.T() + t));
302 p.SetPosition(daughter_X4);
311 int pdg_code = p.
Pdg();
312 bool is_handled =
false;
320 <<
"Can decay particle with PDG code = " << pdg_code
321 <<
"? " << ((is_handled)?
"Yes" :
"No");
328 std::ostringstream fmt;
330 double P0 = vec4.Vect().Mag();
331 double thetaYZ = TMath::ASin(vec4.Py()/P0);
332 double thetaXZ = TMath::ASin(vec4.Px()/(P0 * TMath::Cos(thetaYZ)));
333 double rad_to_degrees = 180./
kPi;
336 <<
", ThetaXZ = " << thetaXZ*rad_to_degrees
337 <<
", ThetaYZ = " << thetaYZ*rad_to_degrees;
361 for (
auto & pdg_code : pdgc_mothers){
365 <<
"\n *** The particle with PDG code = " << pdg_code
366 <<
" was not found in PDGLibrary";
371 bool good_configuration = true ;
373 double DKineticMixing = 0.;
374 this->
GetParam(
"Dark-KineticMixing", DKineticMixing);
375 fEps2 = DKineticMixing * DKineticMixing;
377 bool force_unitarity = false ;
378 GetParam(
"Dark-Mixing-ForceUnitarity", force_unitarity ) ;
380 unsigned int n_min_mixing = force_unitarity ? 3 : 4 ;
382 std::vector<double> DMixing2s;
386 if ( DMixing2s.size () < n_min_mixing ) {
388 good_configuration = false ;
390 <<
"Not enough mixing elements specified, only specified "
391 << DMixing2s.size() <<
" / " << n_min_mixing ;
394 double tot_mix = 0. ;
395 for(
unsigned int i = 0; i < n_min_mixing ; ++i ) {
396 if ( DMixing2s[i] < 0. ) {
397 good_configuration = false ;
399 <<
"Mixing " << i <<
" non positive: " << DMixing2s[i] ;
405 if ( force_unitarity ) {
427 if ( fDMediatorMass >= fDNuMass ) {
428 good_configuration = false ;
430 <<
"Dark mediator mass (" << fDMediatorMass
431 <<
" GeV) too heavy for the dark neutrino ("
432 << fDNuMass <<
" GeV) to decay" ;
442 if ( fDMediatorMass >= pion_threshold ) {
443 good_configuration = false ;
445 <<
"Dark mediator mass (" << fDMediatorMass
446 <<
" GeV) too heavy with respect to the pion decay threshold ("
447 << pion_threshold <<
" GeV)" ;
450 if ( ! good_configuration ) {
451 LOG(
"DarkSectorDecayer",
pFATAL ) <<
"Wrong configuration. Exiting" ;
string P4AsShortString(const TLorentzVector *p)
static RandomGen * Instance()
Access instance.
const TLorentzVector * P4(void) const
Defines the EventRecordVisitorI interface. Concrete implementations of this interface use the 'Visito...
virtual void Configure(const Registry &config)
std::array< double, 4 > fMixing2s
int GetParamVect(const std::string &comm_name, std::vector< T > &v, bool is_top_call=true) const
Handle to load vectors of parameters.
string P4AsString(const TLorentzVector *p)
static const unsigned int kMaxUnweightDecayIterations
A singleton holding random number generator classes. All random number generation in GENIE should tak...
std::pair< std::vector< int >, double > DecayChannel
virtual ~DarkSectorDecayer()
const int kPdgAntiDarkNeutrino
std::vector< GHepParticle > Decay(const GHepParticle &mother, const std::vector< int > &pdg_daughters) const
GHepStatus_t Status(void) const
void SetSpaceTime(std::vector< GHepParticle > &pp, const GHepParticle &mother, double total_amplitude) const
void ProcessEventRecord(GHepRecord *event) const
string Name(void) const
Name that corresponds to the PDG code.
std::vector< DecayChannel > DarkMediatorDecayChannels(void) const
static constexpr double second
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
virtual void LoadConfig(void)
virtual void Configure(const Registry &config)
TGenPhaseSpace fPhaseSpaceGenerator
bool ToBeDecayed(const GHepParticle &p) const
static constexpr double meter
static PDGLibrary * Instance(void)
const int kPdgDNuMediator
static string ParticleGunKineAsString(const TLorentzVector &vec4)
const TLorentzVector * X4(void) const
A registry. Provides the container for algorithm configuration parameters.
int SelectDecayChannel(const std::vector< DecayChannel > &dcs, double total_amplitude) const
TParticlePDG * Find(int pdgc, bool must_exist=true)
bool GetParam(const RgKey &name, T &p, bool is_top_call=true) const
#define SLOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a short string (using the FUNCTION and...
GENIE's GHEP MC event record.
const int kPdgDarkNeutrino
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
TRandom3 & RndDec(void) const
rnd number generator used by decay models
std::vector< DecayChannel > DarkNeutrinoDecayChannels(int mother_pdg) const
STDHEP-like event record entry that can fit a particle or a nucleus.
enum genie::EGHepStatus GHepStatus_t