Version: SMASH-2.0
vtkoutput.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 
10 #include <fstream>
11 #include <memory>
12 
13 #include "smash/clock.h"
14 #include "smash/config.h"
15 #include "smash/file.h"
17 #include "smash/particles.h"
18 #include "smash/vtkoutput.h"
19 
20 namespace smash {
21 static constexpr int LOutput = LogArea::Output::id;
22 
23 VtkOutput::VtkOutput(const bf::path &path, const std::string &name,
24  const OutputParameters &out_par)
25  : OutputInterface(name),
26  base_path_(std::move(path)),
27  is_thermodynamics_output_(name == "Thermodynamics") {
28  if (out_par.part_extended) {
29  logg[LOutput].warn()
30  << "Creating VTK output: There is no extended VTK format.";
31  }
32 }
33 
35 
60 void VtkOutput::at_eventstart(const Particles &particles,
61  const int event_number, const EventInfo &) {
68 
69  current_event_ = event_number;
71  write(particles);
73  }
74 }
75 
76 void VtkOutput::at_eventend(const Particles & /*particles*/,
77  const int /*event_number*/, const EventInfo &) {}
78 
80  const std::unique_ptr<Clock> &,
81  const DensityParameters &,
82  const EventInfo &) {
84  write(particles);
86  }
87 }
88 
89 void VtkOutput::write(const Particles &particles) {
90  char filename[32];
91  snprintf(filename, sizeof(filename), "pos_ev%05i_tstep%05i.vtk",
93  FilePtr file_{std::fopen((base_path_ / filename).native().c_str(), "w")};
94 
95  /* Legacy VTK file format */
96  std::fprintf(file_.get(), "# vtk DataFile Version 2.0\n");
97  std::fprintf(file_.get(), "Generated from molecular-offset data %s\n",
98  VERSION_MAJOR);
99  std::fprintf(file_.get(), "ASCII\n");
100 
101  /* Unstructured data sets are composed of points, lines, polygons, .. */
102  std::fprintf(file_.get(), "DATASET UNSTRUCTURED_GRID\n");
103  std::fprintf(file_.get(), "POINTS %zu double\n", particles.size());
104  for (const auto &p : particles) {
105  std::fprintf(file_.get(), "%g %g %g\n", p.position().x1(),
106  p.position().x2(), p.position().x3());
107  }
108  std::fprintf(file_.get(), "CELLS %zu %zu\n", particles.size(),
109  particles.size() * 2);
110  for (size_t point_index = 0; point_index < particles.size(); point_index++) {
111  std::fprintf(file_.get(), "1 %zu\n", point_index);
112  }
113  std::fprintf(file_.get(), "CELL_TYPES %zu\n", particles.size());
114  for (size_t point_index = 0; point_index < particles.size(); point_index++) {
115  std::fprintf(file_.get(), "1\n");
116  }
117  std::fprintf(file_.get(), "POINT_DATA %zu\n", particles.size());
118  std::fprintf(file_.get(), "SCALARS pdg_codes int 1\n");
119  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
120  for (const auto &p : particles) {
121  std::fprintf(file_.get(), "%s\n", p.pdgcode().string().c_str());
122  }
123  std::fprintf(file_.get(), "SCALARS is_formed int 1\n");
124  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
125  double current_time = particles.time();
126  for (const auto &p : particles) {
127  std::fprintf(file_.get(), "%s\n",
128  (p.formation_time() > current_time) ? "0" : "1");
129  }
130  std::fprintf(file_.get(), "SCALARS cross_section_scaling_factor double 1\n");
131  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
132  for (const auto &p : particles) {
133  std::fprintf(file_.get(), "%g\n", p.xsec_scaling_factor());
134  }
135  std::fprintf(file_.get(), "SCALARS mass double 1\n");
136  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
137  for (const auto &p : particles) {
138  std::fprintf(file_.get(), "%g\n", p.effective_mass());
139  }
140  std::fprintf(file_.get(), "SCALARS N_coll int 1\n");
141  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
142  for (const auto &p : particles) {
143  std::fprintf(file_.get(), "%i\n", p.get_history().collisions_per_particle);
144  }
145  std::fprintf(file_.get(), "SCALARS particle_ID int 1\n");
146  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
147  for (const auto &p : particles) {
148  std::fprintf(file_.get(), "%i\n", p.id());
149  }
150  std::fprintf(file_.get(), "SCALARS baryon_number int 1\n");
151  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
152  for (const auto &p : particles) {
153  std::fprintf(file_.get(), "%i\n", p.pdgcode().baryon_number());
154  }
155  std::fprintf(file_.get(), "SCALARS strangeness int 1\n");
156  std::fprintf(file_.get(), "LOOKUP_TABLE default\n");
157  for (const auto &p : particles) {
158  std::fprintf(file_.get(), "%i\n", p.pdgcode().strangeness());
159  }
160  std::fprintf(file_.get(), "VECTORS momentum double\n");
161  for (const auto &p : particles) {
162  std::fprintf(file_.get(), "%g %g %g\n", p.momentum().x1(),
163  p.momentum().x2(), p.momentum().x3());
164  }
165 }
166 
176 template <typename T>
177 void VtkOutput::write_vtk_header(std::ofstream &file,
178  RectangularLattice<T> &lattice,
179  const std::string &description) {
180  const auto dim = lattice.dimensions();
181  const auto cs = lattice.cell_sizes();
182  const auto orig = lattice.origin();
183  file << "# vtk DataFile Version 2.0\n"
184  << description << "\n"
185  << "ASCII\n"
186  << "DATASET STRUCTURED_POINTS\n"
187  << "DIMENSIONS " << dim[0] << " " << dim[1] << " " << dim[2] << "\n"
188  << "SPACING " << cs[0] << " " << cs[1] << " " << cs[2] << "\n"
189  << "ORIGIN " << orig[0] << " " << orig[1] << " " << orig[2] << "\n"
190  << "POINT_DATA " << lattice.size() << "\n";
191 }
192 
193 template <typename T, typename F>
194 void VtkOutput::write_vtk_scalar(std::ofstream &file,
195  RectangularLattice<T> &lattice,
196  const std::string &varname, F &&get_quantity) {
197  file << "SCALARS " << varname << " double 1\n"
198  << "LOOKUP_TABLE default\n";
199  file << std::setprecision(3);
200  file << std::fixed;
201  const auto dim = lattice.dimensions();
202  lattice.iterate_sublattice({0, 0, 0}, dim, [&](T &node, int ix, int, int) {
203  const double f_from_node = get_quantity(node);
204  file << f_from_node << " ";
205  if (ix == dim[0] - 1) {
206  file << "\n";
207  }
208  });
209 }
210 
211 template <typename T, typename F>
212 void VtkOutput::write_vtk_vector(std::ofstream &file,
213  RectangularLattice<T> &lattice,
214  const std::string &varname, F &&get_quantity) {
215  file << "VECTORS " << varname << " double\n";
216  file << std::setprecision(3);
217  file << std::fixed;
218  const auto dim = lattice.dimensions();
219  lattice.iterate_sublattice({0, 0, 0}, dim, [&](T &node, int, int, int) {
220  const ThreeVector v = get_quantity(node);
221  file << v.x1() << " " << v.x2() << " " << v.x3() << "\n";
222  });
223 }
224 
225 std::string VtkOutput::make_filename(const std::string &descr, int counter) {
226  char suffix[22];
227  snprintf(suffix, sizeof(suffix), "_%05i_tstep%05i.vtk", current_event_,
228  counter);
229  return base_path_.string() + std::string("/") + descr + std::string(suffix);
230 }
231 
233  const DensityType dens_type) {
234  return std::string(to_string(dens_type)) + std::string("_") +
235  std::string(to_string(tq));
236 }
237 
239  const ThermodynamicQuantity tq, const DensityType dens_type,
242  return;
243  }
244  std::ofstream file;
245  const std::string varname = make_varname(tq, dens_type);
246  file.open(make_filename(varname, vtk_density_output_counter_), std::ios::out);
247  write_vtk_header(file, lattice, varname);
248  write_vtk_scalar(file, lattice, varname,
249  [&](DensityOnLattice &node) { return node.density(); });
251 }
252 
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 
278  if (tq == ThermodynamicQuantity::Tmn) {
279  file.open(make_filename(varname, vtk_tmn_output_counter_++), std::ios::out);
280  write_vtk_header(file, Tmn_lattice, varname);
281  for (int i = 0; i < 4; i++) {
282  for (int j = i; j < 4; j++) {
283  write_vtk_scalar(file, Tmn_lattice,
284  varname + std::to_string(i) + std::to_string(j),
285  [&](EnergyMomentumTensor &node) {
286  return node[EnergyMomentumTensor::tmn_index(i, j)];
287  });
288  }
289  }
290  } else if (tq == ThermodynamicQuantity::TmnLandau) {
291  file.open(make_filename(varname, vtk_tmn_landau_output_counter_++),
292  std::ios::out);
293  write_vtk_header(file, Tmn_lattice, varname);
294  for (int i = 0; i < 4; i++) {
295  for (int j = i; j < 4; j++) {
296  write_vtk_scalar(file, Tmn_lattice,
297  varname + std::to_string(i) + std::to_string(j),
298  [&](EnergyMomentumTensor &node) {
299  const FourVector u = node.landau_frame_4velocity();
300  const EnergyMomentumTensor Tmn_L = node.boosted(u);
301  return Tmn_L[EnergyMomentumTensor::tmn_index(i, j)];
302  });
303  }
304  }
305  } else {
306  file.open(make_filename(varname, vtk_v_landau_output_counter_++),
307  std::ios::out);
308  write_vtk_header(file, Tmn_lattice, varname);
309  write_vtk_vector(file, Tmn_lattice, varname,
310  [&](EnergyMomentumTensor &node) {
311  const FourVector u = node.landau_frame_4velocity();
312  return -u.velocity();
313  });
314  }
315 }
316 
319  return;
320  }
321  std::ofstream file;
322  file.open(make_filename("fluidization_td", vtk_fluidization_counter_++),
323  std::ios::out);
324  write_vtk_header(file, gct.lattice(), "fluidization_td");
325  write_vtk_scalar(file, gct.lattice(), "e",
326  [&](ThermLatticeNode &node) { return node.e(); });
327  write_vtk_scalar(file, gct.lattice(), "p",
328  [&](ThermLatticeNode &node) { return node.p(); });
329  write_vtk_vector(file, gct.lattice(), "v",
330  [&](ThermLatticeNode &node) { return node.v(); });
331  write_vtk_scalar(file, gct.lattice(), "T",
332  [&](ThermLatticeNode &node) { return node.T(); });
333  write_vtk_scalar(file, gct.lattice(), "mub",
334  [&](ThermLatticeNode &node) { return node.mub(); });
335  write_vtk_scalar(file, gct.lattice(), "mus",
336  [&](ThermLatticeNode &node) { return node.mus(); });
337 }
338 
339 } // namespace smash
smash
Definition: action.h:24
smash::FilePtr
std::unique_ptr< std::FILE, FileDeleter > FilePtr
A RAII type to replace std::FILE *.
Definition: file.h:63
ThermodynamicQuantity::TmnLandau
smash::VtkOutput::vtk_v_landau_output_counter_
int vtk_v_landau_output_counter_
Number of Landau rest frame velocity vtk output in current event.
Definition: vtkoutput.h:185
smash::VtkOutput::thermodynamics_output
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:238
smash::LOutput
static constexpr int LOutput
Definition: oscaroutput.cc:23
smash::DensityParameters
A class to pre-calculate and store parameters relevant for density calculation.
Definition: density.h:108
smash::fopen
FilePtr fopen(const bf::path &filename, const std::string &mode)
Open a file with given mode.
Definition: file.cc:14
smash::Particles::size
size_t size() const
Definition: particles.h:87
smash::VtkOutput::make_varname
std::string make_varname(const ThermodynamicQuantity tq, const DensityType dens_type)
Make a variable name given quantity and density type.
Definition: vtkoutput.cc:232
smash::OutputInterface::to_string
const char * to_string(const ThermodynamicQuantity tq)
Convert thermodynamic quantities to strings.
Definition: outputinterface.h:184
smash::ThreeVector::x3
double x3() const
Definition: threevector.h:173
smash::VtkOutput::write_vtk_vector
void write_vtk_vector(std::ofstream &file, RectangularLattice< T > &lat, const std::string &varname, F &&function)
Write a VTK vector.
Definition: vtkoutput.cc:212
smash::EnergyMomentumTensor::tmn_index
static std::int8_t tmn_index(std::int8_t mu, std::int8_t nu)
Access the index of component .
Definition: energymomentumtensor.h:54
smash::EnergyMomentumTensor::boosted
EnergyMomentumTensor boosted(const FourVector &u) const
Boost to a given 4-velocity.
Definition: energymomentumtensor.cc:98
smash::VtkOutput::at_eventstart
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:60
smash::VtkOutput::at_eventend
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:76
smash::VtkOutput::write_vtk_scalar
void write_vtk_scalar(std::ofstream &file, RectangularLattice< T > &lat, const std::string &varname, F &&function)
Write a VTK scalar.
Definition: vtkoutput.cc:194
smash::VtkOutput::base_path_
const bf::path base_path_
filesystem path for output
Definition: vtkoutput.h:171
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
smash::DensityOnLattice
A class for time-efficient (time-memory trade-off) calculation of density on the lattice.
Definition: density.h:258
clock.h
smash::VtkOutput::vtk_density_output_counter_
int vtk_density_output_counter_
Number of density lattice vtk output in current event.
Definition: vtkoutput.h:179
smash::VtkOutput::is_thermodynamics_output_
bool is_thermodynamics_output_
Is the VTK output a thermodynamics output.
Definition: vtkoutput.h:189
smash::VtkOutput::vtk_tmn_output_counter_
int vtk_tmn_output_counter_
Number of energy-momentum tensor lattice vtk output in current event.
Definition: vtkoutput.h:181
smash::ThermLatticeNode
The ThermLatticeNode class is intended to compute thermodynamical quantities in a cell given a set of...
Definition: grandcan_thermalizer.h:48
smash::VtkOutput::VtkOutput
VtkOutput(const bf::path &path, const std::string &name, const OutputParameters &out_par)
Create a new VTK output.
Definition: vtkoutput.cc:23
smash::VtkOutput::write_vtk_header
void write_vtk_header(std::ofstream &file, RectangularLattice< T > &lat, const std::string &description)
Write the VTK header.
Definition: vtkoutput.cc:177
forwarddeclarations.h
smash::ThreeVector
Definition: threevector.h:31
smash::OutputParameters::part_extended
bool part_extended
Extended format for particles output.
Definition: outputparameters.h:142
smash::OutputParameters
Helper structure for Experiment to hold output options and parameters.
Definition: outputparameters.h:25
smash::VtkOutput::~VtkOutput
~VtkOutput()
Definition: vtkoutput.cc:34
smash::RectangularLattice
A container class to hold all the arrays on the lattice and access them.
Definition: lattice.h:47
smash::VtkOutput::vtk_fluidization_counter_
int vtk_fluidization_counter_
Number of fluidization output.
Definition: vtkoutput.h:187
ThermodynamicQuantity::Tmn
smash::OutputInterface
Abstraction of generic output.
Definition: outputinterface.h:65
smash::ThreeVector::x1
double x1() const
Definition: threevector.h:165
smash::VtkOutput::vtk_tmn_landau_output_counter_
int vtk_tmn_landau_output_counter_
Number of Landau frame energy-momentum tensor vtk output in current event.
Definition: vtkoutput.h:183
smash::FourVector::velocity
ThreeVector velocity() const
Get the velocity (3-vector divided by zero component).
Definition: fourvector.h:323
vtkoutput.h
smash::VtkOutput::vtk_output_counter_
int vtk_output_counter_
Number of vtk output in current event.
Definition: vtkoutput.h:176
smash::VtkOutput::write
void write(const Particles &particles)
Write the given particles to the output.
Definition: vtkoutput.cc:89
particles.h
smash::EnergyMomentumTensor
Definition: energymomentumtensor.h:29
smash::DensityOnLattice::density
double density(const double norm_factor=1.0)
Compute the net Eckart density on the local lattice.
Definition: density.h:326
smash::Particles
Definition: particles.h:33
smash::DensityType
DensityType
Allows to choose which kind of density to calculate.
Definition: density.h:36
smash::RectangularLattice::cell_sizes
const std::array< double, 3 > & cell_sizes() const
Definition: lattice.h:158
smash::VtkOutput::make_filename
std::string make_filename(const std::string &description, int counter)
Make a file name given a description and a counter.
Definition: vtkoutput.cc:225
smash::RectangularLattice::dimensions
const std::array< int, 3 > & dimensions() const
Definition: lattice.h:155
smash::VtkOutput::current_event_
int current_event_
Event number.
Definition: vtkoutput.h:174
smash::EnergyMomentumTensor::landau_frame_4velocity
FourVector landau_frame_4velocity() const
Find the Landau frame 4-velocity from energy-momentum tensor.
Definition: energymomentumtensor.cc:23
ThermodynamicQuantity
ThermodynamicQuantity
Represents thermodynamic quantities that can be printed out.
Definition: forwarddeclarations.h:186
smash::FourVector
Definition: fourvector.h:33
smash::RectangularLattice::size
std::size_t size() const
Definition: lattice.h:186
smash::GrandCanThermalizer::lattice
RectangularLattice< ThermLatticeNode > & lattice() const
Getter function for the lattice.
Definition: grandcan_thermalizer.h:442
smash::pdg::p
constexpr int p
Proton.
Definition: pdgcode_constants.h:28
file.h
smash::GrandCanThermalizer
The GrandCanThermalizer class implements the following functionality:
Definition: grandcan_thermalizer.h:227
smash::RectangularLattice::origin
const std::array< double, 3 > & origin() const
Definition: lattice.h:161
smash::VtkOutput::at_intermediate_time
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:79
smash::RectangularLattice::iterate_sublattice
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:243
smash::ThreeVector::x2
double x2() const
Definition: threevector.h:169