Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
trento.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file trento.cxx
1 // TRENTO: Reduced Thickness Event-by-event Nuclear Topology
2 // Copyright 2015 Jonah E. Bernhard, J. Scott Moreland
3 // TRENTO3D: Three-dimensional extension of TRENTO by Weiyao Ke
4 // MIT License
5 
6 #include <iostream>
7 #include <stdexcept>
8 #include <string>
9 #include <vector>
10 #include <climits>
11 
12 #include <boost/filesystem.hpp>
13 #include <boost/filesystem/fstream.hpp>
14 #include <boost/program_options.hpp>
15 
16 #include "collider.h"
17 #include "fwd_decl.h"
18 
19 // CMake sets this definition.
20 // Fall back to a sane default.
21 #ifndef TRENTO_VERSION_STRING
22 #define TRENTO_VERSION_STRING "dev"
23 #endif
24 
25 namespace trento {
26 
27 namespace {
28 
29 void print_version() {
30  std::cout << "trento " << TRENTO_VERSION_STRING << '\n';
31 }
32 
33 void print_bibtex() {
34  std::cout <<
35  "TRENTO:\n"
36  "@article{Moreland:2014oya,\n"
37  " author = \"Moreland, J. Scott and Bernhard, Jonah E. and Bass,\n"
38  " Steffen A.\",\n"
39  " title = \"{Alternative ansatz to wounded nucleon and binary\n"
40  " collision scaling in high-energy nuclear collisions}\",\n"
41  " journal = \"Phys.Rev.\",\n"
42  " number = \"1\",\n"
43  " volume = \"C92\",\n"
44  " pages = \"011901\",\n"
45  " doi = \"10.1103/PhysRevC.92.011901\",\n"
46  " year = \"2015\",\n"
47  " eprint = \"1412.4708\",\n"
48  " archivePrefix = \"arXiv\",\n"
49  " primaryClass = \"nucl-th\",\n"
50  " SLACcitation = \"%%CITATION = ARXIV:1412.4708;%%\",\n"
51  "}\n\n";
52 
53  std::cout <<
54  "TRENTO3D:\n"
55  "@article{Ke:2016jrd,\n"
56  " author = \"Ke, Weiyao and Moreland, J. Scott and Bernhard, \n"
57  " Jonah E. and Bass, Steffen A.\",\n"
58  " title = \"{Constraints on rapidity-dependent initial conditions\n"
59  " from charged particle pseudorapidity densities and\n"
60  " two-particle correlations}\",\n"
61  " journal = \"Phys. Rev.\",\n"
62  " volume = \"C96\",\n"
63  " year = \"2017\",\n"
64  " number = \"4\",\n"
65  " pages = \"044912\",\n"
66  " doi = \"10.1103/PhysRevC.96.044912\",\n"
67  " eprint = \"1610.08490\",\n"
68  " archivePrefix = \"arXiv\",\n"
69  " primaryClass = \"nucl-th\",\n"
70  " SLACcitation = \"%%CITATION = ARXIV:1610.08490;%%\"\n";
71 }
72 
73 // TODO
74 // void print_default_config() {
75 // std::cout << "to do\n";
76 // }
77 
78 } // unnamed namespace
79 
80 } // namespace trento
81 
82 int main(int argc, char* argv[]) {
83  using namespace trento;
84 
85  // Parse options with boost::program_options.
86  // There are quite a few options, so let's separate them into logical groups.
87  using OptDesc = po::options_description;
88 
89  using VecStr = std::vector<std::string>;
90  OptDesc main_opts{};
91  main_opts.add_options()
92  ("projectile", po::value<VecStr>()->required()->
93  notifier( // use a lambda to verify there are exactly two projectiles
94  [](const VecStr& projectiles) {
95  if (projectiles.size() != 2)
96  throw po::required_option{"projectile"};
97  }),
98  "projectile symbols")
99  ("number-events", po::value<int>()->default_value(1),
100  "number of events");
101 
102  // Make all main arguments positional.
103  po::positional_options_description positional_opts{};
104  positional_opts
105  .add("projectile", 2)
106  .add("number-events", 1);
107 
108  using VecPath = std::vector<fs::path>;
109  OptDesc general_opts{"general options"};
110  general_opts.add_options()
111  ("help,h", "show this help message and exit")
112  ("version", "print version information and exit")
113  ("bibtex", "print bibtex entry and exit")
114  // ("default-config", "print a config file with default settings and exit")
115  ("config-file,c", po::value<VecPath>()->value_name("FILE"),
116  "configuration file\n(can be passed multiple times)");
117 
118  OptDesc output_opts{"output options"};
119  output_opts.add_options()
120  ("quiet,q", po::bool_switch(),
121  "do not print event properties to stdout")
122  ("output,o", po::value<fs::path>()->value_name("PATH"),
123  "HDF5 file or directory for text files")
124  ("no-header", po::bool_switch(),
125  "do not write headers to text files");
126 
127  OptDesc phys_opts{"physical options"};
128  phys_opts.add_options()
129  ("reduced-thickness,p",
130  po::value<double>()->value_name("FLOAT")->default_value(0., "0"),
131  "reduced thickness parameter")
132  ("fluctuation,k",
133  po::value<double>()->value_name("FLOAT")->default_value(1., "1"),
134  "gamma fluctuation shape parameter")
135  ("nucleon-width,w",
136  po::value<double>()->value_name("FLOAT")->default_value(.5, "0.5"),
137  "Gaussian nucleon width [fm]")
138  ("nucleon-min-dist,d",
139  po::value<double>()->value_name("FLOAT")->default_value(0., "0"),
140  "minimum nucleon-nucleon distance [fm]")
141  ("mean-coeff,m",
142  po::value<double>()->value_name("FLOAT")->default_value(1., "1."),
143  "rapidity mean coefficient")
144  ("std-coeff,s",
145  po::value<double>()->value_name("FLOAT")->default_value(3., "3."),
146  "rapidity std coefficient")
147  ("skew-coeff,t",
148  po::value<double>()->value_name("FLOAT")->default_value(0., "0."),
149  "rapidity skew coefficient")
150  ("skew-type,r",
151  po::value<int>()->value_name("INT")->default_value(1, "1"),
152  "rapidity skew type: 1: relative, 2: absolute, other: no skew")
153  ("jacobian,j",
154  po::value<double>()->value_name("FLOAT")->default_value(0.8, "0.8"),
155  "<pt>/<mt> used in Jacobian")
156  ("normalization,n",
157  po::value<double>()->value_name("FLOAT")->default_value(1., "1"),
158  "normalization factor");
159 
160  OptDesc coll_opts{"collision options"};
161  coll_opts.add_options()
162  ("beam-energy,e",
163  po::value<double>()->value_name("FLOAT")->default_value(2760, "2760"),
164  "collision beam energy sqrt(s) [GeV], initializes cross section")
165  ("cross-section,x",
166  po::value<double>()->value_name("FLOAT")->default_value(-1, "off"),
167  "manual inelastic nucleon-nucleon cross section sigma_NN [fm^2]")
168  ("b-min",
169  po::value<double>()->value_name("FLOAT")->default_value(0., "0"),
170  "minimum impact parameter [fm]")
171  ("b-max",
172  po::value<double>()->value_name("FLOAT")->default_value(-1., "auto"),
173  "maximum impact parameter [fm]")
174  ("npart-min",
175  po::value<int>()->value_name("INT")->default_value(0, "0"),
176  "minimum Npart cut")
177  ("npart-max",
178  po::value<int>()->value_name("INT")->default_value(
179  std::numeric_limits<int>::max(), "INT_MAX"), "maximum Npart cut")
180  ("s-min",
181  po::value<double>()->value_name("FLOAT")->default_value(0., "0"),
182  "minimum entropy cut")
183  ("s-max",
184  po::value<double>()->value_name("FLOAT")->default_value(
185  std::numeric_limits<double>::max(), "DOUBLE_MAX"), "maxmimum entropy cut")
186  ("random-seed",
187  po::value<int64_t>()->value_name("INT")->default_value(-1, "auto"),
188  "random seed")
189  ("ncoll,b", po::bool_switch(),
190  "calculate # of binary collision and binary collision density");
191 
192  OptDesc grid_opts{"grid options"};
193  grid_opts.add_options()
194  ("xy-max",
195  po::value<double>()->value_name("FLOAT")->default_value(10., "10.0"),
196  "xy max [fm]\n(transverse grid from -max to +max)")
197  ("xy-step",
198  po::value<double>()->value_name("FLOAT")->default_value(0.2, "0.2"),
199  "transverse step size [fm]")
200  ("eta-max",
201  po::value<double>()->value_name("FLOAT")->default_value(0.0, "0.0"),
202  "pseudorapidity max \n(eta grid from -max to +max)")
203  ("eta-step",
204  po::value<double>()->value_name("FLOAT")->default_value(0.5, "0.5"),
205  "pseudorapidity step size");
206 
207  // Make a meta-group containing all the option groups except the main
208  // positional options (don't want the auto-generated usage info for those).
209  OptDesc usage_opts{};
210  usage_opts
211  .add(general_opts)
212  .add(output_opts)
213  .add(phys_opts)
214  .add(coll_opts)
215  .add(grid_opts);
216 
217  // Now a meta-group containing _all_ options.
218  OptDesc all_opts{};
219  all_opts
220  .add(usage_opts)
221  .add(main_opts);
222 
223  // Will be used several times.
224  const std::string usage_str{
225  "usage: trento [options] projectile projectile [number-events = 1]\n"};
226  const std::string usage_str3d{
227  "To operate in 3D mode, make sure --eta-max is nonzero.\n"};
228 
229  try {
230  // Initialize a VarMap (boost::program_options::variables_map).
231  // It will contain all configuration values.
232  VarMap var_map{};
233 
234  // Parse command line options.
235  po::store(po::command_line_parser(argc, argv)
236  .options(all_opts).positional(positional_opts).run(), var_map);
237 
238  // Handle options that imply immediate exit.
239  // Must do this _before_ po::notify() since that can throw exceptions.
240  if (var_map.count("help")) {
241  std::cout
242  << usage_str << usage_str3d
243  << "\n"
244  "projectile = { p | d | Cu | Cu2 | Xe | Au | Au2 | Pb | U | U2 | U3 }\n"
245  << usage_opts
246  << "\n"
247  "see the online documentation for complete usage information\n";
248  return 0;
249  }
250  if (var_map.count("version")) {
251  print_version();
252  return 0;
253  }
254  if (var_map.count("bibtex")) {
255  print_bibtex();
256  return 0;
257  }
258  // if (var_map.count("default-config")) {
259  // print_default_config();
260  // return 0;
261  // }
262 
263  // Merge any config files.
264  if (var_map.count("config-file")) {
265  // Everything except general_opts.
266  OptDesc config_file_opts{};
267  config_file_opts
268  .add(main_opts)
269  .add(output_opts)
270  .add(phys_opts)
271  .add(grid_opts);
272 
273  for (const auto& path : var_map["config-file"].as<VecPath>()) {
274  if (!fs::exists(path)) {
275  throw po::error{
276  "configuration file '" + path.string() + "' not found"};
277  }
278  fs::ifstream ifs{path};
279  po::store(po::parse_config_file(ifs, config_file_opts), var_map);
280  }
281  }
282 
283  // Save all the final values into var_map.
284  // Exceptions may occur here.
285  po::notify(var_map);
286 
287  // Go!
288  Collider collider{var_map};
289  collider.run_events();
290  }
291  catch (const po::required_option&) {
292  // Handle this exception separately from others.
293  // This occurs e.g. when the program is excuted with no arguments.
294  std::cerr << usage_str << usage_str3d
295  << "run 'trento --help' for more information\n";
296  return 1;
297  }
298  catch (const std::exception& e) {
299  // For all other exceptions just output the error message.
300  std::cerr << e.what() << '\n';
301  return 1;
302  }
303 
304  return 0;
305 }