Penning Trap Simulation
Simulate particle behavior inside a Penning Trap
Loading...
Searching...
No Matches
PenningTrap.cpp
Go to the documentation of this file.
1
13#include "PenningTrap.hpp"
14#include "constants.hpp"
15#include "typedefs.hpp"
16#include "utils.hpp"
17
18PenningTrap::PenningTrap(double B_0, std::function<double(double)> V_0,
19 double d, double t)
20{
21 this->B_0 = B_0;
22 this->V_0 = V_0;
23 this->d = d;
24 this->t = t;
25}
26
27PenningTrap::PenningTrap(unsigned int i, double B_0,
28 std::function<double(double)> V_0, double d, double t)
29 : PenningTrap::PenningTrap(B_0, V_0, d)
30{
31 vec_3d r, v;
32 for (size_t j = 0; j < i; j++) {
33 r = vec_3d().randn() * .1 * this->d;
34 v = vec_3d().randn() * .1 * this->d;
35 this->add_particle(Particle(1., 40., r, v));
36 }
37}
38
39PenningTrap::PenningTrap(std::vector<Particle> particles, double B_0,
40 std::function<double(double)> V_0, double d, double t)
41 : PenningTrap::PenningTrap(B_0, V_0, d)
42{
43 this->particles = particles;
44}
45
46vec_3d PenningTrap::v_func(unsigned int i, unsigned int j, double dt)
47{
48 switch (i) {
49 case 0:
50 return .5 * dt * this->k_v[0][j];
51 case 1:
52 return .5 * dt * this->k_v[1][j];
53 case 2:
54 return dt * this->k_v[2][j];
55 case 3:
56 return (dt / 6.) * (this->k_v[0][j].eval() + this->k_v[1][j].eval() +
57 this->k_v[2][j].eval() + this->k_v[3][j].eval());
58 default:
59 std::cout << "Not valid!" << std::endl;
60 abort();
61 }
62}
63
64vec_3d PenningTrap::r_func(unsigned int i, unsigned int j, double dt)
65{
66 switch (i) {
67 case 0:
68 return .5 * dt * this->k_r[0][j];
69 case 1:
70 return .5 * dt * this->k_r[1][j];
71 case 2:
72 return dt * this->k_r[2][j];
73 case 3:
74 return (dt / 6.) * (this->k_r[0][j].eval() + this->k_r[1][j].eval() +
75 this->k_r[2][j].eval() + this->k_r[3][j].eval());
76 default:
77 std::cout << "Not valid!" << std::endl;
78 abort();
79 }
80}
81
83{
84 this->particles.push_back(particle);
85}
86
88{
89 r(2) *= -2.;
90 double f = this->V_0(this->t) / (this->d * this->d);
91
92 return f * r;
93}
94
96{
97 return vec_3d{0., 0., this->B_0};
98}
99
100vec_3d PenningTrap::force_on_particle(unsigned int i, unsigned int j)
101{
102 Particle p_j = this->particles[j];
103 // Calculate the difference between the particles' position
104 vec_3d res = this->particles[i].r_vec - p_j.r_vec;
105
106 // Get the distance between the particles
107 double norm = arma::norm(res, 2);
108
109 // Multiply res with p_j's charge divided by the norm cubed
110
111 return vec_3d(res * p_j.q / (norm * norm * norm));
112}
113
115{
116 Particle p = this->particles[i];
117
118 if (arma::norm(p.r_vec) > this->d) {
119 return vec_3d{0., 0., 0.};
120 }
121
122 vec_3d force =
123 p.q * (this->external_E_field(p.r_vec) +
124 arma::cross(p.v_vec, this->external_B_field(p.r_vec)));
125
126 return force;
127}
128
130{
131 Particle p = this->particles[i];
132
133 vec_3d res;
134
135 for (size_t j = 0; j < this->particles.size(); j++) {
136 if (i == j) {
137 continue;
138 }
139
140 res += this->force_on_particle(i, j);
141 }
142
143 return vec_3d(res * K_E * (p.q / p.m));
144}
145
147{
148 return this->total_force_external(i) - this->total_force_particles(i);
149}
150
151void PenningTrap::evolve_RK4(double dt, bool particle_interaction)
152{
153
154 std::vector<Particle> original_particles = this->particles;
155 std::vector<Particle> tmp_particles = this->particles;
156
157 vec_3d (PenningTrap::*force)(unsigned int);
158 if (particle_interaction) {
160 }
161 else {
163 }
164
165 size_t size = this->particles.size();
166
167 this->k_v = sim_arr(4, sim_cols(size));
168 this->k_r = sim_arr(4, sim_cols(size));
169
170 for (size_t i = 0; i < 4; i++) {
171#pragma omp parallel for
172 for (size_t j = 0; j < this->particles.size(); j++) {
173 this->k_v[i][j] = (this->*force)(j) / this->particles[j].m;
174 this->k_r[i][j] = this->particles[j].v_vec;
175
176 Particle *p = &tmp_particles[j];
177
178 p->v_vec = original_particles[j].v_vec + this->v_func(i, j, dt);
179 p->r_vec = original_particles[j].r_vec + this->r_func(i, j, dt);
180 }
181 this->particles = tmp_particles;
182 }
183 this->t += dt;
184}
185
186void PenningTrap::evolve_forward_euler(double dt, bool particle_interaction)
187{
188 std::vector<Particle> new_state = this->particles;
189
190 Particle *p;
191
192 vec_3d (PenningTrap::*force)(unsigned int);
193 if (particle_interaction) {
195 }
196 else {
198 }
199
200#pragma omp parallel for private(p)
201 for (size_t i = 0; i < this->particles.size(); i++) {
202 p = &new_state[i];
203 p->v_vec += dt * (this->*force)(i) / p->m;
204 p->r_vec += dt * this->particles[i].v_vec;
205 }
206
207 this->particles = new_state;
208 this->t += dt;
209}
210
211sim_arr PenningTrap::simulate(double time, unsigned int steps,
212 std::string method, bool particle_interaction)
213{
214 double dt = time / (double)steps;
215
216 sim_arr res(this->particles.size(), sim_cols(steps));
217
218 void (PenningTrap::*func)(double, bool);
219 if (method == "rk4") {
221 }
222 else if (method == "euler") {
224 }
225 else {
226 std::cout << "Not a valid method!" << std::endl;
227 abort();
228 }
229
230 for (size_t j = 0; j < steps; j++) {
231 for (size_t i = 0; i < this->particles.size(); i++) {
232 res[i][j] = this->particles[i].r_vec;
233 }
234 (this->*func)(dt, particle_interaction);
235 }
236
237 return res;
238}
239
240void PenningTrap::write_simulation_to_dir(std::string path, double time,
241 int steps, std::string method,
242 bool particle_interaction)
243{
244 if (path.back() != '/') {
245 path += '/';
246 }
247 if (mkpath(path, 0777) != 0) {
248 std::cout << "Hello" << std::endl;
249 return;
250 }
251
252 sim_arr res = this->simulate(time, steps, method, particle_interaction);
253
254 std::ofstream ofile;
255
256#pragma omp parallel for private(ofile)
257 for (size_t i = 0; i < this->particles.size(); i++) {
258 ofile.open(path + "particle_" + std::to_string(i) + ".txt");
259 for (vec_3d &vec : res[i]) {
260 ofile << vec(0) << "," << vec(1) << "," << vec(2) << "\n";
261 }
262 ofile.close();
263 }
264}
265
266double PenningTrap::fraction_of_particles_left(double time, unsigned int steps, std::string method, bool particle_interaction)
267{
268 sim_arr res = this->simulate(time, steps, method, particle_interaction);
269
270 int particles_left = 0;
271
272 for (Particle p : this->particles) {
273 if (arma::norm(p.r_vec) < this->d) {
274 particles_left++;
275 }
276 }
277
278 return (double) particles_left / (double) this->particles.size();
279}
280
A class for simulating a Penning trap.
A class that holds attributes of a particle.
Definition: Particle.hpp:21
double q
Charge.
Definition: Particle.hpp:23
vec_3d v_vec
velocity
Definition: Particle.hpp:26
double m
Mass.
Definition: Particle.hpp:24
vec_3d r_vec
position
Definition: Particle.hpp:25
A class that simulates a Penning trap.
Definition: PenningTrap.hpp:30
std::vector< Particle > particles
The particles in the Penning trap.
Definition: PenningTrap.hpp:36
double fraction_of_particles_left(double time, unsigned int 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...
double B_0
Magnetic field strength.
Definition: PenningTrap.hpp:32
vec_3d external_E_field(vec_3d r)
Calculate E at point r.
Definition: PenningTrap.cpp:87
vec_3d total_force(unsigned int i)
calculate the total force on a particle p_i.
sim_arr k_r
Definition: PenningTrap.hpp:39
void evolve_RK4(double dt, bool particle_interaction=true)
Go forward one timestep using the RK4 method.
vec_3d r_func(unsigned int i, unsigned int j, double dt)
Helper for evolve_RK4 when calculating values.
Definition: PenningTrap.cpp:64
vec_3d total_force_particles(unsigned int i)
Calculate the total force on a particle p_i from other particles.
sim_arr simulate(double time, unsigned int steps, std::string method="rk4", bool particle_interaction=true)
Simulate the particle system inside the Penning trap over a certain amount of time.
double d
Characteristic dimension.
Definition: PenningTrap.hpp:34
void add_particle(Particle particle)
Add a particle to the system.
Definition: PenningTrap.cpp:82
double t
Current time.
Definition: PenningTrap.hpp:35
vec_3d force_on_particle(unsigned int i, unsigned int j)
Calculate the force between 2 particles.
std::function< double(double)> V_0
Applied potential.
Definition: PenningTrap.hpp:33
void evolve_forward_euler(double dt, bool particle_interaction=true)
Go forward one timestep using the forward Euler method.
void write_simulation_to_dir(std::string path, double time, unsigned int steps, std::string method="rk4", bool particle_interaction=true)
Simulate and write the displacement of all particles to files.
vec_3d external_B_field(vec_3d r)
Calculate B at point r.
Definition: PenningTrap.cpp:95
PenningTrap(double B_0=T, std::function< double(double)> V_0=[](double t) { return 25. *V/1000.;}, double d=500., double t=0.)
Constructor for the PenningTrap class.
Definition: PenningTrap.cpp:18
vec_3d total_force_external(unsigned int i)
Calculate the total external force on a particle.
sim_arr k_v
Definition: PenningTrap.hpp:37
vec_3d v_func(unsigned int i, unsigned int j, double dt)
Helper for evolve_RK4 when calculating values.
Definition: PenningTrap.cpp:46
Library of constants.
#define K_E
Coulomb constant. unit: .
Definition: constants.hpp:15
Useful typedefs for cleaner code.
std::vector< arma::vec::fixed< 3 > > sim_cols
Typedef for the column of the result vector from simulating particles.
Definition: typedefs.hpp:24
arma::vec::fixed< 3 > vec_3d
Typedef for a fixed 3d arma vector.
Definition: typedefs.hpp:36
std::vector< sim_cols > sim_arr
Typedef for the result of the simulate method.
Definition: typedefs.hpp:32
Function prototypes and macros that are useful.
bool mkpath(std::string path, int mode=0777)
Make path given.
Definition: utils.cpp:76