GENIEGenerator
Loading...
Searching...
No Matches
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
27const 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
30const std::string ConfigParser::theNoneName = "none";
31#ifdef INCL_DEEXCITATION_SMM
32const std::string ConfigParser::theSMMName = "SMM";
33#endif
34#ifdef INCL_DEEXCITATION_GEMINIXX
35const std::string ConfigParser::theGEMINIXXName = "GEMINIXX";
36#endif
37#ifdef INCL_DEEXCITATION_ABLAXX
38const std::string ConfigParser::theABLAv3pName = "ABLAv3p";
39#endif
40#ifdef INCL_DEEXCITATION_ABLA07
41const std::string ConfigParser::theABLA07Name = "ABLA07";
42#endif
43
44const std::string ConfigParser::listSeparator = "\n \t";
45
46ConfigParser::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
217ConfigParser::~ConfigParser() {
218}
219
220G4INCL::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
886std::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
910std::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__
const double e