\subsection*{Penning trap}
Penning traps use a combination of a magnetic and electric field to confine the trajectory of a charged particle to a finite volume over long periods of time\cite[p.~9-10]{vogel_particle_2024}. Finite volume in this context refers to volumes in the order of \unit{\mm \cubed} up to \unit{\cm \cubed}. Long time ranges imply a period that exceeds the period of motion of the particle by multiple orders. For the studied case we will use an ideal Penning trap, i.e. there are no inhomogenities in the fields. The magnetic field will be defined as
\begin{equation} \label{eq:B_field}
    B(\vec r, t) = B_0 \Theta\left(d - |\vec r |\right) \cdot \vec e_z,
\end{equation}
with the Heaviside function $\Theta(x)$, and we define two electric fields via the electric potentials
\begin{equation} \label{eq:V_stat}
    \vstat(\vec r, t) = \frac{V_0 \cdot (2z^2 - x^2 - y^2) \Theta\left(d - |\vec r |\right)}{2d^2}
\end{equation}
and
\begin{equation}
    \vdyn(\vec r, t) = (1 + f \cos \omega_V t) \cdot \vstat(\vec r, t).
\end{equation}

\subsection*{Equations of motion}
Using Newton's equations of motion, $\ddot{\vec r} = \vec F / m$, we can derive ordinary differential equations for the position of a particle which is subject to \cref{eq:B_field,eq:V_stat}. As the magnetic field is parallel to the $z$-axis, the differential equation for the vertical component is straightforward to derive. Using the electric field resulting from $\vstat$ (see \cref{app:efield_equations} for details on all electric field components) we find
\begin{equation}
    \ddot z + \omega_z^2 z \equiv \ddot z + \frac{2 q V_0}{m d^2} z = 0.
\end{equation}
This is a simple harmonic oscillator equation which can be solved using standard methods.
In the transversal plane, the equations of motion are coupled due to the Lorentz force $\vec F = q \vec v \times \vec B$. Using the electric field resulting from $\vstat$ (see \cref{app:efield_equations} for details on all electric field components) we find
\begin{align}
    \ddot x - \omega_0 \dot y - \frac{1}{2} \omega_z^2 x &\equiv \ddot x - \frac{q B_0}{m} \dot y - \frac{q V_0}{m d^2} x = 0, \label{eq:transv_eom_x}\\
    \ddot y + \omega_0 \dot x - \frac{1}{2} \omega_z^2 y &\equiv \ddot y + \frac{q B_0}{m} \dot x - \frac{q V_0}{m d^2} y = 0 \label{eq:transv_eom_y}.
\end{align}
Using the sum of equations: $\eqref{eq:transv_eom_x} + i \eqref{eq:transv_eom_y}$, we can use the general definition $f(t) \equiv x(t) + i y(t)$ to derive a single complex differential equation for the transversal motion
\begin{equation} \label{eq:complex_transv_eom}
    \ddot f + i \omega_0 \dot f - \frac{1}{2} \omega_z^2 f = 0.
\end{equation}
After solving the differential equation, the real and imaginary parts of $f(t)$ will correspond to the $x$ and $y$ components of the trajectory, respectively.
\Cref{eq:complex_transv_eom} is a damped harmonic oscillator equation with the general solution
\begin{equation} \label{eq:general_transv_solution}
    f(t) = A_+ e^{-i (\omega_+ t + \phi_+)} + A_- e^{-i (\omega_- t + \phi_-)},
\end{equation}
with the two characteristic frequencies
\begin{equation}
    \omega_\pm = \frac{\omega_0 \pm \sqrt{\omega_0^2 - 2 \omega_z^2}}{2}.
\end{equation}
This solution is valid for $\omega_0^2 > 2 \omega_z^2$. In the case of $\omega_0^2 \leq \omega_z^2$, the oscillation frequencies become complex, leading to exponential growth of the trajectory in the transversal plane. This condition is known as the stability criterion for a Penning trap \cite[p.~67]{vogel_particle_2024}. In terms of the physical parameters of the trap, the stability criterion can be expressed as
\begin{equation}
    \frac{q}{m} B_0^2 > \frac{2 V_0}{d^2}.
\end{equation}
Given this condition, the solution for the transversal motion will be bound, i.e. $|f(t)| < \infty$ for all $t > 0$. Given the stability criterion, the two terms in \cref{eq:general_transv_solution} can be identified as sinusoidal motions with amplitudes $A_\pm$. If the two terms are in phase the upper limit of $|f| \equiv R_+$ will be $R_+ = A_+ + A_-$, while the lower limit for the case of antiparallel phases will be the absolute of the difference in the two amplitudes, $R_- = |A_+ - A_-|$. A analytical solution for a special case of initial conditions is derived in \cref{app:special_case_analytical_solution}.

