diff --git a/include/PenningTrap.hpp b/include/PenningTrap.hpp index eaf89be..9a78784 100644 --- a/include/PenningTrap.hpp +++ b/include/PenningTrap.hpp @@ -222,6 +222,9 @@ public: double fraction_of_particles_left(double time, unsigned int steps, std::string method = "rk4", bool particle_interaction = true); + + vec_3d get_r(int i); + double get_t(); }; #endif diff --git a/latex/images/3d_plot.pdf b/latex/images/3d_plot.pdf new file mode 100644 index 0000000..78b115e Binary files /dev/null and b/latex/images/3d_plot.pdf differ diff --git a/latex/images/phase_space_2_particles.pdf b/latex/images/phase_space_2_particles.pdf new file mode 100644 index 0000000..6c006d4 Binary files /dev/null and b/latex/images/phase_space_2_particles.pdf differ diff --git a/latex/images/phase_space_2_particles_x.pdf b/latex/images/phase_space_2_particles_x.pdf new file mode 100644 index 0000000..7af3a9c Binary files /dev/null and b/latex/images/phase_space_2_particles_x.pdf differ diff --git a/latex/images/phase_space_2_particles_z.pdf b/latex/images/phase_space_2_particles_z.pdf new file mode 100644 index 0000000..86fe6c3 Binary files /dev/null and b/latex/images/phase_space_2_particles_z.pdf differ diff --git a/latex/images/plot_2_particles_xy.pdf b/latex/images/plot_2_particles_xy.pdf new file mode 100644 index 0000000..8e44ccd Binary files /dev/null and b/latex/images/plot_2_particles_xy.pdf differ diff --git a/latex/images/single_particle.pdf b/latex/images/single_particle.pdf index 1180de9..cf0ee5a 100644 Binary files a/latex/images/single_particle.pdf and b/latex/images/single_particle.pdf differ diff --git a/src/PenningTrap.cpp b/src/PenningTrap.cpp index ab99599..d5a3b16 100644 --- a/src/PenningTrap.cpp +++ b/src/PenningTrap.cpp @@ -53,8 +53,8 @@ vec_3d PenningTrap::v_func(unsigned int i, unsigned int j, double dt) case 2: return dt * this->k_v[2][j]; case 3: - return (dt / 6.) * (this->k_v[0][j] + 2.*this->k_v[1][j] + - 2.*this->k_v[2][j] + this->k_v[3][j]); + return (dt / 6.) * (this->k_v[0][j] + 2. * this->k_v[1][j] + + 2. * this->k_v[2][j] + this->k_v[3][j]); default: std::cout << "Not valid!" << std::endl; abort(); @@ -71,8 +71,8 @@ vec_3d PenningTrap::r_func(unsigned int i, unsigned int j, double dt) case 2: return dt * this->k_r[2][j]; case 3: - return (dt / 6.) * (this->k_r[0][j] + 2.*this->k_r[1][j] + - 2.*this->k_r[2][j] + this->k_r[3][j]); + return (dt / 6.) * (this->k_r[0][j] + 2. * this->k_r[1][j] + + 2. * this->k_r[2][j] + this->k_r[3][j]); default: std::cout << "Not valid!" << std::endl; abort(); @@ -106,8 +106,6 @@ vec_3d PenningTrap::force_on_particle(unsigned int i, unsigned int j) // Get the distance between the particles double norm = arma::norm(res, 2); - // Multiply res with p_j's charge divided by the norm cubed - return vec_3d(res * p_j.q / (norm * norm * norm)); } @@ -298,3 +296,13 @@ double PenningTrap::fraction_of_particles_left(double time, unsigned int steps, return (double)particles_left / (double)this->particles.size(); } + +vec_3d PenningTrap::get_r(int i) +{ + return this->particles[i].r_vec; +} + +double PenningTrap::get_t() +{ + return this->t; +} diff --git a/src/main.cpp b/src/main.cpp index 75a842d..19ef8fd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,6 +11,7 @@ * */ #include +#include #include #include #include @@ -29,6 +30,20 @@ Particle p1(CHARGE, MASS, vec_3d{20., 0., 20.}, vec_3d{0., 25., 0.}); Particle p2(CHARGE, MASS, vec_3d{25., 25., 0.}, vec_3d{0., 40., 5.}); +vec_3d analytical_solution_particle_1(double t) +{ + double w_0 = T / MASS; + double w_z2 = (50. * V / 1000.) / (MASS * 500. * 500.); + double w_p = (w_0 + std::sqrt(w_0 * w_0 - 2. * w_z2)) / 2.; + double w_n = (w_0 - std::sqrt(w_0 * w_0 - 2. * w_z2)) / 2.; + double A_p = (25. + w_n * 20.) / (w_n - w_p); + double A_n = -(25. + w_p * 20.) / (w_n - w_p); + std::complex f = A_p * std::exp(std::complex(0., -w_p * t)) + + A_n * std::exp(std::complex(0., -w_n * t)); + vec_3d res{std::real(f), std::imag(f), 20. * std::cos(std::sqrt(w_z2) * t)}; + return res; +} + void simulate_single_particle() { DEBUG("Inside single particle sim"); @@ -37,7 +52,8 @@ void simulate_single_particle() double time = 50.; // microseconds DEBUG("Write to dir"); - trap.write_simulation_to_dir("output/simulate_single_particle", time, N, "rk4", false); + trap.write_simulation_to_dir("output/simulate_single_particle", time, N, + "rk4", false); } void simulate_two_particles() @@ -56,22 +72,40 @@ void simulate_two_particles() void simulate_single_particle_with_different_steps() { - double time = 50; // microseconds + double time = 50.; // microseconds + + std::ofstream ofile; for (int i = 0; i < 4; i++) { - int steps = 4000 * (i + 1); + int steps = 4000 * std::pow(2, i); + double dt = time / (double)steps; + std::string path = "output/relative_error/RK4/"; + mkpath(path); + ofile.open(path + std::to_string(steps) + "_steps.txt"); PenningTrap trap(std::vector{p1}); - trap.write_simulation_to_dir("output/N_steps/RK4/" + - std::to_string(steps) + "_steps", - time, steps, "rk4", false); + for (int i = 0; i < steps; i++) { + trap.evolve_RK4(dt); + ofile << arma::norm(trap.get_r(0) - + analytical_solution_particle_1(trap.get_t())) + << "\n"; + } + ofile.close(); } for (int i = 0; i < 4; i++) { - int steps = 4000 * (i + 1); + int steps = 4000 * std::pow(2, i); + double dt = time / (double)steps; + std::string path = "output/relative_error/euler/"; + mkpath(path); + ofile.open(path + std::to_string(steps) + "_steps.txt"); PenningTrap trap(std::vector{p1}); - trap.write_simulation_to_dir("output/N_steps/euler/" + - std::to_string(steps) + "_steps", - time, steps, "euler", false); + for (int i = 0; i < steps; i++) { + trap.evolve_forward_euler(dt); + ofile << arma::norm(trap.get_r(0) - + analytical_solution_particle_1(trap.get_t())) + << "\n"; + } + ofile.close(); } } @@ -105,7 +139,7 @@ void simulate_100_particles_with_time_potential() std::ofstream ofile; double freq = freq_start; - for (size_t i=0; i