112 using std::ostringstream;
114 using namespace genie;
115 using namespace genie::hnl;
116 using namespace genie::hnl::enums;
118 #ifdef __GENIE_FLUX_DRIVERS_ENABLED__
119 #define __CAN_GENERATE_EVENTS_USING_A_FLUX__
122 #endif // #ifdef __GENIE_FLUX_DRIVERS_ENABLED__
124 #ifdef __GENIE_GEOM_DRIVERS_ENABLED__
125 #define __CAN_USE_ROOT_GEOM__
126 #include <TGeoVolume.h>
127 #include <TGeoManager.h>
128 #include <TGeoShape.h>
129 #include <TGeoBBox.h>
130 #endif // #ifdef __GENIE_GEOM_DRIVERS_ENABLED__
139 #ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX__
140 void GenerateEventsUsingFlux (
void);
143 #endif // #ifdef __GENIE_FLUX_DRIVERS_ENABLED__
146 #ifdef __CAN_USE_ROOT_GEOM__
147 void InitBoundingBox (
void);
148 #endif // #ifdef __CAN_USE_ROOT_GEOM__
173 #ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX__
176 bool gOptIsUsingDk2nu =
false;
177 int gOptFirstEvent = 0;
178 #endif // #ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX__
188 #ifdef __CAN_USE_ROOT_GEOM__
189 TGeoManager * gOptRootGeoManager = 0;
190 TGeoVolume * gOptRootGeoVolume = 0;
191 #endif // #ifdef __CAN_USE_ROOT_GEOM__
219 int main(
int argc,
char ** argv)
222 gErrorIgnoreLevel = kWarning;
242 const Decayer * hnlgen =
dynamic_cast< const Decayer *
>( algHNLGen );
258 while( stIntChannels.size() > 0 ){
261 std::string tmpSt = stIntChannels.substr( stIntChannels.size()-1, stIntChannels.size() );
262 if( std::strcmp( tmpSt.c_str(),
"1" ) == 0 )
265 stIntChannels.erase( stIntChannels.end()-1, stIntChannels.end() );
277 if( gOptIsUsingDk2nu ) {
282 FillFluxNonsense( gnmf );
283 TBranch * flux = ntpw.
EventTree()->Branch(
"flux",
284 "genie::hnl::FluxContainer",
286 flux->SetAutoDelete(kFALSE);
290 <<
"Initialised Ntuple Writer";
304 <<
"Initialised MC job monitor";
309 #ifdef __CAN_USE_ROOT_GEOM__
314 #endif // #ifdef __CAN_USE_ROOT_GEOM__
318 <<
"Using input flux files. These are *flat dk2nu-like ROOT trees, so far...*";
322 int iflux = (gOptFirstEvent < 0) ? 0 : gOptFirstEvent;
int ievent = iflux;
323 int maxFluxEntries = -1;
329 bool tooManyEntries =
false;
332 if( tooManyEntries ){
334 if( (ievent-gOptFirstEvent) % (
gOptNev / 1000) == 0 ){
335 int irat = (iflux-gOptFirstEvent) / (
gOptNev / 1000 );
336 std::cerr << 0.1 * irat <<
" % " <<
" ( " << (iflux-gOptFirstEvent)
337 <<
" seen ), ( " << (ievent-gOptFirstEvent) <<
" / " <<
gOptNev <<
" processed ) \r" << std::flush;
340 if( (ievent-gOptFirstEvent) % (
gOptNev / 10) == 0 ){
341 int irat = (iflux-gOptFirstEvent) / (
gOptNev / 10 );
342 std::cerr << 10.0 * irat <<
" % " <<
" ( " << (iflux-gOptFirstEvent)
343 <<
" seen ), ( " << (ievent-gOptFirstEvent) <<
" / " <<
gOptNev <<
" processed ) \r" << std::flush;
348 if( (ievent-gOptFirstEvent) % (
gOptNev / 1000) == 0 ){
349 int irat = (ievent-gOptFirstEvent) / (
gOptNev / 1000 );
350 std::cerr << 0.1 * irat <<
" % " <<
" ( " << (iflux-gOptFirstEvent)
351 <<
" seen ), ( " << (ievent-gOptFirstEvent) <<
" / " <<
gOptNev <<
" processed ) \r" << std::flush;
354 if( (ievent-gOptFirstEvent) % (
gOptNev / 10) == 0 ){
355 int irat = (ievent-gOptFirstEvent) / (
gOptNev / 10 );
356 std::cerr << 10.0 * irat <<
" % " <<
" ( " << (iflux-gOptFirstEvent)
357 <<
" seen ), ( " << (ievent-gOptFirstEvent) <<
" / " <<
gOptNev <<
" processed ) \r" << std::flush;
362 if( tooManyEntries && ((iflux-gOptFirstEvent) ==
gOptNev) )
break;
363 else if( (ievent-gOptFirstEvent) ==
gOptNev )
break;
365 if( ievent < gOptFirstEvent ){ ievent++;
continue; }
367 assert( ievent >= gOptFirstEvent && gOptFirstEvent >= 0 );
370 <<
" *** Generating event............ " << (ievent-gOptFirstEvent);
375 event->SetXSec( iflux );
383 if(
gOptNev > maxFluxEntries - gOptFirstEvent ){
385 <<
"You have asked for " <<
gOptNev <<
" events, but only provided "
386 << maxFluxEntries - gOptFirstEvent <<
" flux entries. Truncating events to " << maxFluxEntries - gOptFirstEvent <<
".";
387 gOptNev = maxFluxEntries - gOptFirstEvent;
388 tooManyEntries =
true;
390 if( iflux >= maxFluxEntries - 1 ){
392 <<
"Reached end of flux input (iflux = " << iflux <<
"), about to stop.";
397 FillFlux( gnmf, retGnmf );
400 if( ! event->Particle(0) ){ iflux++;
delete event;
continue; }
409 TLorentzVector v4( 0.0, 0.0, 0.0, 0.0 );
411 event->AddParticle( ptHNL );
419 else if( event->Particle(0)->Pdg() > 0 ) typeMod = 1;
420 else if( event->Particle(0)->Pdg() < 0 ) typeMod = -1;
437 <<
"No decay mode specified - sampling from all available modes.";
446 if( event->Particle(0) ){
453 event->AttachSummary(interaction);
461 NTP_FS0_E = ((
event->Particle(1))->P4())->E();
462 NTP_FS0_PX = ((
event->Particle(1))->P4())->Px();
463 NTP_FS0_PY = ((
event->Particle(1))->P4())->Py();
464 NTP_FS0_PZ = ((
event->Particle(1))->P4())->Pz();
466 NTP_FS1_E = ((
event->Particle(2))->P4())->E();
467 NTP_FS1_PX = ((
event->Particle(2))->P4())->Px();
468 NTP_FS1_PY = ((
event->Particle(2))->P4())->Py();
469 NTP_FS1_PZ = ((
event->Particle(2))->P4())->Pz();
470 if( event->Particle(3) ){
472 NTP_FS2_E = ((
event->Particle(3))->P4())->E();
473 NTP_FS2_PX = ((
event->Particle(3))->P4())->Px();
474 NTP_FS2_PY = ((
event->Particle(3))->P4())->Py();
475 NTP_FS2_PZ = ((
event->Particle(3))->P4())->Pz();
489 TLorentzVector * p4HNL =
event->Particle(0)->GetP4();
492 x4mm = *(
event->Vertex());
506 event->Particle(2)->SetPolarization( 1.0,
decayMod );
514 <<
"Generated event: " << *event;
518 mcjmonitor.
Update(ievent,event);
534 #ifdef __CAN_USE_ROOT_GEOM__
535 void InitBoundingBox(
void)
540 <<
"Initialising geometry bounding box.";
551 <<
"No geometry file input detected, making a unit-m side box volume.";
553 TGeoManager *
geom =
new TGeoManager(
"box1",
"A simple box detector" );
556 TGeoMaterial *matVacuum =
new TGeoMaterial(
"Vacuum", 0,0,0);
557 TGeoMaterial *matAl =
new TGeoMaterial(
"Al", 26.98,13,2.7);
559 TGeoMedium *Vacuum =
new TGeoMedium(
"Vacuum",1, matVacuum);
560 TGeoMedium *Al =
new TGeoMedium(
"Root Material",2, matAl);
567 TGeoVolume * topvol = geom->MakeBox(
"TOP", Vacuum, 101.0, 101.0, 101.0 );
568 geom->SetTopVolume( topvol );
571 TGeoVolume * boxvol = geom->MakeBox(
"VOL", Vacuum, 100.5, 100.5, 100.5 );
572 boxvol->SetVisibility(kFALSE);
575 TGeoVolume * box = geom->MakeBox(
"BOX", Al, 100.0, 100.0, 100.0 );
577 TGeoRotation * rot0 =
new TGeoRotation(
"rot0", 90.0, 0.0, 90.0, 90.0, 0.0, 0.0 );
580 topvol->AddNode( box, 1, rot0 );
582 gOptRootGeoManager =
geom;
587 bool geom_is_accessible = ! (gSystem->AccessPathName(
gOptRootGeom.c_str()));
588 if (!geom_is_accessible) {
590 <<
"The specified ROOT geometry doesn't exist! Initialization failed!";
594 if( !gOptRootGeoManager ) gOptRootGeoManager = TGeoManager::Import(
gOptRootGeom.c_str());
596 TGeoVolume * top_volume = gOptRootGeoManager->GetTopVolume();
597 assert( top_volume );
598 TGeoShape * ts = top_volume->GetShape();
600 TGeoBBox * box = (TGeoBBox *)ts;
606 fox = (box->GetOrigin())[0];
607 foy = (box->GetOrigin())[1];
608 foz = (box->GetOrigin())[2];
611 <<
"Before conversion the bounding box has:"
612 <<
"\nOrigin = ( " <<
fox <<
" , " <<
foy <<
" , " <<
foz <<
" )"
613 <<
"\nDimensions = " <<
fdx <<
" x " <<
fdy <<
" x " <<
fdz
614 <<
"\n1cm = 1.0 unit";
625 <<
"Initialised bounding box successfully.";
628 #endif // #ifdef __CAN_USE_ROOT_GEOM__
632 #ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX__
645 ggn.
startPoint.SetXYZ(-9999.9, -9999.9, -9999.9);
651 ggn.
polz.SetXYZ(-9999.9, -9999.9, -9999.9);
653 ggn.
p4.SetPxPyPzE(-9999.9, -9999.9, -9999.9, -9999.9);
654 ggn.
parp4.SetPxPyPzE(-9999.9, -9999.9, -9999.9, -9999.9);
655 ggn.
p4User.SetPxPyPzE(-9999.9, -9999.9, -9999.9, -9999.9);
656 ggn.
parp4User.SetPxPyPzE(-9999.9, -9999.9, -9999.9, -9999.9);
709 #endif // #ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX__
714 TRandom3 & rnd_geo = rnd->
RndGeom();
716 double rndx = 2 * (rnd_geo.Rndm() - 0.5);
717 double rndy = 2 * (rnd_geo.Rndm() - 0.5);
718 double rndz = 2 * (rnd_geo.Rndm() - 0.5);
721 double x_gen =
fox + rndx *
fdx;
722 double y_gen =
foy + rndy *
fdy;
723 double z_gen =
foz + rndz *
fdz;
725 TLorentzVector pos(x_gen, y_gen, z_gen, t_gen);
736 <<
"Instantiating HNL generator.";
745 LOG(
"gevgen_hnl",
pFATAL) <<
"Couldn't instantiate the HNL generator";
751 <<
"HNL generator instantiated successfully.";
765 std::vector< HNLDecayMode_t > intAndValidChannels;
766 for( std::vector< HNLDecayMode_t >::iterator it = intChannels->begin(); it != intChannels->end(); ++it ){
772 intAndValidChannels.emplace_back( mode );
773 auto mapG = gammaMap.find( mode );
774 double theGamma = mapG->second;
779 if( intAndValidChannels.size() == 0 ){
781 <<
"None of the channels specified as interesting are kinematically allowed. Please either increase the HNL mass or change interesting channels in config.";
785 std::map< HNLDecayMode_t, double > intMap =
791 double gammaAll = 0.0, gammaInt = 0.0;
792 for( std::map< HNLDecayMode_t, double >::const_iterator itall = gammaMap.begin() ;
793 itall != gammaMap.end() ; ++itall ){
794 gammaAll += (*itall).second;
796 for( std::map< HNLDecayMode_t, double >::iterator itint = intMap.begin() ;
797 itint != intMap.end() ; ++itint ){
798 gammaInt += (*itint).second;
800 assert( gammaInt > 0.0 && gammaAll >= gammaInt );
804 std::map< HNLDecayMode_t, double > PMap =
809 double ranThrow = rnd->
RndGen().Uniform( 0., 1. );
814 int decay = ( int ) selectedDecayChan;
820 LOG(
"gevgen_hnl",
pINFO) <<
"Parsing command line arguments";
828 char * expargv[ argc + 2 ];
829 bool didFindUserInputTune =
false;
832 if( parser.OptionExists(
"tune") ){
833 didFindUserInputTune =
true;
834 stExtraTuneBit = parser.ArgAsString(
"tune");
836 <<
"Using input HNL tune " << parser.ArgAsString(
"tune");
842 for(
int iArg = 0; iArg < argc; iArg++ ){
843 expargv[iArg] = argv[iArg];
845 if( !didFindUserInputTune ){
846 char * chBit =
const_cast< char *
>( stExtraTuneBit.c_str() );
847 std::string stune(
"--tune");
char * tBit =
const_cast< char *
>( stune.c_str() );
848 expargv[argc] = tBit;
849 expargv[argc+1] = chBit;
853 int expargc = ( didFindUserInputTune ) ? argc : argc+2;
854 std::string stnull(
"");
char * nBit =
const_cast< char *
>( stnull.c_str() );
855 expargv[expargc] = nBit;
860 bool help = parser.OptionExists(
'h');
867 if( parser.OptionExists(
'r') ) {
868 LOG(
"gevgen_hnl",
pDEBUG) <<
"Reading MC run number";
871 LOG(
"gevgen_hnl",
pDEBUG) <<
"Unspecified run number - Using default";
876 if( parser.OptionExists(
'n') ) {
878 <<
"Reading number of events to generate";
879 gOptNev = parser.ArgAsInt(
'n');
882 <<
"You need to specify the number of events";
889 const Decayer * hnlgen =
dynamic_cast< const Decayer *
>( algHNLGen );
892 bool isMonoEnergeticFlux =
true;
893 #ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX__
894 if( parser.OptionExists(
'f') ) {
896 <<
"A flux has been offered. Searching this path: " << parser.ArgAsString(
'f');
897 isMonoEnergeticFlux =
false;
898 gOptFluxFilePath = parser.ArgAsString(
'f');
901 if( gSystem->OpenDirectory( gOptFluxFilePath.c_str() ) != NULL ){
902 gOptIsUsingDk2nu =
true;
904 <<
"dk2nu flux files detected. Will create flux spectrum dynamically.";
907 <<
"Invalid flux file path " << gOptFluxFilePath;
913 <<
"No flux file offered. Assuming monoenergetic flux.";
915 #endif // #ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX__
919 if( isMonoEnergeticFlux ){
920 if( parser.OptionExists(
'E') ) {
922 <<
"Reading HNL energy";
926 <<
"You need to specify the HNL energy";
936 if( parser.OptionExists(
"firstEvent") ) {
937 gOptFirstEvent = parser.ArgAsInt(
"firstEvent");
939 <<
"Starting flux readin at first event = " << gOptFirstEvent;
944 if( parser.OptionExists(
'm') ) {
946 <<
"Reading HNL decay mode";
947 mode = parser.ArgAsInt(
'm');
950 <<
"No decay mode specified - will sample from allowed decay modes";
957 <<
"Specified decay is not allowed kinematically for the given HNL mass";
968 #ifdef __CAN_USE_ROOT_GEOM__
970 if( parser.OptionExists(
'g') ) {
971 LOG(
"gevgen_hnl",
pDEBUG) <<
"Getting input geometry";
972 geom = parser.ArgAsString(
'g');
975 bool accessible_geom_file =
976 ! (gSystem->AccessPathName(geom.c_str()));
977 if (accessible_geom_file) {
982 <<
"Geometry option is not a ROOT file. Please use ROOT geom.";
997 if( parser.OptionExists(
'L') ) {
999 <<
"Checking for input geometry length units";
1000 lunits = parser.ArgAsString(
'L');
1002 LOG(
"gevgen_hnl",
pDEBUG) <<
"Using default geometry length units";
1018 #endif // #ifdef __CAN_USE_ROOT_GEOM__
1021 if( parser.OptionExists(
'o') ) {
1022 LOG(
"gevgen_hnl",
pDEBUG) <<
"Reading the event filename prefix";
1026 <<
"Will set the default event filename prefix";
1031 if( parser.OptionExists(
"seed") ) {
1032 LOG(
"gevgen_hnl",
pINFO) <<
"Reading random number seed";
1035 LOG(
"gevgen_hnl",
pINFO) <<
"Unspecified random number seed - Using default";
1043 ostringstream gminfo;
1045 gminfo <<
"Using ROOT geometry - file: " <<
gOptRootGeom
1048 <<
", length units: " <<
lunits;
1061 <<
"\n @@ Geometry : " << gminfo.str()
1062 <<
"\n @@ Statistics : " <<
gOptNev <<
" events";
1069 <<
"\n gevgen_hnl [-h] "
1071 <<
"\n -n n_of_events"
1072 <<
"\n -f path/to/flux/files"
1073 <<
"\n [-E hnl_energy]"
1074 <<
"\n [--firstEvent first_event_for_dk2nu_readin]"
1075 <<
"\n [-m decay_mode]"
1076 <<
"\n [-g geometry (ROOT file)]"
1077 <<
"\n [-L length_units_at_geom]"
1078 <<
"\n [-o output_event_file_prefix]"
1079 <<
"\n [--seed random_number_seed]"
1080 <<
"\n [--message-thresholds xml_file]"
1081 <<
"\n [--event-record-print-level level]"
1082 <<
"\n [--mc-job-status-refresh-rate rate]"
1084 <<
" Please also read the detailed documentation at http://www.genie-mc.org"
1085 <<
" or look at the source code: $GENIE/src/Apps/gBeamHNLEvGen.cxx"
TLorentzVector parp4
parent momentum at HNL production in NEAR coords [GeV/c]
bool IsHNLMajorana() const
void RandGen(long int seed)
static void SetPrintLevel(int print_level)
HNLDecayMode_t gOptDecayMode
TLorentzVector GeneratePosition(GHepRecord *event)
virtual void SetWeight(double wght)
double Ecm
Parent rest-frame energy of HNL [GeV].
Heavy Neutral Lepton final-state product generator.
double zetaMinus
minimum angular deviation from parent momentum to reach detector [deg]
Heavy Neutral Lepton decay vertex generator given production vertex and momentum ***.
void SetProbeP4(const TLorentzVector &P4)
double nuEcm
Parent rest-frame energy of equivalent SM neutrino [GeV].
double delay
delay HNL would have wrt SMv [ns]
static RandomGen * Instance()
Access instance.
void ProcessEventRecord(GHepRecord *event_rec) const
string AsString(genie::hnl::HNLDecayMode_t hnldm)
Defines the EventRecordVisitorI interface. Concrete implementations of this interface use the 'Visito...
void ReadFromCommandLine(int argc, char **argv)
TVector3 startPoint
parent decay vertex in NEAR coords [m]
int lepPdg
PDG code of lepton produced with HNL on parent decay.
int GetNFluxEntries() const
TVector3 polz
HNL polarisation vector, in HNL rest frame, in NEAR coords.
int parPdg
parent PDG code
A GENIE flux container specific for HNL containers. Based on the dk2nu flux paradigm and genie::flux:...
string P4AsString(const TLorentzVector *p)
void Update(int iev, const EventRecord *event)
double zetaPlus
maximum angular deviation from parent momentum to reach detector [deg]
Algorithm abstract base class.
TVector3 startPointUser
parent decay vertex in USER coords [m]
A singleton holding random number generator classes. All random number generation in GENIE should tak...
TLorentzVector parp4User
parent momentum at HNL production in USER coords [GeV/c]
int main(int argc, char **argv)
std::map< genie::hnl::HNLDecayMode_t, double > SetInterestingChannels(std::vector< genie::hnl::HNLDecayMode_t > intChannels, std::map< genie::hnl::HNLDecayMode_t, double > gammaMap)
double GetHNLMass() const
void SetRefreshRate(int rate)
string kDefOptEvFilePrefix
Summary information for an interaction.
Simple class to create & update MC job status files and env. vars. This is used to be able to keep tr...
Calculates HNL production kinematics & production vertex. Is a concrete implementation of the FluxRec...
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
TLorentzVector p4
HNL momentum in NEAR coords [GeV/c].
TLorentzVector p4User
HNL momentum in USER coords [GeV/c].
string gOptRootGeomTopVol
void ProcessEventRecord(GHepRecord *event_rec) const
double GetHNLLifetime() const
double UnitFromString(string u)
int prodChan
Decay mode that produced HNL.
const Algorithm * GetAlgorithm(const AlgId &algid)
std::map< genie::hnl::HNLDecayMode_t, double > GetValidChannels()
enum genie::hnl::EHNLDecayMode HNLDecayMode_t
map< string, string > gOptFluxShortNames
void Save(void)
get the even tree
FluxContainer RetrieveFluxInfo() const
void SetInterestingChannels(const std::map< genie::hnl::HNLDecayMode_t, double > gammaMap)
TRandom3 & RndGeom(void) const
rnd number generator used by geometry drivers
double acceptance
full acceptance == XYWgt * boostCorr^2 * accCorr
void AddEventRecord(int ievent, const EventRecord *ev_rec)
save the event tree
TVector3 targetPointUser
point in detector HNL is forced towards in USER coords [m]
TVector3 targetPoint
point in detector HNL is forced towards in NEAR coords [m]
double nimpwt
Weight of parent.
std::string GetHNLInterestingChannels() const
Generated Event Record. It is a GHepRecord object that can accept / be visited by EventRecordVisitorI...
double accCorr
acceptance correction (collimation effect. SM v == 1)
void CustomizeFilenamePrefix(string prefix)
void Initialize(void)
add event
string kDefOptFluxFilePath
static RunOpt * Instance(void)
static AlgFactory * Instance()
A utility class to facilitate creating the GENIE MC Ntuple from the output GENIE GHEP event records...
int nuPdg
PDG code of SM neutrino that would have been produced.
static __attribute__((unused)) double fDecayGammas[]
double XYWgt
geometric acceptance (angular size of detector in parent rest frame)
std::map< genie::hnl::HNLDecayMode_t, double > GetProbabilities(std::map< genie::hnl::HNLDecayMode_t, double > gammaMap)
TRandom3 & RndGen(void) const
rnd number generator for generic usage
void SetFirstFluxEntry(int iFirst) const
std::vector< double > GetHNLCouplings() const
int nuProdChan
Decay mode that would have produced SM neutrino.
NtpMCFormat_t kDefOptNtpFormat
InitialState * InitStatePtr(void) const
string PrintFramedMesg(string mesg, unsigned int nl=1, const char f='*')
int SelectDecayMode(std::vector< HNLDecayMode_t > *intChannels, SimpleHNL sh)
void SetProbePdg(int pdg_code)
void MesgThresholds(string inpfile)
const EventRecordVisitorI * HNLGenerator(void)
Command line argument parser.
enum genie::ENtpMCFormat NtpMCFormat_t
genie::hnl::HNLDecayMode_t SelectChannelInclusive(std::map< genie::hnl::HNLDecayMode_t, double > Pmap, double ranThrow)
double boostCorr
boost correction wrt parent rest-frame (ELAB = ECM * boostCorr)
void GetCommandLineArgs(int argc, char **argv)
The GENIE Algorithm Factory.
void ProcessEventRecord(GHepRecord *event) const
void SetGeomFile(std::string geomfile) const
GENIE's GHEP MC event record.
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
STDHEP-like event record entry that can fit a particle or a nucleus.
bool IsKinematicallyAllowed(genie::hnl::HNLDecayMode_t hnldm, double Mhnl)
std::vector< HNLDecayMode_t > gOptIntChannels
void SetInputFluxPath(std::string finpath) const
void SetGeomFile(string geomfile) const
static Interaction * HNL(int probe, double E=0, int decayed_mode=-1)