Penning Trap Simulation
Simulate particle behavior inside a Penning Trap
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1
13#include <cmath>
14#include <complex>
15#include <fstream>
16#include <omp.h>
17#include <string>
18#include <vector>
19
20#include "PenningTrap.hpp"
21#include "constants.hpp"
22#include "utils.hpp"
23
24#define PARTICLES 100
25#define N 40000
26
27// Particles used for testing
28Particle p1(vec3{20., 0., 20.}, vec3{0., 25., 0.});
29Particle p2(vec3{25., 25., 0.}, vec3{0., 40., 5.});
30
38{
39 double w_0 = T / CA_MASS;
40 double w_z2 = (50. * V / 1000.) / (CA_MASS * 500. * 500.);
41 double w_p = (w_0 + std::sqrt(w_0 * w_0 - 2. * w_z2)) / 2.;
42 double w_n = (w_0 - std::sqrt(w_0 * w_0 - 2. * w_z2)) / 2.;
43 double A_p = (25. + w_n * 20.) / (w_n - w_p);
44 double A_n = -(25. + w_p * 20.) / (w_n - w_p);
45 std::cout << A_p << "," << A_n << std::endl;
46 std::complex<double> f =
47 A_p * std::exp(std::complex<double>(0., -w_p * t))
48 + A_n * std::exp(std::complex<double>(0., -w_n * t));
49 vec3 res{std::real(f), std::imag(f), 20. * std::cos(std::sqrt(w_z2) * t)};
50 return res;
51}
52
56{
57 // Initialize trap with particle 1
58 PenningTrap trap(std::vector<Particle>{p1});
59
60 double time = 50.; // microseconds
61
62 // Simulate and write results to file
63 trap.write_simulation_to_dir("output/simulate_single_particle", time, N,
64 "rk4", false);
65}
66
71{
72 // Initialize traps with particles
73 PenningTrap trap_no_interaction(std::vector<Particle>{p1, p2});
74 PenningTrap trap_with_interaction(std::vector<Particle>{p1, p2});
75
76 double time = 50.; // microseconds
77
78 // Simulate and write results to files
79 trap_no_interaction.write_simulation_to_dir(
80 "output/simulate_2_particles/no_interaction", time, N, "rk4", false);
81 trap_with_interaction.write_simulation_to_dir(
82 "output/simulate_2_particles/with_interaction", time, N);
83}
84
89{
90 double time = 50.; // microseconds
91
92 std::ofstream ofile;
93
94 // Calculate relative error for RK4
95 std::string path = "output/relative_error/RK4/";
96 mkpath(path);
97#pragma omp parallel for private(ofile)
98 for (int i = 0; i < 4; i++) {
99 int steps = 4000 * std::pow(2, i);
100 std::cout << steps << std::endl;
101 double dt = time / (double)steps;
102 ofile.open(path + std::to_string(steps) + "_steps.txt");
103 PenningTrap trap(std::vector<Particle>{p1});
104 simulation_t res = trap.simulate(time, steps, "rk4", false);
105 for (int i = 0; i < steps; i++) {
106 ofile << arma::norm(res.r_vecs[0][i]
108 << '\n';
109 }
110 ofile.close();
111 }
112
113 // Calculate relative error for forward Euler
114 path = "output/relative_error/euler/";
115 mkpath(path);
116#pragma omp parallel for private(ofile)
117 for (int i = 0; i < 4; i++) {
118 int steps = 4000 * std::pow(2, i);
119 double dt = time / (double)steps;
120 ofile.open(path + std::to_string(steps) + "_steps.txt");
121 PenningTrap trap(std::vector<Particle>{p1});
122 simulation_t res = trap.simulate(time, steps, "euler", false);
123 for (int i = 0; i < steps; i++) {
124 ofile << arma::norm(res.r_vecs[0][i]
126 << '\n';
127 }
128 ofile.close();
129 }
130}
131
135{
136 PenningTrap trap((unsigned)100);
137
138 double time = 50.; // microseconds
139
140 // trap.write_simulation_to_dir("output/simulate_100_particles", time, N,
141 //"rk4", false);
142 trap.simulate(time, N, "rk4", true);
143}
144
153{
154 double time = 500.;
155
156 double amplitudes[]{.1, .4, .7};
157
158 double freq_start = .2;
159 double freq_end = 2.5;
160 double freq_increment = .02;
161 size_t freq_iterations =
162 (size_t)((freq_end - freq_start) / freq_increment) + 1;
163
164 double res[4][freq_iterations];
165
166 std::string path = "output/time_dependent_potential/";
167 mkpath(path);
168
169 std::ofstream ofile;
170
171#pragma omp parallel for
172 // Insert frequencies
173 for (size_t i = 0; i < freq_iterations; i++) {
174 res[0][i] = freq_start + freq_increment * i;
175 }
176
177#pragma omp parallel
178 {
179 // Each thread creates a PenningTrap instance and reuses it throughout
180 // the sweep.
181 PenningTrap trap((uint)100);
182#pragma omp for collapse(2)
183 for (size_t i = 0; i < 3; i++) {
184 for (size_t j = 0; j < freq_iterations; j++) {
185 // Reset particles and give new time dependent potential.
186 trap.reinitialize(amplitudes[i], res[0][j]);
187 res[i + 1][j] =
188 trap.fraction_of_particles_left(time, N, "rk4", false);
189 }
190 }
191 }
192
193 // Write results to file
194 ofile.open(path + "wide_sweep.txt");
195 for (size_t i = 0; i < freq_iterations; i++) {
196 ofile << res[0][i] << ',' << res[1][i] << ',' << res[2][i] << ','
197 << res[3][i] << '\n';
198 }
199 ofile.close();
200}
201
210{
211 double time = 500.;
212
213 double amplitudes[]{.1, .4, .7};
214
215 double freq_start = 1.1;
216 double freq_end = 1.7;
217 double freq_increment = .002;
218 size_t freq_iterations =
219 (size_t)((freq_end - freq_start) / freq_increment) + 1;
220
221 double res[4][freq_iterations];
222
223 std::string path = "output/time_dependent_potential/";
224 mkpath(path);
225
226 std::ofstream ofile;
227
228#pragma omp parallel for
229 // Insert frequencies
230 for (size_t i = 0; i < freq_iterations; i++) {
231 res[0][i] = freq_start + freq_increment * i;
232 }
233
234#pragma omp parallel
235 {
236 // Each thread creates a PenningTrap instance and reuses it throughout
237 // the sweep.
238 PenningTrap trap((uint)100);
239#pragma omp for collapse(2)
240 for (size_t i = 0; i < 3; i++) {
241 for (size_t j = 0; j < freq_iterations; j++) {
242 // Reset particles and give new time dependent potential.
243 trap.reinitialize(amplitudes[i], res[0][j]);
244 res[i + 1][j] =
245 trap.fraction_of_particles_left(time, N, "rk4", false);
246 }
247 }
248 }
249
250 // Write results to file
251 ofile.open(path + "narrow_sweep.txt");
252 for (size_t i = 0; i < freq_iterations; i++) {
253 ofile << res[0][i] << ',' << res[1][i] << ',' << res[2][i] << ','
254 << res[3][i] << '\n';
255 }
256 ofile.close();
257}
258
267{
268 double time = 500.;
269
270 double amplitudes[]{.1, .4, .7};
271
272 double freq_start = 1.1;
273 double freq_end = 1.7;
274 double freq_increment = .002;
275 size_t freq_iterations =
276 (size_t)((freq_end - freq_start) / freq_increment) + 1;
277
278 double res[4][freq_iterations];
279
280 std::string path = "output/time_dependent_potential/";
281 mkpath(path);
282
283 std::ofstream ofile;
284
285#pragma omp parallel for
286 for (size_t i = 0; i < freq_iterations; i++) {
287 res[0][i] = freq_start + freq_increment * i;
288 }
289
290#pragma omp parallel
291 {
292 // Each thread creates a PenningTrap instance and reuses it throughout
293 // the sweep.
294 PenningTrap trap((uint)100);
295#pragma omp for collapse(2)
296 for (size_t i = 0; i < 3; i++) {
297 for (size_t j = 0; j < freq_iterations; j++) {
298 // Reset particles and give new time dependent potential.
299 trap.reinitialize(amplitudes[i], res[0][j]);
300 res[i + 1][j] = trap.fraction_of_particles_left(time, N);
301 }
302 }
303 }
304
305 // Write results to file
306 ofile.open(path + "narrow_sweep_interactions.txt");
307 for (size_t i = 0; i < freq_iterations; i++) {
308 ofile << res[0][i] << ',' << res[1][i] << ',' << res[2][i] << ','
309 << res[3][i] << '\n';
310 }
311 ofile.close();
312}
313
314int main()
315{
316 int option = 1;
317 bool chosen = false;
318
319 system("clear");
320 std::cout << "(1) All (default)\n"
321 << "(2) Simulate single particle\n"
322 << "(3) simulate 2 particles\n"
323 << "(4) Simulate single particle with different time steps\n"
324 << "(5) Simulate 100 particles\n"
325 << "(6) Potential resonance wide sweep\n"
326 << "(7) Potential resonance narrow sweep without particle "
327 "interactions\n"
328 << "(8) Potential resonance narrow sweep with particle "
329 "interaction\n"
330 << "Select what to run: ";
331 std::cin >> std::noskipws;
332 do {
333 if (!(std::cin >> option) || option < 1 || option > 8) {
334 std::cin.clear();
335 std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
336 system("clear");
337 std::cout
338 << "(1) All (default)\n"
339 << "(2) Simulate single particle\n"
340 << "(3) simulate 2 particles\n"
341 << "(4) Simulate single particle with different time steps\n"
342 << "(5) Simulate 100 particles\n"
343 << "(6) Potential resonance wide sweep\n"
344 << "(7) Potential resonance narrow sweep without particle "
345 "interactions\n"
346 << "(8) Potential resonance narrow sweep with particle "
347 "interaction\n"
348 << "Not a valid option, please enter a valid number: ";
349 } else {
350 chosen = true;
351 }
352 } while (!chosen);
353
354 double start, end;
355
356 system("clear");
357
358 start = omp_get_wtime();
359 switch (option) {
360 case 1:
361 std::cout << "Running simulate_single_particle\n";
363
364 std::cout << "Running simulate_two_particles\n";
366
367 std::cout << "Running simulate_single_particle_with_different_steps\n";
369
370 std::cout << "Running simulate_100_particles\n";
372
373 std::cout << "Running potential_resonance_wide_sweep\n";
375
376 std::cout << "Running potential_resonance_narrow_sweep\n";
378
379 std::cout << "Running potential_resonance_narrow_sweep_interaction\n";
381 break;
382 case 2:
383 std::cout << "Running simulate_single_particle\n";
385 break;
386 case 3:
387 std::cout << "Running simulate_two_particles\n";
389 break;
390 case 4:
391 std::cout << "Running simulate_single_particle_with_different_steps\n";
393 break;
394 case 5:
395 std::cout << "Running simulate_100_particles\n";
397 break;
398 case 6:
399 std::cout << "Running potential_resonance_wide_sweep\n";
401 break;
402 case 7:
403 std::cout << "Running potential_resonance_narrow_sweep\n";
405 break;
406 case 8:
407 std::cout << "Running potential_resonance_narrow_sweep_interaction\n";
409 break;
410 }
411 end = omp_get_wtime();
412
413 std::cout << "Time: " << end - start << " seconds" << std::endl;
414
415 return 0;
416}
A class for simulating a Penning trap.
A class that holds attributes of a particle.
Definition: Particle.hpp:23
A class that simulates a Penning trap.
Definition: PenningTrap.hpp:32
simulation_t simulate(double time, uint steps, std::string method="rk4", bool particle_interaction=true)
Simulate the particle system inside the Penning trap over a certain amount of time.
void reinitialize(double f, double omega_V, double t=0.)
Give all particles new positions and velocities, and change t and V_0.
double fraction_of_particles_left(double time, uint steps, std::string method="rk4", bool particle_interaction=true)
Simulate and calculate what fraction of particles are still left inside the Penning trap after the si...
void write_simulation_to_dir(std::string path, double time, uint steps, std::string method="rk4", bool particle_interaction=true)
Simulate and write the displacement of all particles to files.
Library of constants.
#define T
1 Tesla. unit:
Definition: constants.hpp:21
#define CA_MASS
Mass of a single calcium ion. unit: amu.
Definition: constants.hpp:29
#define V
1 Volt. unit:
Definition: constants.hpp:25
void simulate_100_particles()
Simulate 100 particles over 50 .
Definition: main.cpp:134
Particle p1(vec3{20., 0., 20.}, vec3{0., 25., 0.})
Particle 1.
void potential_resonance_narrow_sweep()
Simulate 100 particles over 500 using a time dependent potential.
Definition: main.cpp:209
void potential_resonance_wide_sweep()
Simulate 100 particles over 500 using a time dependent potential.
Definition: main.cpp:152
void simulate_two_particles()
Simulate 2 particles over the period of 50 with and without particle interactions.
Definition: main.cpp:70
vec3 analytical_solution_particle_1(double t)
The analytical solution for particle p1.
Definition: main.cpp:37
void simulate_single_particle()
Simulate a single particle over the period of 50 .
Definition: main.cpp:55
void potential_resonance_narrow_sweep_interaction()
Simulate 100 particles over 500 using a time dependent potential.
Definition: main.cpp:266
void simulate_single_particle_with_different_steps()
Simulate a single particle over 50 using different amount of steps and different methods.
Definition: main.cpp:88
Particle p2(vec3{25., 25., 0.}, vec3{0., 40., 5.})
Particle 2.
Typedef for PenningTrap::simulation return value.
Definition: typedefs.hpp:40
arma::vec::fixed< 3 > vec3
Typedef for a fixed 3d arma vector.
Definition: typedefs.hpp:23
Function prototypes and macros that are useful.
bool mkpath(std::string path, int mode=0777)
Make path given.
Definition: utils.cpp:72