Version: SMASH-3.0
oscaroutput.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2023
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/oscaroutput.h"
11 
12 #include <filesystem>
13 #include <string>
14 
15 #include "smash/action.h"
16 #include "smash/clock.h"
17 #include "smash/config.h"
19 
20 namespace smash {
21 static constexpr int LHyperSurfaceCrossing = LogArea::HyperSurfaceCrossing::id;
22 
23 template <OscarOutputFormat Format, int Contents>
24 OscarOutput<Format, Contents>::OscarOutput(const std::filesystem::path &path,
25  const std::string &name)
26  : OutputInterface(name),
27  file_{path /
28  (name + ".oscar" + ((Format == OscarFormat1999) ? "1999" : "")),
29  "w"} {
79  if (Format == OscarFormat2013) {
80  std::fprintf(file_.get(),
81  "#!OSCAR2013 %s t x y z mass "
82  "p0 px py pz pdg ID charge\n",
83  name.c_str());
84  std::fprintf(file_.get(),
85  "# Units: fm fm fm fm "
86  "GeV GeV GeV GeV GeV none none e\n");
87  std::fprintf(file_.get(), "# %s\n", SMASH_VERSION);
88  } else if (Format == OscarFormat2013Extended) {
89  std::fprintf(file_.get(),
90  "#!OSCAR2013Extended %s t x y z mass p0 px py pz"
91  " pdg ID charge ncoll form_time xsecfac proc_id_origin"
92  " proc_type_origin time_last_coll pdg_mother1 pdg_mother2"
93  " baryon_number\n",
94  name.c_str());
95  std::fprintf(file_.get(),
96  "# Units: fm fm fm fm GeV GeV GeV GeV GeV"
97  " none none e none fm none none none fm none none none\n");
98  std::fprintf(file_.get(), "# %s\n", SMASH_VERSION);
99  } else {
100  const std::string &oscar_name =
101  name == "particle_lists" ? "final_id_p_x" : name;
102  // This is necessary because OSCAR199A requires
103  // this particular string for particle output.
104 
105  std::fprintf(file_.get(), "# OSC1999A\n# %s\n# %s\n", oscar_name.c_str(),
106  SMASH_VERSION);
107  std::fprintf(file_.get(), "# Block format:\n");
108  std::fprintf(file_.get(), "# nin nout event_number\n");
109  std::fprintf(file_.get(), "# id pdg 0 px py pz p0 mass x y z t\n");
110  std::fprintf(file_.get(),
111  "# End of event: 0 0 event_number"
112  " impact_parameter\n");
113  std::fprintf(file_.get(), "#\n");
114  }
115 }
116 
117 template <OscarOutputFormat Format, int Contents>
118 inline void OscarOutput<Format, Contents>::write(const Particles &particles) {
119  for (const ParticleData &data : particles) {
120  write_particledata(data);
121  }
122 }
123 
124 template <OscarOutputFormat Format, int Contents>
126  const int event_number,
127  const EventInfo &) {
128  current_event_ = event_number;
129  if (Contents & OscarAtEventstart) {
130  if (Format == OscarFormat2013 || Format == OscarFormat2013Extended) {
131  std::fprintf(file_.get(), "# event %i in %zu\n", event_number,
132  particles.size());
133  } else {
134  /* OSCAR line prefix : initial particles; final particles; event id
135  * First block of an event: initial = 0, final = number of particles
136  */
137  const size_t zero = 0;
138  std::fprintf(file_.get(), "%zu %zu %i\n", zero, particles.size(),
139  event_number);
140  }
141  if (!(Contents & OscarParticlesIC)) {
142  // We do not want the inital particle list to be printed in case of IC
143  // output
144  write(particles);
145  }
146  }
147 }
148 
149 template <OscarOutputFormat Format, int Contents>
151  const int event_number,
152  const EventInfo &event) {
153  if (Format == OscarFormat2013 || Format == OscarFormat2013Extended) {
154  if (Contents & OscarParticlesAtEventend ||
155  (Contents & OscarParticlesAtEventendIfNotEmpty && !event.empty_event)) {
156  std::fprintf(file_.get(), "# event %i out %zu\n", event_number,
157  particles.size());
158  write(particles);
159  }
160  // Comment end of an event
161  const char *empty_event_str = event.empty_event ? "no" : "yes";
162  std::fprintf(
163  file_.get(),
164  "# event %i end 0 impact %7.3f scattering_projectile_target %s\n",
165  event_number, event.impact_parameter, empty_event_str);
166  } else {
167  /* OSCAR line prefix : initial particles; final particles; event id
168  * Last block of an event: initial = number of particles, final = 0
169  * Block ends with null interaction. */
170  const size_t zero = 0;
171  if (Contents & OscarParticlesAtEventend ||
172  (Contents & OscarParticlesAtEventendIfNotEmpty && !event.empty_event)) {
173  std::fprintf(file_.get(), "%zu %zu %i\n", particles.size(), zero,
174  event_number);
175  write(particles);
176  }
177  // Null interaction marks the end of an event
178  std::fprintf(file_.get(), "%zu %zu %i %7.3f\n", zero, zero, event_number,
179  event.impact_parameter);
180  }
181  // Flush to disk
182  std::fflush(file_.get());
183 
184  if (Contents & OscarParticlesIC) {
185  // If the runtime is too short some particles might not yet have
186  // reached the hypersurface. Warning is printed.
187  if (particles.size() != 0 && !event.impose_kinematic_cut_for_SMASH_IC) {
189  "End time might be too small for initial conditions output. "
190  "Hypersurface has not yet been crossed by ",
191  particles.size(), " particle(s).");
192  }
193  }
194 }
195 
196 template <OscarOutputFormat Format, int Contents>
198  const double density) {
199  if (Contents & OscarInteractions) {
200  if (Format == OscarFormat2013 || Format == OscarFormat2013Extended) {
201  std::fprintf(file_.get(),
202  "# interaction in %zu out %zu rho %12.7f weight %12.7g"
203  " partial %12.7f type %5i\n",
204  action.incoming_particles().size(),
205  action.outgoing_particles().size(), density,
206  action.get_total_weight(), action.get_partial_weight(),
207  static_cast<int>(action.get_type()));
208  } else {
209  /* OSCAR line prefix : initial final
210  * particle creation: 0 1
211  * particle 2<->2 collision: 2 2
212  * resonance formation: 2 1
213  * resonance decay: 1 2
214  * etc.*/
215  std::fprintf(file_.get(), "%zu %zu %12.7f %12.7f %12.7f %5i\n",
216  action.incoming_particles().size(),
217  action.outgoing_particles().size(), density,
218  action.get_total_weight(), action.get_partial_weight(),
219  static_cast<int>(action.get_type()));
220  }
221  for (const auto &p : action.incoming_particles()) {
222  write_particledata(p);
223  }
224  for (const auto &p : action.outgoing_particles()) {
225  write_particledata(p);
226  }
227  } else if (Contents & OscarParticlesIC) {
228  for (const auto &p : action.incoming_particles()) {
229  write_particledata(p);
230  }
231  }
232 }
233 
234 template <OscarOutputFormat Format, int Contents>
236  const Particles &particles, const std::unique_ptr<Clock> &,
237  const DensityParameters &, const EventInfo &) {
238  if (Contents & OscarTimesteps) {
239  if (Format == OscarFormat2013 || Format == OscarFormat2013Extended) {
240  std::fprintf(file_.get(), "# event %i out %zu\n", current_event_,
241  particles.size());
242  } else {
243  const size_t zero = 0;
244  std::fprintf(file_.get(), "%zu %zu %i\n", particles.size(), zero,
245  current_event_);
246  }
247  write(particles);
248  }
249 }
250 
744 template <OscarOutputFormat Format, int Contents>
746  const ParticleData &data) {
747  const FourVector pos = data.position();
748  const FourVector mom = data.momentum();
749  if (Format == OscarFormat2013) {
750  std::fprintf(file_.get(), "%g %g %g %g %g %.9g %.9g %.9g %.9g %s %i %i\n",
751  pos.x0(), pos.x1(), pos.x2(), pos.x3(), data.effective_mass(),
752  mom.x0(), mom.x1(), mom.x2(), mom.x3(),
753  data.pdgcode().string().c_str(), data.id(),
754  data.type().charge());
755  } else if (Format == OscarFormat2013Extended) {
756  const auto h = data.get_history();
757  std::fprintf(file_.get(),
758  "%g %g %g %g %g %.9g %.9g %.9g"
759  " %.9g %s %i %i %i %g %g %i %i %g %s %s %i\n",
760  pos.x0(), pos.x1(), pos.x2(), pos.x3(), data.effective_mass(),
761  mom.x0(), mom.x1(), mom.x2(), mom.x3(),
762  data.pdgcode().string().c_str(), data.id(),
763  data.type().charge(), h.collisions_per_particle,
764  data.formation_time(), data.xsec_scaling_factor(),
765  h.id_process, static_cast<int>(h.process_type),
766  h.time_last_collision, h.p1.string().c_str(),
767  h.p2.string().c_str(), data.type().baryon_number());
768  } else {
769  std::fprintf(file_.get(), "%i %s %i %g %g %g %g %g %g %g %g %g\n",
770  data.id(), data.pdgcode().string().c_str(), 0, mom.x1(),
771  mom.x2(), mom.x3(), mom.x0(), data.effective_mass(), pos.x1(),
772  pos.x2(), pos.x3(), pos.x0());
773  }
774 }
775 
776 namespace {
788 template <int Contents>
789 std::unique_ptr<OutputInterface> create_select_format(
790  bool modern_format, const std::filesystem::path &path,
791  const OutputParameters &out_par, const std::string &name) {
792  bool extended_format = (Contents & OscarInteractions) ? out_par.coll_extended
793  : out_par.part_extended;
794  if (modern_format && extended_format) {
795  return std::make_unique<OscarOutput<OscarFormat2013Extended, Contents>>(
796  path, name);
797  } else if (modern_format && !extended_format) {
798  return std::make_unique<OscarOutput<OscarFormat2013, Contents>>(path, name);
799  } else if (!modern_format && !extended_format) {
800  return std::make_unique<OscarOutput<OscarFormat1999, Contents>>(path, name);
801  } else {
802  // Only remaining possibility: (!modern_format && extended_format)
803  logg[LOutput].warn() << "Creating Oscar output: "
804  << "There is no extended Oscar1999 format.";
805  return std::make_unique<OscarOutput<OscarFormat1999, Contents>>(path, name);
806  }
807 }
808 } // unnamed namespace
809 
810 std::unique_ptr<OutputInterface> create_oscar_output(
811  const std::string &format, const std::string &content,
812  const std::filesystem::path &path, const OutputParameters &out_par) {
813  if (format != "Oscar2013" && format != "Oscar1999") {
814  throw std::invalid_argument("Creating Oscar output: unknown format");
815  }
816  const bool modern_format = (format == "Oscar2013");
817  if (content == "Particles") {
818  if (out_par.part_only_final == OutputOnlyFinal::Yes) {
819  return create_select_format<OscarParticlesAtEventend>(
820  modern_format, path, out_par, "particle_lists");
821  } else if (out_par.part_only_final == OutputOnlyFinal::IfNotEmpty) {
822  return create_select_format<OscarParticlesAtEventendIfNotEmpty>(
823  modern_format, path, out_par, "particle_lists");
824 
825  } else { // out_par.part_only_final == OutputOnlyFinal::No
828  modern_format, path, out_par, "particle_lists");
829  }
830  } else if (content == "Collisions") {
831  if (out_par.coll_printstartend) {
834  modern_format, path, out_par, "full_event_history");
835  } else {
836  return create_select_format<OscarInteractions>(
837  modern_format, path, out_par, "full_event_history");
838  }
839  } else if (content == "Dileptons") {
840  if (modern_format && out_par.dil_extended) {
841  return std::make_unique<
843  "Dileptons");
844  } else if (modern_format && !out_par.dil_extended) {
845  return std::make_unique<OscarOutput<OscarFormat2013, OscarInteractions>>(
846  path, "Dileptons");
847  } else if (!modern_format && !out_par.dil_extended) {
848  return std::make_unique<OscarOutput<OscarFormat1999, OscarInteractions>>(
849  path, "Dileptons");
850  } else if (!modern_format && out_par.dil_extended) {
851  logg[LOutput].warn()
852  << "Creating Oscar output: "
853  << "There is no extended Oscar1999 (dileptons) format.";
854  }
855  } else if (content == "Photons") {
856  if (modern_format && !out_par.photons_extended) {
857  return std::make_unique<OscarOutput<OscarFormat2013, OscarInteractions>>(
858  path, "Photons");
859  } else if (modern_format && out_par.photons_extended) {
860  return std::make_unique<
862  "Photons");
863  } else if (!modern_format && !out_par.photons_extended) {
864  return std::make_unique<OscarOutput<OscarFormat1999, OscarInteractions>>(
865  path, "Photons");
866  } else if (!modern_format && out_par.photons_extended) {
867  logg[LOutput].warn()
868  << "Creating Oscar output: "
869  << "There is no extended Oscar1999 (photons) format.";
870  }
871  } else if (content == "Initial_Conditions") {
872  if (modern_format && !out_par.ic_extended) {
873  return std::make_unique<
875  path, "SMASH_IC");
876  } else if (modern_format && out_par.ic_extended) {
877  return std::make_unique<OscarOutput<
879  path, "SMASH_IC");
880  } else if (!modern_format && !out_par.ic_extended) {
881  return std::make_unique<
883  path, "SMASH_IC");
884  } else if (!modern_format && out_par.ic_extended) {
885  logg[LOutput].warn()
886  << "Creating Oscar output: "
887  << "There is no extended Oscar1999 (initial conditions) format.";
888  }
889  }
890 
891  throw std::invalid_argument("Create_oscar_output got unknown content.");
892 }
893 
894 } // 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
A class to pre-calculate and store parameters relevant for density calculation.
Definition: density.h:108
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
double x3() const
Definition: fourvector.h:325
double x2() const
Definition: fourvector.h:321
double x0() const
Definition: fourvector.h:313
double x1() const
Definition: fourvector.h:317
Abstraction of generic output.
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:58
PdgCode pdgcode() const
Get the pdgcode of the particle.
Definition: particledata.h:87
const ParticleType & type() const
Get the type of the particle.
Definition: particledata.h:128
double xsec_scaling_factor(double delta_time=0.) const
Return the cross section scaling factor at a given time.
Definition: particledata.cc:85
const FourVector & momentum() const
Get the particle's 4-momentum.
Definition: particledata.h:158
double formation_time() const
Get the absolute formation time of the particle.
Definition: particledata.h:236
double effective_mass() const
Get the particle's effective mass.
Definition: particledata.cc:23
int32_t id() const
Get the id of the particle.
Definition: particledata.h:76
HistoryData get_history() const
Get history information.
Definition: particledata.h:139
const FourVector & position() const
Get the particle's position in Minkowski space.
Definition: particledata.h:204
int32_t charge() const
The charge of the particle.
Definition: particletype.h:188
int baryon_number() const
Definition: particletype.h:209
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
size_t size() const
Definition: particles.h:87
std::string string() const
Definition: pdgcode.h:324
@ IfNotEmpty
Print only final-state particles, and those only if the event is not empty.
@ Yes
Print only final-state particles.
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
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:214
std::unique_ptr< OutputInterface > create_oscar_output(const std::string &format, const std::string &content, const std::filesystem::path &path, const OutputParameters &out_par)
Definition: oscaroutput.cc:810
OscarOutput(const std::filesystem::path &path, const std::string &name)
Create oscar output.
@ OscarParticlesAtEventend
store the state at the end of each event (at_eventend)
Definition: oscaroutput.h:50
@ OscarParticlesAtEventendIfNotEmpty
store the state at the end of each event if it is not empty (at_eventend)
Definition: oscaroutput.h:52
@ OscarAtEventstart
store the state at the start of each event (at_eventstart)
Definition: oscaroutput.h:48
@ OscarInteractions
store interaction information (write_interaction)
Definition: oscaroutput.h:44
@ OscarParticlesIC
store the particles that are removed on the hypersurface
Definition: oscaroutput.h:54
@ OscarTimesteps
store the state after N timesteps (after_Nth_timestep)
Definition: oscaroutput.h:46
@ OscarFormat1999
Definition: oscaroutput.h:32
@ OscarFormat2013Extended
Definition: oscaroutput.h:31
@ OscarFormat2013
Definition: oscaroutput.h:30
std::unique_ptr< OutputInterface > create_select_format(bool modern_format, const std::filesystem::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:789
constexpr int p
Proton.
Definition: action.h:24
static constexpr int LHyperSurfaceCrossing
Definition: binaryoutput.cc:21
static constexpr int LOutput
Structure to contain custom data for output.
bool empty_event
True if no collisions happened.
bool impose_kinematic_cut_for_SMASH_IC
Whether or not kinematic cuts are employed for SMASH IC.
double impact_parameter
Impact parameter for collider modus, otherwise dummy.
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.
OutputOnlyFinal part_only_final
Print only final particles in event.
bool ic_extended
Extended initial conditions output.
bool coll_printstartend
Print initial and final particles in event into collision output.