\subsubsection*{Multiple particles}
For the case of multiple particles, it is important to include the particle-particle interactions. For this analysis we will only consider the Coulomb interaction between the particles, neglecting magnetic interactions. The force on particle $i$ due to all other particles $j$ is then given by
\begin{equation}
    \vec F_i = \frac{q_i}{4 \pi \epsilon_0} \sum_{j \neq i} \frac{q_j (\vec r_j - \vec r_i)}{|\vec r_j - \vec r_i|^3}.
\end{equation}

\subsection*{Numerical Integration Methods}
\subsubsection*{Forward Euler method}
The simplest numerical method to solve the ordinary differential equation system is the Forward Euler method. It is a first order method, meaning that the local truncation error per step is on the order of $\mathcal{O}(h^2)$, with $h$ being the step size. The global error after $N$ steps is therefore on the order of $\mathcal{O}(h)$ \cite{fjordholm_numerical_nodate}. The method is explicit, meaning that the state of the system at the next time step can be calculated directly from the current state. Given a general ordinary differential equation of the form
\begin{equation}
    \dot y(t) = f(t, y(t)),
\end{equation}
the Forward Euler method updates the state of the system as follows:
\begin{equation}
    y_{n+1} = y_n + h f(t_n, y_n).
\end{equation}
For our second order differential equations, we first rewrite them as a system of first order equations. The next state of the system is then calculated using the current position and velocity as \cite{fjordholm_numerical_nodate}
\begin{align}
    \vec r_{n+1} &= \vec r_n + h \vec v_n, \\
    \vec v_{n+1} &= \vec v_n + h \frac{\vec F(\vec r_n, \vec v_n, t_n)}{m}.
\end{align}
This method is computationally inexpensive, as we only need a single force evaluation per time step. However, it is known to be not very accurate.
\subsubsection*{Runge-Kutta 4 method}
The Runge-Kutta 4 (RK4) method is a popular and more accurate method for solving ordinary differential equations. It is a fourth-order method, meaning that the local truncation error per step is on the order of $\mathcal{O}(h^5)$, and the global error after $N$ steps is on the order of $\mathcal{O}(h^4)$ \cite{fjordholm_numerical_nodate}. The RK4 method calculates the next state of the system using a weighted average of four different estimates of the slope (the derivative) at different points within the time step. Given a general ordinary differential equation of the form
\begin{equation}
    \dot y(t) = f(t, y(t)),
\end{equation}
the RK4 method updates the state of the system as follows \cite{cheever_fourth_2022,fjordholm_numerical_nodate}:
\begin{align}
    k_1 &= h f(t_n, y_n), \\
    k_2 &= h f\left(t_n + \frac{h}{2}, y_n + \frac{k_1}{2}\right), \\
    k_3 &= h f\left(t_n + \frac{h}{2}, y_n + \frac{k_2}{2}\right), \\
    k_4 &= h f(t_n + h, y_n + k_3), \\
    y_{n+1} &= y_n + \frac{1}{6}(k_1 + 2k_2 + 2k_3 + k_4).
\end{align}
As this method is again a generalized solver for ODE of the first order, we again rewrite our second order differential equations as a system of first order equations. 

\subsubsection*{Velocity-Verlet method}
In contrast to the previous two methods, the Velocity-Verlet method is a symplectic integrator which is specifically designed for second order differential equations of the form
\begin{equation}
    \ddot{\vec r}(t) = \frac{\vec F(\vec r(t), t)}{m}.
\end{equation}
The method is time-reversible and conserves energy better over long time periods compared to non-symplectic methods like Forward Euler and RK4 \cite{kubar_lecture_2025}. The Velocity-Verlet method updates the position and velocity of the system as follows \cite{kubar_lecture_2025}:
\begin{align}
    \vec r_{n+1} &= \vec r_n + h \vec v_n + \frac{h^2}{2} \vec a_n, \\
    \vec a_{n+1} &= \frac{\vec F(\vec r_{n+1}, t_{n+1})}{m}, \\
    \vec v_{n+1} &= \vec v_n + \frac{h}{2} (\vec a_n + \vec a_{n+1}),
\end{align}
It is important to note that the Velocity-Verlet integrator requires forces to be independent of velocity. In the case, that the algorithm is applicable, it is a very efficient method, as it only requires a single force evaluation per time step, while still being a second order method with a local truncation error per step on the order of $\mathcal{O}(h^3)$ and a global error after $N$ steps on the order of $\mathcal{O}(h^2)$\cite{kubar_lecture_2025}.
Because of the symplectic nature, the low number of force evaluations and the good energy conservation properties, the Velocity-Verlet method is widely used and the quasi-standard in molecular dynamics simulations\cite{kubar_lecture_2025}.

