Version: SMASH-3.1
vtkoutput.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2022
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 
62 void VtkOutput::at_eventstart(const Particles &particles,
63  const int event_number, const EventInfo &) {
70 
71  current_event_ = event_number;
73  write(particles);
75  }
76 }
77 
78 void VtkOutput::at_eventend(const Particles & /*particles*/,
79  const int /*event_number*/, const EventInfo &) {}
80 
82  const std::unique_ptr<Clock> &,
83  const DensityParameters &,
84  const EventInfo &) {
86  write(particles);
88  }
89 }
90 
91 void VtkOutput::write(const Particles &particles) {
92  char filename[32];
93  snprintf(filename, sizeof(filename), "pos_ev%05i_tstep%05i.vtk",
95  FilePtr file_{std::fopen((base_path_ / filename).native().c_str(), "w")};
96 
97  /* Legacy VTK file format */
98  std::fprintf(file_.get(), "# vtk DataFile Version 2.0\n");
99  std::fprintf(file_.get(), "Generated from molecular-offset data %s\n",
100  SMASH_VERSION);
101  std::fprintf(file_.get(), "ASCII\n");
102 
103  /* Unstructured data sets are composed of points, lines, polygons, .. */
104  std::fprintf(file_.get(), "DATASET UNSTRUCTURED_GRID\n");
105  std::fprintf(file_.get(), "POINTS %zu double\n", particles.size());
106  for (const auto &p : particles) {
107  std::fprintf(file_.get(), "%g %g %g\n", p.position().x1(),
108  p.position().x2(), p.position().x3());
109  }
110  std::fprintf(file_.get(), "CELLS %zu %zu\n", particles.size(),
111  particles.size() * 2);
112  for (size_t point_index = 0; point_index < particles.size(); point_index++) {
113  std::fprintf(file_.get(), "1 %zu\n", point_index);
114  }
115  std::fprintf(file_.get(), "CELL_TYPES %zu\n", particles.size());
116  for (size_t point_index = 0; point_index < particles.size(); point_index++) {
117  std::fprintf(file_.get(), "1\n");
118  }
119  std::fprintf(file_.get(), "POINT_DATA %zu\n", particles.size());
120  std::fprintf(file_.get(), "SCALARS pdg_codes int 1\n");
121  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
122  for (const auto &p : particles) {
123  std::fprintf(file_.get(), "%s\n", p.pdgcode().string().c_str());
124  }
125  std::fprintf(file_.get(), "SCALARS is_formed int 1\n");
126  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
127  double current_time = particles.time();
128  for (const auto &p : particles) {
129  std::fprintf(file_.get(), "%s\n",
130  (p.formation_time() > current_time) ? "0" : "1");
131  }
132  std::fprintf(file_.get(), "SCALARS cross_section_scaling_factor double 1\n");
133  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
134  for (const auto &p : particles) {
135  std::fprintf(file_.get(), "%g\n", p.xsec_scaling_factor());
136  }
137  std::fprintf(file_.get(), "SCALARS mass double 1\n");
138  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
139  for (const auto &p : particles) {
140  std::fprintf(file_.get(), "%g\n", p.effective_mass());
141  }
142  std::fprintf(file_.get(), "SCALARS N_coll int 1\n");
143  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
144  for (const auto &p : particles) {
145  std::fprintf(file_.get(), "%i\n", p.get_history().collisions_per_particle);
146  }
147  std::fprintf(file_.get(), "SCALARS particle_ID int 1\n");
148  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
149  for (const auto &p : particles) {
150  std::fprintf(file_.get(), "%i\n", p.id());
151  }
152  std::fprintf(file_.get(), "SCALARS baryon_number int 1\n");
153  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
154  for (const auto &p : particles) {
155  std::fprintf(file_.get(), "%i\n", p.pdgcode().baryon_number());
156  }
157  std::fprintf(file_.get(), "SCALARS strangeness int 1\n");
158  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
159  for (const auto &p : particles) {
160  std::fprintf(file_.get(), "%i\n", p.pdgcode().strangeness());
161  }
162  std::fprintf(file_.get(), "VECTORS momentum double\n");
163  for (const auto &p : particles) {
164  std::fprintf(file_.get(), "%g %g %g\n", p.momentum().x1(),
165  p.momentum().x2(), p.momentum().x3());
166  }
167 }
168 
178 template <typename T>
179 void VtkOutput::write_vtk_header(std::ofstream &file,
180  RectangularLattice<T> &lattice,
181  const std::string &description) {
182  const auto dim = lattice.n_cells();
183  const auto cs = lattice.cell_sizes();
184  const auto orig = lattice.origin();
185  file << "# vtk DataFile Version 2.0\n"
186  << description << "\n"
187  << "ASCII\n"
188  << "DATASET STRUCTURED_POINTS\n"
189  << "DIMENSIONS " << dim[0] << " " << dim[1] << " " << dim[2] << "\n"
190  << "SPACING " << cs[0] << " " << cs[1] << " " << cs[2] << "\n"
191  << "ORIGIN " << orig[0] << " " << orig[1] << " " << orig[2] << "\n"
192  << "POINT_DATA " << lattice.size() << "\n";
193 }
194 
195 template <typename T, typename F>
196 void VtkOutput::write_vtk_scalar(std::ofstream &file,
197  RectangularLattice<T> &lattice,
198  const std::string &varname, F &&get_quantity) {
199  file << "SCALARS " << varname << " double 1\n"
200  << "LOOKUP_TABLE default\n";
201  file << std::setprecision(3);
202  file << std::fixed;
203  const auto dim = lattice.n_cells();
204  lattice.iterate_sublattice({0, 0, 0}, dim, [&](T &node, int ix, int, int) {
205  const double f_from_node = get_quantity(node);
206  file << f_from_node << " ";
207  if (ix == dim[0] - 1) {
208  file << "\n";
209  }
210  });
211 }
212 
213 template <typename T, typename F>
214 void VtkOutput::write_vtk_vector(std::ofstream &file,
215  RectangularLattice<T> &lattice,
216  const std::string &varname, F &&get_quantity) {
217  file << "VECTORS " << varname << " double\n";
218  file << std::setprecision(3);
219  file << std::fixed;
220  const auto dim = lattice.n_cells();
221  lattice.iterate_sublattice({0, 0, 0}, dim, [&](T &node, int, int, int) {
222  const ThreeVector v = get_quantity(node);
223  file << v.x1() << " " << v.x2() << " " << v.x3() << "\n";
224  });
225 }
226 
227 std::string VtkOutput::make_filename(const std::string &descr, int counter) {
228  char suffix[22];
229  snprintf(suffix, sizeof(suffix), "_%05i_tstep%05i.vtk", current_event_,
230  counter);
231  return base_path_.string() + std::string("/") + descr + std::string(suffix);
232 }
233 
235  const DensityType dens_type) {
236  return std::string(to_string(dens_type)) + std::string("_") +
237  std::string(to_string(tq));
238 }
239 
241  const ThermodynamicQuantity tq, const DensityType dens_type,
244  return;
245  }
246  std::ofstream file;
247  const std::string varname = make_varname(tq, dens_type);
248  file.open(make_filename(varname, vtk_density_output_counter_), std::ios::out);
249  write_vtk_header(file, lattice, varname);
250  write_vtk_scalar(file, lattice, varname,
251  [&](DensityOnLattice &node) { return node.rho(); });
253 }
254 
272  const ThermodynamicQuantity tq, const DensityType dens_type,
275  return;
276  }
277  std::ofstream file;
278  const std::string varname = make_varname(tq, dens_type);
279 
280  if (tq == ThermodynamicQuantity::Tmn) {
281  file.open(make_filename(varname, vtk_tmn_output_counter_++), std::ios::out);
282  write_vtk_header(file, Tmn_lattice, varname);
283  for (int i = 0; i < 4; i++) {
284  for (int j = i; j < 4; j++) {
285  write_vtk_scalar(file, Tmn_lattice,
286  varname + std::to_string(i) + std::to_string(j),
287  [&](EnergyMomentumTensor &node) {
288  return node[EnergyMomentumTensor::tmn_index(i, j)];
289  });
290  }
291  }
292  } else if (tq == ThermodynamicQuantity::TmnLandau) {
293  file.open(make_filename(varname, vtk_tmn_landau_output_counter_++),
294  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  const FourVector u = node.landau_frame_4velocity();
302  const EnergyMomentumTensor Tmn_L = node.boosted(u);
303  return Tmn_L[EnergyMomentumTensor::tmn_index(i, j)];
304  });
305  }
306  }
307  } else {
308  file.open(make_filename(varname, vtk_v_landau_output_counter_++),
309  std::ios::out);
310  write_vtk_header(file, Tmn_lattice, varname);
311  write_vtk_vector(file, Tmn_lattice, varname,
312  [&](EnergyMomentumTensor &node) {
313  const FourVector u = node.landau_frame_4velocity();
314  return -u.velocity();
315  });
316  }
317 }
318 
320  const std::string name1, const std::string name2,
321  RectangularLattice<std::pair<ThreeVector, ThreeVector>> &lat) {
322  if (!is_fields_output_) {
323  return;
324  }
325  std::ofstream file1;
326  file1.open(make_filename(name1, vtk_fields_output_counter_), std::ios::out);
327  write_vtk_header(file1, lat, name1);
329  file1, lat, name1,
330  [&](std::pair<ThreeVector, ThreeVector> &node) { return node.first; });
331  std::ofstream file2;
332  file2.open(make_filename(name2, vtk_fields_output_counter_), std::ios::out);
333  write_vtk_header(file2, lat, name2);
335  file2, lat, name2,
336  [&](std::pair<ThreeVector, ThreeVector> &node) { return node.second; });
338 }
339 
342  return;
343  }
344  std::ofstream file;
345  file.open(make_filename("fluidization_td", vtk_fluidization_counter_++),
346  std::ios::out);
347  write_vtk_header(file, gct.lattice(), "fluidization_td");
348  write_vtk_scalar(file, gct.lattice(), "e",
349  [&](ThermLatticeNode &node) { return node.e(); });
350  write_vtk_scalar(file, gct.lattice(), "p",
351  [&](ThermLatticeNode &node) { return node.p(); });
352  write_vtk_vector(file, gct.lattice(), "v",
353  [&](ThermLatticeNode &node) { return node.v(); });
354  write_vtk_scalar(file, gct.lattice(), "T",
355  [&](ThermLatticeNode &node) { return node.T(); });
356  write_vtk_scalar(file, gct.lattice(), "mub",
357  [&](ThermLatticeNode &node) { return node.mub(); });
358  write_vtk_scalar(file, gct.lattice(), "mus",
359  [&](ThermLatticeNode &node) { return node.mus(); });
360 }
361 
362 } // namespace smash
A class for time-efficient (time-memory trade-off) calculation of density on the lattice.
Definition: density.h:315
double rho(const double norm_factor=1.0)
Compute the net Eckart density on the local lattice.
Definition: density.h:384
A class to pre-calculate and store parameters relevant for density calculation.
Definition: density.h:108
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:47
const std::array< double, 3 > & origin() const
Definition: lattice.h:163
const std::array< int, 3 > & n_cells() const
Definition: lattice.h:157
void iterate_sublattice(const std::array< int, 3 > &lower_bounds, const std::array< int, 3 > &upper_bounds, F &&func)
A sub-lattice iterator, which iterates in a 3D-structured manner and calls a function on every cell.
Definition: lattice.h:571
std::size_t size() const
Definition: lattice.h:188
const std::array< double, 3 > & cell_sizes() const
Definition: lattice.h:160
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:185
double x2() const
Definition: threevector.h:181
double x1() const
Definition: threevector.h:177
void write_vtk_scalar(std::ofstream &file, RectangularLattice< T > &lat, const std::string &varname, F &&function)
Write a VTK scalar.
Definition: vtkoutput.cc:196
void at_eventend(const Particles &particles, const int event_number, const EventInfo &event) override
Writes the final particle information list of an event to the VTK output.
Definition: vtkoutput.cc:78
int vtk_density_output_counter_
Number of density lattice vtk output in current event.
Definition: vtkoutput.h:184
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:319
bool is_fields_output_
Is the VTK output an output for fields.
Definition: vtkoutput.h:198
int vtk_output_counter_
Number of vtk output in current event.
Definition: vtkoutput.h:181
void write(const Particles &particles)
Write the given particles to the output.
Definition: vtkoutput.cc:91
int vtk_fluidization_counter_
Number of fluidization output.
Definition: vtkoutput.h:192
int current_event_
Event number.
Definition: vtkoutput.h:179
VtkOutput(const std::filesystem::path &path, const std::string &name, const OutputParameters &out_par)
Create a new VTK output.
Definition: vtkoutput.cc:24
void write_vtk_header(std::ofstream &file, RectangularLattice< T > &lat, const std::string &description)
Write the VTK header.
Definition: vtkoutput.cc:179
int vtk_fields_output_counter_
Number of fields output in current event.
Definition: vtkoutput.h:194
void write_vtk_vector(std::ofstream &file, RectangularLattice< T > &lat, const std::string &varname, F &&function)
Write a VTK vector.
Definition: vtkoutput.cc:214
std::string make_varname(const ThermodynamicQuantity tq, const DensityType dens_type)
Make a variable name given quantity and density type.
Definition: vtkoutput.cc:234
bool is_thermodynamics_output_
Is the VTK output a thermodynamics output.
Definition: vtkoutput.h:196
int vtk_tmn_landau_output_counter_
Number of Landau frame energy-momentum tensor vtk output in current event.
Definition: vtkoutput.h:188
void at_intermediate_time(const Particles &particles, const std::unique_ptr< Clock > &clock, const DensityParameters &dens_param, const EventInfo &event) override
Writes out all current particles.
Definition: vtkoutput.cc:81
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:240
int vtk_v_landau_output_counter_
Number of Landau rest frame velocity vtk output in current event.
Definition: vtkoutput.h:190
void at_eventstart(const Particles &particles, const int event_number, const EventInfo &event) override
Writes the initial particle information list of an event to the VTK output.
Definition: vtkoutput.cc:62
const std::filesystem::path base_path_
filesystem path for output
Definition: vtkoutput.h:176
std::string make_filename(const std::string &description, int counter)
Make a file name given a description and a counter.
Definition: vtkoutput.cc:227
int vtk_tmn_output_counter_
Number of energy-momentum tensor lattice vtk output in current event.
Definition: vtkoutput.h:186
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.
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
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
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
DensityType
Allows to choose which kind of density to calculate.
Definition: density.h:36
Structure to contain custom data for output.
Helper structure for Experiment to hold output options and parameters.
bool part_extended
Extended format for particles output.