/** @file main.cpp * * @author Cory Alexander Balaton (coryab) * @author Janita Ovidie Sandtrøen Willumsen (janitaws) * * @version 0.1 * * @brief The main program for this project * * @bug No known bugs * */ #include #include #include #include #include #include #include "PenningTrap.hpp" #include "utils.hpp" #define PARTICLES 100 #define N 40000 #define CHARGE 1. // unit: e #define MASS 40. // unit: amu // Particles used for testing 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() { // Initialize trap with particle 1 PenningTrap trap(std::vector{p1}); double time = 50.; // microseconds // Simulate and write results to file trap.write_simulation_to_dir("output/simulate_single_particle", time, N, "rk4", false); } void simulate_two_particles() { // Initialize traps with particles PenningTrap trap_no_interaction(std::vector{p1, p2}); PenningTrap trap_with_interaction(std::vector{p1, p2}); double time = 50.; // microseconds // Simulate and write results to files trap_no_interaction.write_simulation_to_dir( "output/simulate_2_particles/no_interaction", time, N, "rk4", false); trap_with_interaction.write_simulation_to_dir( "output/simulate_2_particles/with_interaction", time, N); } void simulate_single_particle_with_different_steps() { double time = 50.; // microseconds std::ofstream ofile; // Calculate relative error for RK4 std::string path = "output/relative_error/RK4/"; mkpath(path); for (int i = 0; i < 4; i++) { int steps = 4000 * std::pow(2, i); double dt = time / (double)steps; ofile.open(path + std::to_string(steps) + "_steps.txt"); PenningTrap trap(std::vector{p1}); simulation_t res = trap.simulate(time, steps, "rk4", false); for (int i = 0; i < steps; i++) { ofile << arma::norm(res.r_vecs[0][i] - analytical_solution_particle_1(dt*i)) << "\n"; } ofile.close(); } // Calculate relative error for forward Euler path = "output/relative_error/euler/"; mkpath(path); for (int i = 0; i < 4; i++) { int steps = 4000 * std::pow(2, i); double dt = time / (double)steps; ofile.open(path + std::to_string(steps) + "_steps.txt"); PenningTrap trap(std::vector{p1}); simulation_t res = trap.simulate(time, steps, "euler", false); for (int i = 0; i < steps; i++) { ofile << arma::norm(res.r_vecs[0][i] - analytical_solution_particle_1(dt*i)) << "\n"; } ofile.close(); } } void simulate_100_particles() { PenningTrap trap((unsigned)100); double time = 50.; // microseconds trap.write_simulation_to_dir("output/simulate_100_particles", time, N, "rk4", false); } // Wide sweep void simulate_100_particles_with_time_potential() { double time = 500.; double amplitudes[]{.1, .4, .7}; double freq_start = .2; double freq_end = 2.5; double freq_increment = .02; size_t freq_iterations = (size_t)((freq_end - freq_start) / freq_increment); double res[4][freq_iterations]; std::string path = "output/time_dependent_potential/"; mkpath(path); std::ofstream ofile; double freq = freq_start; for (size_t i = 0; i < freq_iterations; i++) { res[0][i] = freq; freq += freq_increment; } #pragma omp parallel for collapse(2) num_threads(4) for (size_t i = 0; i < 3; i++) { for (size_t j = 0; j < freq_iterations; j++) { PenningTrap trap( (unsigned)100, T, std::bind( [](double f, double r, double t) { return (25. * V / 1000.) * (1. + f * std::cos(r * t)); }, amplitudes[i], res[0][j], std::placeholders::_1), 500., 0.); res[i + 1][j] = trap.fraction_of_particles_left(time, N, "rk4", false); } } ofile.open(path + "res.txt"); for (size_t i = 0; i < freq_iterations; i++) { ofile << res[0][i] << "," << res[1][i] << "," << res[2][i] << "," << res[3][i] << "\n"; } ofile.close(); } int main() { double t0 = omp_get_wtime(); // simulate_single_particle(); // simulate_two_particles(); simulate_single_particle_with_different_steps(); double t1 = omp_get_wtime(); simulate_100_particles(); //simulate_100_particles_with_time_potential(); double end = omp_get_wtime(); std::cout << "Time: " << (end - t1) << " seconds" << std::endl; return 0; }