138 #if defined(HAVE_FENV_H) && defined(HAVE_FEENABLEEXCEPT)
145 #include <TVector3.h>
152 #include "Framework/Conventions/GBuild.h"
178 #ifdef __GENIE_FLUX_DRIVERS_ENABLED__
179 #ifdef __GENIE_GEOM_DRIVERS_ENABLED__
180 #define __CAN_GENERATE_EVENTS_USING_A_FLUX_OR_TGTMIX__
190 using std::ostringstream;
192 using namespace genie;
193 using namespace genie::controls;
194 using namespace genie::constants;
195 using namespace genie::units;
202 #ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX_OR_TGTMIX__
203 void GenerateEventsUsingFluxOrTgtMix();
205 GFluxI * FluxDriver (
void);
206 GFluxI * MonoEnergeticFluxDriver (
void);
207 GFluxI * TH1FluxDriver (
void);
235 int main(
int argc,
char ** argv)
249 #if defined(HAVE_FENV_H) && defined(HAVE_FEENABLEEXCEPT)
250 feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
257 #ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX_OR_TGTMIX__
258 GenerateEventsUsingFluxOrTgtMix();
261 <<
"\n To be able to generate dark matter events from a flux and/or a target mix"
262 <<
"\n you need to add the following config options at your GENIE installation:"
263 <<
"\n --enable-flux-drivers --enable-geom-drivers \n" ;
275 LOG(
"gmkspl",
pFATAL) <<
" No TuneId in RunOption";
297 double pd = TMath::Sqrt(Ed*Ed - Md*Md);
299 TLorentzVector dm_p4(0.,0.,pd,Ed);
307 <<
"Cross-section risks exceeding unitarity limit - Exiting";
339 <<
"\n ** Will generate " <<
gOptNevents <<
" events for \n"
340 << init_state <<
" at Ev = " << Ed <<
" GeV";
346 <<
" *** Generating event............ " << ievent;
353 <<
"Last attempt failed. Re-trying....";
358 <<
"Generated Event GHEP Record: " << *event;
361 ntpw.AddEventRecord(ievent, event);
362 mcjmonitor.Update(ievent,event);
372 #ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX_OR_TGTMIX__
374 void GenerateEventsUsingFluxOrTgtMix(
void)
377 GFluxI * flux_driver = FluxDriver();
414 LOG(
"gevgen_dm",
pNOTICE) <<
" *** Generating event............ " << ievent;
419 LOG(
"gevgen_dm",
pNOTICE) <<
"Generated Event GHEP Record: " << *event;
422 ntpw.AddEventRecord(ievent, event);
423 mcjmonitor.Update(ievent,event);
451 else flux_driver = TH1FluxDriver();
456 GFluxI * MonoEnergeticFluxDriver(
void)
466 GFluxI * TH1FluxDriver(
void)
473 int flux_entries = 100000;
481 bool input_is_text_file = ! gSystem->AccessPathName(
gOptFlux.c_str());
482 bool input_is_root_file =
gOptFlux.find(
".root") != string::npos &&
484 if(input_is_text_file) {
490 double estep = (emax-emin)/(n-1);
491 double ymax = -1, ry = -1, gy = -1,
e = -1;
492 for(
int i=0; i<n; i++) {
494 ymax = TMath::Max(ymax, input_flux->
Evaluate(
e));
499 spectrum =
new TH1D(
"spectrum",
"dark matter flux", 300, emin, emax);
500 spectrum->SetDirectory(0);
502 for(
int ientry=0; ientry<flux_entries; ientry++) {
508 LOG(
"gevgen_dm",
pFATAL) <<
"Couldn't generate a flux histogram";
511 e = emin + de * r->
RndGen().Rndm();
512 gy = ymax * r->
RndGen().Rndm();
515 if(accept) spectrum->Fill(
e);
520 else if(input_is_root_file) {
525 assert(fv.size()==2);
526 assert( !gSystem->AccessPathName(fv[0].c_str()) );
528 LOG(
"gevgen_dm",
pNOTICE) <<
"Getting input flux from root file: " << fv[0];
529 TFile * flux_file =
new TFile(fv[0].c_str(),
"read");
531 LOG(
"gevgen_dm",
pNOTICE) <<
"Flux name: " << fv[1];
532 TH1D * hst = (TH1D *)flux_file->Get(fv[1].c_str());
535 LOG(
"gevgen_dm",
pNOTICE) << hst->GetEntries();
538 spectrum = (TH1D*)hst->Clone();
539 spectrum->SetNameTitle(
"spectrum",
"dark_matter_flux");
540 spectrum->SetDirectory(0);
541 for(
int ibin = 1; ibin <= hst->GetNbinsX(); ibin++) {
542 if(hst->GetBinLowEdge(ibin) + hst->GetBinWidth(ibin) > emax ||
543 hst->GetBinLowEdge(ibin) < emin) {
544 spectrum->SetBinContent(ibin, 0);
547 bool force_binwidth =
false;
548 #if ROOT_VERSION_CODE <= ROOT_VERSION(9,99,99)
553 TAxis* xaxis = spectrum->GetXaxis();
554 if (xaxis->IsVariableBinSize()) force_binwidth =
true;
556 if ( force_binwidth ) {
557 for(
int ibin = 1; ibin <= spectrum->GetNbinsX(); ++ibin) {
558 double data = spectrum->GetBinContent(ibin);
559 double width = spectrum->GetBinWidth(ibin);
560 spectrum->SetBinContent(ibin,data*width);
565 LOG(
"gevgen_dm",
pNOTICE) << spectrum->GetEntries();
570 LOG(
"gevgen_dm",
pNOTICE) << spectrum->GetEntries();
576 TF1 * input_func =
new TF1(
"input_func",
gOptFlux.c_str(), emin, emax);
577 spectrum =
new TH1D(
"spectrum",
"dark matter flux", 300, emin, emax);
578 spectrum->SetDirectory(0);
579 spectrum->FillRandom(
"input_func", flux_entries);
584 TFile f(
"./input-flux.root",
"recreate");
588 TVector3 bdir (0,0,1);
589 TVector3 bspot(0,0,0);
605 LOG(
"gevgen_dm",
pINFO) <<
"Parsing command line arguments";
616 bool help = parser.OptionExists(
'h');
622 if ( ! parser.OptionExists(
"tune") ) {
623 LOG(
"gevgen_dm",
pFATAL) <<
"No Dark Matter tune selected, please select one ";
629 if( parser.OptionExists(
'n') ) {
630 LOG(
"gevgen_dm",
pINFO) <<
"Reading number of events to generate";
634 <<
"Unspecified number of events to generate - Using default";
639 if( parser.OptionExists(
'r') ) {
640 LOG(
"gevgen_dm",
pINFO) <<
"Reading MC run number";
643 LOG(
"gevgen_dm",
pINFO) <<
"Unspecified run number - Using default";
648 if( parser.OptionExists(
'o') ) {
649 LOG(
"gevgen_dm",
pINFO) <<
"Reading output file name";
661 bool using_flux =
false;
662 if( parser.OptionExists(
'f') ) {
663 LOG(
"gevgen_dm",
pINFO) <<
"Reading flux function";
668 if(parser.OptionExists(
's')) {
670 <<
"-s option no longer available. Please read the revised code documentation";
680 if( parser.OptionExists(
'e') ) {
681 LOG(
"gevgen_dm",
pINFO) <<
"Reading dark matter energy";
682 string dme = parser.ArgAsString(
'e');
685 if(dme.find(
",") != string::npos) {
688 assert(nurange.size() == 2);
689 double emin = atof(nurange[0].c_str());
690 double emax = atof(nurange[1].c_str());
691 assert(emax>emin && emin>=0);
693 gOptDMEnergyRange = emax-emin;
696 <<
"No flux was specified but an energy range was input!";
698 <<
"Events will be generated at fixed E = " <<
gOptDMEnergy <<
" GeV";
699 gOptDMEnergyRange = -1;
703 gOptDMEnergyRange = -1;
706 LOG(
"gevgen_dm",
pFATAL) <<
"Unspecified dark matter energy - Exiting";
712 if( parser.OptionExists(
'm') ) {
713 LOG(
"gevgen_dm",
pINFO) <<
"Reading dark matter mass";
716 LOG(
"gevgen_dm",
pFATAL) <<
"Unspecified dark matter mass - Exiting";
722 if( parser.OptionExists(
'g') ) {
723 LOG(
"gevgen_dm",
pINFO) <<
"Reading mediator coupling";
726 LOG(
"gevgen_dm",
pINFO) <<
"Unspecified mediator coupling - Using value from config file";
731 bool using_tgtmix =
false;
732 if( parser.OptionExists(
't') ) {
733 LOG(
"gevgen_dm",
pINFO) <<
"Reading target mix";
734 string stgtmix = parser.ArgAsString(
't');
737 if(tgtmix.size()==1) {
738 int pdg = atoi(tgtmix[0].c_str());
740 gOptTgtMix.insert(map<int, double>::value_type(pdg, wgt));
743 vector<string>::const_iterator tgtmix_iter = tgtmix.begin();
744 for( ; tgtmix_iter != tgtmix.end(); ++tgtmix_iter) {
745 string tgt_with_wgt = *tgtmix_iter;
746 string::size_type open_bracket = tgt_with_wgt.find(
"[");
747 string::size_type close_bracket = tgt_with_wgt.find(
"]");
748 string::size_type ibeg = 0;
749 string::size_type iend = open_bracket;
750 string::size_type jbeg = open_bracket+1;
751 string::size_type jend = close_bracket-1;
752 int pdg = atoi(tgt_with_wgt.substr(ibeg,iend).c_str());
753 double wgt = atof(tgt_with_wgt.substr(jbeg,jend).c_str());
755 <<
"Adding to target mix: pdg = " << pdg <<
", wgt = " << wgt;
756 gOptTgtMix.insert(map<int, double>::value_type(pdg, wgt));
761 LOG(
"gevgen_dm",
pFATAL) <<
"Unspecified target PDG code - Exiting";
767 if( parser.OptionExists(
'z') ) {
768 LOG(
"gevgen_dm",
pINFO) <<
"Reading mediator mass ratio";
771 LOG(
"gevgen_dm",
pINFO) <<
"Unspecified mediator mass ratio - Using default";
778 if( parser.OptionExists(
"seed") ) {
779 LOG(
"gevgen_dm",
pINFO) <<
"Reading random number seed";
782 LOG(
"gevgen_dm",
pINFO) <<
"Unspecified random number seed - Using default";
787 if( parser.OptionExists(
"cross-sections") ) {
788 LOG(
"gevgen_dm",
pINFO) <<
"Reading cross-section file";
791 LOG(
"gevgen_dm",
pINFO) <<
"Unspecified cross-section file";
808 <<
"Random number seed was not set, using default";
817 <<
"No input cross-section spline file";
823 if(gOptDMEnergyRange>0) {
825 <<
"Dark matter energy: ["
834 <<
"Target code (PDG) & weight fraction (in case of multiple targets): ";
837 map<int,double>::const_iterator iter;
839 int tgtpdgc = iter->first;
840 double wgt = iter->second;
842 <<
" >> " << tgtpdgc <<
" (weight fraction = " << wgt <<
")";
853 <<
"\n\n" <<
"Syntax:" <<
"\n"
854 <<
"\n gevgen_dm [-h]"
857 <<
"\n -e energy (or energy range) "
859 <<
"\n -t target_pdg "
860 <<
"\n [-g zp_coupling]"
861 <<
"\n [-z med_ratio]"
862 <<
"\n [-f flux_description]"
863 <<
"\n [-o outfile_name]"
865 <<
"\n [--seed random_number_seed]"
866 <<
"\n [--cross-sections xml_file]"
867 <<
"\n [--event-generator-list list_name]"
868 <<
"\n [--message-thresholds xml_file]"
869 <<
"\n [--unphysical-event-mask mask]"
870 <<
"\n [--event-record-print-level level]"
871 <<
"\n [--mc-job-status-refresh-rate rate]"
872 <<
"\n [--cache-file root_file]"
883 r->
Get(
"ZpCoupling", gzp);
884 double gzp4 = TMath::Power(gzp,4);
886 double Mzp2 = Mzp*Mzp;
888 double xsec_est = gzp4 / (4. *
kPi * Mzp2);
895 double pcm2 = M2 * (Ed2 - ml2) / (ml2 + M2 + 2.*M*Ed);
896 double xsec_lim =
kPi / pcm2;
897 bool unitary = xsec_lim > xsec_est;
900 <<
"Estimated a cross-section " << xsec_est/
cm2 <<
" cm^2";
902 <<
"Unitarity limit set to " << xsec_lim/
cm2 <<
" cm^2";
void RandGen(long int seed)
static void SetPrintLevel(int print_level)
void XSecTable(string inpfile, bool require_table)
void SetUnphysEventMask(const TBits &mask)
bool CheckUnitarityLimit(void)
void AddDarkMatter(double mass, double med_ratio)
static const double kNucleonMass
static RandomGen * Instance()
Access instance.
void SetEventGeneratorList(string listname)
void ReadFromCommandLine(int argc, char **argv)
A numeric analysis tool class for interpolating 1-D functions.
map< int, double > gOptTgtMix
double Evaluate(double x) const
A singleton holding random number generator classes. All random number generation in GENIE should tak...
Registry * CommonList(const string &file_id, const string &set_name) const
int main(int argc, char **argv)
void UseFluxDriver(GFluxI *flux)
Simple class to create & update MC job status files and env. vars. This is used to be able to keep tr...
A GENIE `MC Job Driver'. Can be used for setting up complicated event generation cases involving deta...
void Get(RgKey key, const RegistryItemI *&item) const
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
void SetEventGeneratorList(string listname)
static constexpr double cm2
void ForceSingleProbScale(void)
A generic GENIE flux driver. Generates a 'cylindrical' neutrino beam along the input direction...
A simple GENIE flux driver for monoenergetic neutrinos along the z direction. Can handle a mix of neu...
void Configure(bool calc_prob_scales=true)
GENIE Event Generation Driver. A minimalist user interface object for generating neutrino interaction...
void Lock(void)
locks the registry
void SetTransverseRadius(double Rt)
void SetNuDirection(const TVector3 &direction)
void BuildTune()
build tune and inform XSecSplineList
EventRecord * GenerateEvent(void)
void UnLock(void)
unlocks the registry (doesn't unlock items)
Generated Event Record. It is a GHepRecord object that can accept / be visited by EventRecordVisitorI...
static PDGLibrary * Instance(void)
static RunOpt * Instance(void)
vector< string > Split(string input, string delim)
A utility class to facilitate creating the GENIE MC Ntuple from the output GENIE GHEP event records...
A registry. Provides the container for algorithm configuration parameters.
bool gOptUsingFluxOrTgtMix
TRandom3 & RndGen(void) const
rnd number generator for generic usage
void Configure(int nu_pdgc, int Z, int A)
NtpMCFormat_t kDefOptNtpFormat
string PrintFramedMesg(string mesg, unsigned int nl=1, const char f='*')
A vector of EventGeneratorI objects.
void GenerateEventsAtFixedInitState(void)
void SetBeamSpot(const TVector3 &spot)
void MesgThresholds(string inpfile)
void AddEnergySpectrum(int nu_pdgc, TH1D *spectrum)
Command line argument parser.
enum genie::ENtpMCFormat NtpMCFormat_t
void GetCommandLineArgs(int argc, char **argv)
Defines the GENIE Geometry Analyzer Interface.
static const unsigned int kRjMaxIterations
void SetUnphysEventMask(const TBits &mask)
void Set(RgIMapPair entry)
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
void UseGeomAnalyzer(GeomAnalyzerI *geom)
void UseSplines(bool useLogE=true)
The PointGeomAnalyzer class is the simplest implementation of the GeomAnalyserI interface and defines...
void CacheFile(string inpfile)
void EnableBareXSecPreCalc(bool flag)
static AlgConfigPool * Instance()
Initial State information.
GENIE Interface for user-defined flux classes.
EventRecord * GenerateEvent(const TLorentzVector &nu4p)