Version: SMASH-1.7
rootoutput.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2019
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/rootoutput.h"
11 #include "TFile.h"
12 #include "TTree.h"
13 #include "smash/action.h"
14 #include "smash/clock.h"
16 #include "smash/particles.h"
17 
18 namespace smash {
19 
86 RootOutput::RootOutput(const bf::path &path, const std::string &name,
87  const OutputParameters &out_par)
88  : OutputInterface(name),
89  filename_(path / (name + ".root")),
90  write_collisions_(name == "Collisions" || name == "Dileptons" ||
91  name == "Photons"),
92  write_particles_(name == "Particles"),
93  write_initial_conditions_(name == "SMASH_IC"),
94  particles_only_final_(out_par.part_only_final),
95  autosave_frequency_(1000),
96  part_extended_(out_par.part_extended),
97  coll_extended_(out_par.coll_extended),
98  ic_extended_(out_par.ic_extended) {
100  filename_unfinished_ += ".unfinished";
102  make_unique<TFile>(filename_unfinished_.native().c_str(), "NEW");
103  init_trees();
104 }
105 
108  particles_tree_ = new TTree("particles", "particles");
109 
110  particles_tree_->Branch("npart", &npart, "npart/I");
111  particles_tree_->Branch("impact_b", &impact_b, "impact_b/D");
112  particles_tree_->Branch("empty_event", &empty_event_, "empty_event/O");
113  particles_tree_->Branch("ev", &ev, "ev/I");
114  particles_tree_->Branch("tcounter", &tcounter, "tcounter/I");
115 
116  particles_tree_->Branch("pdgcode", &pdgcode[0], "pdgcode[npart]/I");
117  particles_tree_->Branch("charge", &charge[0], "charge[npart]/I");
118 
119  particles_tree_->Branch("p0", &p0[0], "p0[npart]/D");
120  particles_tree_->Branch("px", &px[0], "px[npart]/D");
121  particles_tree_->Branch("py", &py[0], "py[npart]/D");
122  particles_tree_->Branch("pz", &pz[0], "pz[npart]/D");
123 
124  particles_tree_->Branch("t", &t[0], "t[npart]/D");
125  particles_tree_->Branch("x", &x[0], "x[npart]/D");
126  particles_tree_->Branch("y", &y[0], "y[npart]/D");
127  particles_tree_->Branch("z", &z[0], "z[npart]/D");
128 
129  if (part_extended_ || ic_extended_) {
130  particles_tree_->Branch("coll_per_part", &coll_per_part_[0],
131  "coll_per_part[npart]/I");
132  particles_tree_->Branch("formation_time", &formation_time_[0],
133  "formation_time[npart]/D");
134  particles_tree_->Branch("xsec_factor", &xsec_factor_[0],
135  "xsec_factor[npart]/D");
136  particles_tree_->Branch("proc_id_origin", &proc_id_origin_[0],
137  "proc_id_origin[npart]/I");
138  particles_tree_->Branch("proc_type_origin", &proc_type_origin_[0],
139  "proc_type_origin[npart]/I");
140  particles_tree_->Branch("time_last_coll", &time_last_coll_[0],
141  "time_last_coll[npart]/D");
142  particles_tree_->Branch("pdg_mother1", &pdg_mother1_[0],
143  "pdg_mother1[npart]/I");
144  particles_tree_->Branch("pdg_mother2", &pdg_mother2_[0],
145  "pdg_mother2[npart]/I");
146  }
147  }
148 
149  if (write_collisions_) {
150  collisions_tree_ = new TTree("collisions", "collisions");
151 
152  collisions_tree_->Branch("nin", &nin, "nin/I");
153  collisions_tree_->Branch("nout", &nout, "nout/I");
154  collisions_tree_->Branch("npart", &npart, "npart/I");
155  collisions_tree_->Branch("ev", &ev, "ev/I");
156  collisions_tree_->Branch("weight", &wgt, "weight/D");
157  collisions_tree_->Branch("partial_weight", &par_wgt, "partial_weight/D");
158 
159  collisions_tree_->Branch("pdgcode", &pdgcode[0], "pdgcode[npart]/I");
160  collisions_tree_->Branch("charge", &charge[0], "charge[npart]/I");
161 
162  collisions_tree_->Branch("p0", &p0[0], "p0[npart]/D");
163  collisions_tree_->Branch("px", &px[0], "px[npart]/D");
164  collisions_tree_->Branch("py", &py[0], "py[npart]/D");
165  collisions_tree_->Branch("pz", &pz[0], "pz[npart]/D");
166 
167  collisions_tree_->Branch("t", &t[0], "t[npart]/D");
168  collisions_tree_->Branch("x", &x[0], "x[npart]/D");
169  collisions_tree_->Branch("y", &y[0], "y[npart]/D");
170  collisions_tree_->Branch("z", &z[0], "z[npart]/D");
171 
172  if (coll_extended_) {
173  collisions_tree_->Branch("coll_per_part", &coll_per_part_[0],
174  "coll_per_part[npart]/I");
175  collisions_tree_->Branch("formation_time", &formation_time_[0],
176  "formation_time[npart]/D");
177  collisions_tree_->Branch("xsec_factor", &xsec_factor_[0],
178  "xsec_factor[npart]/D");
179  collisions_tree_->Branch("proc_id_origin", &proc_id_origin_[0],
180  "proc_id_origin[npart]/I");
181  collisions_tree_->Branch("proc_type_origin", &proc_type_origin_[0],
182  "proc_type_origin[npart]/I");
183  collisions_tree_->Branch("time_last_coll", &time_last_coll_[0],
184  "time_last_coll[npart]/D");
185  collisions_tree_->Branch("pdg_mother1", &pdg_mother1_[0],
186  "pdg_mother1[npart]/I");
187  collisions_tree_->Branch("pdg_mother2", &pdg_mother2_[0],
188  "pdg_mother2[npart]/I");
189  }
190  }
191 }
192 
198  // kOverwrite option prevents from writing extra TKey objects into root file
199  root_out_file_->Write("", TObject::kOverwrite);
200  root_out_file_->Close();
201  bf::rename(filename_unfinished_, filename_);
202 }
203 
204 void RootOutput::at_eventstart(const Particles &particles,
205  const int event_number) {
206  // save event number
207  current_event_ = event_number;
208 
210  output_counter_ = 0;
211  // This is to have only one output of positive impact parameter per event
212  impact_b = -1.0;
213  empty_event_ = false;
214  particles_to_tree(particles);
215  output_counter_++;
216  }
217 }
218 
220  const std::unique_ptr<Clock> &,
221  const DensityParameters &) {
223  particles_to_tree(particles);
224  output_counter_++;
225  }
226 }
227 
228 void RootOutput::at_eventend(const Particles &particles,
229  const int /*event_number*/,
230  double impact_parameter, bool empty_event) {
231  impact_b = impact_parameter;
232  empty_event_ = empty_event;
233  if (write_particles_) {
234  particles_to_tree(particles);
235  }
236  /* Forced regular dump from operational memory to disk. Very demanding!
237  * If program crashes written data will NOT be lost. */
240  particles_tree_->AutoSave("SaveSelf");
241  }
242  if (write_collisions_) {
243  collisions_tree_->AutoSave("SaveSelf");
244  }
245  }
246 
248  // If the runtime is too short some particles might not yet have
249  // reached the hypersurface. Warning is printed.
250  if (particles.size() != 0) {
251  const auto &log = logger<LogArea::HyperSurfaceCrossing>();
252  log.warn(
253  "End time might be too small for initial conditions output. "
254  "Hypersurface has not yet been crossed by ",
255  particles.size(), " particle(s).");
256  }
257  }
258 }
259 
261  const double /*density*/) {
262  if (write_collisions_) {
264  action.get_total_weight(), action.get_partial_weight());
265  }
266 
270  }
271 }
272 
273 template <typename T>
274 void RootOutput::particles_to_tree(T &particles) {
275  int i = 0;
276 
278  ev = current_event_;
279 
280  for (const auto &p : particles) {
281  // Buffer full - flush to tree, else fill with particles
282  if (i >= max_buffer_size_) {
284  i = 0;
285  particles_tree_->Fill();
286  } else {
287  t[i] = p.position().x0();
288  x[i] = p.position().x1();
289  y[i] = p.position().x2();
290  z[i] = p.position().x3();
291 
292  p0[i] = p.momentum().x0();
293  px[i] = p.momentum().x1();
294  py[i] = p.momentum().x2();
295  pz[i] = p.momentum().x3();
296 
297  pdgcode[i] = p.pdgcode().get_decimal();
298  charge[i] = p.type().charge();
299 
300  if (part_extended_ || ic_extended_) {
301  const auto h = p.get_history();
302  formation_time_[i] = p.formation_time();
303  xsec_factor_[i] = p.xsec_scaling_factor();
304  time_last_coll_[i] = h.time_last_collision;
305  coll_per_part_[i] = h.collisions_per_particle;
306  proc_id_origin_[i] = h.id_process;
307  proc_type_origin_[i] = static_cast<int>(h.process_type);
308  pdg_mother1_[i] = h.p1.get_decimal();
309  pdg_mother2_[i] = h.p2.get_decimal();
310  }
311 
312  i++;
313  }
314  }
315  // Flush rest to tree
316  if (i > 0) {
317  npart = i;
318  particles_tree_->Fill();
319  }
320 }
321 
322 void RootOutput::collisions_to_tree(const ParticleList &incoming,
323  const ParticleList &outgoing,
324  const double weight,
325  const double partial_weight) {
326  ev = current_event_;
327  nin = incoming.size();
328  nout = outgoing.size();
329  npart = nin + nout;
330  wgt = weight;
331  par_wgt = partial_weight;
332 
333  int i = 0;
334 
335  /* It is assumed that nin + nout < max_buffer_size_
336  * This is true for any possible reaction for current buffer size: 10000
337  * But if one wants initial/final particles written to collisions
338  * then implementation should be updated. */
339 
340  for (const ParticleList &plist : {incoming, outgoing}) {
341  for (const auto &p : plist) {
342  t[i] = p.position().x0();
343  x[i] = p.position().x1();
344  y[i] = p.position().x2();
345  z[i] = p.position().x3();
346 
347  p0[i] = p.momentum().x0();
348  px[i] = p.momentum().x1();
349  py[i] = p.momentum().x2();
350  pz[i] = p.momentum().x3();
351 
352  pdgcode[i] = p.pdgcode().get_decimal();
353  charge[i] = p.type().charge();
354 
355  if (coll_extended_) {
356  const auto h = p.get_history();
357  formation_time_[i] = p.formation_time();
358  xsec_factor_[i] = p.xsec_scaling_factor();
359  time_last_coll_[i] = h.time_last_collision;
360  coll_per_part_[i] = h.collisions_per_particle;
361  proc_id_origin_[i] = h.id_process;
362  proc_type_origin_[i] = static_cast<int>(h.process_type);
363  pdg_mother1_[i] = h.p1.get_decimal();
364  pdg_mother2_[i] = h.p2.get_decimal();
365  }
366 
367  i++;
368  }
369  }
370 
371  collisions_tree_->Fill();
372 }
373 } // namespace smash
std::array< double, max_buffer_size_ > formation_time_
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:195
const bf::path filename_
Filename of output.
Definition: rootoutput.h:150
bool write_initial_conditions_
Option to write particles tree for initial conditions.
Definition: rootoutput.h:211
A class to pre-calculate and store parameters relevant for density calculation.
Definition: density.h:106
int nout
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:199
void particles_to_tree(T &particles)
Writes particles to a tree defined by treename.
Definition: rootoutput.cc:274
bool empty_event_
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:201
int current_event_
Number of current event.
Definition: rootoutput.h:188
std::array< int, max_buffer_size_ > proc_id_origin_
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:197
~RootOutput()
Destructor.
Definition: rootoutput.cc:197
bool write_particles_
Option to write particles tree.
Definition: rootoutput.h:208
std::array< double, max_buffer_size_ > py
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:195
std::unique_ptr< TFile > root_out_file_
Pointer to root output file.
Definition: rootoutput.h:154
void at_eventstart(const Particles &particles, const int event_number) override
update event number and writes intermediate particles to a tree.
Definition: rootoutput.cc:204
std::array< double, max_buffer_size_ > x
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:195
int npart
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:199
std::array< double, max_buffer_size_ > p0
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:195
virtual double get_partial_weight() const =0
Return the specific weight for the chosen outgoing channel, which is mainly used for the partial weig...
std::array< double, max_buffer_size_ > time_last_coll_
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:195
TTree * particles_tree_
TTree for particles output.
Definition: rootoutput.h:161
void init_trees()
Basic initialization routine, creating the TTree objects for particles and collisions.
Definition: rootoutput.cc:106
int nin
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:199
virtual ProcessType get_type() const
Get the process type.
Definition: action.h:130
Hypersurface crossing Particles are removed from the evolution and printed to a separate output to se...
const bool coll_extended_
Whether extended collisions output is on.
Definition: rootoutput.h:230
void collisions_to_tree(const ParticleList &incoming, const ParticleList &outgoing, const double weight, const double partial_weight)
Writes collisions to a tree defined by treename.
Definition: rootoutput.cc:322
const bool part_extended_
Whether extended particle output is on.
Definition: rootoutput.h:228
std::array< double, max_buffer_size_ > t
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:195
size_t size() const
Definition: particles.h:87
RootOutput(const bf::path &path, const std::string &name, const OutputParameters &out_par)
Construct ROOT output.
Definition: rootoutput.cc:86
int output_counter_
Number of output in a given event.
Definition: rootoutput.h:186
std::array< double, max_buffer_size_ > z
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:195
std::array< int, max_buffer_size_ > proc_type_origin_
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:197
void at_intermediate_time(const Particles &particles, const std::unique_ptr< Clock > &clock, const DensityParameters &dens_param) override
Writes intermediate particles to a tree defined by treename, if it is allowed (i.e., particles_only_final_ is false).
Definition: rootoutput.cc:219
Helper structure for Experiment to hold output options and parameters.
Action is the base class for a generic process that takes a number of incoming particles and transfor...
Definition: action.h:34
virtual double get_total_weight() const =0
Return the total weight value, which is mainly used for the weight output entry.
std::array< double, max_buffer_size_ > y
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:195
const bool ic_extended_
Whether extended ic output is on.
Definition: rootoutput.h:232
bool write_collisions_
Option to write collisions tree.
Definition: rootoutput.h:205
std::array< double, max_buffer_size_ > px
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:195
double wgt
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:200
bf::path filename_unfinished_
Filename of output as long as simulation is still running.
Definition: rootoutput.h:152
void at_interaction(const Action &action, const double density) override
Writes collisions to a tree defined by treename.
Definition: rootoutput.cc:260
double impact_b
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:200
constexpr int p
Proton.
void at_eventend(const Particles &particles, const int event_number, double impact_parameter, bool empty_event) override
update event number and impact parameter, and writes intermediate particles to a tree.
Definition: rootoutput.cc:228
TTree * collisions_tree_
TTree for collision output.
Definition: rootoutput.h:168
int tcounter
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:199
std::array< double, max_buffer_size_ > xsec_factor_
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:195
bool particles_only_final_
Print only final particles in the event, no intermediate output.
Definition: rootoutput.h:214
const ParticleList & incoming_particles() const
Get the list of particles that go into the action.
Definition: action.cc:58
std::array< int, max_buffer_size_ > charge
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:197
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
std::array< int, max_buffer_size_ > pdg_mother1_
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:197
int ev
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:199
std::array< double, max_buffer_size_ > pz
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:195
const ParticleList & outgoing_particles() const
Get the list of particles that resulted from the action.
Definition: action.h:244
std::array< int, max_buffer_size_ > pdgcode
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:197
int autosave_frequency_
Root file cannot be read if it was not properly closed and finalized.
Definition: rootoutput.h:225
Abstraction of generic output.
std::array< int, max_buffer_size_ > coll_per_part_
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:197
static const int max_buffer_size_
Maximal buffer size.
Definition: rootoutput.h:191
Definition: action.h:24
std::array< int, max_buffer_size_ > pdg_mother2_
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:197
double par_wgt
Buffer for filling TTree. See class documentation for definitions.
Definition: rootoutput.h:200