GENIEGenerator
Loading...
Searching...
No Matches
gEvGenDM.cxx
Go to the documentation of this file.
1//____________________________________________________________________________
2/*!
3
4\program gevgen_dm
5
6\brief A simple 'generic' GENIE DM+A event generation driver (gevgen_dm).
7
8 It handles:
9 a) event generation for a fixed init state (DM+A) at fixed energy, or
10 b) event generation for simple fluxes (specified either via some
11 functional form, tabular text file or a ROOT histogram) and for
12 simple 'geometries' (a target mix with its corresponding weights)
13
14 See the GENIE manual for other apps handling experiment-specific
15 event generation cases using the outputs of detailed dark matter flux
16 simulations and realistic detector geometry descriptions.
17
18 Syntax :
19 gevgen_dm [-h]
20 [-r run#]
21 -n nev
22 -e energy (or energy range)
23 -m mass
24 -t target_pdg
25 [-g zp_coupling]
26 [-z med_ratio]
27 [-f flux_description]
28 [-o outfile_name]
29 [-w]
30 [--seed random_number_seed]
31 [--cross-sections xml_file]
32 [--event-generator-list list_name]
33 [--tune genie_tune]
34 [--message-thresholds xml_file]
35 [--unphysical-event-mask mask]
36 [--event-record-print-level level]
37 [--mc-job-status-refresh-rate rate]
38 [--cache-file root_file]
39
40 Options :
41 [] Denotes an optional argument.
42 -h
43 Prints-out help on using gevgen_dm and exits.
44 -n
45 Specifies the number of events to generate.
46 -r
47 Specifies the MC run number.
48 -e
49 Specifies the dark matter energy.
50 If what follows the -e option is a comma separated pair of values
51 it will be interpreted as an energy range for the flux specified
52 via the -f option (see below).
53 -m
54 Specifies the dark matter mass.
55 -t
56 Specifies the target PDG code (pdg format: 10LZZZAAAI) _or_ a target
57 mix (pdg codes with corresponding weights) typed as a comma-separated
58 list of pdg codes with the corresponding weight fractions in brackets,
59 eg code1[fraction1],code2[fraction2],...
60 For example, to use a target mix of 95% O16 and 5% H type:
61 `-t 1000080160[0.95],1000010010[0.05]'.
62 -z
63 Specifies the ratio of the mediator mass to dark matter mass.
64 Default: 0.5
65 -g
66 Specifies the Z' coupling constant
67 Default: Value in UserPhysicsOptions.xml
68 -f
69 Specifies the dark matter flux spectrum.
70 It can be any of:
71 -- A function:
72 eg ` -f x*x+4*exp(-x)'
73 -- A vector file:
74 The vector file should contain 2 columns corresponding to
75 energy,flux (see $GENIE/data/flux/ for few examples).
76 -- A 1-D ROOT histogram (TH1D):
77 The general syntax is `-f /full/path/file.root,object_name'
78 -o
79 Specifies the name of the output file events will be saved in.
80 -w
81 Forces generation of weighted events.
82 This option is relevant only if a dark matter flux is specified.
83 Note that 'weighted' refers to the selection of the primary
84 flux dark matter + target that were forced to interact. A weighting
85 scheme for the generated kinematics of individual processes can
86 still be in effect if enabled..
87 ** Only use that option if you understand what it means **
88 --seed
89 Random number seed.
90 --cross-sections
91 Name (incl. full path) of an XML file with pre-computed
92 cross-section values used for constructing splines.
93 --event-generator-list
94 List of event generators to load in event generation drivers.
95 [default: "Default"].
96 --tune
97 Specifies a GENIE comprehensive dark matter interaction model tune.
98 [default: "Default"].
99 --message-thresholds
100 Allows users to customize the message stream thresholds.
101 The thresholds are specified using an XML file.
102 See $GENIE/config/Messenger.xml for the XML schema.
103 --unphysical-event-mask
104 Allows users to specify a 16-bit mask to allow certain types of
105 unphysical events to be written in the output file.
106 [default: all unphysical events are rejected]
107 --event-record-print-level
108 Allows users to set the level of information shown when the event
109 record is printed in the screen. See GHepRecord::Print().
110 --mc-job-status-refresh-rate
111 Allows users to customize the refresh rate of the status file.
112 --cache-file
113 Allows users to specify a cache file so that the cache can be
114 re-used in subsequent MC jobs.
115
116 *** See the User Manual for more details and examples. ***
117
118\author Joshua Berger <jberger \at physics.wisc.edu>
119 University of Wisconsin-Madison
120 Costas Andreopoulos <c.andreopoulos \at cern.ch>
121 University of Liverpool
122
123\created September 1, 2017
124
125\cpright Copyright (c) 2003-2025, The GENIE Collaboration
126 For the full text of the license visit http://copyright.genie-mc.org
127
128*/
129//____________________________________________________________________________
130
131#include <cstdlib>
132#include <cassert>
133#include <sstream>
134#include <string>
135#include <vector>
136#include <map>
137
138#if defined(HAVE_FENV_H) && defined(HAVE_FEENABLEEXCEPT)
139#include <fenv.h> // for `feenableexcept`
140#endif
141
142#include <TFile.h>
143#include <TTree.h>
144#include <TSystem.h>
145#include <TVector3.h>
146#include <TH1.h>
147#include <TF1.h>
148
149
152#include "Framework/Conventions/GBuild.h"
177
178#ifdef __GENIE_FLUX_DRIVERS_ENABLED__
179#ifdef __GENIE_GEOM_DRIVERS_ENABLED__
180#define __CAN_GENERATE_EVENTS_USING_A_FLUX_OR_TGTMIX__
184#endif
185#endif
186
187using std::string;
188using std::vector;
189using std::map;
190using std::ostringstream;
191
192using namespace genie;
193using namespace genie::controls;
194using namespace genie::constants;
195using namespace genie::units;
196
197void GetCommandLineArgs (int argc, char ** argv);
198void Initialize (void);
199void PrintSyntax (void);
200bool CheckUnitarityLimit(void);
201
202#ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX_OR_TGTMIX__
203void GenerateEventsUsingFluxOrTgtMix();
204GeomAnalyzerI * GeomDriver (void);
205GFluxI * FluxDriver (void);
206GFluxI * MonoEnergeticFluxDriver (void);
207GFluxI * TH1FluxDriver (void);
208#endif
209
211
212//Default options (override them using the command line arguments):
213int kDefOptNevents = 0; // n-events to generate
215Long_t kDefOptRunNu = 0; // default run number
216
217//User-specified options:
218int gOptNevents; // n-events to generate
219double gOptDMEnergy; // dark matter E, or min dark matter energy in spectrum
220double gOptDMEnergyRange;// energy range in input spectrum
221double gOptDMMass; // dark matter mass
222double gOptZpCoupling; // mediator coupling
223map<int,double> gOptTgtMix; // target mix (each with its relative weight)
224double gOptMedRatio; // ratio of mediator to DM mass
225Long_t gOptRunNu; // run number
226string gOptFlux; //
229long int gOptRanSeed; // random number seed
230string gOptInpXSecFile; // cross-section splines
231string gOptOutFileName; // Optional outfile name
232string gOptStatFileName; // Status file name, set if gOptOutFileName was set.
233
234//____________________________________________________________________________
235int main(int argc, char ** argv)
236{
237 GetCommandLineArgs(argc,argv);
239 if (gOptZpCoupling > 0.) {
240 Registry * r = AlgConfigPool::Instance()->CommonList("Param", "BoostedDarkMatter");
241 r->UnLock();
242 r->Set("ZpCoupling", gOptZpCoupling);
243 r->Lock();
244 }
245 Initialize();
246
247
248 // throw on NaNs and Infs...
249#if defined(HAVE_FENV_H) && defined(HAVE_FEENABLEEXCEPT)
250 feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
251#endif
252 //
253 // Generate dark matter events
254 //
255
257#ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX_OR_TGTMIX__
258 GenerateEventsUsingFluxOrTgtMix();
259#else
260 LOG("gevgen_dm", pERROR)
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" ;
264#endif
265 } else {
267 }
268 return 0;
269}
270//____________________________________________________________________________
272{
273
274 if ( ! RunOpt::Instance()->Tune() ) {
275 LOG("gmkspl", pFATAL) << " No TuneId in RunOption";
276 exit(-1);
277 }
279
280 // Initialization of random number generators, cross-section table,
281 // messenger thresholds, cache file
282 utils::app_init::MesgThresholds(RunOpt::Instance()->MesgThresholdFiles());
286
287 // Set GHEP print level
288 GHepRecord::SetPrintLevel(RunOpt::Instance()->EventRecordPrintLevel());
289}
290//____________________________________________________________________________
292{
293 int dark_matter = kPdgDarkMatter;
294 int target = gOptTgtMix.begin()->first;
295 double Ed = gOptDMEnergy;
296 double Md = gOptDMMass;
297 double pd = TMath::Sqrt(Ed*Ed - Md*Md);
298 assert(pd>=0.);
299 TLorentzVector dm_p4(0.,0.,pd,Ed); // px,py,pz,E (GeV)
300
301 // Create init state
302 InitialState init_state(target, dark_matter);
303
304 bool unitary = CheckUnitarityLimit();
305 if (!unitary) {
306 LOG("gevgen_dm", pFATAL)
307 << "Cross-section risks exceeding unitarity limit - Exiting";
308 exit(1);
309 }
310
311
312 // Create/config event generation driver
313 GEVGDriver evg_driver;
315 evg_driver.SetUnphysEventMask(*RunOpt::Instance()->UnphysEventMask());
316 evg_driver.Configure(init_state);
317
318 // Initialize an Ntuple Writer
320
321 // If an output file name has been specified... use it
322 if (!gOptOutFileName.empty()){
324 }
325 ntpw.Initialize();
326
327
328 // Create an MC Job Monitor
329 GMCJMonitor mcjmonitor(gOptRunNu);
330 mcjmonitor.SetRefreshRate(RunOpt::Instance()->MCJobStatusRefreshRate());
331
332 // If a status file name has been given... use it
333 if (!gOptStatFileName.empty()){
335 }
336
337
338 LOG("gevgen_dm", pNOTICE)
339 << "\n ** Will generate " << gOptNevents << " events for \n"
340 << init_state << " at Ev = " << Ed << " GeV";
341
342 // Generate events / print the GHEP record / add it to the ntuple
343 int ievent = 0;
344 while (ievent < gOptNevents) {
345 LOG("gevgen_dm", pNOTICE)
346 << " *** Generating event............ " << ievent;
347
348 // generate a single event
349 EventRecord * event = evg_driver.GenerateEvent(dm_p4);
350
351 if(!event) {
352 LOG("gevgen_dm", pNOTICE)
353 << "Last attempt failed. Re-trying....";
354 continue;
355 }
356
357 LOG("gevgen_dm", pNOTICE)
358 << "Generated Event GHEP Record: " << *event;
359
360 // add event at the output ntuple, refresh the mc job monitor & clean up
361 ntpw.AddEventRecord(ievent, event);
362 mcjmonitor.Update(ievent,event);
363 ievent++;
364 delete event;
365 }
366
367 // Save the generated MC events
368 ntpw.Save();
369}
370//____________________________________________________________________________
371
372#ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX_OR_TGTMIX__
373//............................................................................
374void GenerateEventsUsingFluxOrTgtMix(void)
375{
376 // Get flux and geom drivers
377 GFluxI * flux_driver = FluxDriver();
378 GeomAnalyzerI * geom_driver = GeomDriver();
379
380 // Create the monte carlo job driver
381 GMCJDriver * mcj_driver = new GMCJDriver;
383 mcj_driver->SetUnphysEventMask(*RunOpt::Instance()->UnphysEventMask());
384 mcj_driver->UseFluxDriver(flux_driver);
385 mcj_driver->UseGeomAnalyzer(geom_driver);
386 mcj_driver->Configure();
387 mcj_driver->UseSplines();
388 if(!gOptWeighted)
389 mcj_driver->ForceSingleProbScale();
390
391 // Initialize an Ntuple Writer to save GHEP records into a TTree
393
394 // If an output file name has been specified... use it
395 if (!gOptOutFileName.empty()){
396 ntpw.CustomizeFilename(gOptOutFileName);
397 }
398 ntpw.Initialize();
399
400 // Create an MC Job Monitor
401 GMCJMonitor mcjmonitor(gOptRunNu);
402 mcjmonitor.SetRefreshRate(RunOpt::Instance()->MCJobStatusRefreshRate());
403
404 // If a status file name has been given... use it
405 if (!gOptStatFileName.empty()){
406 mcjmonitor.CustomizeFilename(gOptStatFileName);
407 }
408
409
410 // Generate events / print the GHEP record / add it to the ntuple
411 int ievent = 0;
412 while ( ievent < gOptNevents) {
413
414 LOG("gevgen_dm", pNOTICE) << " *** Generating event............ " << ievent;
415
416 // generate a single event for dark matter particles coming from the specified flux
417 EventRecord * event = mcj_driver->GenerateEvent();
418
419 LOG("gevgen_dm", pNOTICE) << "Generated Event GHEP Record: " << *event;
420
421 // add event at the output ntuple, refresh the mc job monitor & clean-up
422 ntpw.AddEventRecord(ievent, event);
423 mcjmonitor.Update(ievent,event);
424 ievent++;
425 delete event;
426 }
427
428 // Save the generated MC events
429 ntpw.Save();
430
431 delete flux_driver;
432 delete geom_driver;
433 delete mcj_driver;;
434}
435//____________________________________________________________________________
436GeomAnalyzerI * GeomDriver(void)
437{
438// create a trivial point geometry with the specified target or target mix
439
441 return geom_driver;
442}
443//____________________________________________________________________________
444GFluxI * FluxDriver(void)
445{
446// create & configure one of the generic flux drivers
447//
448 GFluxI * flux_driver = 0;
449
450 if(gOptDMEnergyRange<0) flux_driver = MonoEnergeticFluxDriver();
451 else flux_driver = TH1FluxDriver();
452
453 return flux_driver;
454}
455//____________________________________________________________________________
456GFluxI * MonoEnergeticFluxDriver(void)
457{
458//
459//
462 GFluxI * flux_driver = dynamic_cast<GFluxI *>(flux);
463 return flux_driver;
464}
465//____________________________________________________________________________
466GFluxI * TH1FluxDriver(void)
467{
468//
469//
471 TH1D * spectrum = 0;
472
473 int flux_entries = 100000;
474
475 double emin = gOptDMEnergy;
476 double emax = gOptDMEnergy+gOptDMEnergyRange;
477 double de = gOptDMEnergyRange;
478
479 // check whether the input flux is a file or a functional form
480 //
481 bool input_is_text_file = ! gSystem->AccessPathName(gOptFlux.c_str());
482 bool input_is_root_file = gOptFlux.find(".root") != string::npos &&
483 gOptFlux.find(",") != string::npos;
484 if(input_is_text_file) {
485 //
486 // ** generate the flux histogram from the x,y pairs in the input text file
487 //
488 Spline * input_flux = new Spline(gOptFlux.c_str());
489 int n = 100;
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++) {
493 e = emin + i*estep;
494 ymax = TMath::Max(ymax, input_flux->Evaluate(e));
495 }
496 ymax *= 1.3;
497
499 spectrum = new TH1D("spectrum","dark matter flux", 300, emin, emax);
500 spectrum->SetDirectory(0);
501
502 for(int ientry=0; ientry<flux_entries; ientry++) {
503 bool accept = false;
504 unsigned int iter=0;
505 while(!accept) {
506 iter++;
507 if(iter > kRjMaxIterations) {
508 LOG("gevgen_dm", pFATAL) << "Couldn't generate a flux histogram";
509 exit(1);
510 }
511 e = emin + de * r->RndGen().Rndm();
512 gy = ymax * r->RndGen().Rndm();
513 ry = input_flux->Evaluate(e);
514 accept = gy < ry;
515 if(accept) spectrum->Fill(e);
516 }
517 }
518 delete input_flux;
519 }
520 else if(input_is_root_file) {
521 //
522 // ** extract specified flux histogram from the input root file
523 //
524 vector<string> fv = utils::str::Split(gOptFlux,",");
525 assert(fv.size()==2);
526 assert( !gSystem->AccessPathName(fv[0].c_str()) );
527
528 LOG("gevgen_dm", pNOTICE) << "Getting input flux from root file: " << fv[0];
529 TFile * flux_file = new TFile(fv[0].c_str(),"read");
530
531 LOG("gevgen_dm", pNOTICE) << "Flux name: " << fv[1];
532 TH1D * hst = (TH1D *)flux_file->Get(fv[1].c_str());
533 assert(hst);
534
535 LOG("gevgen_dm", pNOTICE) << hst->GetEntries();
536
537 // Copy in the flux histogram from the root file and remove bins outside the emin,emax range
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);
545 }
546 }
547 bool force_binwidth = false;
548#if ROOT_VERSION_CODE <= ROOT_VERSION(9,99,99)
549 // GetRandom() sampling on variable bin width histograms does not
550 // correctly account for bin widths for all versions of ROOT prior
551 // to (currently forever). At some point this might change and
552 // the necessity of this code snippet will go away
553 TAxis* xaxis = spectrum->GetXaxis();
554 if (xaxis->IsVariableBinSize()) force_binwidth = true;
555#endif
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);
561 }
562 }
563
564
565 LOG("gevgen_dm", pNOTICE) << spectrum->GetEntries();
566
567 flux_file->Close();
568 delete flux_file;
569
570 LOG("gevgen_dm", pNOTICE) << spectrum->GetEntries();
571
572 } else {
573 //
574 // ** generate the flux histogram from the input functional form
575 //
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);
580 delete input_func;
581 }
582 // save input flux
583
584 TFile f("./input-flux.root","recreate");
585 spectrum->Write();
586 f.Close();
587
588 TVector3 bdir (0,0,1);
589 TVector3 bspot(0,0,0);
590
591 flux->SetNuDirection (bdir);
592 flux->SetBeamSpot (bspot);
593 flux->SetTransverseRadius (-1);
594 flux->AddEnergySpectrum (kPdgDarkMatter, spectrum);
595
596 GFluxI * flux_driver = dynamic_cast<GFluxI *>(flux);
597 return flux_driver;
598}
599//............................................................................
600#endif
601
602//____________________________________________________________________________
603void GetCommandLineArgs(int argc, char ** argv)
604{
605 LOG("gevgen_dm", pINFO) << "Parsing command line arguments";
606
607 // Common run options. Set defaults and read.
610
611 // Parse run options for this app
612
613 CmdLnArgParser parser(argc,argv);
614
615 // help?
616 bool help = parser.OptionExists('h');
617 if(help) {
618 PrintSyntax();
619 exit(0);
620 }
621
622 if ( ! parser.OptionExists("tune") ) {
623 LOG("gevgen_dm", pFATAL) << "No Dark Matter tune selected, please select one ";
624 LOG("gevgen_dm", pFATAL) << "Exiting ";
625 exit( 0 ) ;
626 }
627
628 // number of events
629 if( parser.OptionExists('n') ) {
630 LOG("gevgen_dm", pINFO) << "Reading number of events to generate";
631 gOptNevents = parser.ArgAsInt('n');
632 } else {
633 LOG("gevgen_dm", pINFO)
634 << "Unspecified number of events to generate - Using default";
636 }
637
638 // run number
639 if( parser.OptionExists('r') ) {
640 LOG("gevgen_dm", pINFO) << "Reading MC run number";
641 gOptRunNu = parser.ArgAsLong('r');
642 } else {
643 LOG("gevgen_dm", pINFO) << "Unspecified run number - Using default";
645 }
646
647 // Output file name
648 if( parser.OptionExists('o') ) {
649 LOG("gevgen_dm", pINFO) << "Reading output file name";
650 gOptOutFileName = parser.ArgAsString('o');
651
653 // strip the output file format and replace with .status
654 if (gOptOutFileName.find_last_of(".") != string::npos)
656 gOptStatFileName.substr(0, gOptOutFileName.find_last_of("."));
657 gOptStatFileName .append(".status");
658 }
659
660 // flux functional form
661 bool using_flux = false;
662 if( parser.OptionExists('f') ) {
663 LOG("gevgen_dm", pINFO) << "Reading flux function";
664 gOptFlux = parser.ArgAsString('f');
665 using_flux = true;
666 }
667
668 if(parser.OptionExists('s')) {
669 LOG("gevgen_dm", pWARN)
670 << "-s option no longer available. Please read the revised code documentation";
671 gAbortingInErr = true;
672 exit(1);
673 }
674
675
676 // generate weighted events option (only relevant if using a flux)
677 gOptWeighted = parser.OptionExists('w');
678
679 // dark matter energy
680 if( parser.OptionExists('e') ) {
681 LOG("gevgen_dm", pINFO) << "Reading dark matter energy";
682 string dme = parser.ArgAsString('e');
683
684 // is it just a value or a range (comma separated set of values)
685 if(dme.find(",") != string::npos) {
686 // split the comma separated list
687 vector<string> nurange = utils::str::Split(dme, ",");
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);
692 gOptDMEnergy = emin;
693 gOptDMEnergyRange = emax-emin;
694 if(!using_flux) {
695 LOG("gevgen_dm", pWARN)
696 << "No flux was specified but an energy range was input!";
697 LOG("gevgen_dm", pWARN)
698 << "Events will be generated at fixed E = " << gOptDMEnergy << " GeV";
700 }
701 } else {
702 gOptDMEnergy = atof(dme.c_str());
704 }
705 } else {
706 LOG("gevgen_dm", pFATAL) << "Unspecified dark matter energy - Exiting";
707 PrintSyntax();
708 exit(1);
709 }
710
711 // dark matter mass
712 if( parser.OptionExists('m') ) {
713 LOG("gevgen_dm", pINFO) << "Reading dark matter mass";
714 gOptDMMass = parser.ArgAsDouble('m');
715 } else {
716 LOG("gevgen_dm", pFATAL) << "Unspecified dark matter mass - Exiting";
717 PrintSyntax();
718 exit(1);
719 }
720
721 // mediator coupling
722 if( parser.OptionExists('g') ) {
723 LOG("gevgen_dm", pINFO) << "Reading mediator coupling";
724 gOptZpCoupling = parser.ArgAsDouble('g');
725 } else {
726 LOG("gevgen_dm", pINFO) << "Unspecified mediator coupling - Using value from config file";
727 gOptZpCoupling = -1.;
728 }
729
730 // target mix (their PDG codes with their corresponding weights)
731 bool using_tgtmix = false;
732 if( parser.OptionExists('t') ) {
733 LOG("gevgen_dm", pINFO) << "Reading target mix";
734 string stgtmix = parser.ArgAsString('t');
735 gOptTgtMix.clear();
736 vector<string> tgtmix = utils::str::Split(stgtmix,",");
737 if(tgtmix.size()==1) {
738 int pdg = atoi(tgtmix[0].c_str());
739 double wgt = 1.0;
740 gOptTgtMix.insert(map<int, double>::value_type(pdg, wgt));
741 } else {
742 using_tgtmix = true;
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());
754 LOG("Main", pNOTICE)
755 << "Adding to target mix: pdg = " << pdg << ", wgt = " << wgt;
756 gOptTgtMix.insert(map<int, double>::value_type(pdg, wgt));
757 }//tgtmix_iter
758 }//>1
759
760 } else {
761 LOG("gevgen_dm", pFATAL) << "Unspecified target PDG code - Exiting";
762 PrintSyntax();
763 exit(1);
764 }
765
766 // mediator mass ratio
767 if( parser.OptionExists('z') ) {
768 LOG("gevgen_dm", pINFO) << "Reading mediator mass ratio";
769 gOptMedRatio = parser.ArgAsDouble('z');
770 } else {
771 LOG("gevgen_dm", pINFO) << "Unspecified mediator mass ratio - Using default";
772 gOptMedRatio = 0.5;
773 }
774
775 gOptUsingFluxOrTgtMix = using_flux || using_tgtmix;
776
777 // random number seed
778 if( parser.OptionExists("seed") ) {
779 LOG("gevgen_dm", pINFO) << "Reading random number seed";
780 gOptRanSeed = parser.ArgAsLong("seed");
781 } else {
782 LOG("gevgen_dm", pINFO) << "Unspecified random number seed - Using default";
783 gOptRanSeed = -1;
784 }
785
786 // input cross-section file
787 if( parser.OptionExists("cross-sections") ) {
788 LOG("gevgen_dm", pINFO) << "Reading cross-section file";
789 gOptInpXSecFile = parser.ArgAsString("cross-sections");
790 } else {
791 LOG("gevgen_dm", pINFO) << "Unspecified cross-section file";
792 gOptInpXSecFile = "";
793 }
794
795 //
796 // print-out the command line options
797 //
798 LOG("gevgen_dm", pNOTICE)
799 << "\n"
800 << utils::print::PrintFramedMesg("gevgen_dm job configuration");
801 LOG("gevgen_dm", pNOTICE)
802 << "MC Run Number: " << gOptRunNu;
803 if(gOptRanSeed != -1) {
804 LOG("gevgen_dm", pNOTICE)
805 << "Random number seed: " << gOptRanSeed;
806 } else {
807 LOG("gevgen_dm", pNOTICE)
808 << "Random number seed was not set, using default";
809 }
810 LOG("gevgen_dm", pNOTICE)
811 << "Number of events requested: " << gOptNevents;
812 if(gOptInpXSecFile.size() > 0) {
813 LOG("gevgen_dm", pNOTICE)
814 << "Using cross-section splines read from: " << gOptInpXSecFile;
815 } else {
816 LOG("gevgen_dm", pNOTICE)
817 << "No input cross-section spline file";
818 }
819 LOG("gevgen_dm", pNOTICE)
820 << "Flux: " << gOptFlux;
821 LOG("gevgen_dm", pNOTICE)
822 << "Generate weighted events? " << gOptWeighted;
823 if(gOptDMEnergyRange>0) {
824 LOG("gevgen_dm", pNOTICE)
825 << "Dark matter energy: ["
826 << gOptDMEnergy << ", " << gOptDMEnergy+gOptDMEnergyRange << "]";
827 } else {
828 LOG("gevgen_dm", pNOTICE)
829 << "Dark matter energy: " << gOptDMEnergy;
830 }
831 LOG("gevgen_dm", pNOTICE)
832 << "Dark matter mass: " << gOptDMMass;
833 LOG("gevgen_dm", pNOTICE)
834 << "Target code (PDG) & weight fraction (in case of multiple targets): ";
835 LOG("gevgen_dm", pNOTICE)
836 << "Mediator mass ratio: " << gOptMedRatio;
837 map<int,double>::const_iterator iter;
838 for(iter = gOptTgtMix.begin(); iter != gOptTgtMix.end(); ++iter) {
839 int tgtpdgc = iter->first;
840 double wgt = iter->second;
841 LOG("gevgen_dm", pNOTICE)
842 << " >> " << tgtpdgc << " (weight fraction = " << wgt << ")";
843 }
844 LOG("gevgen_dm", pNOTICE) << "\n";
845
846 LOG("gevgen_dm", pNOTICE) << *RunOpt::Instance();
847
848}
849//____________________________________________________________________________
850void PrintSyntax(void)
851{
852 LOG("gevgen_dm", pNOTICE)
853 << "\n\n" << "Syntax:" << "\n"
854 << "\n gevgen_dm [-h]"
855 << "\n [-r run#]"
856 << "\n -n nev"
857 << "\n -e energy (or energy range) "
858 << "\n -m mass"
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]"
864 << "\n [-w]"
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]"
873 << "\n";
874}
875//____________________________________________________________________________
877{
878 // Before generating the events, perform a simple sanity check
879 // We estimate the leading divergent piece of the cross-section
880 // We make sure it does not exceed the unitarity limit
881 double gzp;
882 Registry * r = AlgConfigPool::Instance()->CommonList("Param", "BoostedDarkMatter");
883 r->Get("ZpCoupling", gzp);
884 double gzp4 = TMath::Power(gzp,4);
885 double Mzp = gOptMedRatio * gOptDMMass;
886 double Mzp2 = Mzp*Mzp;
887 // The leading, forward-dominated piece is the same for both DM models
888 double xsec_est = gzp4 / (4. * kPi * Mzp2);
889 double ml = gOptDMMass;
890 double ml2 = ml*ml;
891 double M = kNucleonMass;
892 double M2 = M*M;
893 double Ed = gOptDMEnergy;
894 double Ed2 = Ed*Ed;
895 double pcm2 = M2 * (Ed2 - ml2) / (ml2 + M2 + 2.*M*Ed);
896 double xsec_lim = kPi / pcm2;
897 bool unitary = xsec_lim > xsec_est;
898 if (!unitary) {
899 LOG("gevgen_dm", pWARN)
900 << "Estimated a cross-section " << xsec_est/cm2 << " cm^2";
901 LOG("gevgen_dm", pWARN)
902 << "Unitarity limit set to " << xsec_lim/cm2 << " cm^2";
903 }
904 return unitary;
905}
906//____________________________________________________________________________
#define pNOTICE
Definition Messenger.h:61
#define pINFO
Definition Messenger.h:62
#define pERROR
Definition Messenger.h:59
#define pFATAL
Definition Messenger.h:56
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE,...
Definition Messenger.h:96
#define pWARN
Definition Messenger.h:60
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils.
int main()
static AlgConfigPool * Instance()
Registry * CommonList(const string &file_id, const string &set_name) const
Command line argument parser.
string ArgAsString(char opt)
double ArgAsDouble(char opt)
bool OptionExists(char opt)
was option set?
A vector of EventGeneratorI objects.
Generated Event Record. It is a GHepRecord object that can accept / be visited by EventRecordVisitorI...
Definition EventRecord.h:37
GENIE Event Generation Driver. A minimalist user interface object for generating neutrino interaction...
Definition GEVGDriver.h:54
void SetUnphysEventMask(const TBits &mask)
void Configure(int nu_pdgc, int Z, int A)
EventRecord * GenerateEvent(const TLorentzVector &nu4p)
void SetEventGeneratorList(string listname)
GENIE Interface for user-defined flux classes.
Definition GFluxI.h:29
static void SetPrintLevel(int print_level)
A GENIE ‘MC Job Driver’. Can be used for setting up complicated event generation cases involving deta...
Definition GMCJDriver.h:46
void ForceSingleProbScale(void)
void UseFluxDriver(GFluxI *flux)
void UseGeomAnalyzer(GeomAnalyzerI *geom)
void Configure(bool calc_prob_scales=true)
void UseSplines(bool useLogE=true)
void SetUnphysEventMask(const TBits &mask)
void SetEventGeneratorList(string listname)
EventRecord * GenerateEvent(void)
Simple class to create & update MC job status files and env. vars. This is used to be able to keep tr...
Definition GMCJMonitor.h:31
void CustomizeFilename(string filename)
void Update(int iev, const EventRecord *event)
void SetRefreshRate(int rate)
Defines the GENIE Geometry Analyzer Interface.
Initial State information.
A utility class to facilitate creating the GENIE MC Ntuple from the output GENIE GHEP event records.
Definition NtpWriter.h:39
void CustomizeFilename(string filename)
void Initialize(void)
add event
Definition NtpWriter.cxx:83
void Save(void)
get the even tree
void AddEventRecord(int ievent, const EventRecord *ev_rec)
save the event tree
Definition NtpWriter.cxx:57
void AddDarkMatter(double mass, double med_ratio)
static PDGLibrary * Instance(void)
A singleton holding random number generator classes. All random number generation in GENIE should tak...
Definition RandomGen.h:29
static RandomGen * Instance()
Access instance.
Definition RandomGen.cxx:74
TRandom3 & RndGen(void) const
rnd number generator for generic usage
Definition RandomGen.h:80
A registry. Provides the container for algorithm configuration parameters.
Definition Registry.h:65
void Lock(void)
locks the registry
Definition Registry.cxx:148
void Set(RgIMapPair entry)
Definition Registry.cxx:267
void Get(RgKey key, const RegistryItemI *&item) const
Definition Registry.cxx:325
void UnLock(void)
unlocks the registry (doesn't unlock items)
Definition Registry.cxx:153
void ReadFromCommandLine(int argc, char **argv)
Definition RunOpt.cxx:99
void BuildTune()
build tune and inform XSecSplineList
Definition RunOpt.cxx:92
void EnableBareXSecPreCalc(bool flag)
Definition RunOpt.h:62
static RunOpt * Instance(void)
Definition RunOpt.cxx:54
A numeric analysis tool class for interpolating 1-D functions.
Definition Spline.h:58
double Evaluate(double x) const
Definition Spline.cxx:363
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...
The PointGeomAnalyzer class is the simplest implementation of the GeomAnalyserI interface and defines...
long int gOptRanSeed
NtpMCFormat_t kDefOptNtpFormat
Long_t gOptRunNu
map< int, double > gOptTgtMix
string gOptInpXSecFile
double gOptDMEnergy
Definition gEvGenDM.cxx:219
double gOptMedRatio
Definition gEvGenDM.cxx:224
double gOptZpCoupling
Definition gEvGenDM.cxx:222
void GenerateEventsAtFixedInitState(void)
Definition gEvGenDM.cxx:291
double gOptDMMass
Definition gEvGenDM.cxx:221
void Initialize(void)
Definition gEvGenDM.cxx:271
void GetCommandLineArgs(int argc, char **argv)
Definition gEvGenDM.cxx:603
void PrintSyntax(void)
Definition gEvGenDM.cxx:850
bool CheckUnitarityLimit(void)
Definition gEvGenDM.cxx:876
double gOptDMEnergyRange
Definition gEvGenDM.cxx:220
string gOptFlux
Definition gEvGen.cxx:234
bool gOptWeighted
Definition gEvGen.cxx:236
Long_t kDefOptRunNu
Definition gEvGen.cxx:225
bool gOptUsingFluxOrTgtMix
Definition gEvGen.cxx:238
string gOptOutFileName
Definition gEvGen.cxx:241
int kDefOptNevents
Definition gEvGen.cxx:223
int gOptNevents
Definition gEvGen.cxx:228
string gOptStatFileName
Definition gEvGen.cxx:242
const double e
Basic constants.
Misc GENIE control constants.
static const unsigned int kRjMaxIterations
Definition Controls.h:26
GENIE flux drivers.
Utilities for improving the code readability when using PDG codes.
Physical System of Units.
static constexpr double cm2
Definition Units.h:69
void XSecTable(string inpfile, bool require_table)
Definition AppInit.cxx:38
void RandGen(long int seed)
Definition AppInit.cxx:30
void MesgThresholds(string inpfile)
Definition AppInit.cxx:99
void CacheFile(string inpfile)
Definition AppInit.cxx:117
string PrintFramedMesg(string mesg, unsigned int nl=1, const char f=' *')
vector< string > Split(string input, string delim)
THE MAIN GENIE PROJECT NAMESPACE
Definition AlgCmp.h:25
const int kPdgDarkMatter
Definition PDGCodes.h:218
bool gAbortingInErr
Definition Messenger.cxx:34
@ kNFGHEP
Definition NtpMCFormat.h:30
enum genie::ENtpMCFormat NtpMCFormat_t