Version: SMASH-3.4
vtkoutput.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2022,2024-2026
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/vtkoutput.h"
11 
12 #include <fstream>
13 #include <memory>
14 #include <utility>
15 
16 #include "smash/clock.h"
17 #include "smash/config.h"
18 #include "smash/file.h"
20 #include "smash/particles.h"
21 
22 namespace smash {
23 
24 VtkOutput::VtkOutput(const std::filesystem::path &path, const std::string &name,
25  const OutputParameters &out_par)
26  : OutputInterface(name),
27  base_path_(std::move(path)),
28  is_thermodynamics_output_(name == "Thermodynamics"),
29  is_fields_output_(name == "Fields") {
30  if (out_par.part_extended) {
31  logg[LOutput].warn()
32  << "Creating VTK output: There is no extended VTK format.";
33  }
34 }
35 
37 
38 /*!\Userguide
39  * \page doxypage_output_vtk
40  *
41  * In general, VTK is a very versatile format which allows many possible
42  * structures. For information on the generic VTK format, please visit
43  * <a href="http://vtk.org">the official VTK website</a>. VTK output is known to
44  * work with <a href="http://paraview.org">ParaView</a>, a free visualization
45  * and data analysis software. Files of this format are supposed to be used as a
46  * black box and opened with <a href="http://paraview.org">ParaView</a>, but at
47  * the same time they are human-readable text files. This page describes only
48  * SMASH-specific VTK format.
49  *
50  * SMASH VTK files contain a snapshot of the simulation for a certain output
51  * time step. VTK output files are written at the initialization of an event,
52  * i.e. the starting time of an event, and at every output time step specified
53  * by either \ref key_output_out_interval_ "Output_Interval" or \ref
54  * key_output_out_times_ "Output_Times". For every output time step a separate
55  * VTK file is written.
56  *
57  * VTK output is currently implemented for the following \ref output_contents_
58  * "output contents":
59  *
60  * - \b %Particles:
61  * - Filename structure:
62  * `pos_ev<event>_ens<ensemble>_tstep<timestep_counter>.vtk`
63  * - Files contain particle coordinates, momenta, PDG codes,
64  * cross-section scaling factors, information if a particle is already
65  * formed, ID, number of collisions, baryon number, strangeness, and
66  * masses.
67  *
68  * - \b Coulomb:
69  * - Filename structure:
70  * - Electric field: `Efield_<event>_tstep<timestep_counter>.vtk`
71  * - Magnetic field: `Bfield_<event>_tstep<timestep_counter>.vtk`
72  * - Files contain a three vector per lattice cell for the fields.
73  * This output requires a \ref doxypage_input_conf_lattice and
74  * \ref doxypage_input_conf_pot_coulomb "coulomb potential" in the
75  * configuration file.
76  *
77  * - \b Thermodynamics:
78  * - Density on the lattice can be printed out in the VTK format of
79  * structured grid.
80  * - Filename structure:
81  * `<density_type>_<density_name>_<event_number>_tstep<timestep_counter>.vtk`
82  * - Additionally to density, energy-momentum tensor \f$T^{\mu\nu}\f$,
83  * energy-momentum tensor in Landau rest frame \f$T^{\mu\nu}_L \f$
84  * and velocity of Landau rest frame \f$v_L\f$ on the lattice can be
85  * printed out in the VTK format of structured grid.
86  * - Filename structure:
87  * `<density_type>_<quantity>_<event_number>_tstep<timestep_counter>.vtk`
88  *
89  * For the possible output configurations see
90  * \ref input_output_content_specific_ "content-specific output options".
91  */
92 
93 void VtkOutput::at_eventstart(const Particles &particles,
94  const EventLabel &event_label,
95  const EventInfo &) {
101 
102  current_event_ = event_label.event_number;
103  current_ensemble_ = event_label.ensemble_number;
106  write(particles);
108  }
109 }
110 
111 void VtkOutput::at_eventend(const Particles & /*particles*/,
112  const EventLabel & /*event_number*/,
113  const EventInfo &) {}
114 
116  const std::unique_ptr<Clock> &,
117  const DensityParameters &,
118  const EventLabel &event_label,
119  const EventInfo &) {
120  current_event_ = event_label.event_number;
121  current_ensemble_ = event_label.ensemble_number;
123  write(particles);
125  }
126 }
127 
128 void VtkOutput::write(const Particles &particles) {
129  char filename[64];
130  snprintf(filename, sizeof(filename), "pos_ev%05i_ens%05i_tstep%05i.vtk",
133  FilePtr file_{std::fopen((base_path_ / filename).native().c_str(), "w")};
134 
135  /* Legacy VTK file format */
136  std::fprintf(file_.get(), "# vtk DataFile Version 2.0\n");
137  std::fprintf(file_.get(), "Generated from molecular-offset data %s\n",
138  SMASH_VERSION);
139  std::fprintf(file_.get(), "ASCII\n");
140 
141  /* Unstructured data sets are composed of points, lines, polygons, .. */
142  std::fprintf(file_.get(), "DATASET UNSTRUCTURED_GRID\n");
143  std::fprintf(file_.get(), "POINTS %zu double\n", particles.size());
144  for (const auto &p : particles) {
145  std::fprintf(file_.get(), "%g %g %g\n", p.position().x1(),
146  p.position().x2(), p.position().x3());
147  }
148  std::fprintf(file_.get(), "CELLS %zu %zu\n", particles.size(),
149  particles.size() * 2);
150  for (size_t point_index = 0; point_index < particles.size(); point_index++) {
151  std::fprintf(file_.get(), "1 %zu\n", point_index);
152  }
153  std::fprintf(file_.get(), "CELL_TYPES %zu\n", particles.size());
154  for (size_t point_index = 0; point_index < particles.size(); point_index++) {
155  std::fprintf(file_.get(), "1\n");
156  }
157  std::fprintf(file_.get(), "POINT_DATA %zu\n", particles.size());
158  std::fprintf(file_.get(), "SCALARS pdg_codes int 1\n");
159  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
160  for (const auto &p : particles) {
161  std::fprintf(file_.get(), "%s\n", p.pdgcode().string().c_str());
162  }
163  std::fprintf(file_.get(), "SCALARS is_formed int 1\n");
164  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
165  double current_time = particles.time();
166  for (const auto &p : particles) {
167  std::fprintf(file_.get(), "%s\n",
168  (p.formation_time() > current_time) ? "0" : "1");
169  }
170  std::fprintf(file_.get(), "SCALARS cross_section_scaling_factor double 1\n");
171  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
172  for (const auto &p : particles) {
173  std::fprintf(file_.get(), "%g\n", p.xsec_scaling_factor());
174  }
175  std::fprintf(file_.get(), "SCALARS mass double 1\n");
176  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
177  for (const auto &p : particles) {
178  std::fprintf(file_.get(), "%g\n", p.effective_mass());
179  }
180  std::fprintf(file_.get(), "SCALARS N_coll int 1\n");
181  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
182  for (const auto &p : particles) {
183  std::fprintf(file_.get(), "%i\n", p.get_history().collisions_per_particle);
184  }
185  std::fprintf(file_.get(), "SCALARS particle_ID int 1\n");
186  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
187  for (const auto &p : particles) {
188  std::fprintf(file_.get(), "%i\n", p.id());
189  }
190  std::fprintf(file_.get(), "SCALARS baryon_number int 1\n");
191  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
192  for (const auto &p : particles) {
193  std::fprintf(file_.get(), "%i\n", p.pdgcode().baryon_number());
194  }
195  std::fprintf(file_.get(), "SCALARS strangeness int 1\n");
196  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
197  for (const auto &p : particles) {
198  std::fprintf(file_.get(), "%i\n", p.pdgcode().strangeness());
199  }
200  std::fprintf(file_.get(), "VECTORS momentum double\n");
201  for (const auto &p : particles) {
202  std::fprintf(file_.get(), "%g %g %g\n", p.momentum().x1(),
203  p.momentum().x2(), p.momentum().x3());
204  }
205 }
206 
207 template <typename T>
208 void VtkOutput::write_vtk_header(std::ofstream &file,
210  const std::string &description) {
211  const auto dim = lattice.n_cells();
212  const auto cs = lattice.cell_sizes();
213  const auto orig = lattice.origin();
214  file << "# vtk DataFile Version 2.0\n"
215  << description << "\n"
216  << "ASCII\n"
217  << "DATASET STRUCTURED_POINTS\n"
218  << "DIMENSIONS " << dim[0] << " " << dim[1] << " " << dim[2] << "\n"
219  << "SPACING " << cs[0] << " " << cs[1] << " " << cs[2] << "\n"
220  << "ORIGIN " << orig[0] << " " << orig[1] << " " << orig[2] << "\n"
221  << "POINT_DATA " << lattice.size() << "\n";
222 }
223 
224 template <typename T, typename F>
225 void VtkOutput::write_vtk_scalar(std::ofstream &file,
227  const std::string &varname, F &&get_quantity) {
228  file << "SCALARS " << varname << " double 1\n"
229  << "LOOKUP_TABLE default\n";
230  file << std::setprecision(3);
231  file << std::fixed;
232  const auto dim = lattice.n_cells();
233  lattice.iterate_sublattice({0, 0, 0}, dim, [&](T &node, int ix, int, int) {
234  const double f_from_node = get_quantity(node);
235  file << f_from_node << " ";
236  if (ix == dim[0] - 1) {
237  file << "\n";
238  }
239  });
240 }
241 
242 template <typename T, typename F>
243 void VtkOutput::write_vtk_vector(std::ofstream &file,
245  const std::string &varname, F &&get_quantity) {
246  file << "VECTORS " << varname << " double\n";
247  file << std::setprecision(3);
248  file << std::fixed;
249  const auto dim = lattice.n_cells();
250  lattice.iterate_sublattice({0, 0, 0}, dim, [&](T &node, int, int, int) {
251  const ThreeVector v = get_quantity(node);
252  file << v.x1() << " " << v.x2() << " " << v.x3() << "\n";
253  });
254 }
255 
256 std::string VtkOutput::make_filename(const std::string &descr, int counter) {
257  char suffix[22];
258  snprintf(suffix, sizeof(suffix), "_%05i_tstep%05i.vtk", current_event_,
259  counter);
260  return base_path_.string() + std::string("/") + descr + std::string(suffix);
261 }
262 
264  const DensityType dens_type) {
265  return std::string(to_string(dens_type)) + std::string("_") +
266  std::string(to_string(tq));
267 }
268 
270  const ThermodynamicQuantity tq, const DensityType dens_type,
273  return;
274  }
275  std::ofstream file;
276  const std::string varname = make_varname(tq, dens_type);
277  file.open(make_filename(varname, vtk_density_output_counter_), std::ios::out);
278  write_vtk_header(file, lattice, varname);
279  write_vtk_scalar(file, lattice, varname,
280  [&](DensityOnLattice &node) { return node.rho(); });
282 }
283 
285  const ThermodynamicQuantity tq, const DensityType dens_type,
288  return;
289  }
290  std::ofstream file;
291  const std::string varname = make_varname(tq, dens_type);
292 
293  if (tq == ThermodynamicQuantity::Tmn) {
294  file.open(make_filename(varname, vtk_tmn_output_counter_++), std::ios::out);
295  write_vtk_header(file, Tmn_lattice, varname);
296  for (int i = 0; i < 4; i++) {
297  for (int j = i; j < 4; j++) {
298  write_vtk_scalar(file, Tmn_lattice,
299  varname + std::to_string(i) + std::to_string(j),
300  [&](EnergyMomentumTensor &node) {
301  return node[EnergyMomentumTensor::tmn_index(i, j)];
302  });
303  }
304  }
305  } else if (tq == ThermodynamicQuantity::TmnLandau) {
306  file.open(make_filename(varname, vtk_tmn_landau_output_counter_++),
307  std::ios::out);
308  write_vtk_header(file, Tmn_lattice, varname);
309  for (int i = 0; i < 4; i++) {
310  for (int j = i; j < 4; j++) {
311  write_vtk_scalar(file, Tmn_lattice,
312  varname + std::to_string(i) + std::to_string(j),
313  [&](EnergyMomentumTensor &node) {
314  const FourVector u = node.landau_frame_4velocity();
315  const EnergyMomentumTensor Tmn_L = node.boosted(u);
316  return Tmn_L[EnergyMomentumTensor::tmn_index(i, j)];
317  });
318  }
319  }
320  } else {
321  file.open(make_filename(varname, vtk_v_landau_output_counter_++),
322  std::ios::out);
323  write_vtk_header(file, Tmn_lattice, varname);
324  write_vtk_vector(file, Tmn_lattice, varname,
325  [&](EnergyMomentumTensor &node) {
326  const FourVector u = node.landau_frame_4velocity();
327  return -u.velocity();
328  });
329  }
330 }
331 
333  const std::string name1, const std::string name2,
334  RectangularLattice<std::pair<ThreeVector, ThreeVector>> &lat) {
335  if (!is_fields_output_) {
336  return;
337  }
338  std::ofstream file1;
339  file1.open(make_filename(name1, vtk_fields_output_counter_), std::ios::out);
340  write_vtk_header(file1, lat, name1);
342  file1, lat, name1,
343  [&](std::pair<ThreeVector, ThreeVector> &node) { return node.first; });
344  std::ofstream file2;
345  file2.open(make_filename(name2, vtk_fields_output_counter_), std::ios::out);
346  write_vtk_header(file2, lat, name2);
348  file2, lat, name2,
349  [&](std::pair<ThreeVector, ThreeVector> &node) { return node.second; });
351 }
352 
355  return;
356  }
357  std::ofstream file;
358  file.open(make_filename("fluidization_td", vtk_fluidization_counter_++),
359  std::ios::out);
360  write_vtk_header(file, gct.lattice(), "fluidization_td");
361  write_vtk_scalar(file, gct.lattice(), "e",
362  [&](ThermLatticeNode &node) { return node.e(); });
363  write_vtk_scalar(file, gct.lattice(), "p",
364  [&](ThermLatticeNode &node) { return node.p(); });
365  write_vtk_vector(file, gct.lattice(), "v",
366  [&](ThermLatticeNode &node) { return node.v(); });
367  write_vtk_scalar(file, gct.lattice(), "T",
368  [&](ThermLatticeNode &node) { return node.T(); });
369  write_vtk_scalar(file, gct.lattice(), "mub",
370  [&](ThermLatticeNode &node) { return node.mub(); });
371  write_vtk_scalar(file, gct.lattice(), "mus",
372  [&](ThermLatticeNode &node) { return node.mus(); });
373 }
374 
375 } // namespace smash
A class for time-efficient (time-memory trade-off) calculation of density on the lattice.
Definition: density.h:304
double rho(const double norm_factor=1.0)
Compute the net Eckart density on the local lattice.
Definition: density.h:373
A class to pre-calculate and store parameters relevant for density calculation.
Definition: density.h:92
The EnergyMomentumTensor class represents a symmetric positive semi-definite energy-momentum tensor .
EnergyMomentumTensor boosted(const FourVector &u) const
Boost to a given 4-velocity.
FourVector landau_frame_4velocity() const
Find the Landau frame 4-velocity from energy-momentum tensor.
static std::int8_t tmn_index(std::int8_t mu, std::int8_t nu)
Access the index of component .
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
ThreeVector velocity() const
Get the velocity (3-vector divided by zero component).
Definition: fourvector.h:333
The GrandCanThermalizer class implements the following functionality:
RectangularLattice< ThermLatticeNode > & lattice() const
Getter function for the lattice.
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
double time() const
Returns the time of the computational frame.
Definition: particles.h:100
size_t size() const
Definition: particles.h:87
A container class to hold all the arrays on the lattice and access them.
Definition: lattice.h:49
The ThermLatticeNode class is intended to compute thermodynamical quantities in a cell given a set of...
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
void write_vtk_scalar(std::ofstream &file, RectangularLattice< T > &lat, const std::string &varname, F &&function)
Write a VTK scalar.
Definition: vtkoutput.cc:225
int vtk_density_output_counter_
Number of density lattice vtk output in current event.
Definition: vtkoutput.h:203
void fields_output(const std::string name1, const std::string name2, RectangularLattice< std::pair< ThreeVector, ThreeVector >> &lat) override
Write fields in vtk output Fields are a pair of threevectors for example electric and magnetic field.
Definition: vtkoutput.cc:332
bool is_fields_output_
Is the VTK output an output for fields.
Definition: vtkoutput.h:217
std::pair< int, int > counter_key()
Create the key to access the vtk_output_counter_ map.
Definition: vtkoutput.h:184
void write(const Particles &particles)
Write the given particles to the output.
Definition: vtkoutput.cc:128
int vtk_fluidization_counter_
Number of fluidization output.
Definition: vtkoutput.h:211
int current_event_
Event number.
Definition: vtkoutput.h:192
VtkOutput(const std::filesystem::path &path, const std::string &name, const OutputParameters &out_par)
Create a new VTK output.
Definition: vtkoutput.cc:24
int current_ensemble_
Ensemble number.
Definition: vtkoutput.h:194
void write_vtk_header(std::ofstream &file, RectangularLattice< T > &lat, const std::string &description)
Write the VTK header.
Definition: vtkoutput.cc:208
int vtk_fields_output_counter_
Number of fields output in current event.
Definition: vtkoutput.h:213
void write_vtk_vector(std::ofstream &file, RectangularLattice< T > &lat, const std::string &varname, F &&function)
Write a VTK vector.
Definition: vtkoutput.cc:243
std::map< std::pair< int, int >, int > vtk_output_counter_
Counters to keep track of time steps per event and per ensemble.
Definition: vtkoutput.h:200
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 VTK output.
Definition: vtkoutput.cc:111
std::string make_varname(const ThermodynamicQuantity tq, const DensityType dens_type)
Make a variable name given quantity and density type.
Definition: vtkoutput.cc:263
bool is_thermodynamics_output_
Is the VTK output a thermodynamics output.
Definition: vtkoutput.h:215
int vtk_tmn_landau_output_counter_
Number of Landau frame energy-momentum tensor vtk output in current event.
Definition: vtkoutput.h:207
void thermodynamics_output(const ThermodynamicQuantity tq, const DensityType dt, RectangularLattice< DensityOnLattice > &lattice) override
Prints the density lattice in VTK format on a grid.
Definition: vtkoutput.cc:269
int vtk_v_landau_output_counter_
Number of Landau rest frame velocity vtk output in current event.
Definition: vtkoutput.h:209
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 out all current particles.
Definition: vtkoutput.cc:115
const std::filesystem::path base_path_
filesystem path for output
Definition: vtkoutput.h:189
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 VTK output.
Definition: vtkoutput.cc:93
std::string make_filename(const std::string &description, int counter)
Make a file name given a description and a counter.
Definition: vtkoutput.cc:256
int vtk_tmn_output_counter_
Number of energy-momentum tensor lattice vtk output in current event.
Definition: vtkoutput.h:205
ThermodynamicQuantity
Represents thermodynamic quantities that can be printed out See user guide description for more infor...
@ Tmn
Energy-momentum tensor in lab frame.
@ TmnLandau
Energy-momentum tensor in Landau rest frame.
DensityType
Allows to choose which kind of density to calculate.
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > & logg
An array that stores all pre-configured Logger objects.
Definition: logging.h:245
constexpr Section lattice
Section for the lattice.
Definition: input_keys.h:149
constexpr int p
Proton.
Definition: action.h:24
std::unique_ptr< std::FILE, FileDeleter > FilePtr
A RAII type to replace std::FILE *.
Definition: file.h:61
std::string to_string(ThermodynamicQuantity quantity)
Convert a ThermodynamicQuantity enum value to its corresponding string.
Definition: stringify.cc:26
FilePtr fopen(const std::filesystem::path &filename, const std::string &mode)
Open a file with given mode.
Definition: file.cc:14
static constexpr int LOutput
Structure to contain custom data for output.
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.
Helper structure for Experiment to hold output options and parameters.
bool part_extended
Extended format for particles output.