Molecular Dynamics Simulation  1.0
VelocityProfileInterceptor.cpp
Go to the documentation of this file.
2 
3 #include <chrono>
4 
6 #include "utils/ArrayUtils.h"
7 
8 VelocityProfileInterceptor::VelocityProfileInterceptor(std::pair<std::array<double, 3>, std::array<double, 3>> box, size_t num_bins,
9  size_t sample_every_x_percent)
10  : box(box), num_bins(num_bins), sample_every_x_percent(sample_every_x_percent) {}
11 
13  bool append = simulation.params.start_iteration != 0;
14 
15  csv_writer_x = std::make_unique<CSVWriter>(simulation.params.output_dir_path / "statistics" / "velocity_profile_x_axis.csv", append);
16  csv_writer_y = std::make_unique<CSVWriter>(simulation.params.output_dir_path / "statistics" / "velocity_profile_y_axis.csv", append);
17  csv_writer_z = std::make_unique<CSVWriter>(simulation.params.output_dir_path / "statistics" / "velocity_profile_z_axis.csv", append);
18 
19  bin_width[0] = (box.second[0] - box.first[0]) / num_bins;
20  bin_width[1] = (box.second[1] - box.first[1]) / num_bins;
21  bin_width[2] = (box.second[2] - box.first[2]) / num_bins;
22 
23  csv_writer_x->initialize(
24  {"iteration", "bin_index (w= " + std::to_string(bin_width[0]) + ")", "avg_velocity_x", "avg_velocity_y", "avg_velocity_z"});
25 
26  csv_writer_y->initialize(
27  {"iteration", "bin_index (w= " + std::to_string(bin_width[1]) + ")", "avg_velocity_x", "avg_velocity_y", "avg_velocity_z"});
28 
29  csv_writer_z->initialize(
30  {"iteration", "bin_index (w= " + std::to_string(bin_width[2]) + ")", "avg_velocity_x", "avg_velocity_y", "avg_velocity_z"});
31 
32  auto expected_iterations = static_cast<size_t>(std::ceil(simulation.params.end_time / simulation.params.delta_t));
33  SimulationInterceptor::every_nth_iteration = std::max(1, static_cast<int>(sample_every_x_percent * expected_iterations / 100));
34 
35  if (simulation.params.start_iteration == 0) {
36  (*this)(0, simulation);
37  }
38 }
39 
40 void VelocityProfileInterceptor::operator()(size_t iteration, Simulation& simulation) {
41  std::map<size_t, std::array<double, 3>> avg_velocity_per_bin_index_x;
42  std::map<size_t, std::array<double, 3>> avg_velocity_per_bin_index_y;
43  std::map<size_t, std::array<double, 3>> avg_velocity_per_bin_index_z;
44 
45  std::map<size_t, size_t> samples_per_bin_index_x;
46  std::map<size_t, size_t> samples_per_bin_index_y;
47  std::map<size_t, size_t> samples_per_bin_index_z;
48 
49  for (auto& particle : *simulation.particle_container) {
50  auto& velocity = particle.getV();
51  auto& position = particle.getX();
52 
53  // check if particle is in box
54  if (position[0] < box.first[0] || position[0] > box.second[0] || position[1] < box.first[1] || position[1] > box.second[1] ||
55  position[2] < box.first[2] || position[2] > box.second[2]) {
56  continue;
57  }
58 
59  size_t bin_index_x = std::floor((position[0] - box.first[0]) / bin_width[0]);
60  size_t bin_index_y = std::floor((position[1] - box.first[1]) / bin_width[1]);
61  size_t bin_index_z = std::floor((position[2] - box.first[2]) / bin_width[2]);
62 
63  avg_velocity_per_bin_index_x[bin_index_x] =
64  (1.0 / (samples_per_bin_index_x[bin_index_x] + 1)) *
65  (samples_per_bin_index_x[bin_index_x] * avg_velocity_per_bin_index_x[bin_index_x] + velocity);
66 
67  avg_velocity_per_bin_index_y[bin_index_y] =
68  (1.0 / (samples_per_bin_index_y[bin_index_y] + 1)) *
69  (samples_per_bin_index_y[bin_index_y] * avg_velocity_per_bin_index_y[bin_index_y] + velocity);
70 
71  avg_velocity_per_bin_index_z[bin_index_z] =
72  (1.0 / (samples_per_bin_index_z[bin_index_z] + 1)) *
73  (samples_per_bin_index_z[bin_index_z] * avg_velocity_per_bin_index_z[bin_index_z] + velocity);
74 
75  samples_per_bin_index_x[bin_index_x]++;
76  samples_per_bin_index_y[bin_index_y]++;
77  samples_per_bin_index_z[bin_index_z]++;
78  }
79 
80  for (auto& [bin_index, avg_velocity] : avg_velocity_per_bin_index_x) {
81  csv_writer_x->writeRow({iteration, bin_index, avg_velocity[0], avg_velocity[1], avg_velocity[2]});
82  }
83 
84  for (auto& [bin_index, avg_velocity] : avg_velocity_per_bin_index_y) {
85  csv_writer_y->writeRow({iteration, bin_index, avg_velocity[0], avg_velocity[1], avg_velocity[2]});
86  }
87 
88  for (auto& [bin_index, avg_velocity] : avg_velocity_per_bin_index_z) {
89  csv_writer_z->writeRow({iteration, bin_index, avg_velocity[0], avg_velocity[1], avg_velocity[2]});
90  }
91 }
92 
93 void VelocityProfileInterceptor::onSimulationEnd(size_t iteration, Simulation& simulation) {}
94 
96  std::string indent = std::string(depth * 2, ' ');
97 
98  Logger::logger->info("{}╟┤{}VelocityProfile: {}", indent, ansi_orange_bold, ansi_end);
99  Logger::logger->info("{}║ ┌Observed box: ({}, {}, {}) - ({}, {}, {})", indent, box.first[0], box.first[1], box.first[2],
100  box.second[0], box.second[1], box.second[2]);
101  Logger::logger->info("{}║ ├Number of bins per axis: {}", indent, num_bins);
102  Logger::logger->info("{}║ └Sample every x percent: {}", indent, sample_every_x_percent);
103 }
104 
105 VelocityProfileInterceptor::operator std::string() const {
106  return fmt::format("VelocityProfile: num_bins={}, sample_every_x_percent={}", num_bins, sample_every_x_percent);
107 }
const std::string ansi_end
Definition: Logger.h:13
const std::string ansi_orange_bold
Definition: Logger.h:10
static std::shared_ptr< spdlog::logger > logger
Publically accessible shared pointer to the logger.
Definition: Logger.h:35
double delta_t
Time step of a single simulation iteration.
std::filesystem::path output_dir_path
Path to the directory in which to save the simulation output.
size_t start_iteration
Start iteration of the simulation.
double end_time
End time of the simulation.
Class to run a simulation.
Definition: Simulation.h:20
std::unique_ptr< ParticleContainer > particle_container
Reference to the ParticleContainer on whose content the simulation is performed.
Definition: Simulation.h:50
const SimulationParams & params
Reference to the simulation parameters object.
Definition: Simulation.h:45
VelocityProfileInterceptor(std::pair< std::array< double, 3 >, std::array< double, 3 >> box, size_t num_bins, size_t sample_every_x_percent)
Construct a new Thermostat Interceptor object.
std::unique_ptr< CSVWriter > csv_writer_x
std::unique_ptr< CSVWriter > csv_writer_y
std::pair< std::array< double, 3 >, std::array< double, 3 > > box
void logSummary(int depth) const override
Logs the summary of the radial distribution function.
std::unique_ptr< CSVWriter > csv_writer_z
void operator()(size_t iteration, Simulation &simulation) override
This function is called on every nth iteration. It counts the number of particle updates which have b...
void onSimulationEnd(size_t iteration, Simulation &simulation) override
This function is empty as the thermostat doesnt need to do anything at the end of the simulation.
void onSimulationStart(Simulation &simulation) override
This function is sets the particle_updates to 0 and initializes the start time of the simulation.
std::string to_string(const Container &container, const std::string &delimiter=", ", const std::array< std::string, 2 > &surround={"[", "]"})
Definition: ArrayUtils.h:97