Version: SMASH-2.0
oscaroutput.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2020
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 #include "smash/oscaroutput.h"
10 
11 #include <string>
12 
13 #include <boost/filesystem.hpp>
14 
15 #include "smash/action.h"
16 #include "smash/clock.h"
17 #include "smash/config.h"
18 #include "smash/cxx14compat.h"
20 
21 namespace smash {
22 static constexpr int LHyperSurfaceCrossing = LogArea::HyperSurfaceCrossing::id;
23 static constexpr int LOutput = LogArea::Output::id;
24 
25 template <OscarOutputFormat Format, int Contents>
27  const std::string &name)
28  : OutputInterface(name),
29  file_{path /
30  (name + ".oscar" + ((Format == OscarFormat1999) ? "1999" : "")),
31  "w"} {
81  if (Format == OscarFormat2013) {
82  std::fprintf(file_.get(),
83  "#!OSCAR2013 %s t x y z mass "
84  "p0 px py pz pdg ID charge\n",
85  name.c_str());
86  std::fprintf(file_.get(),
87  "# Units: fm fm fm fm "
88  "GeV GeV GeV GeV GeV none none e\n");
89  std::fprintf(file_.get(), "# %s\n", VERSION_MAJOR);
90  } else if (Format == OscarFormat2013Extended) {
91  std::fprintf(file_.get(),
92  "#!OSCAR2013Extended %s t x y z mass p0 px py pz"
93  " pdg ID charge ncoll form_time xsecfac proc_id_origin"
94  " proc_type_origin time_last_coll pdg_mother1 pdg_mother2\n",
95  name.c_str());
96  std::fprintf(file_.get(),
97  "# Units: fm fm fm fm GeV GeV GeV GeV GeV"
98  " none none e none fm none none none fm none none\n");
99  std::fprintf(file_.get(), "# %s\n", VERSION_MAJOR);
100  } else {
101  const std::string &oscar_name =
102  name == "particle_lists" ? "final_id_p_x" : name;
103  // This is necessary because OSCAR199A requires
104  // this particular string for particle output.
105 
106  std::fprintf(file_.get(), "# OSC1999A\n# %s\n# %s\n", oscar_name.c_str(),
107  VERSION_MAJOR);
108  std::fprintf(file_.get(), "# Block format:\n");
109  std::fprintf(file_.get(), "# nin nout event_number\n");
110  std::fprintf(file_.get(), "# id pdg 0 px py pz p0 mass x y z t\n");
111  std::fprintf(file_.get(),
112  "# End of event: 0 0 event_number"
113  " impact_parameter\n");
114  std::fprintf(file_.get(), "#\n");
115  }
116 }
117 
118 template <OscarOutputFormat Format, int Contents>
119 inline void OscarOutput<Format, Contents>::write(const Particles &particles) {
120  for (const ParticleData &data : particles) {
121  write_particledata(data);
122  }
123 }
124 
125 template <OscarOutputFormat Format, int Contents>
127  const int event_number,
128  const EventInfo &) {
129  current_event_ = event_number;
130  if (Contents & OscarAtEventstart) {
131  if (Format == OscarFormat2013 || Format == OscarFormat2013Extended) {
132  std::fprintf(file_.get(), "# event %i in %zu\n", event_number,
133  particles.size());
134  } else {
135  /* OSCAR line prefix : initial particles; final particles; event id
136  * First block of an event: initial = 0, final = number of particles
137  */
138  const size_t zero = 0;
139  std::fprintf(file_.get(), "%zu %zu %i\n", zero, particles.size(),
140  event_number);
141  }
142  if (!(Contents & OscarParticlesIC)) {
143  // We do not want the inital particle list to be printed in case of IC
144  // output
145  write(particles);
146  }
147  }
148 }
149 
150 template <OscarOutputFormat Format, int Contents>
152  const int event_number,
153  const EventInfo &event) {
154  if (Format == OscarFormat2013 || Format == OscarFormat2013Extended) {
155  if (Contents & OscarParticlesAtEventend ||
156  (Contents & OscarParticlesAtEventendIfNotEmpty && !event.empty_event)) {
157  std::fprintf(file_.get(), "# event %i out %zu\n", event_number,
158  particles.size());
159  write(particles);
160  }
161  // Comment end of an event
162  const char *empty_event_str = event.empty_event ? "no" : "yes";
163  std::fprintf(
164  file_.get(),
165  "# event %i end 0 impact %7.3f scattering_projectile_target %s\n",
166  event_number, event.impact_parameter, empty_event_str);
167  } else {
168  /* OSCAR line prefix : initial particles; final particles; event id
169  * Last block of an event: initial = number of particles, final = 0
170  * Block ends with null interaction. */
171  const size_t zero = 0;
172  if (Contents & OscarParticlesAtEventend ||
173  (Contents & OscarParticlesAtEventendIfNotEmpty && !event.empty_event)) {
174  std::fprintf(file_.get(), "%zu %zu %i\n", particles.size(), zero,
175  event_number);
176  write(particles);
177  }
178  // Null interaction marks the end of an event
179  std::fprintf(file_.get(), "%zu %zu %i %7.3f\n", zero, zero, event_number,
180  event.impact_parameter);
181  }
182  // Flush to disk
183  std::fflush(file_.get());
184 
185  if (Contents & OscarParticlesIC) {
186  // If the runtime is too short some particles might not yet have
187  // reached the hypersurface. Warning is printed.
188  if (particles.size() != 0) {
190  "End time might be too small for initial conditions output. "
191  "Hypersurface has not yet been crossed by ",
192  particles.size(), " particle(s).");
193  }
194  }
195 }
196 
197 template <OscarOutputFormat Format, int Contents>
199  const double density) {
200  if (Contents & OscarInteractions) {
201  if (Format == OscarFormat2013 || Format == OscarFormat2013Extended) {
202  std::fprintf(file_.get(),
203  "# interaction in %zu out %zu rho %12.7f weight %12.7g"
204  " partial %12.7f type %5i\n",
205  action.incoming_particles().size(),
206  action.outgoing_particles().size(), density,
207  action.get_total_weight(), action.get_partial_weight(),
208  static_cast<int>(action.get_type()));
209  } else {
210  /* OSCAR line prefix : initial final
211  * particle creation: 0 1
212  * particle 2<->2 collision: 2 2
213  * resonance formation: 2 1
214  * resonance decay: 1 2
215  * etc.*/
216  std::fprintf(file_.get(), "%zu %zu %12.7f %12.7f %12.7f %5i\n",
217  action.incoming_particles().size(),
218  action.outgoing_particles().size(), density,
219  action.get_total_weight(), action.get_partial_weight(),
220  static_cast<int>(action.get_type()));
221  }
222  for (const auto &p : action.incoming_particles()) {
223  write_particledata(p);
224  }
225  for (const auto &p : action.outgoing_particles()) {
226  write_particledata(p);
227  }
228  } else if (Contents & OscarParticlesIC) {
229  for (const auto &p : action.incoming_particles()) {
230  write_particledata(p);
231  }
232  }
233 }
234 
235 template <OscarOutputFormat Format, int Contents>
237  const Particles &particles, const std::unique_ptr<Clock> &,
238  const DensityParameters &, const EventInfo &) {
239  if (Contents & OscarTimesteps) {
240  if (Format == OscarFormat2013 || Format == OscarFormat2013Extended) {
241  std::fprintf(file_.get(), "# event %i out %zu\n", current_event_ + 1,
242  particles.size());
243  } else {
244  const size_t zero = 0;
245  std::fprintf(file_.get(), "%zu %zu %i\n", particles.size(), zero,
246  current_event_ + 1);
247  }
248  write(particles);
249  }
250 }
251 
704 template <OscarOutputFormat Format, int Contents>
706  const ParticleData &data) {
707  const FourVector pos = data.position();
708  const FourVector mom = data.momentum();
709  if (Format == OscarFormat2013) {
710  std::fprintf(file_.get(), "%g %g %g %g %g %.9g %.9g %.9g %.9g %s %i %i\n",
711  pos.x0(), pos.x1(), pos.x2(), pos.x3(), data.effective_mass(),
712  mom.x0(), mom.x1(), mom.x2(), mom.x3(),
713  data.pdgcode().string().c_str(), data.id(),
714  data.type().charge());
715  } else if (Format == OscarFormat2013Extended) {
716  const auto h = data.get_history();
717  std::fprintf(
718  file_.get(),
719  "%g %g %g %g %g %.9g %.9g %.9g"
720  " %.9g %s %i %i %i %g %g %i %i %g %s %s\n",
721  pos.x0(), pos.x1(), pos.x2(), pos.x3(), data.effective_mass(), mom.x0(),
722  mom.x1(), mom.x2(), mom.x3(), data.pdgcode().string().c_str(),
723  data.id(), data.type().charge(), h.collisions_per_particle,
724  data.formation_time(), data.xsec_scaling_factor(), h.id_process,
725  static_cast<int>(h.process_type), h.time_last_collision,
726  h.p1.string().c_str(), h.p2.string().c_str());
727  } else {
728  std::fprintf(file_.get(), "%i %s %i %g %g %g %g %g %g %g %g %g\n",
729  data.id(), data.pdgcode().string().c_str(), 0, mom.x1(),
730  mom.x2(), mom.x3(), mom.x0(), data.effective_mass(), pos.x1(),
731  pos.x2(), pos.x3(), pos.x0());
732  }
733 }
734 
735 namespace {
747 template <int Contents>
748 std::unique_ptr<OutputInterface> create_select_format(
749  bool modern_format, const bf::path &path, const OutputParameters &out_par,
750  const std::string &name) {
751  bool extended_format = (Contents & OscarInteractions) ? out_par.coll_extended
752  : out_par.part_extended;
753  if (modern_format && extended_format) {
754  return make_unique<OscarOutput<OscarFormat2013Extended, Contents>>(path,
755  name);
756  } else if (modern_format && !extended_format) {
757  return make_unique<OscarOutput<OscarFormat2013, Contents>>(path, name);
758  } else if (!modern_format && !extended_format) {
759  return make_unique<OscarOutput<OscarFormat1999, Contents>>(path, name);
760  } else {
761  // Only remaining possibility: (!modern_format && extended_format)
762  logg[LOutput].warn() << "Creating Oscar output: "
763  << "There is no extended Oscar1999 format.";
764  return make_unique<OscarOutput<OscarFormat1999, Contents>>(path, name);
765  }
766 }
767 } // unnamed namespace
768 
769 std::unique_ptr<OutputInterface> create_oscar_output(
770  const std::string &format, const std::string &content, const bf::path &path,
771  const OutputParameters &out_par) {
772  if (format != "Oscar2013" && format != "Oscar1999") {
773  throw std::invalid_argument("Creating Oscar output: unknown format");
774  }
775  const bool modern_format = (format == "Oscar2013");
776  if (content == "Particles") {
777  if (out_par.part_only_final == OutputOnlyFinal::Yes) {
778  return create_select_format<OscarParticlesAtEventend>(
779  modern_format, path, out_par, "particle_lists");
780  } else if (out_par.part_only_final == OutputOnlyFinal::IfNotEmpty) {
781  return create_select_format<OscarParticlesAtEventendIfNotEmpty>(
782  modern_format, path, out_par, "particle_lists");
783 
784  } else { // out_par.part_only_final == OutputOnlyFinal::No
787  modern_format, path, out_par, "particle_lists");
788  }
789  } else if (content == "Collisions") {
790  if (out_par.coll_printstartend) {
793  modern_format, path, out_par, "full_event_history");
794  } else {
795  return create_select_format<OscarInteractions>(
796  modern_format, path, out_par, "full_event_history");
797  }
798  } else if (content == "Dileptons") {
799  if (modern_format && out_par.dil_extended) {
800  return make_unique<
802  "Dileptons");
803  } else if (modern_format && !out_par.dil_extended) {
804  return make_unique<OscarOutput<OscarFormat2013, OscarInteractions>>(
805  path, "Dileptons");
806  } else if (!modern_format && !out_par.dil_extended) {
807  return make_unique<OscarOutput<OscarFormat1999, OscarInteractions>>(
808  path, "Dileptons");
809  } else if (!modern_format && out_par.dil_extended) {
810  logg[LOutput].warn()
811  << "Creating Oscar output: "
812  << "There is no extended Oscar1999 (dileptons) format.";
813  }
814  } else if (content == "Photons") {
815  if (modern_format && !out_par.photons_extended) {
816  return make_unique<OscarOutput<OscarFormat2013, OscarInteractions>>(
817  path, "Photons");
818  } else if (modern_format && out_par.photons_extended) {
819  return make_unique<
821  "Photons");
822  } else if (!modern_format && !out_par.photons_extended) {
823  return make_unique<OscarOutput<OscarFormat1999, OscarInteractions>>(
824  path, "Photons");
825  } else if (!modern_format && out_par.photons_extended) {
826  logg[LOutput].warn()
827  << "Creating Oscar output: "
828  << "There is no extended Oscar1999 (photons) format.";
829  }
830  } else if (content == "Initial_Conditions") {
831  if (modern_format && !out_par.ic_extended) {
832  return make_unique<
834  path, "SMASH_IC");
835  } else if (modern_format && out_par.ic_extended) {
838  path, "SMASH_IC");
839  } else if (!modern_format && !out_par.ic_extended) {
840  return make_unique<
842  path, "SMASH_IC");
843  } else if (!modern_format && out_par.ic_extended) {
844  logg[LOutput].warn()
845  << "Creating Oscar output: "
846  << "There is no extended Oscar1999 (initial conditions) format.";
847  }
848  }
849 
850  throw std::invalid_argument("Create_oscar_output got unknown content.");
851 }
852 
853 } // namespace smash
smash::Action::get_type
virtual ProcessType get_type() const
Get the process type.
Definition: action.h:131
smash
Definition: action.h:24
smash::ParticleData::xsec_scaling_factor
double xsec_scaling_factor(double delta_time=0.) const
Return the cross section scaling factor at a given time.
Definition: particledata.cc:78
smash::OutputParameters::ic_extended
bool ic_extended
Extended initial conditions output.
Definition: outputparameters.h:160
smash::LOutput
static constexpr int LOutput
Definition: oscaroutput.cc:23
smash::ParticleData::momentum
const FourVector & momentum() const
Get the particle's 4-momentum.
Definition: particledata.h:152
smash::DensityParameters
A class to pre-calculate and store parameters relevant for density calculation.
Definition: density.h:108
smash::Particles::size
size_t size() const
Definition: particles.h:87
smash::ParticleData
Definition: particledata.h:52
smash::ParticleData::id
int32_t id() const
Get the id of the particle.
Definition: particledata.h:70
cxx14compat.h
smash::OscarTimesteps
store the state after N timesteps (after_Nth_timestep)
Definition: oscaroutput.h:46
smash::OscarFormat2013Extended
Definition: oscaroutput.h:31
smash::FourVector::x3
double x3() const
Definition: fourvector.h:315
smash::ParticleData::effective_mass
double effective_mass() const
Get the particle's effective mass.
Definition: particledata.cc:21
smash::ParticleData::get_history
HistoryData get_history() const
Get history information.
Definition: particledata.h:133
smash::Action::get_partial_weight
virtual double get_partial_weight() const =0
Return the specific weight for the chosen outgoing channel, which is mainly used for the partial weig...
smash::ParticleData::pdgcode
PdgCode pdgcode() const
Get the pdgcode of the particle.
Definition: particledata.h:81
smash::OscarOutput
Definition: oscaroutput.h:65
action.h
smash::FourVector::x1
double x1() const
Definition: fourvector.h:307
smash::EventInfo
Structure to contain custom data for output.
Definition: outputinterface.h:35
smash::logg
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
clock.h
smash::Action::outgoing_particles
const ParticleList & outgoing_particles() const
Get the list of particles that resulted from the action.
Definition: action.h:245
smash::PdgCode::string
std::string string() const
Definition: pdgcode.h:250
forwarddeclarations.h
smash::OutputParameters::part_extended
bool part_extended
Extended format for particles output.
Definition: outputparameters.h:142
smash::ParticleData::formation_time
double formation_time() const
Get the absolute formation time of the particle.
Definition: particledata.h:230
OutputOnlyFinal::IfNotEmpty
Print only final-state particles, and those only if the event is not empty.
smash::OutputParameters
Helper structure for Experiment to hold output options and parameters.
Definition: outputparameters.h:25
smash::format
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:307
smash::create_oscar_output
std::unique_ptr< OutputInterface > create_oscar_output(const std::string &format, const std::string &content, const bf::path &path, const OutputParameters &out_par)
Definition: oscaroutput.cc:769
smash::OutputParameters::photons_extended
bool photons_extended
Extended format for photon output.
Definition: outputparameters.h:157
smash::FourVector::x0
double x0() const
Definition: fourvector.h:303
smash::make_unique
std::unique_ptr< T > make_unique(Args &&... args)
Definition for make_unique Is in C++14's standard library; necessary for older compilers.
Definition: cxx14compat.h:25
smash::ParticleData::position
const FourVector & position() const
Get the particle's position in Minkowski space.
Definition: particledata.h:198
smash::OscarFormat1999
Definition: oscaroutput.h:32
smash::FourVector::x2
double x2() const
Definition: fourvector.h:311
smash::OutputInterface
Abstraction of generic output.
Definition: outputinterface.h:65
smash::OutputParameters::coll_extended
bool coll_extended
Extended format for collisions output.
Definition: outputparameters.h:148
smash::Action::get_total_weight
virtual double get_total_weight() const =0
Return the total weight value, which is mainly used for the weight output entry.
smash::OutputParameters::coll_printstartend
bool coll_printstartend
Print initial and final particles in event into collision output.
Definition: outputparameters.h:151
smash::LHyperSurfaceCrossing
static constexpr int LHyperSurfaceCrossing
Definition: hypersurfacecrossingaction.cc:16
OutputOnlyFinal::Yes
Print only final-state particles.
smash::anonymous_namespace{oscaroutput.cc}::create_select_format
std::unique_ptr< OutputInterface > create_select_format(bool modern_format, const bf::path &path, const OutputParameters &out_par, const std::string &name)
Helper function that creates the oscar output with the format selected by create_oscar_output (except...
Definition: oscaroutput.cc:748
oscaroutput.h
smash::OscarOutput::OscarOutput
OscarOutput(const bf::path &path, const std::string &name)
Create oscar output.
smash::OscarParticlesAtEventendIfNotEmpty
store the state at the end of each event if it is not empty (at_eventend)
Definition: oscaroutput.h:52
smash::OscarInteractions
store interaction information (write_interaction)
Definition: oscaroutput.h:44
smash::OscarAtEventstart
store the state at the start of each event (at_eventstart)
Definition: oscaroutput.h:48
smash::OscarFormat2013
Definition: oscaroutput.h:30
smash::Particles
Definition: particles.h:33
smash::EventInfo::empty_event
bool empty_event
True if no collisions happened.
Definition: outputinterface.h:51
smash::OscarParticlesIC
store the particles that are removed on the hypersurface
Definition: oscaroutput.h:54
smash::Action
Definition: action.h:35
smash::OutputParameters::part_only_final
OutputOnlyFinal part_only_final
Print only final particles in event.
Definition: outputparameters.h:145
smash::FourVector
Definition: fourvector.h:33
smash::pdg::p
constexpr int p
Proton.
Definition: pdgcode_constants.h:28
smash::Action::incoming_particles
const ParticleList & incoming_particles() const
Get the list of particles that go into the action.
Definition: action.cc:57
smash::OscarParticlesAtEventend
store the state at the end of each event (at_eventend)
Definition: oscaroutput.h:50
smash::ParticleData::type
const ParticleType & type() const
Get the type of the particle.
Definition: particledata.h:122
smash::ParticleType::charge
int32_t charge() const
The charge of the particle.
Definition: particletype.h:188
smash::OutputParameters::dil_extended
bool dil_extended
Extended format for dilepton output.
Definition: outputparameters.h:154