Version: SMASH-3.4
thermodynamicoutput.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2022,2026
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
11 
12 #include <filesystem>
13 #include <fstream>
14 #include <memory>
15 
16 #include "smash/clock.h"
17 #include "smash/config.h"
18 #include "smash/density.h"
21 #include "smash/vtkoutput.h"
22 
23 namespace smash {
24 
25 /*!\Userguide
26  * \page doxypage_output_thermodyn
27  *
28  * The thermodynamics output (thermodynamics.dat) is used to output either:
29  * \li thermodynamic quantities at one point (\key Smearing: on)
30  * \li thermodynamic quantities averaged over every particle
31  * in an event (\key Smearing: off - mostly useful for box setups).
32  *
33  * Smearing can be switched on or off in the configuration file, see
34  * \ref input_output_content_specific_ "content-specific output options".
35  *
36  * The calculated quantities of the file can include: the Eckart density, the
37  * energy-momentum tensor in the lab and/or Landau frame, the Landau
38  * velocity and the electric/baryonic/strange currents (they will also be
39  * outputted in this order); note that the
40  * Eckart density is currently not affected by turning smearing off, and
41  * will always return the density at a point.
42  * \n
43  * Which of these quantities are outputted needs to be specified in the config
44  * file. They will be calculated using **one** of the following density types:
45  * hadron, baryon, baryonic isospin, pion, or none.\n
46  * The output file does contain any information about whether all hadrons are
47  * included or \ref key_output_thermo_only_part_ "only participants".
48  *
49  * The format of the file is the following: \n
50  *
51  * \n
52  * **Header in case of evaluation at one point**
53  * \code
54  * # **smash_version** thermodynamics output
55  * # @ point ( **position** ) [fm]
56  * # **density_type**
57  * # time [fm], ** a list of all columns that will be printed, + units **
58  * \endcode
59  *
60  * The header consists of 4 lines starting with a '#', containing the following
61  * information:
62  * -# SMASH-version and the information, that 'thermodynamic output' is provided
63  * -# The point of evaluation
64  * -# The density type, as specified in the config file
65  * -# The header with all column names
66  *
67  * \n
68  * **Header in case of average over the entire volume**
69  * \code
70  * # **smash_version** thermodynamics output
71  * # averaged over the entire volume
72  * # **density_type**
73  * # time [fm], ** a list of all columns that will be printed, + units **
74  * \endcode
75  *
76  * The header consists of 4 lines starting with a '#', containing the following
77  * information:
78  * -# SMASH-version and the information, that 'thermodynamic output' is provided
79  * -# The info that the quantities are 'averaged over the entire volume'
80  * -# The density type, as specified in the config file
81  * -# The header with all column names
82  *
83  * \n
84  * **Event Header** \n
85  * Each event is indicated with an event starting line:
86  * \code
87  * # event number
88  * \endcode
89  * where
90  * \li \key number: Event number
91  *
92  * Note, that 'event' is not a variable but a word that is printed. \n
93  *
94  * The event indication line is followed by the data lines formatted as:
95  * <div class="fragment">
96  * <div class="line"> <span class="preprocessor">
97  * time [density] [10 cols Tmunu_Lab] [10 cols Tmunu_Landau] [3 cols v_Landau]
98  * [4 cols el_current] [4 cols bar_current] [4 cols str_current] </span></div>
99  * </div>
100  * where
101  * \li \key density: The density specified in the configuration file.
102  * \li \key Tmunu_Lab: Energy-momentum tensor in the lab frame (10 columns).
103  * \li \key Tmunu_Landau: Energy-momentum tensor in the Landau frame
104  * (10 columns).
105  * \li \key v_Landau: The velocity in Landau frame (3 columns).
106  * \li \key el_current: The electric current in the lab frame (4 columns).
107  * \li \key bar_current: The baryonic current in the lab frame (4 columns).
108  * \li \key str_current: The strange current in the lab frame (4 columns).
109  *
110  * Note that the number of columns depends on what was specified in the
111  * configuration file,
112  * i.e. all quantities in brackets will only be there if specifically asked for.
113  */
114 
115 ThermodynamicOutput::ThermodynamicOutput(const std::filesystem::path &path,
116  const std::string &name,
117  const OutputParameters &out_par)
118  : OutputInterface(name),
119  file_{path / "thermodynamics.dat", "w"},
120  out_par_(out_par) {
121  std::fprintf(file_.get(), "# %s thermodynamics output\n", SMASH_VERSION);
122  const ThreeVector r = out_par.td_position;
124  std::fprintf(file_.get(), "# only participants are taken into account\n");
125  }
126  if (out_par_.td_smearing) {
127  std::fprintf(file_.get(), "# @ point (%6.2f, %6.2f, %6.2f) [fm]\n", r.x1(),
128  r.x2(), r.x3());
129  } else {
130  std::fprintf(file_.get(), "# averaged over the entire volume\n");
131  }
132  std::fprintf(file_.get(), "# %s\n", to_string(out_par.td_dens_type));
133  std::fprintf(file_.get(), "# time [fm], ");
134  if (out_par_.td_rho_eckart) {
135  std::fprintf(file_.get(), "%s [fm^-3], ",
137  }
138  if (out_par_.td_tmn) {
139  if (out_par_.td_smearing) {
140  std::fprintf(file_.get(), "%s [GeV/fm^3] 00 01 02 03 11 12 13 22 23 33, ",
142  } else {
143  std::fprintf(file_.get(), "%s [GeV] 00 01 02 03 11 12 13 22 23 33, ",
145  }
146  }
147  if (out_par_.td_tmn_landau) {
148  if (out_par_.td_smearing) {
149  std::fprintf(file_.get(), "%s [GeV/fm^3] 00 01 02 03 11 12 13 22 23 33, ",
151  } else {
152  std::fprintf(file_.get(), "%s [GeV] 00 01 02 03 11 12 13 22 23 33, ",
154  }
155  }
156  if (out_par_.td_v_landau) {
157  std::fprintf(file_.get(), "%s x y z, ",
159  }
160  if (out_par_.td_jQBS) {
161  if (out_par_.td_smearing) {
162  std::fprintf(file_.get(), "j_QBS [(Q,B,S)/fm^3] (0 1 2 3)x3");
163  } else {
164  std::fprintf(file_.get(), "j_QBS [(Q,B,S)] (0 1 2 3)x3");
165  }
166  }
167  std::fprintf(file_.get(), "\n");
168 }
169 
171 
173  const std::vector<Particles> & /*particles*/, const int event_number) {
174  std::fprintf(file_.get(), "# event %i\n", event_number);
175 }
176 
178  const std::vector<Particles> & /*particles*/, const int /*event_number*/) {
179  std::fflush(file_.get());
180 }
181 
183  const std::vector<Particles> &ensembles,
184  const std::unique_ptr<Clock> &clock, const DensityParameters &dens_param) {
185  std::fprintf(file_.get(), "%6.2f ", clock->current_time());
186  constexpr bool compute_gradient = false;
187  if (out_par_.td_rho_eckart) {
188  FourVector jmu = FourVector();
189  for (const Particles &particles : ensembles) {
190  jmu += std::get<1>(current_eckart(
191  out_par_.td_position, particles, dens_param, out_par_.td_dens_type,
192  compute_gradient, out_par_.td_smearing));
193  }
194  std::fprintf(file_.get(), "%15.12f ", jmu.abs());
195  }
198  for (const Particles &particles : ensembles) {
199  for (const auto &p : particles) {
200  if (dens_param.only_participants()) {
201  // if this condition holds, the hadron is a spectator and we skip it
202  if (p.get_history().collisions_per_particle == 0) {
203  continue;
204  }
205  }
206  if (dens_param.ignore_unformed()) {
207  if (p.xsec_scaling_factor() < 1) {
208  continue;
209  }
210  }
211  const double dens_factor =
213  if (std::abs(dens_factor) < really_small) {
214  continue;
215  }
216  if (out_par_.td_smearing) {
217  const auto sf =
219  p.position().threevec() - out_par_.td_position, p.momentum(),
220  1.0 / p.momentum().abs(), dens_param, compute_gradient)
221  .first;
222  if (sf < really_small) {
223  continue;
224  }
225  Tmn.add_particle(p, dens_factor * sf * dens_param.norm_factor_sf());
226  } else {
227  Tmn.add_particle(p, dens_factor);
228  }
229  }
230  }
231  const FourVector u = Tmn.landau_frame_4velocity();
232  const EnergyMomentumTensor Tmn_L = Tmn.boosted(u);
233  if (out_par_.td_tmn) {
234  for (int i = 0; i < 10; i++) {
235  std::fprintf(file_.get(), "%15.12f ", Tmn[i]);
236  }
237  }
238  if (out_par_.td_tmn_landau) {
239  for (int i = 0; i < 10; i++) {
240  std::fprintf(file_.get(), "%15.12f ", Tmn_L[i]);
241  }
242  }
243  if (out_par_.td_v_landau) {
244  std::fprintf(file_.get(), "%15.12f %15.12f %15.12f ", -u[1] / u[0],
245  -u[2] / u[0], -u[3] / u[0]);
246  }
247  }
248  if (out_par_.td_jQBS) {
249  FourVector jQ = FourVector(), jB = FourVector(), jS = FourVector();
250  for (const Particles &particles : ensembles) {
251  jQ += std::get<1>(current_eckart(out_par_.td_position, particles,
252  dens_param, DensityType::Charge,
253  compute_gradient, out_par_.td_smearing));
254  jB += std::get<1>(current_eckart(out_par_.td_position, particles,
255  dens_param, DensityType::Baryon,
256  compute_gradient, out_par_.td_smearing));
257  jS += std::get<1>(current_eckart(out_par_.td_position, particles,
258  dens_param, DensityType::Strangeness,
259  compute_gradient, out_par_.td_smearing));
260  }
261  std::fprintf(file_.get(), "%15.12f %15.12f %15.12f %15.12f ", jQ[0], jQ[1],
262  jQ[2], jQ[3]);
263  std::fprintf(file_.get(), "%15.12f %15.12f %15.12f %15.12f ", jB[0], jB[1],
264  jB[2], jB[3]);
265  std::fprintf(file_.get(), "%15.12f %15.12f %15.12f %15.12f ", jS[0], jS[1],
266  jS[2], jS[3]);
267  }
268  std::fprintf(file_.get(), "\n");
269 }
270 
272  const char *file_name, const ParticleList &plist,
273  const DensityParameters &param, DensityType dens_type,
274  const ThreeVector &line_start, const ThreeVector &line_end, int n_points) {
275  ThreeVector r;
276  std::ofstream a_file;
277  a_file.open(file_name, std::ios::out);
278  const bool compute_gradient = false;
279  const bool smearing = true;
280 
281  for (int i = 0; i <= n_points; i++) {
282  r = line_start + (line_end - line_start) * (1.0 * i / n_points);
283  double rho_eck = std::get<0>(
284  current_eckart(r, plist, param, dens_type, compute_gradient, smearing));
285  a_file << r.x1() << " " << r.x2() << " " << r.x3() << " " << rho_eck
286  << "\n";
287  }
288 }
289 
290 } // namespace smash
A class to pre-calculate and store parameters relevant for density calculation.
Definition: density.h:92
bool ignore_unformed() const
Definition: density.h:156
bool only_participants() const
Definition: density.h:154
double norm_factor_sf() const
Definition: density.h:152
The EnergyMomentumTensor class represents a symmetric positive semi-definite energy-momentum tensor .
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
double abs() const
calculate the lorentz invariant absolute value
Definition: fourvector.h:464
Abstraction of generic output.
const char * to_string(const ThermodynamicQuantity tq)
Convert thermodynamic quantities to strings.
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
FILE * get()
Get the underlying FILE* pointer.
Definition: file.cc:27
void at_eventend(const std::vector< Particles > &ensembles, const int event_number) override
Only flush the output the file.
void density_along_line(const char *file_name, const ParticleList &plist, const DensityParameters &param, DensityType dens_type, const ThreeVector &line_start, const ThreeVector &line_end, int n_points)
Print density along the specified line.
ThermodynamicOutput(const std::filesystem::path &path, const std::string &name, const OutputParameters &out_par)
Construct Output param[in] path Path to output param[in] name Filename param[in] out_par Parameters o...
void at_intermediate_time(const std::vector< Particles > &ensembles, const std::unique_ptr< Clock > &clock, const DensityParameters &dens_param) override
Write thermodynamics every fixed time interval.
void at_eventstart(const std::vector< Particles > &ensembles, const int event_number) override
Write the event header.
RenamingFilePtr file_
Pointer to output file.
const OutputParameters out_par_
Structure that holds all the information about what to printout.
~ThermodynamicOutput()
Default destructor.
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:31
double x3() const
Definition: threevector.h:194
double x2() const
Definition: threevector.h:190
double x1() const
Definition: threevector.h:186
@ EckartDensity
Density in the Eckart frame.
@ Tmn
Energy-momentum tensor in lab frame.
@ LandauVelocity
Velocity of the Landau rest frame.
@ TmnLandau
Energy-momentum tensor in Landau rest frame.
DensityType
Allows to choose which kind of density to calculate.
constexpr int p
Proton.
Definition: action.h:24
std::tuple< double, FourVector, ThreeVector, ThreeVector, FourVector, FourVector, FourVector, FourVector > current_eckart(const ThreeVector &r, const ParticleList &plist, const DensityParameters &par, DensityType dens_type, bool compute_gradient, bool smearing)
Calculates Eckart rest frame density and 4-current of a given density type and optionally the gradien...
Definition: density.cc:176
std::pair< double, ThreeVector > unnormalized_smearing_factor(const ThreeVector &r, const FourVector &p, const double m_inv, const DensityParameters &dens_par, const bool compute_gradient=false)
Implements gaussian smearing for any quantity.
Definition: density.cc:38
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:41
double density_factor(const ParticleType &type, DensityType dens_type)
Get the factor that determines how much a particle contributes to the density type that is computed.
Definition: density.cc:17
Helper structure for Experiment to hold output options and parameters.
bool td_v_landau
Print out Landau velocity of type td_dens_type or not?
bool td_tmn_landau
Print out energy-momentum tensor in Landau rest frame (of type td_dens_type) or not?
bool td_jQBS
Print out QBS 4-currents or not?
DensityType td_dens_type
Type (e.g., baryon/pion/hadron) of thermodynamic quantity.
bool td_tmn
Print out energy-momentum tensor of type td_dens_type or not?
bool td_smearing
Whether smearing is on or off; WARNING : if smearing is off, then final result is in GeV instead of G...
bool td_rho_eckart
Print out Eckart rest frame density of type td_dens_type or not?
bool td_only_participants
Flag reporting whether only participants are considered (true) or also spectators (false)
ThreeVector td_position
Point, where thermodynamic quantities are calculated.