Molecular Dynamics Simulation  1.0
Simulation.cpp
Go to the documentation of this file.
1 #include "Simulation.h"
2 
3 #include <spdlog/fmt/chrono.h>
4 
5 #include <chrono>
6 #include <filesystem>
7 #include <iostream>
8 #include <tuple>
9 
11 #include "io/logger/Logger.h"
20 
21 Simulation::Simulation(const std::vector<Particle>& initial_particles, const SimulationParams& params, IntegrationMethod integration_method)
22  : params(params), integration_functor(get_integration_functor(integration_method)) {
23  // Create particle container
24  if (std::holds_alternative<SimulationParams::LinkedCellsType>(params.container_type)) {
25  auto lc_type = std::get<SimulationParams::LinkedCellsType>(params.container_type);
27  std::make_unique<LinkedCellsContainer>(lc_type.domain_size, lc_type.cutoff_radius, lc_type.boundary_conditions);
28  } else if (std::holds_alternative<SimulationParams::DirectSumType>(params.container_type)) {
29  particle_container = std::make_unique<DirectSumContainer>();
30  } else {
31  throw std::runtime_error("Unknown container type");
32  }
33 
34  // Add particles to container
35  particle_container->reserve(initial_particles.size());
36  for (auto& particle : initial_particles) {
37  particle_container->addParticle(particle);
38  }
39 }
40 
41 Simulation::~Simulation() = default;
42 
44  size_t iteration = params.start_iteration;
45  double simulated_time = params.start_iteration * params.delta_t;
46 
47  // Calculate initial forces
48  particle_container->prepareForceCalculation();
49  particle_container->applySimpleForces(params.simple_forces);
50  particle_container->applyPairwiseForces(params.pairwise_forces);
51  particle_container->applyTargettedForces(params.targetted_forces, simulated_time);
52 
53  Logger::logger->info("Simulation started...");
54 
55  std::time_t t_start_helper = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
56  Logger::logger->info("Start time: {}", fmt::format("{:%A %Y-%m-%d %H:%M:%S}", fmt::localtime(t_start_helper)));
57 
58  // Notify interceptors that the simulation is about to start
59  for (auto& interceptor : params.interceptors) {
60  (*interceptor).onSimulationStart(*this);
61  }
62 
63  auto t_start = std::chrono::high_resolution_clock::now();
64 
65  while (simulated_time < params.end_time) {
67  simulated_time);
68 
69  ++iteration;
70  simulated_time += params.delta_t;
71 
72  // Notify interceptors of the current iteration
73  for (auto& interceptor : params.interceptors) {
74  (*interceptor).notify(iteration, *this);
75  }
76  }
77 
78  auto t_end = std::chrono::high_resolution_clock::now();
79 
80  // Notify interceptors that the simulation has ended
81  for (auto& interceptor : params.interceptors) {
82  (*interceptor).onSimulationEnd(iteration, *this);
83  }
84 
85  Logger::logger->info("Simulation finished.");
86  Logger::logger->info("End time: {}", fmt::format("{:%A %Y-%m-%d %H:%M:%S}", fmt::localtime(t_end)));
87 
88  std::vector<std::string> interceptor_summaries;
89  for (auto& interceptor : params.interceptors) {
90  auto summary = std::string(*interceptor);
91  if (!summary.empty()) {
92  interceptor_summaries.push_back(summary);
93  }
94  }
95 
96  auto total_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(t_end - t_start).count();
97 
98  SimulationOverview overview{params, total_time_ms / 1000.0, iteration, interceptor_summaries,
99  std::vector<Particle>(particle_container->begin(), particle_container->end())};
100 
101  return overview;
102 }
std::unique_ptr< IntegrationFunctor > get_integration_functor(IntegrationMethod method)
Returns the corresponding integration functor for the given integration method.
IntegrationMethod
Enum class to specify the integration method.
static std::shared_ptr< spdlog::logger > logger
Publically accessible shared pointer to the logger.
Definition: Logger.h:35
Class to store some overview data of an executed simulation.
Contains all parameters needed to run a simulation.
std::vector< std::shared_ptr< PairwiseForceSource > > pairwise_forces
Pairwise Forces to be applied to the particles.
double delta_t
Time step of a single simulation iteration.
std::vector< std::shared_ptr< SimulationInterceptor > > interceptors
List of interceptors to be used in the simulation.
size_t start_iteration
Start iteration of the simulation.
std::vector< std::shared_ptr< SimpleForceSource > > simple_forces
Simple Forces to be applied to the particles.
std::vector< std::shared_ptr< TargettedForceSource > > targetted_forces
Targetted Forces to be applied to the particles.
std::variant< DirectSumType, LinkedCellsType > container_type
Type of the particle container.
double end_time
End time of the simulation.
Simulation(const std::vector< Particle > &particles, const SimulationParams &params, IntegrationMethod integration_method=IntegrationMethod::VERLET)
Construct a new Simulation object and initialize all the necessary components.
Definition: Simulation.cpp:21
std::unique_ptr< ParticleContainer > particle_container
Reference to the ParticleContainer on whose content the simulation is performed.
Definition: Simulation.h:50
SimulationOverview runSimulation()
Runs the simulation, using the parameters given at construction and returns a SimulationOverview obje...
Definition: Simulation.cpp:43
std::unique_ptr< IntegrationFunctor > integration_functor
Functor used to integrate the particles.
Definition: Simulation.h:55
const SimulationParams & params
Reference to the simulation parameters object.
Definition: Simulation.h:45