Version: SMASH-3.3
binaryoutput.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2020,2022-2025
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/binaryoutput.h"
11 
12 #include <cstdint>
13 #include <filesystem>
14 #include <string>
15 
16 #include "smash/action.h"
17 #include "smash/clock.h"
18 #include "smash/config.h"
19 
20 namespace smash {
21 
22 static auto get_list_of_binary_quantities(const std::string &content,
23  const std::string &format,
24  const OutputParameters &parameters);
25 
26 static auto get_binary_filename(const std::string &content,
27  const std::vector<std::string> &quantities) {
28  std::string filename = content;
29  if (content == "Particles" || content == "Collisions") {
30  std::transform(filename.begin(), filename.end(), filename.begin(),
31  [](unsigned char c) { return std::tolower(c); });
32  } else if (content == "Photons" || content == "Dileptons") {
33  // Nothing to be done here
34  } else if (content == "Initial_Conditions") {
35  filename = "SMASH_IC";
36  } else {
37  throw std::invalid_argument(
38  "Unknown content to get the binary output filename.");
39  }
40  if (quantities == OutputDefaultQuantities::oscar2013) {
41  filename += "_oscar2013";
42  } else if (quantities == OutputDefaultQuantities::oscar2013extended) {
43  filename += "_oscar2013_extended";
44  } else {
45  filename += "_custom";
46  }
47  return filename + ".bin";
48 }
49 
202 BinaryOutputBase::BinaryOutputBase(const std::filesystem::path &path,
203  const std::string &mode,
204  const std::string &name,
205  const std::vector<std::string> &quantities)
206  : OutputInterface(name), file_{path, mode}, formatter_(quantities) {
207  if (quantities.empty()) {
208  throw std::invalid_argument(
209  "Empty quantities list passed to 'BinaryOutputBase' constructor.");
210  }
211  std::fwrite("SMSH", 4, 1, file_.get()); // magic number
212  write(format_version_); // file format version number
213  std::uint16_t format_variant{};
214  if (quantities == OutputDefaultQuantities::oscar2013) {
215  format_variant = 0;
216  } else if (quantities == OutputDefaultQuantities::oscar2013extended) {
217  format_variant = 1;
218  } else {
219  format_variant = format_custom_;
220  }
221  write(format_variant);
222  write(SMASH_VERSION);
223 }
224 
225 // write functions:
226 void BinaryOutputBase::write(const char c) {
227  std::fwrite(&c, sizeof(char), 1, file_.get());
228 }
230  std::fwrite(chunk.data(), sizeof(char), chunk.size(), file_.get());
231 }
232 
233 void BinaryOutputBase::write(const std::string &s) {
234  const auto size = smash::numeric_cast<uint32_t>(s.size());
235  std::fwrite(&size, sizeof(std::uint32_t), 1, file_.get());
236  std::fwrite(s.c_str(), s.size(), 1, file_.get());
237 }
238 
239 void BinaryOutputBase::write(const double x) {
240  std::fwrite(&x, sizeof(x), 1, file_.get());
241 }
242 
244  std::fwrite(v.begin(), sizeof(*v.begin()), 4, file_.get());
245 }
246 
247 void BinaryOutputBase::write(const Particles &particles) {
248  write_in_chunk<ToBinary>(
249  particles, formatter_,
250  [this](const ToBinary::type &buf) { this->write(buf); });
251 }
252 
253 void BinaryOutputBase::write(const ParticleList &particles) {
254  write_in_chunk<ToBinary>(
255  particles, formatter_,
256  [this](const ToBinary::type &buf) { this->write(buf); });
257 }
258 
260  write(formatter_.single_particle_data(p));
261 }
262 
264  const std::filesystem::path &path, std::string name,
265  const OutputParameters &out_par, const std::vector<std::string> &quantities)
266  : BinaryOutputBase(path / get_binary_filename(name, quantities), "wb", name,
267  quantities),
268  print_start_end_(out_par.coll_printstartend) {}
269 
271  const EventLabel &event_label,
272  const EventInfo &) {
273  const char pchar = 'p';
274  if (print_start_end_) {
275  std::fwrite(&pchar, sizeof(char), 1, file_.get());
276  write(event_label.event_number);
277  write(event_label.ensemble_number);
278  write(particles.size());
279  write(particles);
280  }
281 }
282 
284  const EventLabel &event_label,
285  const EventInfo &event) {
286  const char pchar = 'p';
287  if (print_start_end_) {
288  std::fwrite(&pchar, sizeof(char), 1, file_.get());
289  write(event_label.event_number);
290  write(event_label.ensemble_number);
291  write(particles.size());
292  write(particles);
293  }
294 
295  // Event end line
296  const char fchar = 'f';
297  std::fwrite(&fchar, sizeof(char), 1, file_.get());
298  write(event_label.event_number);
299  write(event_label.ensemble_number);
300  write(event.impact_parameter);
301  const char empty = event.empty_event;
302  write(empty);
303 
304  // Flush to disk
305  std::fflush(file_.get());
306 }
307 
309  const double density) {
310  const char ichar = 'i';
311  std::fwrite(&ichar, sizeof(char), 1, file_.get());
312  write(action.incoming_particles().size());
313  write(action.outgoing_particles().size());
314  std::fwrite(&density, sizeof(double), 1, file_.get());
315  const double weight = action.get_total_weight();
316  std::fwrite(&weight, sizeof(double), 1, file_.get());
317  const double partial_weight = action.get_partial_weight();
318  std::fwrite(&partial_weight, sizeof(double), 1, file_.get());
319  const auto type = static_cast<uint32_t>(action.get_type());
320  std::fwrite(&type, sizeof(uint32_t), 1, file_.get());
321  write(action.incoming_particles());
322  write(action.outgoing_particles());
323 }
324 
326  const std::filesystem::path &path, std::string name,
327  const OutputParameters &out_par, const std::vector<std::string> &quantities)
328  : BinaryOutputBase(path / get_binary_filename(name, quantities), "wb", name,
329  quantities),
330  only_final_(out_par.part_only_final) {}
331 
333  const EventLabel &event_label,
334  const EventInfo &) {
335  const char pchar = 'p';
337  std::fwrite(&pchar, sizeof(char), 1, file_.get());
338  write(event_label.event_number);
339  write(event_label.ensemble_number);
340  write(particles.size());
341  write(particles);
342  }
343 }
344 
346  const EventLabel &event_label,
347  const EventInfo &event) {
348  const char pchar = 'p';
350  std::fwrite(&pchar, sizeof(char), 1, file_.get());
351  write(event_label.event_number);
352  write(event_label.ensemble_number);
353  write(particles.size());
354  write(particles);
355  }
356 
357  // Event end line
358  const char fchar = 'f';
359  std::fwrite(&fchar, sizeof(char), 1, file_.get());
360  write(event_label.event_number);
361  write(event_label.ensemble_number);
362  write(event.impact_parameter);
363  const char empty = event.empty_event;
364  write(empty);
365 
366  // Flush to disk
367  std::fflush(file_.get());
368 }
369 
371  const std::unique_ptr<Clock> &,
372  const DensityParameters &,
373  const EventLabel &event_label,
374  const EventInfo &) {
375  const char pchar = 'p';
377  std::fwrite(&pchar, sizeof(char), 1, file_.get());
378  write(event_label.event_number);
379  write(event_label.ensemble_number);
380  write(particles.size());
381  write(particles);
382  }
383 }
384 
386  const std::filesystem::path &path, std::string name,
387  const std::vector<std::string> &quantities)
388  : BinaryOutputBase(path / get_binary_filename(name, quantities), "wb", name,
389  quantities) {}
390 
392  const EventLabel &,
393  const EventInfo &) {}
394 
396  [[maybe_unused]] const Particles &particles, const EventLabel &event_label,
397  const EventInfo &event) {
398  // Event end line
399  const char fchar = 'f';
400  std::fwrite(&fchar, sizeof(char), 1, file_.get());
401  write(event_label.event_number);
402  write(event_label.ensemble_number);
403  write(event.impact_parameter);
404  const char empty = event.empty_event;
405  write(empty);
406 
407  // Flush to disk
408  std::fflush(file_.get());
409 }
410 
412  const double) {
413  if (action.get_type() == ProcessType::Fluidization ||
415  const char pchar = 'p';
416  std::fwrite(&pchar, sizeof(char), 1, file_.get());
417  write(action.incoming_particles().size());
418  write(action.incoming_particles());
419  }
420 }
421 
422 static auto get_list_of_binary_quantities(const std::string &content,
423  const std::string &format,
424  const OutputParameters &parameters) {
425  const bool is_extended = std::invoke([&content, &parameters]() {
426  if (content == "Particles")
427  return parameters.part_extended;
428  else if (content == "Collisions")
429  return parameters.coll_extended;
430  else if (content == "Dileptons")
431  return parameters.dil_extended;
432  else if (content == "Photons")
433  return parameters.photons_extended;
434  else if (content == "Initial_Conditions")
435  return parameters.ic_extended;
436  else
437  return false;
438  });
439  const auto default_quantities =
442  if (format == "Oscar2013_bin") {
443  return default_quantities;
444  } else if (format == "Binary") {
445  if (content == "Particles" || content == "Collisions" ||
446  content == "Dileptons" || content == "Photons" ||
447  content == "Initial_Conditions") {
448  auto list_of_quantities = parameters.quantities.at(content);
449  if (list_of_quantities.empty()) {
450  return default_quantities;
451  } else {
452  return list_of_quantities;
453  }
454  } else {
455  /* Note that this function should not be called with "Binary" format for
456  * output contents which do not support custom binary quantities. Hence we
457  * throw here to prevent such a case.*/
458  throw std::invalid_argument(
459  "Unknown content to get the list of quantities for binary output.");
460  }
461  } else {
462  throw std::invalid_argument(
463  "Unknown format to get the list of quantities for binary output.");
464  }
465 }
466 
467 std::unique_ptr<OutputInterface> create_binary_output(
468  const std::string &format, const std::string &content,
469  const std::filesystem::path &path, const OutputParameters &out_par) {
470  const auto quantities =
471  get_list_of_binary_quantities(content, format, out_par);
472  if (content == "Particles") {
473  return std::make_unique<BinaryOutputParticles>(path, content, out_par,
474  quantities);
475  } else if (content == "Collisions" || content == "Dileptons" ||
476  content == "Photons") {
477  return std::make_unique<BinaryOutputCollisions>(path, content, out_par,
478  quantities);
479  } else if (content == "Initial_Conditions") {
480  return std::make_unique<BinaryOutputInitialConditions>(path, content,
481  quantities);
482  } else {
483  throw std::invalid_argument("Binary output not available for '" + content +
484  "' content.");
485  }
486 }
487 
488 } // namespace smash
Action is the base class for a generic process that takes a number of incoming particles and transfor...
Definition: action.h:35
virtual ProcessType get_type() const
Get the process type.
Definition: action.h:131
virtual double get_total_weight() const =0
Return the total weight value, which is mainly used for the weight output entry.
const ParticleList & incoming_particles() const
Get the list of particles that go into the action.
Definition: action.cc:58
virtual double get_partial_weight() const =0
Return the specific weight for the chosen outgoing channel, which is mainly used for the partial weig...
const ParticleList & outgoing_particles() const
Get the list of particles that resulted from the action.
Definition: action.h:247
Base class for SMASH binary output.
Definition: binaryoutput.h:30
void write(const ToBinary::type &chunk)
Write several bytes to the binary output.
void write_particledata(const ParticleData &p)
Write particle data to binary output.
const uint16_t format_version_
Binary file format version number.
Definition: binaryoutput.h:131
const uint16_t format_custom_
Format variant number associated to the custom quantities case.
Definition: binaryoutput.h:133
OutputFormatter< ToBinary > formatter_
The output formatter.
Definition: binaryoutput.h:135
RenamingFilePtr file_
Binary particles output file path.
Definition: binaryoutput.h:127
BinaryOutputBase(const std::filesystem::path &path, const std::string &mode, const std::string &name, const std::vector< std::string > &quantities)
Create binary output base.
void at_interaction(const Action &action, const double density) override
Writes an interaction block, including information about the incoming and outgoing particles,...
void at_eventstart(const Particles &particles, const EventLabel &event_label, const EventInfo &event) override
Writes the initial particle information list of an event to the binary output.
void at_eventend(const Particles &particles, const EventLabel &event_label, const EventInfo &event) override
Writes the final particle information list of an event to the binary output.
BinaryOutputCollisions(const std::filesystem::path &path, std::string name, const OutputParameters &out_par, const std::vector< std::string > &quantities)
Create binary particle output.
bool print_start_end_
Write initial and final particles additonally to collisions?
Definition: binaryoutput.h:194
void at_eventend(const Particles &particles, const EventLabel &event_label, const EventInfo &event) override
Writes the final particle information of an event to the binary output.
BinaryOutputInitialConditions(const std::filesystem::path &path, std::string name, const std::vector< std::string > &quantities)
Create binary initial conditions particle output.
void at_interaction(const Action &action, const double) override
Writes particles that are removed when crossing the hypersurface to the output.
void at_eventstart(const Particles &, const EventLabel &, const EventInfo &) override
Writes the initial particle information of an event to the binary output.
void at_eventstart(const Particles &particles, const EventLabel &event_label, const EventInfo &event) override
Writes the initial particle information of an event to the binary output.
void at_intermediate_time(const Particles &particles, const std::unique_ptr< Clock > &clock, const DensityParameters &dens_param, const EventLabel &event_label, const EventInfo &event) override
Writes particles at each time interval; fixed by option OUTPUT_INTERVAL.
OutputOnlyFinal only_final_
Whether final- or initial-state particles should be written.
Definition: binaryoutput.h:260
BinaryOutputParticles(const std::filesystem::path &path, std::string name, const OutputParameters &out_par, const std::vector< std::string > &quantities)
Create binary particle output.
void at_eventend(const Particles &particles, const EventLabel &event_label, const EventInfo &event) override
Writes the final particle information of an event to the binary output.
A class to pre-calculate and store parameters relevant for density calculation.
Definition: density.h:92
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
iterator begin()
Definition: fourvector.h:291
Abstraction of generic output.
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:59
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
size_t size() const
Definition: particles.h:87
FILE * get()
Get the underlying FILE* pointer.
Definition: file.cc:27
std::vector< char > type
Return type of this converter.
@ IfNotEmpty
Print only final-state particles, and those only if the event is not empty.
@ No
Print initial, intermediate and final-state particles.
FormattingHelper< T > format(const T &value, const char *unit, int width=-1, int precision=-1)
Acts as a stream modifier for std::ostream to output an object with an optional suffix string and wit...
Definition: logging.h:217
std::unique_ptr< OutputInterface > create_binary_output(const std::string &format, const std::string &content, const std::filesystem::path &path, const OutputParameters &out_par)
Create a binary output object.
constexpr int p
Proton.
Definition: action.h:24
@ FluidizationNoRemoval
See here for a short description.
@ Fluidization
See here for a short description.
static auto get_list_of_binary_quantities(const std::string &content, const std::string &format, const OutputParameters &parameters)
static auto get_binary_filename(const std::string &content, const std::vector< std::string > &quantities)
Definition: binaryoutput.cc:26
Structure to contain custom data for output.
bool empty_event
True if no collisions happened.
double impact_parameter
Impact parameter for collider modus, otherwise dummy.
Structure to contain information about the event and ensemble numbers.
int32_t ensemble_number
The number of the ensemble.
int32_t event_number
The number of the event.
static const std::vector< std::string > oscar2013
Quantities output in OSCAR2013 format.
static const std::vector< std::string > oscar2013extended
Quantities output in Extended OSCAR2013 format.
Helper structure for Experiment to hold output options and parameters.
bool dil_extended
Extended format for dilepton output.
bool coll_extended
Extended format for collisions output.
bool part_extended
Extended format for particles output.
bool photons_extended
Extended format for photon output.
std::map< std::string, std::vector< std::string > > quantities
Map of quantities to be printed in the output.
bool ic_extended
Extended initial conditions output.