GENIEGenerator
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
INCLConfigParser.cxx
Go to the documentation of this file.
1 #include "Framework/Conventions/GBuild.h"
2 #ifdef __GENIE_INCL_ENABLED__
3 
4 /** \file ConfigParser.cxx
5  * \brief A class for parsing input and producing a INCL++ Config
6  * Copied from INC++ main
7  * see ConfigParser.h for more information
8  *
9  * \date 17th July 2014
10  * \author Davide Mancusi
11  */
12 
13 #ifdef HAS_BOOST_PROGRAM_OPTIONS
14 //#include "ConfigParser.hh" // this would be INCL copy of header
15 #include "INCLConfigParser.h" // GENIE copy
16 
17 #include "G4INCLLogger.hh"
18 #include "G4INCLParticleTable.hh"
19 #include "DatafilePaths.hh"
20 
21 #include <fstream>
22 #include <cstdlib>
23 #include <sstream>
24 #include <cerrno>
25 #include <cstdlib>
26 
27 const std::string ConfigParser::suggestHelpMsg = "You might want to run `INCLCascade --help' to get a help message.\n";
28 
29 // Define the names of the de-excitation models
30 const std::string ConfigParser::theNoneName = "none";
31 #ifdef INCL_DEEXCITATION_SMM
32 const std::string ConfigParser::theSMMName = "SMM";
33 #endif
34 #ifdef INCL_DEEXCITATION_GEMINIXX
35 const std::string ConfigParser::theGEMINIXXName = "GEMINIXX";
36 #endif
37 #ifdef INCL_DEEXCITATION_ABLAXX
38 const std::string ConfigParser::theABLAv3pName = "ABLAv3p";
39 #endif
40 #ifdef INCL_DEEXCITATION_ABLA07
41 const std::string ConfigParser::theABLA07Name = "ABLA07";
42 #endif
43 
44 const std::string ConfigParser::listSeparator = "\n \t";
45 
46 ConfigParser::ConfigParser() :
47  runOptDesc("Run options"),
48  hiddenOptDesc("Hidden options"),
49  genericOptDesc("Generic options"),
50  physicsOptDesc("Physics options"),
51  deExcitationModelList(
52  listSeparator + theNoneName
53 #ifdef INCL_DEEXCITATION_ABLA07
54  + listSeparator + theABLA07Name
55 #endif
56 #ifdef INCL_DEEXCITATION_ABLAXX
57  + listSeparator + theABLAv3pName
58 #endif
59 #ifdef INCL_DEEXCITATION_GEMINIXX
60  + listSeparator + theGEMINIXXName
61 #endif
62 #ifdef INCL_DEEXCITATION_SMM
63  + listSeparator + theSMMName
64 #endif
65  )
66 {
67  // Define the default de-excitation model, in decreasing order of priority
68  defaultDeExcitationModel = theNoneName;
69 #ifdef INCL_DEEXCITATION_SMM
70  defaultDeExcitationModel = theSMMName;
71 #endif
72 #ifdef INCL_DEEXCITATION_GEMINIXX
73  defaultDeExcitationModel = theGEMINIXXName;
74 #endif
75 #ifdef INCL_DEEXCITATION_ABLAXX
76  defaultDeExcitationModel = theABLAv3pName;
77 #endif
78 #ifdef INCL_DEEXCITATION_ABLA07
79  defaultDeExcitationModel = theABLA07Name;
80 #endif
81 
82  // Append " (default)" to the name of the default model
83  size_t defaultModelIndex = deExcitationModelList.find(defaultDeExcitationModel);
84  if(defaultModelIndex!=std::string::npos) {
85  deExcitationModelList = deExcitationModelList.substr(0, defaultModelIndex+defaultDeExcitationModel.size())
86  + " (default)"
87  + deExcitationModelList.substr(defaultModelIndex+defaultDeExcitationModel.size(), std::string::npos);
88  }
89 
90  // Hidden options
91  hiddenOptDesc.add_options()
92  ("input-file", po::value<std::string>(&config.inputFileName), "input file")
93  ("impact-parameter", po::value<double>(&config.impactParameter)->default_value(-1.), "impact parameter")
94  ("cascade-action", po::value<std::string>(&config.cascadeAction)->default_value("default"), "cascade action:\n \tdefault (default)\n \tavatar-dump")
95  ;
96 
97  // Generic options
98  std::stringstream verbosityDescription;
99  verbosityDescription << "set verbosity level:\n"
100  << " 0: \tquiet, suppress all output messages\n"
101  << " " << G4INCL::InfoMsg << ": \tminimal logging\n"
102  << " " << G4INCL::FatalMsg << ": \tlog fatal error messages as well\n"
103  << " " << G4INCL::ErrorMsg << ": \tlog error messages as well\n"
104  << " " << G4INCL::WarningMsg << ": \tlog warning messages as well\n"
105  << " " << G4INCL::DebugMsg << ": \tlog debug messages as well\n"
106  << " " << G4INCL::DataBlockMsg << ": \tlog data-block messages as well";
107 
108  genericOptDesc.add_options()
109  ("help,h", "produce this help message")
110  ("version", "print version string and exit")
111  ;
112 
113  // Run-specific options
114  std::stringstream randomSeedsDescription;
115  randomSeedsDescription << "comma-separated list of seeds for the random-number generator. Allowed seed range: "
116  << randomSeedMin << "-" << randomSeedMax << ".";
117 
118  runOptDesc.add_options()
119  ("title", po::value<std::string>(&config.title)->default_value("INCL default run title"), "run title")
120  ("output,o", po::value<std::string>(&config.outputFileRoot), "root for generating output file names. File-specific suffixes (.root, .out, etc.) will be appended to this root. Defaults to the input file name, if given; otherwise, defaults to a string composed of the explicitly specified options and of a customisable suffix, if provided using the -s option")
121  ("suffix,s", po::value<std::string>(&config.fileSuffix), "suffix to be appended to generated output file names")
122  ("logfile,l", po::value<std::string>(&config.logFileName), "log file name. Defaults to `<output_root>.log'. Use `-' if you want to redirect logging to stdout")
123  ("number-shots,N", po::value<int>(&config.nShots), "* number of shots")
124  ("target,t", po::value<std::string>(&config.targetString), "* target nuclide. Can be specified as Fe56, 56Fe, Fe-56, 56-Fe, Fe_56, 56_Fe or Fe. If the mass number is omitted, natural target composition is assumed.")
125  ("projectile,p", po::value<std::string>(&config.projectileString), "* projectile name:\n"
126  " \tproton, p\n"
127  " \tneutron, n\n"
128  " \tpi+, piplus, pion+, pionplus\n"
129  " \tpi0, pizero, pion0, pionzero\n"
130  " \tpi-, piminus, pion-, pionminus\n"
131  " \td, t, a, deuteron, triton, alpha\n"
132  " \tHe-4, He4, 4He (and so on)")
133  ("energy,E", po::value<double>(&config.projectileKineticEnergy), "* total kinetic energy of the projectile, in MeV")
134  ("verbose-event", po::value<int>(&config.verboseEvent)->default_value(-1), "request verbose logging for the specified event only")
135  ("random-number-generator", po::value<std::string>(&config.randomNumberGenerator)->default_value("Ranecu"), "Random number generator to use:\n \tRanecu (2 seeds, default)\n \tRanecu3 (3 seeds)")
136  ("random-seeds", po::value<std::string>(&config.randomSeeds)->default_value("666,777,1234"), randomSeedsDescription.str().c_str())
137  ("autosave-frequency", po::value<unsigned int>(&config.autosaveFrequency)->default_value(10000), "frequency between automatic saves of the output/log files")
138 #ifdef INCL_ROOT_USE
139  ("root-selection", po::value<std::string>(&config.rootSelectionString)->default_value(""), "ROOT selection for abridged output ROOT tree. For example: \"A==1 && Z==0 && theta<3\" selects only events where a neutron is scattered in the forward direction.")
140  ("concise-root-tree", po::value<bool>(&config.conciseROOTTree)->default_value(false), "whether INCL++ should output a concise ROOT event tree:\n \ttrue, 1\n \tfalse, 0 (default)")
141 #endif
142  ("inverse-kinematics", po::value<bool>(&config.inverseKinematics)->default_value(false), "whether INCL++ should output variables describing the reaction in inverse kinematics:\n \ttrue, 1\n \tfalse, 0 (default)")
143  ("inclxx-datafile-path", po::value<std::string>(&config.INCLXXDataFilePath)->default_value(defaultINCLXXDatafilePath),
144  "path to the INCL++ data files")
145 #ifdef INCL_DEEXCITATION_ABLA07
146  ("abla07-datafile-path", po::value<std::string>(&config.abla07DataFilePath)->default_value(defaultABLA07DatafilePath),
147  "path to the ABLA07 data files")
148 #endif
149 #ifdef INCL_DEEXCITATION_ABLAXX
150  ("ablav3p-cxx-datafile-path", po::value<std::string>(&config.ablav3pCxxDataFilePath)->default_value(defaultABLAXXDatafilePath),
151  "path to the ABLAv3p data files")
152 #endif
153 #ifdef INCL_DEEXCITATION_GEMINIXX
154  ("geminixx-datafile-path", po::value<std::string>(&config.geminixxDataFilePath)->default_value(defaultGEMINIXXDatafilePath),
155  "path to the GEMINI++ data files")
156 #endif
157  ("verbosity,v", po::value<int>(&config.verbosity)->default_value(4), verbosityDescription.str().c_str())
158  ;
159 
160  // Physics options
161  physicsOptDesc.add_options()
162  ("de-excitation,d", po::value<std::string>(&config.deExcitationString)->default_value(defaultDeExcitationModel.c_str()), ("which de-excitation model to use:" + deExcitationModelList).c_str())
163 #ifdef INCL_DEEXCITATION_FERMI_BREAKUP
164  ("max-mass-fermi-breakup", po::value<int>(&config.maxMassFermiBreakUp)->default_value(16), "Maximum remnant mass for Fermi break-up (0-16). Default: 16.")
165  ("max-charge-fermi-breakup", po::value<int>(&config.maxChargeFermiBreakUp)->default_value(8), "Maximum remnant mass for Fermi break-up (0-8). Default: 8.")
166 #endif
167  ("pauli", po::value<std::string>(&config.pauliString)->default_value("strict-statistical"), "Pauli-blocking algorithm:\n"
168  " \tstrict-statistical (default)\n"
169  " \tstrict\n"
170  " \tstatistical\n"
171  " \tglobal\n"
172  " \tnone")
173  ("cdpp", po::value<bool>(&config.CDPP)->default_value(true), "whether to apply CDPP after collisions:\n \ttrue, 1 (default)\n \tfalse, 0")
174  ("coulomb", po::value<std::string>(&config.coulombString)->default_value("non-relativistic"), "Coulomb-distortion algorithm:\n \tnon-relativistic (default)\n \tnone")
175  ("potential", po::value<std::string>(&config.potentialString)->default_value("isospin-energy"), "nucleon potential:\n \tisospin-energy-smooth\n \tisospin-energy (default)\n \tisospin\n \tconstant")
176  ("pion-potential", po::value<bool>(&config.pionPotential)->default_value("true"), "whether to use a pion potential:\n \ttrue, 1 (default)\n \tfalse, 0")
177  ("local-energy-BB", po::value<std::string>(&config.localEnergyBBString)->default_value("first-collision"), "local energy in baryon-baryon collisions:\n \talways\n \tfirst-collision (default)\n \tnever")
178  ("local-energy-pi", po::value<std::string>(&config.localEnergyPiString)->default_value("first-collision"), "local energy in pi-N collisions and in delta decays:\n \talways\n \tfirst-collision (default)\n \tnever")
179  ("cluster-algorithm", po::value<std::string>(&config.clusterAlgorithmString)->default_value("intercomparison"), "clustering algorithm for production of composites:\n \tintercomparison (default)\n \tnone")
180  ("cluster-max-mass", po::value<int>(&config.clusterMaxMass)->default_value(8), "maximum mass of produced composites:\n \tminimum 2\n \tmaximum 12")
181  ("back-to-spectator", po::value<bool>(&config.backToSpectator)->default_value("true"), "whether to use back-to-spectator:\n \ttrue, 1 (default)\n \tfalse, 0")
182  ("use-real-masses", po::value<bool>(&config.useRealMasses)->default_value("true"), "whether to use real masses for the outgoing particle energies:\n \ttrue, 1 (default)\n \tfalse, 0")
183  ("separation-energies", po::value<std::string>(&config.separationEnergyString)->default_value("INCL"), "how to assign the separation energies of the INCL nucleus:\n \tINCL (default)\n \treal\n \treal-light")
184  ("fermi-momentum", po::value<std::string>(&config.fermiMomentumString)->default_value("constant"), "how to assign the Fermi momentum of the INCL nucleus:\n \tconstant (default)\n \tconstant-light\n \tmass-dependent\n \t[a positive value]")
185  ("cutNN", po::value<double>(&config.cutNN)->default_value(1910.), "minimum CM energy for nucleon-nucleon collisions, in MeV. Default: 1910.")
186  ("rp-correlation", po::value<double>(&config.rpCorrelationCoefficient)->default_value(1.), "correlation coefficient for the r-p correlation. Default: 1 (full correlation).")
187  ("rp-correlation-p", po::value<double>(&config.rpCorrelationCoefficientProton)->default_value(1.), "correlation coefficient for the proton r-p correlation. Overrides the value specified using the rp-correlation option. Default: 1 (full correlation).")
188  ("rp-correlation-n", po::value<double>(&config.rpCorrelationCoefficientNeutron)->default_value(1.), "correlation coefficient for the neutron r-p correlation. Overrides the value specified using the rp-correlation option. Default: 1 (full correlation).")
189  ("neutron-skin", po::value<double>(&config.neutronSkin)->default_value(0.), "thickness of the neutron skin, in fm. Default: 0.")
190  ("neutron-halo", po::value<double>(&config.neutronHalo)->default_value(0.), "thickness of the neutron halo, in fm. Default: 0.")
191  ("refraction", po::value<bool>(&config.refraction)->default_value(false), "whether to use refraction when particles are transmitted. Default: false.")
192  ("cross-sections", po::value<std::string>(&config.crossSectionsString)->default_value("multipions"), "cross-section parametrizations:\n"
193  " \tmultipions (default)\n"
194  " \ttruncated-multipions\n"
195  " \tincl46")
196  ("max-number-multipions", po::value<int>(&config.maxNumberMultipions)->default_value(-1), "maximum number of pions that can be produced in multipion collisions. When specified with arg>0, it enforces cross-sections=truncated-multipions. Default: -1 (no limit).")
197  ("phase-space-generator", po::value<std::string>(&config.phaseSpaceGenerator)->default_value("raubold-lynch"), "algorithm to generate phase-space decays:\n \tRaubold-Lynch (default)\n \tKopylov")
198  ("hadronization-time", po::value<double>(&config.hadronizationTime)->default_value(0.), "Hadronization time, in fm/c. Particles emerging from collisions are forbidden to recollide within this time. Default: 0.")
199  ;
200 
201  // Select options allowed on the command line
202  cmdLineOptions.add(hiddenOptDesc).add(genericOptDesc).add(runOptDesc).add(physicsOptDesc);
203 
204  // Select options allowed in config files
205  configFileOptions.add(runOptDesc).add(physicsOptDesc);
206 
207  // Select visible options
208  visibleOptions.add(genericOptDesc).add(runOptDesc).add(physicsOptDesc);
209 
210  // Declare input-file as a positional option (if we just provide a file
211  // name on the command line, it should be interpreted as an input-file
212  // option).
213  p.add("input-file", 1);
214 
215 }
216 
217 ConfigParser::~ConfigParser() {
218 }
219 
220 G4INCL::Config *ConfigParser::parse(int argc, char *argv[]) {
221 
222  config.init();
223 
224  try {
225 
226  // Disable guessing of option names
227  const int cmdstyle =
228  po::command_line_style::default_style &
229  ~po::command_line_style::allow_guessing;
230  variablesMap.clear();
231 
232  // Result of the option processing
233  po::store(po::command_line_parser(argc, argv).
234  style(cmdstyle).
235  options(cmdLineOptions).positional(p).run(), variablesMap);
236  po::notify(variablesMap);
237 
238  // If an input file was specified, merge the options with the command-line
239  // options.
240  if(variablesMap.count("input-file")) {
241  std::ifstream inputFileStream(config.inputFileName.c_str());
242  if(!inputFileStream) {
243  std::cerr << "Cannot open input file: " << config.inputFileName << '\n';
244  return NULL;
245  } else {
246  // Merge options from the input file
247  po::parsed_options parsedOptions = po::parse_config_file(inputFileStream, configFileOptions, true);
248 
249  // Make sure that the unhandled options are all "*-datafile-path"
250  std::vector<std::string> unhandledOptions =
251  po::collect_unrecognized(parsedOptions.options, po::exclude_positional);
252  bool ignoreNext = false;
253  const std::string match = "-datafile-path";
254  for(std::vector<std::string>::const_iterator i=unhandledOptions.begin(), e=unhandledOptions.end(); i!=e; ++i) {
255  if(ignoreNext) {
256  ignoreNext=false;
257  continue;
258  }
259  if(i->rfind(match) == i->length()-match.length()) {
260  std::cout << "# Ignoring unrecognized option " << *i << '\n';
261  ignoreNext = true;
262  } else {
263  std::cerr << "Error: unrecognized option " << *i << '\n';
264  std::cerr << suggestHelpMsg;
265  return NULL;
266  }
267  }
268 
269  // Store the option values in the variablesMap
270  po::store(parsedOptions, variablesMap);
271  po::notify(variablesMap);
272  }
273  inputFileStream.close();
274  }
275 
276  // Process the options from the user-specific config file ~/.inclxxrc
277  std::string configFileName;
278  const char * const configFileVar = getenv("INCLXXRC");
279  if(configFileVar)
280  configFileName = configFileVar;
281  else {
282  const char * const homeDirectoryPointer = getenv("HOME");
283  if(homeDirectoryPointer) { // Check if we can find the home directory
284  std::string homeDirectory(homeDirectoryPointer);
285  configFileName = homeDirectory + "/.inclxxrc";
286  } else {
287  std::cerr << "Could not determine the user's home directory. "
288  << "Are you running Linux, Unix or BSD?"<< std::endl;
289  return NULL;
290  }
291  }
292 
293  std::ifstream configFileStream(configFileName.c_str());
294  if(configFileStream) {
295  std::cout << "# Reading config file " << configFileName << std::endl;
296 
297  // Merge options from the input file
298  po::parsed_options parsedOptions = po::parse_config_file(configFileStream, configFileOptions, true);
299  po::store(parsedOptions, variablesMap);
300 
301  // Make sure that the unhandled options are all "*-datafile-path"
302  std::vector<std::string> unhandledOptions =
303  po::collect_unrecognized(parsedOptions.options, po::exclude_positional);
304  bool ignoreNext = false;
305  const std::string match = "-datafile-path";
306  for(std::vector<std::string>::const_iterator i=unhandledOptions.begin(), e=unhandledOptions.end(); i!=e; ++i) {
307  if(ignoreNext) {
308  ignoreNext=false;
309  continue;
310  }
311  if(i->rfind(match) == i->length()-match.length()) {
312  std::cout << "Ignoring unrecognized option " << *i << std::endl;
313  ignoreNext = true;
314  } else {
315  std::cerr << "Error: unrecognized option " << *i << std::endl;
316  std::cerr << suggestHelpMsg;
317  return NULL;
318  }
319  }
320 
321  // Store the option values in the variablesMap
322  po::store(parsedOptions, variablesMap);
323  po::notify(variablesMap);
324  }
325  configFileStream.close();
326 
327 
328 
329  /* *******************
330  * Process the options
331  * *******************/
332 
333  // -h/--help: print the help message and exit successfully
334  if(variablesMap.count("help")) {
335  std::cout
336  << "Usage: INCLCascade [options] <input_file>" << std::endl
337  << std::endl << "Options marked with a * are compulsory, i.e. they must be provided either on\nthe command line or in the input file." << std::endl
338  << visibleOptions << std::endl;
339  return NULL;
340  }
341 
342  // --version: print the version string and exit successfully
343  if(variablesMap.count("version")) {
344  std::cout <<"INCL++ version " << config.getVersionString() << std::endl;
345  return NULL;
346  }
347 
348  // Check if the required options are present
349  std::string missingOption("");
350  if(!variablesMap.count("number-shots"))
351  missingOption = "number-shots";
352  else if(!variablesMap.count("target"))
353  missingOption = "target";
354  else if(!variablesMap.count("projectile"))
355  missingOption = "projectile";
356  else if(!variablesMap.count("energy"))
357  missingOption = "energy";
358  if(!missingOption.empty()) {
359  std::cerr << "Required option " << missingOption << " is missing." << std::endl;
360  std::cerr << suggestHelpMsg;
361  return NULL;
362  }
363 
364  // -p/--projectile: projectile species
365  config.projectileSpecies = G4INCL::ParticleSpecies(config.projectileString);
366  if(config.projectileSpecies.theType == G4INCL::UnknownParticle) {
367  std::cerr << "Error: unrecognized particle type " << config.projectileString << std::endl;
368  std::cerr << suggestHelpMsg;
369  return NULL;
370  }
371 
372  // -t/--target: target species
373  if(variablesMap.count("target")) {
374  config.targetSpecies = G4INCL::ParticleSpecies(config.targetString);
375  if(config.targetSpecies.theType!=G4INCL::Composite) {
376  std::cerr << "Unrecognized target. You specified: " << config.targetString << std::endl
377  << " The target nuclide must be specified in one of the following forms:" << std::endl
378  << " Fe56, 56Fe, Fe-56, 56-Fe, Fe_56, 56_Fe, Fe" << std::endl
379  << " You can also use IUPAC element names (such as Uuh)." << std::endl;
380  std::cerr << suggestHelpMsg;
381  return NULL;
382  }
383  if(config.targetSpecies.theA==0)
384  config.naturalTarget = true;
385  }
386 
387  // --pauli
388  if(variablesMap.count("pauli")) {
389  std::string pauliNorm = config.pauliString;
390  std::transform(pauliNorm.begin(), pauliNorm.end(), pauliNorm.begin(), ::tolower);
391  if(pauliNorm=="statistical")
392  config.pauliType = G4INCL::StatisticalPauli;
393  else if(pauliNorm=="strict")
394  config.pauliType = G4INCL::StrictPauli;
395  else if(pauliNorm=="strict-statistical")
396  config.pauliType = G4INCL::StrictStatisticalPauli;
397  else if(pauliNorm=="global")
398  config.pauliType = G4INCL::GlobalPauli;
399  else if(pauliNorm=="none")
400  config.pauliType = G4INCL::NoPauli;
401  else {
402  std::cerr << "Unrecognized Pauli-blocking algorithm. Must be one of:" << std::endl
403  << " strict-statistical (default)" << std::endl
404  << " strict" << std::endl
405  << " statistical" << std::endl
406  << " global" << std::endl
407  << " none" << std::endl;
408  std::cerr << suggestHelpMsg;
409  return NULL;
410  }
411  }
412 
413  // --coulomb
414  if(variablesMap.count("coulomb")) {
415  std::string coulombNorm = config.coulombString;
416  std::transform(coulombNorm.begin(), coulombNorm.end(), coulombNorm.begin(), ::tolower);
417  if(coulombNorm=="non-relativistic")
418  config.coulombType = G4INCL::NonRelativisticCoulomb;
419  else if(coulombNorm=="none")
420  config.coulombType = G4INCL::NoCoulomb;
421  else {
422  std::cerr << "Unrecognized Coulomb-distortion algorithm. Must be one of:" << std::endl
423  << " non-relativistic (default)" << std::endl
424  << " none" << std::endl;
425  std::cerr << suggestHelpMsg;
426  return NULL;
427  }
428  }
429 
430  // --potential
431  if(variablesMap.count("potential")) {
432  std::string potentialNorm = config.potentialString;
433  std::transform(potentialNorm.begin(), potentialNorm.end(), potentialNorm.begin(), ::tolower);
434  if(potentialNorm=="isospin-energy-smooth") {
435  config.potentialType = G4INCL::IsospinEnergySmoothPotential;
436  } else if(potentialNorm=="isospin-energy") {
437  config.potentialType = G4INCL::IsospinEnergyPotential;
438  } else if(potentialNorm=="isospin")
439  config.potentialType = G4INCL::IsospinPotential;
440  else if(potentialNorm=="constant")
441  config.potentialType = G4INCL::ConstantPotential;
442  else {
443  std::cerr << "Unrecognized potential type. Must be one of:" << std::endl
444  << " isospin-energy-smooth" << std::endl
445  << " isospin-energy (default)" << std::endl
446  << " isospin" << std::endl
447  << " constant" << std::endl;
448  std::cerr << suggestHelpMsg;
449  return NULL;
450  }
451  }
452 
453  // --local-energy-BB
454  if(variablesMap.count("local-energy-BB")) {
455  std::string localEnergyBBNorm = config.localEnergyBBString;
456  std::transform(localEnergyBBNorm.begin(), localEnergyBBNorm.end(), localEnergyBBNorm.begin(), ::tolower);
457  if(localEnergyBBNorm=="always") {
458  config.localEnergyBBType = G4INCL::AlwaysLocalEnergy;
459  } else if(localEnergyBBNorm=="first-collision")
460  config.localEnergyBBType = G4INCL::FirstCollisionLocalEnergy;
461  else if(localEnergyBBNorm=="never")
462  config.localEnergyBBType = G4INCL::NeverLocalEnergy;
463  else {
464  std::cerr << "Unrecognized local-energy-BB type. Must be one of:" << std::endl
465  << " always" << std::endl
466  << " first-collision (default)" << std::endl
467  << " never" << std::endl;
468  std::cerr << suggestHelpMsg;
469  return NULL;
470  }
471  }
472 
473  // --local-energy-pi
474  if(variablesMap.count("local-energy-pi")) {
475  std::string localEnergyPiNorm = config.localEnergyPiString;
476  std::transform(localEnergyPiNorm.begin(), localEnergyPiNorm.end(), localEnergyPiNorm.begin(), ::tolower);
477  if(localEnergyPiNorm=="always") {
478  config.localEnergyPiType = G4INCL::AlwaysLocalEnergy;
479  } else if(localEnergyPiNorm=="first-collision")
480  config.localEnergyPiType = G4INCL::FirstCollisionLocalEnergy;
481  else if(localEnergyPiNorm=="never")
482  config.localEnergyPiType = G4INCL::NeverLocalEnergy;
483  else {
484  std::cerr << "Unrecognized local-energy-pi type. Must be one of:" << std::endl
485  << " always" << std::endl
486  << " first-collision" << std::endl
487  << " never (default)" << std::endl;
488  std::cerr << suggestHelpMsg;
489  return NULL;
490  }
491  }
492 
493  // -d/--de-excitation
494  if(variablesMap.count("de-excitation")) {
495  std::string deExcitationNorm = config.deExcitationString;
496  std::transform(deExcitationNorm.begin(),
497  deExcitationNorm.end(),
498  deExcitationNorm.begin(), ::tolower);
499  if(deExcitationNorm=="none")
500  config.deExcitationType = G4INCL::DeExcitationNone;
501 #ifdef INCL_DEEXCITATION_ABLAXX
502  else if(deExcitationNorm=="ablav3p")
503  config.deExcitationType = G4INCL::DeExcitationABLAv3p;
504 #endif
505 #ifdef INCL_DEEXCITATION_ABLA07
506  else if(deExcitationNorm=="abla07")
507  config.deExcitationType = G4INCL::DeExcitationABLA07;
508 #endif
509 #ifdef INCL_DEEXCITATION_SMM
510  else if(deExcitationNorm=="smm")
511  config.deExcitationType = G4INCL::DeExcitationSMM;
512 #endif
513 #ifdef INCL_DEEXCITATION_GEMINIXX
514  else if(deExcitationNorm=="geminixx")
515  config.deExcitationType = G4INCL::DeExcitationGEMINIXX;
516 #endif
517  else {
518  std::cerr << "Unrecognized de-excitation model. "
519  << "Must be one of:" << std::endl
520  << deExcitationModelList << std::endl;
521  std::cerr << suggestHelpMsg;
522  return NULL;
523  }
524  }
525 
526 #ifdef INCL_DEEXCITATION_FERMI_BREAKUP
527  // --max-mass-fermi-breakup and --max-charge-fermi-breakup
528  if(variablesMap.count("max-mass-fermi-breakup")) {
529  if(config.maxMassFermiBreakUp<0 || config.maxMassFermiBreakUp>16) {
530  std::cerr << "The maximum mass for Fermi breakup must belong to the [0,16] interval. " << std::endl;
531  std::cerr << suggestHelpMsg;
532  return NULL;
533  }
534  }
535  if(variablesMap.count("max-charge-fermi-breakup")) {
536  if(config.maxChargeFermiBreakUp<0 || config.maxChargeFermiBreakUp>8) {
537  std::cerr << "The maximum charge for Fermi breakup must belong to the [0,8] interval. " << std::endl;
538  std::cerr << suggestHelpMsg;
539  return NULL;
540  }
541  }
542 #endif
543 
544  // --cluster-algorithm
545  if(variablesMap.count("cluster-algorithm")) {
546  std::string clusterAlgorithmNorm = config.clusterAlgorithmString;
547  std::transform(clusterAlgorithmNorm.begin(),
548  clusterAlgorithmNorm.end(),
549  clusterAlgorithmNorm.begin(), ::tolower);
550  if(clusterAlgorithmNorm=="none")
551  config.clusterAlgorithmType = G4INCL::NoClusterAlgorithm;
552  else if(clusterAlgorithmNorm=="intercomparison")
553  config.clusterAlgorithmType = G4INCL::IntercomparisonClusterAlgorithm;
554  else {
555  std::cerr << "Unrecognized cluster algorithm. "
556  << "Must be one of:" << std::endl
557  << " intercomparison (default)" << std::endl
558  << " none" << std::endl;
559  std::cerr << suggestHelpMsg;
560  return NULL;
561  }
562  }
563 
564  // --cluster-max-mass
565  if(variablesMap.count("cluster-max-mass") && config.clusterMaxMass < 2 && config.clusterMaxMass > 12) {
566  std::cerr << "Maximum cluster mass outside the allowed range. Must be between 2 and 12 (included)"
567  << std::endl
568  << suggestHelpMsg;
569  return NULL;
570  }
571 
572  // --separation-energies
573  if(variablesMap.count("separation-energies")) {
574  std::string separationEnergyNorm = config.separationEnergyString;
575  std::transform(separationEnergyNorm.begin(),
576  separationEnergyNorm.end(),
577  separationEnergyNorm.begin(), ::tolower);
578  if(separationEnergyNorm=="incl")
579  config.separationEnergyType = G4INCL::INCLSeparationEnergy;
580  else if(separationEnergyNorm=="real")
581  config.separationEnergyType = G4INCL::RealSeparationEnergy;
582  else if(separationEnergyNorm=="real-light")
583  config.separationEnergyType = G4INCL::RealForLightSeparationEnergy;
584  else {
585  std::cerr << "Unrecognized separation-energies option. "
586  << "Must be one of:" << std::endl
587  << " INCL (default)" << std::endl
588  << " real" << std::endl
589  << " real-light" << std::endl;
590  std::cerr << suggestHelpMsg;
591  return NULL;
592  }
593  } else {
594  config.separationEnergyType = G4INCL::INCLSeparationEnergy;
595  }
596 
597  // --fermi-momentum
598  if(variablesMap.count("fermi-momentum")) {
599  std::string fermiMomentumNorm = config.fermiMomentumString;
600  std::transform(fermiMomentumNorm.begin(),
601  fermiMomentumNorm.end(),
602  fermiMomentumNorm.begin(), ::tolower);
603  if(fermiMomentumNorm=="constant")
604  config.fermiMomentumType = G4INCL::ConstantFermiMomentum;
605  else if(fermiMomentumNorm=="constant-light")
606  config.fermiMomentumType = G4INCL::ConstantLightFermiMomentum;
607  else if(fermiMomentumNorm=="mass-dependent")
608  config.fermiMomentumType = G4INCL::MassDependentFermiMomentum;
609  else {
610  // Try to convert the option value to a float, and bomb out on failure
611  errno = 0;
612  char *tail;
613  config.fermiMomentum = strtod(fermiMomentumNorm.c_str(), &tail);
614  if(errno || *tail!='\0') {
615  std::cerr << "Unrecognized fermi-momentum option. "
616  << "Must be one of:" << std::endl
617  << " constant (default)" << std::endl
618  << " constant-light" << std::endl
619  << " mass-dependent" << std::endl
620  << " [a postiive value]" << std::endl;
621  std::cerr << suggestHelpMsg;
622  return NULL;
623  }
624  if(config.fermiMomentum<=0.) {
625  std::cerr << "Values passed to fermi-momentum must be positive." << std::endl;
626  std::cerr << suggestHelpMsg;
627  return NULL;
628  }
629  config.fermiMomentumType = G4INCL::ConstantFermiMomentum;
630  }
631  } else {
632  config.fermiMomentumType = G4INCL::ConstantFermiMomentum;
633  }
634 
635  // --rp-correlation / --rp-correlation-p / --rp-correlation-n
636  if(variablesMap.count("rp-correlation")) {
637  if(!variablesMap.count("rp-correlation-p") || variablesMap.find("rp-correlation-p")->second.defaulted())
638  config.rpCorrelationCoefficientProton = config.rpCorrelationCoefficient;
639  if(!variablesMap.count("rp-correlation-n") || variablesMap.find("rp-correlation-n")->second.defaulted())
640  config.rpCorrelationCoefficientNeutron = config.rpCorrelationCoefficient;
641  }
642 
643  // --cross-sections
644  if(variablesMap.count("cross-sections")) {
645  std::string crossSectionsNorm = config.crossSectionsString;
646  std::transform(crossSectionsNorm.begin(), crossSectionsNorm.end(), crossSectionsNorm.begin(), ::tolower);
647  if(crossSectionsNorm=="incl46")
648  config.crossSectionsType = G4INCL::INCL46CrossSections;
649  else if(crossSectionsNorm=="multipions")
650  config.crossSectionsType = G4INCL::MultiPionsCrossSections;
651  else if(crossSectionsNorm=="truncated-multipions")
652  config.crossSectionsType = G4INCL::TruncatedMultiPionsCrossSections;
653  else {
654  std::cerr << "Unrecognized cross section parametrization. Must be one of:" << std::endl
655  << " multipions (default)" << std::endl
656  << " truncated-multipions" << std::endl
657  << " incl46" << std::endl;
658  std::cerr << suggestHelpMsg;
659  return NULL;
660  }
661  }
662 
663  // --max-number-multipions
664  if(!variablesMap["max-number-multipions"].defaulted() && !variablesMap["cross-sections"].defaulted()) {
665  if(config.crossSectionsType!=G4INCL::TruncatedMultiPionsCrossSections) {
666  // enforce cross-sections=truncated-multipions
667  config.crossSectionsString = "truncated-multipions";
668  config.crossSectionsType = G4INCL::TruncatedMultiPionsCrossSections;
669  }
670  }
671 
672  // --phase-space-generator
673  if(variablesMap.count("phase-space-generator")) {
674  std::string phaseSpaceGeneratorNorm = config.phaseSpaceGenerator;
675  std::transform(phaseSpaceGeneratorNorm.begin(),
676  phaseSpaceGeneratorNorm.end(),
677  phaseSpaceGeneratorNorm.begin(), ::tolower);
678  if(phaseSpaceGeneratorNorm=="raubold-lynch")
679  config.phaseSpaceGeneratorType = G4INCL::RauboldLynchType;
680  else if(phaseSpaceGeneratorNorm=="kopylov")
681  config.phaseSpaceGeneratorType = G4INCL::KopylovType;
682  else {
683  std::cerr << "Unrecognized phase-space-generator option. "
684  << "Must be one of:" << std::endl
685  << " Raubold-Lynch (default)" << std::endl
686  << " Kopylov" << std::endl;
687  std::cerr << suggestHelpMsg;
688  return NULL;
689  }
690  } else {
691  config.phaseSpaceGeneratorType = G4INCL::RauboldLynchType;
692  }
693 
694  // --cascade-action
695  if(variablesMap.count("cascade-action")) {
696  std::string cascadeActionNorm = config.cascadeAction;
697  std::transform(cascadeActionNorm.begin(),
698  cascadeActionNorm.end(),
699  cascadeActionNorm.begin(), ::tolower);
700  if(cascadeActionNorm=="default")
701  config.cascadeActionType = G4INCL::DefaultActionType;
702  else if(cascadeActionNorm=="avatar-dump")
703  config.cascadeActionType = G4INCL::AvatarDumpActionType;
704  else {
705  std::cerr << "Unrecognized cascade-action option. "
706  << "Must be one of:" << std::endl
707  << " default (default)" << std::endl
708  << " avatar-dump" << std::endl;
709  std::cerr << suggestHelpMsg;
710  return NULL;
711  }
712  } else {
713  config.cascadeActionType = G4INCL::DefaultActionType;
714  }
715 
716  // -s/--suffix
717  if(!variablesMap.count("suffix")) {
718  // update the value in the variables_map
719  variablesMap.insert(std::make_pair("suffix", po::variable_value(boost::any(config.fileSuffix), false)));
720  }
721 
722  // --*-path: perform tilde expansion on the datafile paths
723  if(variablesMap.count("inclxx-datafile-path"))
724  config.INCLXXDataFilePath = G4INCL::String::expandPath(config.INCLXXDataFilePath);
725 #ifdef INCL_DEEXCITATION_ABLAXX
726  if(variablesMap.count("ablav3p-cxx-datafile-path"))
727  config.ablav3pCxxDataFilePath = G4INCL::String::expandPath(config.ablav3pCxxDataFilePath);
728 #endif
729 #ifdef INCL_DEEXCITATION_ABLA07
730  if(variablesMap.count("abla07-datafile-path"))
731  config.abla07DataFilePath = G4INCL::String::expandPath(config.abla07DataFilePath);
732 #endif
733 #ifdef INCL_DEEXCITATION_GEMINIXX
734  if(variablesMap.count("geminixx-datafile-path"))
735  config.geminixxDataFilePath = G4INCL::String::expandPath(config.geminixxDataFilePath);
736 #endif
737 
738  // --output: path expansion is applied
739  if(variablesMap.count("output")) {
740  config.outputFileRoot = G4INCL::String::expandPath(config.outputFileRoot);
741  } else {
742  // construct a reasonable output file root if not specified
743  std::stringstream outputFileRootStream;
744  // If an input file was specified, use its name as the output file root
745  if(variablesMap.count("input-file"))
746  outputFileRootStream << config.inputFileName << config.fileSuffix;
747  else {
748  outputFileRootStream.precision(0);
749  outputFileRootStream.setf(std::ios::fixed, std::ios::floatfield);
750  outputFileRootStream <<
751  G4INCL::ParticleTable::getShortName(config.projectileSpecies) << "_" <<
752  G4INCL::ParticleTable::getShortName(config.targetSpecies) << "_" <<
753  config.projectileKineticEnergy;
754  outputFileRootStream.precision(2);
755 
756  // Append suffixes to the output file root for each explicitly specified CLI option
757  typedef po::variables_map::const_iterator BPOVMIter;
758  for(BPOVMIter i=variablesMap.begin(), e=variablesMap.end(); i!=e; ++i) {
759  std::string const &name = i->first;
760  // Only process CLI options
761  if(name!="projectile"
762  && name!="target"
763  && name!="energy"
764  && name!="number-shots"
765  && name!="random-seeds"
766  && name!="random-number-generator"
767  && name!="verbosity"
768  && name!="verbose-event"
769  && name!="suffix"
770 #ifdef INCL_ROOT_USE
771  && name!="root-selection"
772  && name!="concise-root-tree"
773 #endif
774  && name!="inverse-kinematics"
775  && name!="inclxx-datafile-path"
776 #ifdef INCL_DEEXCITATION_ABLA07
777  && name!="abla07-datafile-path"
778 #endif
779 #ifdef INCL_DEEXCITATION_ABLAXX
780  && name!="ablav3p-cxx-datafile-path"
781 #endif
782 #ifdef INCL_DEEXCITATION_GEMINIXX
783  && name!="geminixx-datafile-path"
784 #endif
785  ) {
786  po::variable_value v = i->second;
787  if(!v.defaulted()) {
788  const std::type_info &type = v.value().type();
789  if(type==typeid(std::string))
790  outputFileRootStream << "_" << name << "=" << v.as<std::string>();
791  else if(type==typeid(float))
792  outputFileRootStream << "_" << name << "=" << v.as<float>();
793  else if(type==typeid(double))
794  outputFileRootStream << "_" << name << "=" << v.as<double>();
795  else if(type==typeid(int))
796  outputFileRootStream << "_" << name << "=" << v.as<int>();
797  else if(type==typeid(bool))
798  outputFileRootStream << "_" << name << "=" << v.as<bool>();
799  }
800  }
801  }
802 
803  outputFileRootStream << config.fileSuffix;
804  }
805 
806  // update the variable
807  config.outputFileRoot = outputFileRootStream.str();
808  // update the value in the variables_map
809  variablesMap.insert(std::make_pair("output", po::variable_value(boost::any(config.outputFileRoot), false)));
810  }
811 
812  // -l/--logfile
813  if(!variablesMap.count("logfile")) {
814  // update the variable
815  config.logFileName = config.outputFileRoot + ".log";
816  // update the value in the variables_map
817  variablesMap.insert(std::make_pair("logfile", po::variable_value(boost::any(config.logFileName), false)));
818  } else {
819  // perform path expansion
820  config.logFileName = G4INCL::String::expandPath(config.logFileName);
821  }
822 
823  // --random-number-generator
824  if(variablesMap.count("random-number-generator")) {
825  std::string randomNumberGeneratorNorm = config.randomNumberGenerator;
826  std::transform(randomNumberGeneratorNorm.begin(),
827  randomNumberGeneratorNorm.end(),
828  randomNumberGeneratorNorm.begin(), ::tolower);
829  if(randomNumberGeneratorNorm=="ranecu")
830  config.rngType = G4INCL::RanecuType;
831  else if(randomNumberGeneratorNorm=="ranecu3")
832  config.rngType = G4INCL::Ranecu3Type;
833  else {
834  std::cerr << "Unrecognized random-number-generator option. "
835  << "Must be one of:" << std::endl
836  << " Ranecu (2 seeds, default)" << std::endl
837  << " Ranecu3 (3 seeds)" << std::endl;
838  std::cerr << suggestHelpMsg;
839  return NULL;
840  }
841  } else {
842  config.rngType = G4INCL::RanecuType;
843  }
844 
845  // --random-seeds
846  if(variablesMap.count("random-seeds")) {
847  config.randomSeedVector.clear();
848 
849  std::vector<std::string> tokens = G4INCL::String::tokenize(config.randomSeeds, ", \t");
850  for(std::vector<std::string>::const_iterator i=tokens.begin(), e=tokens.end(); i!=e; ++i) {
851  if(!G4INCL::String::isInteger(*i)) {
852  std::cerr << "Invalid random seed, must be an integer. Parsed token: "
853  << *i << std::endl;
854  std::cerr << suggestHelpMsg;
855  return NULL;
856  }
857 
858  std::stringstream ss(*i);
859  int seed;
860  ss >> seed;
861 
862  if(seed<randomSeedMin || seed>randomSeedMax) {
863  std::cerr << "Invalid value for random-seed-1. "
864  << "Allowed range: [" << randomSeedMin << ", " << randomSeedMax << "]." << std::endl;
865  std::cerr << suggestHelpMsg;
866  return NULL;
867  }
868 
869  config.randomSeedVector.push_back(seed);
870  }
871  }
872 
873  }
874  catch(std::exception& e)
875  {
876  std::cerr << e.what() << "\n";
877  std::cerr << suggestHelpMsg;
878  return NULL;
879  }
880 
881  // Copy the config into a new object and return it
882  G4INCL::Config *aConfig = new G4INCL::Config(config);
883  return aConfig;
884 }
885 
886 std::string ConfigParser::echo(G4INCL::Config const * const aConfig) {
887  config = *aConfig;
888  std::stringstream ss;
889  ss << "###########################\n"
890  << "### Start of input echo ###\n"
891  << "###########################\n\n"
892  << "# You may re-use this snippet of the log file as an input file!\n"
893  << "# Options marked with a * are compulsory.\n"
894  << "\n### Run options\n" << echoOptionsDescription(runOptDesc)
895  << "\n### Physics options\n" << echoOptionsDescription(physicsOptDesc)
896  << "\n# the projectile nuclide was parsed as Z=" << config.projectileSpecies.theZ
897  << ", A=" << config.projectileSpecies.theA
898  << "\n# the target nuclide was parsed as Z=" << config.targetSpecies.theZ;
899  if(config.targetSpecies.theA>0)
900  ss << ", A=" << config.targetSpecies.theA;
901  else
902  ss << ", natural target";
903  ss << "\n\n#########################\n"
904  << "### End of input echo ###\n"
905  << "#########################" << std::endl;
906 
907  return ss.str();
908 }
909 
910 std::string ConfigParser::echoOptionsDescription(const po::options_description &aDesc) {
911  typedef std::vector< boost::shared_ptr< po::option_description > > OptVector;
912  typedef std::vector< boost::shared_ptr< po::option_description > >::const_iterator OptIter;
913 
914  std::stringstream ss;
915  ss << std::boolalpha;
916  OptVector const &anOptVect = aDesc.options();
917  for(OptIter opt=anOptVect.begin(), e=anOptVect.end(); opt!=e; ++opt) {
918  std::string optDescription = (*opt)->description();
919  G4INCL::String::wrap(optDescription);
920  G4INCL::String::replaceAll(optDescription, "\n", "\n# ");
921  ss << "\n# " << optDescription << '\n';
922  const std::string &name = (*opt)->long_name();
923  ss << name << " = ";
924  po::variable_value const &value = variablesMap.find(name)->second;
925  std::type_info const &type = value.value().type();
926  if(type == typeid(std::string)) {
927  const std::string s = value.as<std::string>();
928  if(s.empty())
929  ss << "\"\"";
930  else
931  ss << s;
932  } else if(type == typeid(int))
933  ss << value.as<int>();
934  else if(type == typeid(unsigned int))
935  ss << value.as<unsigned int>();
936  else if(type == typeid(float))
937  ss << value.as<float>();
938  else if(type == typeid(double))
939  ss << value.as<double>();
940  else if(type == typeid(bool))
941  ss << value.as<bool>();
942  ss << '\n';
943  }
944  return ss.str();
945 }
946 #endif
947 
948 #endif // __GENIE_INCL_ENABLED__
static constexpr double s
Definition: Units.h:95
const double e