\subsubsection*{Boris algorithm}
The Boris algorithm is a widely used method for integrating the equations of motion of charged particles in electromagnetic fields \cite{webb_symplectic_2014,noauthor_pdf_2025}. It is particularly well-suited for problems where the Lorentz force plays a significant role, as it is designed to handle the velocity-dependent nature of the magnetic force. The Boris algorithm is a symplectic integrator\cite{webb_symplectic_2014}\footnote{The simplecticity of Boris algorithm is controversial with disagreement between papers \cite{noauthor_pdf_2025}. All publications agree on the fact, that Boris algorithm is phase-space preserving at the very least.}, which means it conserves the phase space volume and exhibits good long-term energy conservation properties. The algorithm updates the position and velocity of a charged particle in a magnetic field as follows:
We define two auxiliary velocities $\vec v^-$ and $\vec v^+$, which represent the velocity before and after the magnetic field rotation, respectively. The algorithm proceeds in the following steps \cite{hoppock_iwhoppockboris-algorithm_2025}:
\begin{align}
    \vec v^- &= \vec v_n + \frac{q \vec E h}{2m}\\
    \vec v' &= \vec v^- + \vec v^- \times \vec t\\
    \vec v^+ &= \vec v^- + \vec v' \times \vec s
\end{align}
with
\begin{align}
    \vec t &= \frac{q \vec B h}{2m}\\
    \vec s &= \frac{2 \vec t}{1 + |\vec t|^2}.
\end{align}
The final update of the velocity and position is then given by
\begin{align}
    \vec v_{n+1} &= \vec v^+ + \frac{q \vec E h}{2m}\\
    \vec r_{n+1} &= \vec r_n + h \vec v_{n+1}
\end{align}

\subsection*{Code Structure}
The basic framework for the numerical analysis is based on a \texttt{PenningTrap} class, which contains all the particles present in the trap, as well as a parametrization of the electric and magnetic fields. The particles are represented by a \texttt{Particle} class, which contains the physical properties of the particle, as well as its current position and velocity. With this information, the \texttt{PenningTrap} class can calculate the forces acting on each particle, including the external fields and the particle-particle interactions. The particle-particle interactions can be toggled on and off, allowing for a simulation of both scenarios. The external fields can be modified by supplying a field-method of the form \texttt{external\_field(const arma::vec\& r, double t, const PenningTrap\& trap)}. The reference to the \texttt{PenningTrap} allows for the parameters of the field to be stored in the trap object. The implementation of the \texttt{Particle} and \texttt{PenningTrap} classes can be found in \texttt{/src/project3/include/classes.hpp} of the project repository, as well as in the corresponding source file \texttt{/src/project3/src/classes.cpp}.

\subsection*{Numerical Methods Implementation}
All numerical methods are implemented as classes inheriting from a base class \texttt{Solver}. The base class contains a reference to the \texttt{PenningTrap} object, as well as the time step size. The recording of particle properties over time, like position and velocity is part of the general \texttt{Solver} class. Each derived class implements the \texttt{step()} method, which updates the state of the system by one time step using the respective numerical method. The implementation of the \texttt{Solver} class and its derived classes can be found in \texttt{/src/project3/include/solvers.hpp} of the project repository, as well as in the corresponding source file \texttt{/src/project3/src/solvers.cpp}. The following solvers are implemented:\texttt{Forward\-Euler\-Solver}, \texttt{RK4\-Solver}, \texttt{Velocity\-Verlet\-Solver} and \texttt{Analytical\-Solver}, which implements the analytical solution for a special case of initial conditions (see \cref{app:special_case_analytical_solution}).

Unless otherwise specified, the simulations are run with the following parameters:
\begin{itemize}
    \item Trap parameters: $V_0 = \qty{25.0}{\mV},\, B_0 = \qty{1.00}{\tesla},\, d = \qty{500}{\um}$
    \item Particle parameters: $q = e,\, m = \qty{40.078}{\amu}$
    \item Simulation parameters: $T = n_\mathrm{steps} \cdot h = \qty{50}{\us}$.
\end{itemize}
\subsection*{Tools}
All simulations are written in C++ and compiled using \texttt{g++ (GCC) 15.2.1 20250808 (Red Hat 15.2.1-1)}. For optimization, the \texttt{-O3} flag is used. The code makes use of the Armadillo library\cite{sanderson_armadillo_2025,sanderson_practical_2019} for linear algebra operations and the argparse library\cite{pranav_p-ranavargparse_2025} for command line argument parsing.
To visualize the results and analyze the data, Python 3.13.7 with the libraries \texttt{numpy} \cite{harris_array_2020}, \texttt{matplotlib} \cite{hunter_matplotlib_2007} and \texttt{pandas} \cite{team_pandas-devpandas_2025} is used. To create easy to use command line interfaces for the Python scripts, the \texttt{typer} library\cite{ramirez_typer_nodate} is used.

As a large number of simulations need to be run for different parameters, a bash script is used to automate the process. The script can be found in \texttt{/src/project3/generate\_results.sh} of the project repository. It uses the \texttt{pueue} task management tool\cite{beer_nukesorpueue_2025} to run multiple simulations in parallel, making use of all available CPU cores. To automate the plot generation, the script \texttt{generate\_plots.sh} is used, which can be found in the same directory.

To aid in the development process, the large language model GitHub Copilot\cite{noauthor_github_2025} was used to generate code snippets and provide suggestions for code completion. Other large language models were not used in the writing of this report.