From 64d467c6ca2eb8148a82ae55d6ad3c8cec32f3a8 Mon Sep 17 00:00:00 2001 From: Lars Bogner Date: Tue, 14 Oct 2025 18:16:02 +0200 Subject: [PATCH] Initial commit for project 3..... A lot happend --- .gitignore | 12 +- projects/project2/main.pdf | Bin 247899 -> 248011 bytes projects/project3/chapters/conclusion.tex | 0 projects/project3/chapters/introduction.tex | 5 + projects/project3/chapters/methods.tex | 101 + projects/project3/chapters/results.tex | 9 + projects/project3/main.pdf | Bin 0 -> 210192 bytes projects/project3/main.tex | 156 ++ projects/project3/mainNotes.bib | 0 projects/project3/ref.bib | 187 ++ pyproject.toml | 1 + src/project3/generate_results.sh | 87 + src/project3/include/argparse/argparse.hpp | 2589 +++++++++++++++++++ src/project3/include/classes.hpp | 85 + src/project3/include/constants.hpp | 13 + src/project3/include/solvers.hpp | 92 + src/project3/many_particles.cpp | 173 ++ src/project3/progress.sh | 36 + src/project3/python/plot_energies.py | 35 + src/project3/python/plot_resonances.py | 49 + src/project3/python/plot_trajectories.py | 93 + src/project3/src/classes.cpp | 223 ++ src/project3/src/solvers.cpp | 340 +++ src/project3/two_particles.cpp | 126 + uv.lock | 81 + 25 files changed, 4492 insertions(+), 1 deletion(-) create mode 100644 projects/project3/chapters/conclusion.tex create mode 100644 projects/project3/chapters/introduction.tex create mode 100644 projects/project3/chapters/methods.tex create mode 100644 projects/project3/chapters/results.tex create mode 100644 projects/project3/main.pdf create mode 100644 projects/project3/main.tex create mode 100644 projects/project3/mainNotes.bib create mode 100644 projects/project3/ref.bib create mode 100755 src/project3/generate_results.sh create mode 100644 src/project3/include/argparse/argparse.hpp create mode 100644 src/project3/include/classes.hpp create mode 100644 src/project3/include/constants.hpp create mode 100644 src/project3/include/solvers.hpp create mode 100644 src/project3/many_particles.cpp create mode 100755 src/project3/progress.sh create mode 100644 src/project3/python/plot_energies.py create mode 100644 src/project3/python/plot_resonances.py create mode 100644 src/project3/python/plot_trajectories.py create mode 100644 src/project3/src/classes.cpp create mode 100644 src/project3/src/solvers.cpp create mode 100644 src/project3/two_particles.cpp diff --git a/.gitignore b/.gitignore index 4e122a1..ed13ab5 100644 --- a/.gitignore +++ b/.gitignore @@ -280,4 +280,14 @@ src/project2/buckling_beam_solver src/project2/off_diagonal_finder src/project2/scaling_tester -src/project2/*.txt \ No newline at end of file +src/project2/*.txt + +# Project 3 executables +src/project3/two_particles +src/project3/many_particles +src/project3/results/*.dat +src/project3/results/*/*.dat +src/project3/results/*/*/*.red +*.tar.gz +*_timing.txt +run_stats.json \ No newline at end of file diff --git a/projects/project2/main.pdf b/projects/project2/main.pdf index 41f6c9564df43b09b964d7d5304932dba818a6eb..23a1dc479aba419dfcdb49a339b3d3b1ec2e111d 100644 GIT binary patch delta 21420 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 delta 21295 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 diff --git a/projects/project3/chapters/conclusion.tex b/projects/project3/chapters/conclusion.tex new file mode 100644 index 0000000..e69de29 diff --git a/projects/project3/chapters/introduction.tex b/projects/project3/chapters/introduction.tex new file mode 100644 index 0000000..2efb54a --- /dev/null +++ b/projects/project3/chapters/introduction.tex @@ -0,0 +1,5 @@ +Penning traps are useful appliances to capture charged particles without contact to any matter surrounding the particles \cite[11]{vogel_particle_2024}. This property of Penning traps is especially useful in the study of antimatter, as any contact to matter would lead to the direct annihilation of the antimatter. Therefore, Penning traps have become an essential tool in the antimatter research. Experiments like ALPHA-g \cite{bertsche_prospects_2018} and AEgIS \cite{scampoli_aegis_2014} at CERN have successfully deployed Penning traps for such applications. + +To plan future antimatter experiments it is essential to be able to simulate Penning traps. Without the ability of the behavior of particles within such a trap, a precise planning of the Penning trap and antimatter experiment is not possible. Key criterion for a successful simulation in this context is accuracy of the numerical simulation in terms of precise trajectories and key statistical properties of the captured particles, e.g. the kinetic energy. A second metric that is very important to the usefulness of such numerical simulations is the computational performance of the simulation as this decides whether the simulation is even possible or not with finite computing resources. To find the optimal balance between the finite computing power available and an accurate result, different integration algorithms will be compared to solve the ordinary differential equations at play in the Penning Trap. + +In \cref{sec:methods} the methods employed in the simulation will be expanded on. In detail the implementation of the source code will be discussed as well as the specific Penning trap used for the study, introduced. Thirdly the algorithms behind the numerical integration methods will be explained. \Cref{sec:results_and_discussion} will show the results obtained from our implementation and discuss their practical implications. This section will be split into four parts expanding on the accuracy of the trajectories, the energy conservation in the system, the computational performance of the different algorithms as well as a discussion on the limit of many particles in the trap. Lastly in \cref{sec:conclusion} our findings will be summarized and consequences of the results derived. \ No newline at end of file diff --git a/projects/project3/chapters/methods.tex b/projects/project3/chapters/methods.tex new file mode 100644 index 0000000..e47f9eb --- /dev/null +++ b/projects/project3/chapters/methods.tex @@ -0,0 +1,101 @@ +\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} +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)$. 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 +\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)$. 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: +\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. The Velocity-Verlet method updates the position and velocity of the system as follows: +\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)$. + +\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 postion 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}). + +\subsection*{Tools} +\textcolor{red}{TODO} \ No newline at end of file diff --git a/projects/project3/chapters/results.tex b/projects/project3/chapters/results.tex new file mode 100644 index 0000000..7ea86a7 --- /dev/null +++ b/projects/project3/chapters/results.tex @@ -0,0 +1,9 @@ +\subsection{Numerical Accuracy of Trajectories} + +\subsection{Energy Conservation} + + +\subsection{Performance and Efficiency} + +\subsection{Many-Body Simulations} + diff --git a/projects/project3/main.pdf b/projects/project3/main.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f84eb7806681a712a05eba93ea3ab3a80d8f4039 GIT binary patch literal 210192 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%0ADdU+aEDBxli0 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 F{}-5>{G0#) literal 0 HcmV?d00001 diff --git a/projects/project3/main.tex b/projects/project3/main.tex new file mode 100644 index 0000000..128d958 --- /dev/null +++ b/projects/project3/main.tex @@ -0,0 +1,156 @@ +% USEFUL LINKS: +% ------------- +% +% - UiO LaTeX guides: https://www.mn.uio.no/ifi/tjenester/it/hjelp/latex/ +% - Mathematics: https://en.wikibooks.org/wiki/LaTeX/Mathematics +% - Physics: https://ctan.uib.no/macros/latex/contrib/physics/physics.pdf +% - Basics of Tikz: https://en.wikibooks.org/wiki/LaTeX/PGF/Tikz +% - All the colors! https://en.wikibooks.org/wiki/LaTeX/Colors +% - How to make tables: https://en.wikibooks.org/wiki/LaTeX/Tables +% - Code listing styles: https://en.wikibooks.org/wiki/LaTeX/Source_Code_Listings +% - \includegraphics https://en.wikibooks.org/wiki/LaTeX/Importing_Graphics +% - Learn more about figures: https://en.wikibooks.org/wiki/LaTeX/Floats,_Figures_and_Captions +% - Automagic bibliography: https://en.wikibooks.org/wiki/LaTeX/Bibliography_Management (this one is kinda difficult the first time) +% +% (This document is of class "revtex4-1", the REVTeX Guide explains how the class works) +% REVTeX Guide: http://www.physics.csbsju.edu/370/papers/Journal_Style_Manuals/auguide4-1.pdf +% +% +% COMPILING THE .pdf FILE IN THE LINUX TERMINAL +% --------------------------------------------- +% +% [terminal]$ pdflatex report_example.tex +% +% Run the command twice, always. +% +% When using references, footnotes, etc. you should run the following chain of commands: +% +% [terminal]$ pdflatex report_example.tex +% [terminal]$ bibtex report_example +% [terminal]$ pdflatex report_example.tex +% [terminal]$ pdflatex report_example.tex +% +% This series of commands can of course be gathered into a single-line command: +% [terminal]$ pdflatex report_example.tex && bibtex report_example.aux && pdflatex report_example.tex && pdflatex report_example.tex +% +% ---------------------------------------------------- + + + +% \documentclass[english,notitlepage,reprint,nofootinbib]{revtex4-2} % defines the basic parameters of the document +\documentclass[english,notitlepage,reprint,nofootinbib]{revtex4-2} % defines the basic parameters of the document +% If you want a single-column, remove "reprint" +\usepackage{silence} +\WarningFilter{revtex4-2}{Repair the float} + +% Allows special characters (including æøå) +\usepackage[utf8]{inputenc} +\usepackage[english]{babel} + +% Note that you may need to download some of these packages manually, it depends on your setup. +% It may be usefult to download TeXMaker, because it includes a large library of the most common packages. + +\usepackage{amssymb} % mathematical symbols (physics imports amsmath) +\usepackage{amsmath} +\usepackage{graphicx} % include graphics such as plots +\usepackage{xcolor} % set colors +\usepackage{hyperref} % automagic cross-referencing +\usepackage{listings} % display code +\usepackage{subfigure} % imports a lot of cool and useful figure commands +% \usepackage{float} +%\usepackage[section]{placeins} +\usepackage{algorithm} +\usepackage[noend]{algpseudocode} +\usepackage{subfigure} +\usepackage{tikz} +\usepackage{cleveref} +\usepackage{siunitx} +\usetikzlibrary{quantikz} +% defines the color of hyperref objects +% Blending two colors: blue!80!black = 80% blue and 20% black +\hypersetup{ % this is just my personal choice, feel free to change things + colorlinks, + linkcolor={red!50!black}, + citecolor={blue!50!black}, + urlcolor={blue!80!black}} + + +% =========================================== +\newcommand{\vstat}{V_\mathrm{stat.}} +\newcommand{\vdyn}{V_\mathrm{dyn.}} +\newcommand{\estat}{E_\mathrm{stat.}} +\newcommand{\edyn}{E_\mathrm{dyn.}} +\newcommand{\estatc}[1]{E_{\mathrm{stat.},#1}} +\newcommand{\edync}[1]{E_{\mathrm{dyn.},#1}} + +\begin{document} + +\title{Accuracy and Stability of Numerical Integration Methods in Penning Trap Simulations} % self-explanatory +\author{Lars Bogner} % self-explanatory +\date{\today} % self-explanatory +\noaffiliation % ignore this, but keep it. + +%This is how we create an abstract section. +\begin{abstract} + \textcolor{red}{TODO: ABSTRACT HERE.} +\end{abstract} +\maketitle + + +% =========================================== +\section{Introduction} +\input{chapters/introduction} + +% =========================================== +\section{Methods}\label{sec:methods} +% +\input{chapters/methods} + + +% =========================================== +\section{Results and discussion}\label{sec:results_and_discussion} +% +\input{chapters/results} + +% =========================================== +\section{Conclusion}\label{sec:conclusion} +% +\input{chapters/conclusion} + +% =========================================== +\appendix +\section{Electric Field Equations} \label{app:efield_equations} +Here we derive the electric field equations used in \cref{sec:methods}. The electric field following from $\vstat$ defined in \cref{eq:V_stat} is given by +\begin{align} + \estatc{x} &= -\frac{\partial \vstat}{\partial x} = \frac{V_0}{d^2} x, \\ + \estatc{y} &= -\frac{\partial \vstat}{\partial y} = \frac{V_0}{d^2} y, \\ + \estatc{z} &= -\frac{\partial \vstat}{\partial z} = -\frac{2 V_0}{d^2} z, +\end{align} +for all $|\vec r| < d$ and zero otherwise. The electric field following from $\vdyn$ is simply +\begin{equation} + \edyn = (1 + f \cos \omega_V t) \cdot \estat. +\end{equation} + +\section{Special Case Analytical Solution} \label{app:special_case_analytical_solution} +In the special case of a single particle in the potential $\vstat$, with the inital conditions $\vec{r}(t_0) = (x_0, 0, z_0)$ and $\vec{v}(t_0) = (0, v_0, 0)$, we can derive an analytical solution for the trajectory. The solution for the $z$ component is straightforward +\begin{equation} + z(t) = z_0 \cos(\omega_z t). +\end{equation} +From the equation system +\begin{align} + f(0) = A_+ e^{-i \phi_+} + A_- e^{-i \phi_-} &\equiv x_0, \\ + \dot f(0) = -i \omega_+ A_+ e^{-i \phi_+} - i \omega_- A_- e^{-i \phi_-} &\equiv i v_0, +\end{align} +we derive $\phi_\pm = 0$ as $f(0) \in \mathbb{R}$ and therefore $A_+ + A_- = x_0$ and $\omega_+ A_+ + \omega_- A_- = -v_0$. Solving this system of equations for $A_\pm$ we find +\begin{equation} + A_\pm =\pm \frac{v_0 + \omega_\mp x_0}{\omega_- - \omega_+}. +\end{equation} + +% =========================================== +\onecolumngrid +% \bibliographystyle{apalike} +\bibliographystyle{unsrt} +\bibliography{ref} + + +\end{document} \ No newline at end of file diff --git a/projects/project3/mainNotes.bib b/projects/project3/mainNotes.bib new file mode 100644 index 0000000..e69de29 diff --git a/projects/project3/ref.bib b/projects/project3/ref.bib new file mode 100644 index 0000000..299e0f8 --- /dev/null +++ b/projects/project3/ref.bib @@ -0,0 +1,187 @@ + +@article{harris_array_2020, + title = {Array programming with {NumPy}}, + volume = {585}, + url = {https://doi.org/10.1038/s41586-020-2649-2}, + doi = {10.1038/s41586-020-2649-2}, + pages = {357--362}, + number = {7825}, + journaltitle = {Nature}, + author = {Harris, Charles R. and Millman, K. Jarrod and Walt, Stéfan J. van der and Gommers, Ralf and Virtanen, Pauli and Cournapeau, David and Wieser, Eric and Taylor, Julian and Berg, Sebastian and Smith, Nathaniel J. and Kern, Robert and Picus, Matti and Hoyer, Stephan and Kerkwijk, Marten H. van and Brett, Matthew and Haldane, Allan and Río, Jaime Fernández del and Wiebe, Mark and Peterson, Pearu and Gérard-Marchant, Pierre and Sheppard, Kevin and Reddy, Tyler and Weckesser, Warren and Abbasi, Hameer and Gohlke, Christoph and Oliphant, Travis E.}, + date = {2020-09}, + note = {Publisher: Springer Science and Business Media {LLC}}, +} + +@article{hunter_matplotlib_2007, + title = {Matplotlib: A 2D graphics environment}, + volume = {9}, + doi = {10.1109/MCSE.2007.55}, + abstract = {Matplotlib is a 2D graphics package used for Python for application development, interactive scripting, and publication-quality image generation across user interfaces and operating systems.}, + pages = {90--95}, + number = {3}, + journaltitle = {Computing in Science \& Engineering}, + author = {Hunter, J. D.}, + date = {2007}, + note = {Publisher: {IEEE} {COMPUTER} {SOC}}, +} + +@article{pedregosa_scikit-learn_2011, + title = {Scikit-learn: Machine Learning in Python}, + volume = {12}, + pages = {2825--2830}, + journaltitle = {Journal of Machine Learning Research}, + author = {Pedregosa, F. and Varoquaux, G. and Gramfort, A. and Michel, V. and Thirion, B. and Grisel, O. and Blondel, M. and Prettenhofer, P. and Weiss, R. and Dubourg, V. and Vanderplas, J. and Passos, A. and Cournapeau, D. and Brucher, M. and Perrot, M. and Duchesnay, E.}, + date = {2011}, +} + +@inreference{noauthor_stochastic_2025, + title = {Stochastic gradient descent}, + rights = {Creative Commons Attribution-{ShareAlike} License}, + url = {https://en.wikipedia.org/w/index.php?title=Stochastic_gradient_descent&oldid=1309164477}, + abstract = {Stochastic gradient descent (often abbreviated {SGD}) is an iterative method for optimizing an objective function with suitable smoothness properties (e.g. differentiable or subdifferentiable). It can be regarded as a stochastic approximation of gradient descent optimization, since it replaces the actual gradient (calculated from the entire data set) by an estimate thereof (calculated from a randomly selected subset of the data). Especially in high-dimensional optimization problems this reduces the very high computational burden, achieving faster iterations in exchange for a lower convergence rate. +The basic idea behind stochastic approximation can be traced back to the Robbins–Monro algorithm of the 1950s. Today, stochastic gradient descent has become an important optimization method in machine learning.}, + booktitle = {Wikipedia}, + urldate = {2025-09-22}, + date = {2025-09-02}, + langid = {english}, + note = {Page Version {ID}: 1309164477}, + file = {Snapshot:/home/lars/Zotero/storage/B6CVR59B/index.html:text/html}, +} + +@unpublished{elstner_lecture_2025, + location = {Karlsruhe Institute for Technology, Karlsruhe}, + title = {Lecture: Machine Learning for Chemistry}, + type = {Lecture}, + howpublished = {Lecture}, + author = {Elstner, Marcus and Kubar, Tomas}, + date = {2025-05-20}, + langid = {german}, + file = {PDF:/home/lars/Zotero/storage/5LSLJMK8/Elstner and Kubar - 2025 - Lecture Machine Learning for Chemistry.pdf:application/pdf}, +} + +@online{lekhansh_lasso_2024, + title = {Lasso vs. Ridge Regression: A Detailed Comparison}, + url = {https://medium.com/@tyagi.lekhansh/lasso-vs-ridge-regression-a-detailed-comparison-140f7832c624}, + shorttitle = {Lasso vs. Ridge Regression}, + abstract = {In the realm of regression analysis, Lasso (Least Absolute Shrinkage and Selection Operator) and Ridge Regression are two popular…}, + titleaddon = {Medium}, + author = {Lekhansh}, + urldate = {2025-09-22}, + date = {2024-09-04}, + langid = {english}, +} + +@book{hastie_elements_2009, + location = {New York, {NY}}, + title = {The Elements of Statistical Learning}, + rights = {http://www.springer.com/tdm}, + isbn = {978-0-387-84857-0 978-0-387-84858-7}, + url = {http://link.springer.com/10.1007/978-0-387-84858-7}, + series = {Springer Series in Statistics}, + publisher = {Springer}, + author = {Hastie, Trevor and Tibshirani, Robert and Friedman, Jerome}, + urldate = {2025-09-22}, + date = {2009}, + doi = {10.1007/978-0-387-84858-7}, + keywords = {Averaging, Boosting, classification, clustering, data mining, machine learning, Projection pursuit, Random Forest, supervised learning, Support Vector Machine, unsupervised learning}, + file = {Full Text PDF:/home/lars/Zotero/storage/D3N4DVY9/Hastie et al. - 2009 - The Elements of Statistical Learning.pdf:application/pdf}, +} + +@book{goodfellow_deep_2016, + title = {Deep Learning}, + publisher = {{MIT} Press}, + author = {Goodfellow, Ian and Bengio, Yoshua and Courville, Aaron}, + date = {2016}, +} + +@book{bishop_pattern_2006, + location = {New York}, + title = {Pattern recognition and machine learning}, + isbn = {978-0-387-31073-2}, + series = {Information science and statistics}, + publisher = {Springer}, + author = {Bishop, Christopher M.}, + date = {2006}, + langid = {english}, + file = {PDF:/home/lars/Zotero/storage/9H5W9BGC/Bishop - 2006 - Pattern recognition and machine learning.pdf:application/pdf}, +} + +@online{roskam_supercritical_2025, + title = {Supercritical Fluid Chromatography for Chiral Analysis, Part 1: Theoretical Background {\textbar} {LCGC} International}, + url = {https://www.chromatographyonline.com/view/supercritical-fluid-chromatography-for-chiral-analysis-part-1-theoretical-background}, + shorttitle = {Supercritical Fluid Chromatography for Chiral Analysis, Part 1}, + abstract = {With the substantial developments carried out over the past years in instrumentation, columns, and detector hyphenation, the interest in chiral supercritical fluid chromatography ({SFC}) has been steadily growing in various fields. In the first part of this review article, the theoretical advantages, technological developments, and common practices in chiral {SFC} are discussed.}, + author = {Roskam, Gerry and Velde, Bas van de and Gargano, Andrea and Kohler, Isabelle}, + urldate = {2025-10-05}, + date = {2025-10-05}, + langid = {english}, + file = {Snapshot:/home/lars/Zotero/storage/LWSHJMVJ/supercritical-fluid-chromatography-for-chiral-analysis-part-1-theoretical-background.html:text/html}, +} + +@article{furet_first_2022, + title = {The First Class of Small Molecules Potently Disrupting the {YAP}‐{TEAD} Interaction by Direct Competition}, + volume = {17}, + doi = {10.1002/cmdc.202200303}, + abstract = {Inhibition of the {YAP}‐{TEAD} protein‐protein interaction is an attractive therapeutic concept under intense investigation with the objective to treat cancers associated with a dysregulation of the Hippo pathway. However, owing to the very extended surface of interaction of the two proteins, the identification of small drug‐like molecules able to efficiently prevent {YAP} from binding to {TEAD} by direct competition has been elusive so far. We disclose here the discovery of the first class of small molecules potently inhibiting the {YAP}‐{TEAD} interaction by binding at one of the main interaction sites of {YAP} at the surface of {TEAD}. These inhibitors, providing a path forward to pharmacological intervention in the Hippo pathway, evolved from a weakly active virtual screening hit advanced to high potency by structure‐based design.}, + journaltitle = {{ChemMedChem}}, + shortjournal = {{ChemMedChem}}, + author = {Furet, Pascal and Bordas, Vincent and Douget, Mickaël and Salem, Bahaa and Mesrouze, Yannick and Imbach‐Weese, Patricia and Sellner, Holger and Vögtle, Markus and Soldermann, Nicolas and Chapeau, Emilie and Wartmann, Markus and Scheufler, Clemens and Fernández, César and Kallen, Joerg and Guagnano, Vito and Chene, Patrick and Schmelzle, Tobias}, + date = {2022-09-02}, + file = {Full Text PDF:/home/lars/Zotero/storage/J399MX84/Furet et al. - 2022 - The First Class of Small Molecules Potently Disrupting the YAP‐TEAD Interaction by Direct Competitio.pdf:application/pdf}, +} + +@book{vogel_particle_2024, + location = {Cham}, + title = {Particle Confinement in Penning Traps: An Introduction}, + volume = {126}, + rights = {https://www.springernature.com/gp/researchers/text-and-data-mining}, + isbn = {978-3-031-55419-3 978-3-031-55420-9}, + url = {https://link.springer.com/10.1007/978-3-031-55420-9}, + series = {Springer Series on Atomic, Optical, and Plasma Physics}, + shorttitle = {Particle Confinement in Penning Traps}, + publisher = {Springer International Publishing}, + author = {Vogel, Manuel}, + urldate = {2025-10-09}, + date = {2024}, + langid = {english}, + doi = {10.1007/978-3-031-55420-9}, + keywords = {Confined ions and plasmas, Highly charged ions, Ion trapping, Laser Cooling, Magnetic moments, Particle confinement, Penning traps, Precision spectroscopy, Resistive Cooling, Stored ions, Trapped charged particles, Unified notation Penning traps}, + file = {Full Text PDF:/home/lars/Zotero/storage/SI8SF7RF/Vogel - 2024 - Particle Confinement in Penning Traps An Introduction.pdf:application/pdf}, +} + +@article{scampoli_aegis_2014, + title = {The {AEgIS} experiment at {CERN} for the measurement of antihydrogen gravity acceleration}, + volume = {29}, + issn = {0217-7323}, + url = {https://www.worldscientific.com/doi/abs/10.1142/S0217732314300171}, + doi = {10.1142/S0217732314300171}, + abstract = {The Antihydrogen Experiment: Gravity, Interferometry, Spectroscopy ({AEgIS}) experiment is conducted by an international collaboration based at {CERN} whose aim is to perform the first direct measurement of the gravitational acceleration of antihydrogen in the local field of the Earth, with Δg/g = 1\% precision as a first achievement. The idea is to produce cold (100 {mK}) antihydrogen through a pulsed charge exchange reaction by overlapping clouds of antiprotons, from the Antiproton Decelerator ({AD}) and positronium atoms inside a Penning trap. The antihydrogen has to be produced in an excited Rydberg state to be subsequently accelerated to form a beam. The deflection of the antihydrogen beam can then be measured by using a moiré deflectometer coupled to a position sensitive detector to register the impact point of the anti-atoms through the vertex reconstruction of their annihilation products. After being approved in late 2008, {AEgIS} started taking data in a commissioning phase in 2012. This paper presents an outline of the experiment with a brief overview of its physics motivation and of the state-of-the-art of the g measurement on antimatter. Particular attention is given to the current status of the emulsion-based position detector needed to measure the sag in {AEgIS}.}, + pages = {1430017}, + number = {17}, + journaltitle = {Modern Physics Letters A}, + shortjournal = {Mod. Phys. Lett. A}, + author = {Scampoli, Paola and Storey, James}, + urldate = {2025-10-09}, + date = {2014-06-07}, + note = {Publisher: World Scientific Publishing Co.}, + keywords = {Antihydrogen, gravity, high resolution tracking detector}, +} + +@article{bertsche_prospects_2018, + title = {Prospects for comparison of matter and antimatter gravitation with {ALPHA}-g}, + volume = {376}, + url = {https://royalsocietypublishing.org/doi/full/10.1098/rsta.2017.0265}, + doi = {10.1098/rsta.2017.0265}, + abstract = {The {ALPHA} experiment has recently entered an expansion phase of its experimental programme, driven in part by the expected benefits of conducting experiments in the framework of the new {AD} + {ELENA} antiproton facility at {CERN}. With antihydrogen trapping now a routine operation in the {ALPHA} experiment, the collaboration is leading progress towards precision atomic measurements on trapped antihydrogen atoms, with the first excitation of the 1S–2S transition and the first measurement of the antihydrogen hyperfine spectrum (Ahmadi et al. 2017 Nature 541, 506–510 (doi:10.1038/nature21040); Nature 548, 66–69 (doi:10.1038/nature23446)). We are building on these successes to extend our physics programme to include a measurement of antimatter gravitation. We plan to expand a proof-of-principle method (Amole et al. 2013 Nat. Commun. 4, 1785 (doi:10.1038/ncomms2787)), first demonstrated in the original {ALPHA} apparatus, and perform a precise measurement of antimatter gravitational acceleration with the aim of achieving a test of the weak equivalence principle at the 1\% level. The design of this apparatus has drawn from a growing body of experience on the simulation and verification of antihydrogen orbits confined within magnetic-minimum atom traps. The new experiment, {ALPHA}-g, will be an additional atom-trapping apparatus located at the {ALPHA} experiment with the intention of measuring antihydrogen gravitation. + +This article is part of the Theo Murphy meeting issue ‘Antiproton physics in the {ELENA} era’.}, + pages = {20170265}, + number = {2116}, + journaltitle = {Philosophical Transactions of the Royal Society A: Mathematical, Physical and Engineering Sciences}, + author = {Bertsche, W. A.}, + urldate = {2025-10-09}, + date = {2018-02-19}, + note = {Publisher: Royal Society}, + keywords = {antigravity, antihydrogen, antimatter, {CPT}, gravity, Lorentz invariance}, + file = {Full Text PDF:/home/lars/Zotero/storage/7YM83XXD/Bertsche - 2018 - Prospects for comparison of matter and antimatter gravitation with ALPHA-g.pdf:application/pdf}, +} diff --git a/pyproject.toml b/pyproject.toml index c101e28..f4bfa6b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,4 +8,5 @@ dependencies = [ "numpy>=2.3.2", "pandas>=2.3.2", "scipy>=1.16.1", + "typer>=0.19.2", ] diff --git a/src/project3/generate_results.sh b/src/project3/generate_results.sh new file mode 100755 index 0000000..4821636 --- /dev/null +++ b/src/project3/generate_results.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +PUEUE=true +NORMAL_MANY_PARTICLE_SIMULATION=true +OSCILLATING_FIELD_SIMULATION=false + +echo "Removing old results..." +mkdir -p results +rm results/*.dat + +echo "Compiling binaries..." +rm -f two_particles many_particles +g++ -O3 -larmadillo -I ./include src/* two_particles.cpp -o two_particles +g++ -O3 -larmadillo -I ./include src/* many_particles.cpp -o many_particles +echo "Finished compiling." + +if $PUEUE; then + echo "Using pueue to generate results in parallel..." + systemctl --user start pueued + pueue parallel 8 + pueue clean + COMMAND_PREFIX="pueue add " +else + echo "Generating results sequentially..." + COMMAND_PREFIX="" +fi + +for N in 4000 8000 16000 32000 +do + for interactions in "" "--disable-interactions" + do + for n in 1 2 + do + $COMMAND_PREFIX ./two_particles -N $N -n $n $interactions + $COMMAND_PREFIX ./two_particles -N $N -n $n $interactions -E + $COMMAND_PREFIX ./two_particles -N $N -n $n $interactions -V + done + done + # The analytical solution is only valid for one particle (second particle has v_z) without interactions + $COMMAND_PREFIX ./two_particles -N $N -n 1 --disable-interactions -A +done + +if $NORMAL_MANY_PARTICLE_SIMULATION; then + for N in 4000 8000 16000 32000 + do + for interactions in "" "--disable-interactions" + do + for n in 10 50 100 + do + $COMMAND_PREFIX ./many_particles -N $N -n $n $interactions + $COMMAND_PREFIX ./many_particles -N $N -n $n $interactions -E + $COMMAND_PREFIX ./many_particles -N $N -n $n $interactions -V + done + done + done +fi + +if $OSCILLATING_FIELD_SIMULATION; then + N=40000 + n=100 + reduced_output="--reduced-output" + interactions="--disable-interactions" + for amplitude in 0.1 0.4 0.7 + do + for frequency in $(seq 0.2 0.02 2.5) + do + $COMMAND_PREFIX ./many_particles -N $N -t -n $n $interactions -O -f $amplitude -w $frequency $reduced_output + $COMMAND_PREFIX ./many_particles -N $N -t -n $n $interactions -V -O -f $amplitude -w $frequency $reduced_output + done + done + interactions="" + for amplitude in 0.1 0.4 0.7 + do + for frequency in $(seq 1.0 0.005 1.8) + do + $COMMAND_PREFIX ./many_particles -N $N -t -n $n $interactions -O -f $amplitude -w $frequency $reduced_output + $COMMAND_PREFIX ./many_particles -N $N -t -n $n $interactions -V -O -f $amplitude -w $frequency $reduced_output + done + done +fi + + +echo "All tasks added to pueue." + +echo "Use 'pueue status' to check the status of the tasks." + +pueue status \ No newline at end of file diff --git a/src/project3/include/argparse/argparse.hpp b/src/project3/include/argparse/argparse.hpp new file mode 100644 index 0000000..06d30fd --- /dev/null +++ b/src/project3/include/argparse/argparse.hpp @@ -0,0 +1,2589 @@ +/* + __ _ _ __ __ _ _ __ __ _ _ __ ___ ___ + / _` | '__/ _` | '_ \ / _` | '__/ __|/ _ \ Argument Parser for Modern C++ +| (_| | | | (_| | |_) | (_| | | \__ \ __/ http://github.com/p-ranav/argparse + \__,_|_| \__, | .__/ \__,_|_| |___/\___| + |___/|_| + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2019-2022 Pranav Srinivas Kumar +and other contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#pragma once + +#include + +#ifndef ARGPARSE_MODULE_USE_STD_MODULE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#ifndef ARGPARSE_CUSTOM_STRTOF +#define ARGPARSE_CUSTOM_STRTOF strtof +#endif + +#ifndef ARGPARSE_CUSTOM_STRTOD +#define ARGPARSE_CUSTOM_STRTOD strtod +#endif + +#ifndef ARGPARSE_CUSTOM_STRTOLD +#define ARGPARSE_CUSTOM_STRTOLD strtold +#endif + +namespace argparse { + +namespace details { // namespace for helper methods + +template +struct HasContainerTraits : std::false_type {}; + +template <> struct HasContainerTraits : std::false_type {}; + +template <> struct HasContainerTraits : std::false_type {}; + +template +struct HasContainerTraits< + T, std::void_t().begin()), + decltype(std::declval().end()), + decltype(std::declval().size())>> : std::true_type {}; + +template +inline constexpr bool IsContainer = HasContainerTraits::value; + +template +struct HasStreamableTraits : std::false_type {}; + +template +struct HasStreamableTraits< + T, + std::void_t() << std::declval())>> + : std::true_type {}; + +template +inline constexpr bool IsStreamable = HasStreamableTraits::value; + +constexpr std::size_t repr_max_container_size = 5; + +template std::string repr(T const &val) { + if constexpr (std::is_same_v) { + return val ? "true" : "false"; + } else if constexpr (std::is_convertible_v) { + return '"' + std::string{std::string_view{val}} + '"'; + } else if constexpr (IsContainer) { + std::stringstream out; + out << "{"; + const auto size = val.size(); + if (size > 1) { + out << repr(*val.begin()); + std::for_each( + std::next(val.begin()), + std::next( + val.begin(), + static_cast( + std::min(size, repr_max_container_size) - 1)), + [&out](const auto &v) { out << " " << repr(v); }); + if (size <= repr_max_container_size) { + out << " "; + } else { + out << "..."; + } + } + if (size > 0) { + out << repr(*std::prev(val.end())); + } + out << "}"; + return out.str(); + } else if constexpr (IsStreamable) { + std::stringstream out; + out << val; + return out.str(); + } else { + return ""; + } +} + +namespace { + +template constexpr bool standard_signed_integer = false; +template <> constexpr bool standard_signed_integer = true; +template <> constexpr bool standard_signed_integer = true; +template <> constexpr bool standard_signed_integer = true; +template <> constexpr bool standard_signed_integer = true; +template <> constexpr bool standard_signed_integer = true; + +template constexpr bool standard_unsigned_integer = false; +template <> constexpr bool standard_unsigned_integer = true; +template <> constexpr bool standard_unsigned_integer = true; +template <> constexpr bool standard_unsigned_integer = true; +template <> constexpr bool standard_unsigned_integer = true; +template <> +constexpr bool standard_unsigned_integer = true; + +} // namespace + +constexpr int radix_2 = 2; +constexpr int radix_8 = 8; +constexpr int radix_10 = 10; +constexpr int radix_16 = 16; + +template +constexpr bool standard_integer = + standard_signed_integer || standard_unsigned_integer; + +template +constexpr decltype(auto) +apply_plus_one_impl(F &&f, Tuple &&t, Extra &&x, + std::index_sequence /*unused*/) { + return std::invoke(std::forward(f), std::get(std::forward(t))..., + std::forward(x)); +} + +template +constexpr decltype(auto) apply_plus_one(F &&f, Tuple &&t, Extra &&x) { + return details::apply_plus_one_impl( + std::forward(f), std::forward(t), std::forward(x), + std::make_index_sequence< + std::tuple_size_v>>{}); +} + +constexpr auto pointer_range(std::string_view s) noexcept { + return std::tuple(s.data(), s.data() + s.size()); +} + +template +constexpr bool starts_with(std::basic_string_view prefix, + std::basic_string_view s) noexcept { + return s.substr(0, prefix.size()) == prefix; +} + +enum class chars_format { + scientific = 0xf1, + fixed = 0xf2, + hex = 0xf4, + binary = 0xf8, + general = fixed | scientific +}; + +struct ConsumeBinaryPrefixResult { + bool is_binary; + std::string_view rest; +}; + +constexpr auto consume_binary_prefix(std::string_view s) + -> ConsumeBinaryPrefixResult { + if (starts_with(std::string_view{"0b"}, s) || + starts_with(std::string_view{"0B"}, s)) { + s.remove_prefix(2); + return {true, s}; + } + return {false, s}; +} + +struct ConsumeHexPrefixResult { + bool is_hexadecimal; + std::string_view rest; +}; + +using namespace std::literals; + +constexpr auto consume_hex_prefix(std::string_view s) + -> ConsumeHexPrefixResult { + if (starts_with("0x"sv, s) || starts_with("0X"sv, s)) { + s.remove_prefix(2); + return {true, s}; + } + return {false, s}; +} + +template +inline auto do_from_chars(std::string_view s) -> T { + T x{0}; + auto [first, last] = pointer_range(s); + auto [ptr, ec] = std::from_chars(first, last, x, Param); + if (ec == std::errc()) { + if (ptr == last) { + return x; + } + throw std::invalid_argument{"pattern '" + std::string(s) + + "' does not match to the end"}; + } + if (ec == std::errc::invalid_argument) { + throw std::invalid_argument{"pattern '" + std::string(s) + "' not found"}; + } + if (ec == std::errc::result_out_of_range) { + throw std::range_error{"'" + std::string(s) + "' not representable"}; + } + return x; // unreachable +} + +template struct parse_number { + auto operator()(std::string_view s) -> T { + return do_from_chars(s); + } +}; + +template struct parse_number { + auto operator()(std::string_view s) -> T { + if (auto [ok, rest] = consume_binary_prefix(s); ok) { + return do_from_chars(rest); + } + throw std::invalid_argument{"pattern not found"}; + } +}; + +template struct parse_number { + auto operator()(std::string_view s) -> T { + if (starts_with("0x"sv, s) || starts_with("0X"sv, s)) { + if (auto [ok, rest] = consume_hex_prefix(s); ok) { + try { + return do_from_chars(rest); + } catch (const std::invalid_argument &err) { + throw std::invalid_argument("Failed to parse '" + std::string(s) + + "' as hexadecimal: " + err.what()); + } catch (const std::range_error &err) { + throw std::range_error("Failed to parse '" + std::string(s) + + "' as hexadecimal: " + err.what()); + } + } + } else { + // Allow passing hex numbers without prefix + // Shape 'x' already has to be specified + try { + return do_from_chars(s); + } catch (const std::invalid_argument &err) { + throw std::invalid_argument("Failed to parse '" + std::string(s) + + "' as hexadecimal: " + err.what()); + } catch (const std::range_error &err) { + throw std::range_error("Failed to parse '" + std::string(s) + + "' as hexadecimal: " + err.what()); + } + } + + throw std::invalid_argument{"pattern '" + std::string(s) + + "' not identified as hexadecimal"}; + } +}; + +template struct parse_number { + auto operator()(std::string_view s) -> T { + auto [ok, rest] = consume_hex_prefix(s); + if (ok) { + try { + return do_from_chars(rest); + } catch (const std::invalid_argument &err) { + throw std::invalid_argument("Failed to parse '" + std::string(s) + + "' as hexadecimal: " + err.what()); + } catch (const std::range_error &err) { + throw std::range_error("Failed to parse '" + std::string(s) + + "' as hexadecimal: " + err.what()); + } + } + + auto [ok_binary, rest_binary] = consume_binary_prefix(s); + if (ok_binary) { + try { + return do_from_chars(rest_binary); + } catch (const std::invalid_argument &err) { + throw std::invalid_argument("Failed to parse '" + std::string(s) + + "' as binary: " + err.what()); + } catch (const std::range_error &err) { + throw std::range_error("Failed to parse '" + std::string(s) + + "' as binary: " + err.what()); + } + } + + if (starts_with("0"sv, s)) { + try { + return do_from_chars(rest); + } catch (const std::invalid_argument &err) { + throw std::invalid_argument("Failed to parse '" + std::string(s) + + "' as octal: " + err.what()); + } catch (const std::range_error &err) { + throw std::range_error("Failed to parse '" + std::string(s) + + "' as octal: " + err.what()); + } + } + + try { + return do_from_chars(rest); + } catch (const std::invalid_argument &err) { + throw std::invalid_argument("Failed to parse '" + std::string(s) + + "' as decimal integer: " + err.what()); + } catch (const std::range_error &err) { + throw std::range_error("Failed to parse '" + std::string(s) + + "' as decimal integer: " + err.what()); + } + } +}; + +namespace { + +template inline const auto generic_strtod = nullptr; +template <> inline const auto generic_strtod = ARGPARSE_CUSTOM_STRTOF; +template <> inline const auto generic_strtod = ARGPARSE_CUSTOM_STRTOD; +template <> +inline const auto generic_strtod = ARGPARSE_CUSTOM_STRTOLD; + +} // namespace + +template inline auto do_strtod(std::string const &s) -> T { + if (isspace(static_cast(s[0])) || s[0] == '+') { + throw std::invalid_argument{"pattern '" + s + "' not found"}; + } + + auto [first, last] = pointer_range(s); + char *ptr; + + errno = 0; + auto x = generic_strtod(first, &ptr); + if (errno == 0) { + if (ptr == last) { + return x; + } + throw std::invalid_argument{"pattern '" + s + + "' does not match to the end"}; + } + if (errno == ERANGE) { + throw std::range_error{"'" + s + "' not representable"}; + } + return x; // unreachable +} + +template struct parse_number { + auto operator()(std::string const &s) -> T { + if (auto r = consume_hex_prefix(s); r.is_hexadecimal) { + throw std::invalid_argument{ + "chars_format::general does not parse hexfloat"}; + } + if (auto r = consume_binary_prefix(s); r.is_binary) { + throw std::invalid_argument{ + "chars_format::general does not parse binfloat"}; + } + + try { + return do_strtod(s); + } catch (const std::invalid_argument &err) { + throw std::invalid_argument("Failed to parse '" + s + + "' as number: " + err.what()); + } catch (const std::range_error &err) { + throw std::range_error("Failed to parse '" + s + + "' as number: " + err.what()); + } + } +}; + +template struct parse_number { + auto operator()(std::string const &s) -> T { + if (auto r = consume_hex_prefix(s); !r.is_hexadecimal) { + throw std::invalid_argument{"chars_format::hex parses hexfloat"}; + } + if (auto r = consume_binary_prefix(s); r.is_binary) { + throw std::invalid_argument{"chars_format::hex does not parse binfloat"}; + } + + try { + return do_strtod(s); + } catch (const std::invalid_argument &err) { + throw std::invalid_argument("Failed to parse '" + s + + "' as hexadecimal: " + err.what()); + } catch (const std::range_error &err) { + throw std::range_error("Failed to parse '" + s + + "' as hexadecimal: " + err.what()); + } + } +}; + +template struct parse_number { + auto operator()(std::string const &s) -> T { + if (auto r = consume_hex_prefix(s); r.is_hexadecimal) { + throw std::invalid_argument{ + "chars_format::binary does not parse hexfloat"}; + } + if (auto r = consume_binary_prefix(s); !r.is_binary) { + throw std::invalid_argument{"chars_format::binary parses binfloat"}; + } + + return do_strtod(s); + } +}; + +template struct parse_number { + auto operator()(std::string const &s) -> T { + if (auto r = consume_hex_prefix(s); r.is_hexadecimal) { + throw std::invalid_argument{ + "chars_format::scientific does not parse hexfloat"}; + } + if (auto r = consume_binary_prefix(s); r.is_binary) { + throw std::invalid_argument{ + "chars_format::scientific does not parse binfloat"}; + } + if (s.find_first_of("eE") == std::string::npos) { + throw std::invalid_argument{ + "chars_format::scientific requires exponent part"}; + } + + try { + return do_strtod(s); + } catch (const std::invalid_argument &err) { + throw std::invalid_argument("Failed to parse '" + s + + "' as scientific notation: " + err.what()); + } catch (const std::range_error &err) { + throw std::range_error("Failed to parse '" + s + + "' as scientific notation: " + err.what()); + } + } +}; + +template struct parse_number { + auto operator()(std::string const &s) -> T { + if (auto r = consume_hex_prefix(s); r.is_hexadecimal) { + throw std::invalid_argument{ + "chars_format::fixed does not parse hexfloat"}; + } + if (auto r = consume_binary_prefix(s); r.is_binary) { + throw std::invalid_argument{ + "chars_format::fixed does not parse binfloat"}; + } + if (s.find_first_of("eE") != std::string::npos) { + throw std::invalid_argument{ + "chars_format::fixed does not parse exponent part"}; + } + + try { + return do_strtod(s); + } catch (const std::invalid_argument &err) { + throw std::invalid_argument("Failed to parse '" + s + + "' as fixed notation: " + err.what()); + } catch (const std::range_error &err) { + throw std::range_error("Failed to parse '" + s + + "' as fixed notation: " + err.what()); + } + } +}; + +template +std::string join(StrIt first, StrIt last, const std::string &separator) { + if (first == last) { + return ""; + } + std::stringstream value; + value << *first; + ++first; + while (first != last) { + value << separator << *first; + ++first; + } + return value.str(); +} + +template struct can_invoke_to_string { + template + static auto test(int) + -> decltype(std::to_string(std::declval()), std::true_type{}); + + template static auto test(...) -> std::false_type; + + static constexpr bool value = decltype(test(0))::value; +}; + +template struct IsChoiceTypeSupported { + using CleanType = typename std::decay::type; + static const bool value = std::is_integral::value || + std::is_same::value || + std::is_same::value || + std::is_same::value; +}; + +template +std::size_t get_levenshtein_distance(const StringType &s1, + const StringType &s2) { + std::vector> dp( + s1.size() + 1, std::vector(s2.size() + 1, 0)); + + for (std::size_t i = 0; i <= s1.size(); ++i) { + for (std::size_t j = 0; j <= s2.size(); ++j) { + if (i == 0) { + dp[i][j] = j; + } else if (j == 0) { + dp[i][j] = i; + } else if (s1[i - 1] == s2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1]; + } else { + dp[i][j] = 1 + std::min({dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]}); + } + } + } + + return dp[s1.size()][s2.size()]; +} + +template +std::string get_most_similar_string(const std::map &map, + const std::string &input) { + std::string most_similar{}; + std::size_t min_distance = (std::numeric_limits::max)(); + + for (const auto &entry : map) { + std::size_t distance = get_levenshtein_distance(entry.first, input); + if (distance < min_distance) { + min_distance = distance; + most_similar = entry.first; + } + } + + return most_similar; +} + +} // namespace details + +enum class nargs_pattern { optional, any, at_least_one }; + +enum class default_arguments : unsigned int { + none = 0, + help = 1, + version = 2, + all = help | version, +}; + +inline default_arguments operator&(const default_arguments &a, + const default_arguments &b) { + return static_cast( + static_cast::type>(a) & + static_cast::type>(b)); +} + +class ArgumentParser; + +class Argument { + friend class ArgumentParser; + friend auto operator<<(std::ostream &stream, const ArgumentParser &parser) + -> std::ostream &; + + template + explicit Argument(std::string_view prefix_chars, + std::array &&a, + std::index_sequence /*unused*/) + : m_accepts_optional_like_value(false), + m_is_optional((is_optional(a[I], prefix_chars) || ...)), + m_is_required(false), m_is_repeatable(false), m_is_used(false), + m_is_hidden(false), m_prefix_chars(prefix_chars) { + ((void)m_names.emplace_back(a[I]), ...); + std::sort( + m_names.begin(), m_names.end(), [](const auto &lhs, const auto &rhs) { + return lhs.size() == rhs.size() ? lhs < rhs : lhs.size() < rhs.size(); + }); + } + +public: + template + explicit Argument(std::string_view prefix_chars, + std::array &&a) + : Argument(prefix_chars, std::move(a), std::make_index_sequence{}) {} + + Argument &help(std::string help_text) { + m_help = std::move(help_text); + return *this; + } + + Argument &metavar(std::string metavar) { + m_metavar = std::move(metavar); + return *this; + } + + template Argument &default_value(T &&value) { + m_num_args_range = NArgsRange{0, m_num_args_range.get_max()}; + m_default_value_repr = details::repr(value); + + if constexpr (std::is_convertible_v) { + m_default_value_str = std::string{std::string_view{value}}; + } else if constexpr (details::can_invoke_to_string::value) { + m_default_value_str = std::to_string(value); + } + + m_default_value = std::forward(value); + return *this; + } + + Argument &default_value(const char *value) { + return default_value(std::string(value)); + } + + Argument &required() { + m_is_required = true; + return *this; + } + + Argument &implicit_value(std::any value) { + m_implicit_value = std::move(value); + m_num_args_range = NArgsRange{0, 0}; + return *this; + } + + // This is shorthand for: + // program.add_argument("foo") + // .default_value(false) + // .implicit_value(true) + Argument &flag() { + default_value(false); + implicit_value(true); + return *this; + } + + template + auto action(F &&callable, Args &&... bound_args) + -> std::enable_if_t, + Argument &> { + using action_type = std::conditional_t< + std::is_void_v>, + void_action, valued_action>; + if constexpr (sizeof...(Args) == 0) { + m_actions.emplace_back(std::forward(callable)); + } else { + m_actions.emplace_back( + [f = std::forward(callable), + tup = std::make_tuple(std::forward(bound_args)...)]( + std::string const &opt) mutable { + return details::apply_plus_one(f, tup, opt); + }); + } + return *this; + } + + auto &store_into(bool &var) { + if ((!m_default_value.has_value()) && (!m_implicit_value.has_value())) { + flag(); + } + if (m_default_value.has_value()) { + var = std::any_cast(m_default_value); + } + action([&var](const auto & /*unused*/) { + var = true; + return var; + }); + return *this; + } + + template ::value>::type * = nullptr> + auto &store_into(T &var) { + if (m_default_value.has_value()) { + var = std::any_cast(m_default_value); + } + action([&var](const auto &s) { + var = details::parse_number()(s); + return var; + }); + return *this; + } + + template ::value>::type * = nullptr> + auto &store_into(T &var) { + if (m_default_value.has_value()) { + var = std::any_cast(m_default_value); + } + action([&var](const auto &s) { + var = details::parse_number()(s); + return var; + }); + return *this; + } + + auto &store_into(std::string &var) { + if (m_default_value.has_value()) { + var = std::any_cast(m_default_value); + } + action([&var](const std::string &s) { + var = s; + return var; + }); + return *this; + } + + auto &store_into(std::filesystem::path &var) { + if (m_default_value.has_value()) { + var = std::any_cast(m_default_value); + } + action([&var](const std::string &s) { var = s; }); + return *this; + } + + auto &store_into(std::vector &var) { + if (m_default_value.has_value()) { + var = std::any_cast>(m_default_value); + } + action([this, &var](const std::string &s) { + if (!m_is_used) { + var.clear(); + } + m_is_used = true; + var.push_back(s); + return var; + }); + return *this; + } + + auto &store_into(std::vector &var) { + if (m_default_value.has_value()) { + var = std::any_cast>(m_default_value); + } + action([this, &var](const std::string &s) { + if (!m_is_used) { + var.clear(); + } + m_is_used = true; + var.push_back(details::parse_number()(s)); + return var; + }); + return *this; + } + + auto &store_into(std::set &var) { + if (m_default_value.has_value()) { + var = std::any_cast>(m_default_value); + } + action([this, &var](const std::string &s) { + if (!m_is_used) { + var.clear(); + } + m_is_used = true; + var.insert(s); + return var; + }); + return *this; + } + + auto &store_into(std::set &var) { + if (m_default_value.has_value()) { + var = std::any_cast>(m_default_value); + } + action([this, &var](const std::string &s) { + if (!m_is_used) { + var.clear(); + } + m_is_used = true; + var.insert(details::parse_number()(s)); + return var; + }); + return *this; + } + + auto &append() { + m_is_repeatable = true; + return *this; + } + + // Cause the argument to be invisible in usage and help + auto &hidden() { + m_is_hidden = true; + return *this; + } + + template + auto scan() -> std::enable_if_t, Argument &> { + static_assert(!(std::is_const_v || std::is_volatile_v), + "T should not be cv-qualified"); + auto is_one_of = [](char c, auto... x) constexpr { + return ((c == x) || ...); + }; + + if constexpr (is_one_of(Shape, 'd') && details::standard_integer) { + action(details::parse_number()); + } else if constexpr (is_one_of(Shape, 'i') && + details::standard_integer) { + action(details::parse_number()); + } else if constexpr (is_one_of(Shape, 'u') && + details::standard_unsigned_integer) { + action(details::parse_number()); + } else if constexpr (is_one_of(Shape, 'b') && + details::standard_unsigned_integer) { + action(details::parse_number()); + } else if constexpr (is_one_of(Shape, 'o') && + details::standard_unsigned_integer) { + action(details::parse_number()); + } else if constexpr (is_one_of(Shape, 'x', 'X') && + details::standard_unsigned_integer) { + action(details::parse_number()); + } else if constexpr (is_one_of(Shape, 'a', 'A') && + std::is_floating_point_v) { + action(details::parse_number()); + } else if constexpr (is_one_of(Shape, 'e', 'E') && + std::is_floating_point_v) { + action(details::parse_number()); + } else if constexpr (is_one_of(Shape, 'f', 'F') && + std::is_floating_point_v) { + action(details::parse_number()); + } else if constexpr (is_one_of(Shape, 'g', 'G') && + std::is_floating_point_v) { + action(details::parse_number()); + } else { + static_assert(alignof(T) == 0, "No scan specification for T"); + } + + return *this; + } + + Argument &nargs(std::size_t num_args) { + m_num_args_range = NArgsRange{num_args, num_args}; + return *this; + } + + Argument &nargs(std::size_t num_args_min, std::size_t num_args_max) { + m_num_args_range = NArgsRange{num_args_min, num_args_max}; + return *this; + } + + Argument &nargs(nargs_pattern pattern) { + switch (pattern) { + case nargs_pattern::optional: + m_num_args_range = NArgsRange{0, 1}; + break; + case nargs_pattern::any: + m_num_args_range = + NArgsRange{0, (std::numeric_limits::max)()}; + break; + case nargs_pattern::at_least_one: + m_num_args_range = + NArgsRange{1, (std::numeric_limits::max)()}; + break; + } + return *this; + } + + Argument &remaining() { + m_accepts_optional_like_value = true; + return nargs(nargs_pattern::any); + } + + template void add_choice(T &&choice) { + static_assert(details::IsChoiceTypeSupported::value, + "Only string or integer type supported for choice"); + static_assert(std::is_convertible_v || + details::can_invoke_to_string::value, + "Choice is not convertible to string_type"); + if (!m_choices.has_value()) { + m_choices = std::vector{}; + } + + if constexpr (std::is_convertible_v) { + m_choices.value().push_back( + std::string{std::string_view{std::forward(choice)}}); + } else if constexpr (details::can_invoke_to_string::value) { + m_choices.value().push_back(std::to_string(std::forward(choice))); + } + } + + Argument &choices() { + if (!m_choices.has_value()) { + throw std::runtime_error("Zero choices provided"); + } + return *this; + } + + template + Argument &choices(T &&first, U &&... rest) { + add_choice(std::forward(first)); + choices(std::forward(rest)...); + return *this; + } + + void find_default_value_in_choices_or_throw() const { + + const auto &choices = m_choices.value(); + + if (m_default_value.has_value()) { + if (std::find(choices.begin(), choices.end(), m_default_value_str) == + choices.end()) { + // provided arg not in list of allowed choices + // report error + + std::string choices_as_csv = + std::accumulate(choices.begin(), choices.end(), std::string(), + [](const std::string &a, const std::string &b) { + return a + (a.empty() ? "" : ", ") + b; + }); + + throw std::runtime_error( + std::string{"Invalid default value "} + m_default_value_repr + + " - allowed options: {" + choices_as_csv + "}"); + } + } + } + + template + bool is_value_in_choices(Iterator option_it) const { + + const auto &choices = m_choices.value(); + + return (std::find(choices.begin(), choices.end(), *option_it) != + choices.end()); + } + + template + void throw_invalid_arguments_error(Iterator option_it) const { + const auto &choices = m_choices.value(); + const std::string choices_as_csv = std::accumulate( + choices.begin(), choices.end(), std::string(), + [](const std::string &option_a, const std::string &option_b) { + return option_a + (option_a.empty() ? "" : ", ") + option_b; + }); + + throw std::runtime_error(std::string{"Invalid argument "} + + details::repr(*option_it) + + " - allowed options: {" + choices_as_csv + "}"); + } + + /* The dry_run parameter can be set to true to avoid running the actions, + * and setting m_is_used. This may be used by a pre-processing step to do + * a first iteration over arguments. + */ + template + Iterator consume(Iterator start, Iterator end, + std::string_view used_name = {}, bool dry_run = false) { + if (!m_is_repeatable && m_is_used) { + throw std::runtime_error( + std::string("Duplicate argument ").append(used_name)); + } + m_used_name = used_name; + + std::size_t passed_options = 0; + + if (m_choices.has_value()) { + // Check each value in (start, end) and make sure + // it is in the list of allowed choices/options + const auto max_number_of_args = m_num_args_range.get_max(); + const auto min_number_of_args = m_num_args_range.get_min(); + for (auto it = start; it != end; ++it) { + if (is_value_in_choices(it)) { + passed_options += 1; + continue; + } + + if ((passed_options >= min_number_of_args) && + (passed_options <= max_number_of_args)) { + break; + } + + throw_invalid_arguments_error(it); + } + } + + const auto num_args_max = + (m_choices.has_value()) ? passed_options : m_num_args_range.get_max(); + const auto num_args_min = m_num_args_range.get_min(); + std::size_t dist = 0; + if (num_args_max == 0) { + if (!dry_run) { + m_values.emplace_back(m_implicit_value); + for(auto &action: m_actions) { + std::visit([&](const auto &f) { f({}); }, action); + } + if(m_actions.empty()){ + std::visit([&](const auto &f) { f({}); }, m_default_action); + } + m_is_used = true; + } + return start; + } + if ((dist = static_cast(std::distance(start, end))) >= + num_args_min) { + if (num_args_max < dist) { + end = std::next(start, static_cast( + num_args_max)); + } + if (!m_accepts_optional_like_value) { + end = std::find_if( + start, end, + std::bind(is_optional, std::placeholders::_1, m_prefix_chars)); + dist = static_cast(std::distance(start, end)); + if (dist < num_args_min) { + throw std::runtime_error("Too few arguments for '" + + std::string(m_used_name) + "'."); + } + } + struct ActionApply { + void operator()(valued_action &f) { + std::transform(first, last, std::back_inserter(self.m_values), f); + } + + void operator()(void_action &f) { + std::for_each(first, last, f); + if (!self.m_default_value.has_value()) { + if (!self.m_accepts_optional_like_value) { + self.m_values.resize( + static_cast(std::distance(first, last))); + } + } + } + + Iterator first, last; + Argument &self; + }; + if (!dry_run) { + for(auto &action: m_actions) { + std::visit(ActionApply{start, end, *this}, action); + } + if(m_actions.empty()){ + std::visit(ActionApply{start, end, *this}, m_default_action); + } + m_is_used = true; + } + return end; + } + if (m_default_value.has_value()) { + if (!dry_run) { + m_is_used = true; + } + return start; + } + throw std::runtime_error("Too few arguments for '" + + std::string(m_used_name) + "'."); + } + + /* + * @throws std::runtime_error if argument values are not valid + */ + void validate() const { + if (m_is_optional) { + // TODO: check if an implicit value was programmed for this argument + if (!m_is_used && !m_default_value.has_value() && m_is_required) { + throw_required_arg_not_used_error(); + } + if (m_is_used && m_is_required && m_values.empty()) { + throw_required_arg_no_value_provided_error(); + } + } else { + if (!m_num_args_range.contains(m_values.size()) && + !m_default_value.has_value()) { + throw_nargs_range_validation_error(); + } + } + + if (m_choices.has_value()) { + // Make sure the default value (if provided) + // is in the list of choices + find_default_value_in_choices_or_throw(); + } + } + + std::string get_names_csv(char separator = ',') const { + return std::accumulate( + m_names.begin(), m_names.end(), std::string{""}, + [&](const std::string &result, const std::string &name) { + return result.empty() ? name : result + separator + name; + }); + } + + std::string get_usage_full() const { + std::stringstream usage; + + usage << get_names_csv('/'); + const std::string metavar = !m_metavar.empty() ? m_metavar : "VAR"; + if (m_num_args_range.get_max() > 0) { + usage << " " << metavar; + if (m_num_args_range.get_max() > 1) { + usage << "..."; + } + } + return usage.str(); + } + + std::string get_inline_usage() const { + std::stringstream usage; + // Find the longest variant to show in the usage string + std::string longest_name = m_names.front(); + for (const auto &s : m_names) { + if (s.size() > longest_name.size()) { + longest_name = s; + } + } + if (!m_is_required) { + usage << "["; + } + usage << longest_name; + const std::string metavar = !m_metavar.empty() ? m_metavar : "VAR"; + if (m_num_args_range.get_max() > 0) { + usage << " " << metavar; + if (m_num_args_range.get_max() > 1 && + m_metavar.find("> <") == std::string::npos) { + usage << "..."; + } + } + if (!m_is_required) { + usage << "]"; + } + if (m_is_repeatable) { + usage << "..."; + } + return usage.str(); + } + + std::size_t get_arguments_length() const { + + std::size_t names_size = std::accumulate( + std::begin(m_names), std::end(m_names), std::size_t(0), + [](const auto &sum, const auto &s) { return sum + s.size(); }); + + if (is_positional(m_names.front(), m_prefix_chars)) { + // A set metavar means this replaces the names + if (!m_metavar.empty()) { + // Indent and metavar + return 2 + m_metavar.size(); + } + + // Indent and space-separated + return 2 + names_size + (m_names.size() - 1); + } + // Is an option - include both names _and_ metavar + // size = text + (", " between names) + std::size_t size = names_size + 2 * (m_names.size() - 1); + if (!m_metavar.empty() && m_num_args_range == NArgsRange{1, 1}) { + size += m_metavar.size() + 1; + } + return size + 2; // indent + } + + friend std::ostream &operator<<(std::ostream &stream, + const Argument &argument) { + std::stringstream name_stream; + name_stream << " "; // indent + if (argument.is_positional(argument.m_names.front(), + argument.m_prefix_chars)) { + if (!argument.m_metavar.empty()) { + name_stream << argument.m_metavar; + } else { + name_stream << details::join(argument.m_names.begin(), + argument.m_names.end(), " "); + } + } else { + name_stream << details::join(argument.m_names.begin(), + argument.m_names.end(), ", "); + // If we have a metavar, and one narg - print the metavar + if (!argument.m_metavar.empty() && + argument.m_num_args_range == NArgsRange{1, 1}) { + name_stream << " " << argument.m_metavar; + } + else if (!argument.m_metavar.empty() && + argument.m_num_args_range.get_min() == argument.m_num_args_range.get_max() && + argument.m_metavar.find("> <") != std::string::npos) { + name_stream << " " << argument.m_metavar; + } + } + + // align multiline help message + auto stream_width = stream.width(); + auto name_padding = std::string(name_stream.str().size(), ' '); + auto pos = std::string::size_type{}; + auto prev = std::string::size_type{}; + auto first_line = true; + auto hspace = " "; // minimal space between name and help message + stream << name_stream.str(); + std::string_view help_view(argument.m_help); + while ((pos = argument.m_help.find('\n', prev)) != std::string::npos) { + auto line = help_view.substr(prev, pos - prev + 1); + if (first_line) { + stream << hspace << line; + first_line = false; + } else { + stream.width(stream_width); + stream << name_padding << hspace << line; + } + prev += pos - prev + 1; + } + if (first_line) { + stream << hspace << argument.m_help; + } else { + auto leftover = help_view.substr(prev, argument.m_help.size() - prev); + if (!leftover.empty()) { + stream.width(stream_width); + stream << name_padding << hspace << leftover; + } + } + + // print nargs spec + if (!argument.m_help.empty()) { + stream << " "; + } + stream << argument.m_num_args_range; + + bool add_space = false; + if (argument.m_default_value.has_value() && + argument.m_num_args_range != NArgsRange{0, 0}) { + stream << "[default: " << argument.m_default_value_repr << "]"; + add_space = true; + } else if (argument.m_is_required) { + stream << "[required]"; + add_space = true; + } + if (argument.m_is_repeatable) { + if (add_space) { + stream << " "; + } + stream << "[may be repeated]"; + } + stream << "\n"; + return stream; + } + + template bool operator!=(const T &rhs) const { + return !(*this == rhs); + } + + /* + * Compare to an argument value of known type + * @throws std::logic_error in case of incompatible types + */ + template bool operator==(const T &rhs) const { + if constexpr (!details::IsContainer) { + return get() == rhs; + } else { + using ValueType = typename T::value_type; + auto lhs = get(); + return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs), + std::end(rhs), [](const auto &a, const auto &b) { + return std::any_cast(a) == b; + }); + } + } + + /* + * positional: + * _empty_ + * '-' + * '-' decimal-literal + * !'-' anything + */ + static bool is_positional(std::string_view name, + std::string_view prefix_chars) { + auto first = lookahead(name); + + if (first == eof) { + return true; + } + if (prefix_chars.find(static_cast(first)) != + std::string_view::npos) { + name.remove_prefix(1); + if (name.empty()) { + return true; + } + return is_decimal_literal(name); + } + return true; + } + +private: + class NArgsRange { + std::size_t m_min; + std::size_t m_max; + + public: + NArgsRange(std::size_t minimum, std::size_t maximum) + : m_min(minimum), m_max(maximum) { + if (minimum > maximum) { + throw std::logic_error("Range of number of arguments is invalid"); + } + } + + bool contains(std::size_t value) const { + return value >= m_min && value <= m_max; + } + + bool is_exact() const { return m_min == m_max; } + + bool is_right_bounded() const { + return m_max < (std::numeric_limits::max)(); + } + + std::size_t get_min() const { return m_min; } + + std::size_t get_max() const { return m_max; } + + // Print help message + friend auto operator<<(std::ostream &stream, const NArgsRange &range) + -> std::ostream & { + if (range.m_min == range.m_max) { + if (range.m_min != 0 && range.m_min != 1) { + stream << "[nargs: " << range.m_min << "] "; + } + } else { + if (range.m_max == (std::numeric_limits::max)()) { + stream << "[nargs: " << range.m_min << " or more] "; + } else { + stream << "[nargs=" << range.m_min << ".." << range.m_max << "] "; + } + } + return stream; + } + + bool operator==(const NArgsRange &rhs) const { + return rhs.m_min == m_min && rhs.m_max == m_max; + } + + bool operator!=(const NArgsRange &rhs) const { return !(*this == rhs); } + }; + + void throw_nargs_range_validation_error() const { + std::stringstream stream; + if (!m_used_name.empty()) { + stream << m_used_name << ": "; + } else { + stream << m_names.front() << ": "; + } + if (m_num_args_range.is_exact()) { + stream << m_num_args_range.get_min(); + } else if (m_num_args_range.is_right_bounded()) { + stream << m_num_args_range.get_min() << " to " + << m_num_args_range.get_max(); + } else { + stream << m_num_args_range.get_min() << " or more"; + } + stream << " argument(s) expected. " << m_values.size() << " provided."; + throw std::runtime_error(stream.str()); + } + + void throw_required_arg_not_used_error() const { + std::stringstream stream; + stream << m_names.front() << ": required."; + throw std::runtime_error(stream.str()); + } + + void throw_required_arg_no_value_provided_error() const { + std::stringstream stream; + stream << m_used_name << ": no value provided."; + throw std::runtime_error(stream.str()); + } + + static constexpr int eof = std::char_traits::eof(); + + static auto lookahead(std::string_view s) -> int { + if (s.empty()) { + return eof; + } + return static_cast(static_cast(s[0])); + } + + /* + * decimal-literal: + * '0' + * nonzero-digit digit-sequence_opt + * integer-part fractional-part + * fractional-part + * integer-part '.' exponent-part_opt + * integer-part exponent-part + * + * integer-part: + * digit-sequence + * + * fractional-part: + * '.' post-decimal-point + * + * post-decimal-point: + * digit-sequence exponent-part_opt + * + * exponent-part: + * 'e' post-e + * 'E' post-e + * + * post-e: + * sign_opt digit-sequence + * + * sign: one of + * '+' '-' + */ + static bool is_decimal_literal(std::string_view s) { + auto is_digit = [](auto c) constexpr { + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return true; + default: + return false; + } + }; + + // precondition: we have consumed or will consume at least one digit + auto consume_digits = [=](std::string_view sd) { + // NOLINTNEXTLINE(readability-qualified-auto) + auto it = std::find_if_not(std::begin(sd), std::end(sd), is_digit); + return sd.substr(static_cast(it - std::begin(sd))); + }; + + switch (lookahead(s)) { + case '0': { + s.remove_prefix(1); + if (s.empty()) { + return true; + } + goto integer_part; + } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + s = consume_digits(s); + if (s.empty()) { + return true; + } + goto integer_part_consumed; + } + case '.': { + s.remove_prefix(1); + goto post_decimal_point; + } + default: + return false; + } + + integer_part: + s = consume_digits(s); + integer_part_consumed: + switch (lookahead(s)) { + case '.': { + s.remove_prefix(1); + if (is_digit(lookahead(s))) { + goto post_decimal_point; + } else { + goto exponent_part_opt; + } + } + case 'e': + case 'E': { + s.remove_prefix(1); + goto post_e; + } + default: + return false; + } + + post_decimal_point: + if (is_digit(lookahead(s))) { + s = consume_digits(s); + goto exponent_part_opt; + } + return false; + + exponent_part_opt: + switch (lookahead(s)) { + case eof: + return true; + case 'e': + case 'E': { + s.remove_prefix(1); + goto post_e; + } + default: + return false; + } + + post_e: + switch (lookahead(s)) { + case '-': + case '+': + s.remove_prefix(1); + } + if (is_digit(lookahead(s))) { + s = consume_digits(s); + return s.empty(); + } + return false; + } + + static bool is_optional(std::string_view name, + std::string_view prefix_chars) { + return !is_positional(name, prefix_chars); + } + + /* + * Get argument value given a type + * @throws std::logic_error in case of incompatible types + */ + template T get() const { + if (!m_values.empty()) { + if constexpr (details::IsContainer) { + return any_cast_container(m_values); + } else { + return std::any_cast(m_values.front()); + } + } + if (m_default_value.has_value()) { + return std::any_cast(m_default_value); + } + if constexpr (details::IsContainer) { + if (!m_accepts_optional_like_value) { + return any_cast_container(m_values); + } + } + + throw std::logic_error("No value provided for '" + m_names.back() + "'."); + } + + /* + * Get argument value given a type. + * @pre The object has no default value. + * @returns The stored value if any, std::nullopt otherwise. + */ + template auto present() const -> std::optional { + if (m_default_value.has_value()) { + throw std::logic_error("Argument with default value always presents"); + } + if (m_values.empty()) { + return std::nullopt; + } + if constexpr (details::IsContainer) { + return any_cast_container(m_values); + } + return std::any_cast(m_values.front()); + } + + template + static auto any_cast_container(const std::vector &operand) -> T { + using ValueType = typename T::value_type; + + T result; + std::transform( + std::begin(operand), std::end(operand), std::back_inserter(result), + [](const auto &value) { return std::any_cast(value); }); + return result; + } + + void set_usage_newline_counter(int i) { m_usage_newline_counter = i; } + + void set_group_idx(std::size_t i) { m_group_idx = i; } + + std::vector m_names; + std::string_view m_used_name; + std::string m_help; + std::string m_metavar; + std::any m_default_value; + std::string m_default_value_repr; + std::optional + m_default_value_str; // used for checking default_value against choices + std::any m_implicit_value; + std::optional> m_choices{std::nullopt}; + using valued_action = std::function; + using void_action = std::function; + std::vector> m_actions; + std::variant m_default_action{ + std::in_place_type, + [](const std::string &value) { return value; }}; + std::vector m_values; + NArgsRange m_num_args_range{1, 1}; + // Bit field of bool values. Set default value in ctor. + bool m_accepts_optional_like_value : 1; + bool m_is_optional : 1; + bool m_is_required : 1; + bool m_is_repeatable : 1; + bool m_is_used : 1; + bool m_is_hidden : 1; // if set, does not appear in usage or help + std::string_view m_prefix_chars; // ArgumentParser has the prefix_chars + int m_usage_newline_counter = 0; + std::size_t m_group_idx = 0; +}; + +class ArgumentParser { +public: + explicit ArgumentParser(std::string program_name = {}, + std::string version = "1.0", + default_arguments add_args = default_arguments::all, + bool exit_on_default_arguments = true, + std::ostream &os = std::cout) + : m_program_name(std::move(program_name)), m_version(std::move(version)), + m_exit_on_default_arguments(exit_on_default_arguments), + m_parser_path(m_program_name) { + if ((add_args & default_arguments::help) == default_arguments::help) { + add_argument("-h", "--help") + .action([&](const auto & /*unused*/) { + os << help().str(); + if (m_exit_on_default_arguments) { + std::exit(0); + } + }) + .default_value(false) + .help("shows help message and exits") + .implicit_value(true) + .nargs(0); + } + if ((add_args & default_arguments::version) == default_arguments::version) { + add_argument("-v", "--version") + .action([&](const auto & /*unused*/) { + os << m_version << std::endl; + if (m_exit_on_default_arguments) { + std::exit(0); + } + }) + .default_value(false) + .help("prints version information and exits") + .implicit_value(true) + .nargs(0); + } + } + + ~ArgumentParser() = default; + + // ArgumentParser is meant to be used in a single function. + // Setup everything and parse arguments in one place. + // + // ArgumentParser internally uses std::string_views, + // references, iterators, etc. + // Many of these elements become invalidated after a copy or move. + ArgumentParser(const ArgumentParser &other) = delete; + ArgumentParser &operator=(const ArgumentParser &other) = delete; + ArgumentParser(ArgumentParser &&) noexcept = delete; + ArgumentParser &operator=(ArgumentParser &&) = delete; + + explicit operator bool() const { + auto arg_used = std::any_of(m_argument_map.cbegin(), m_argument_map.cend(), + [](auto &it) { return it.second->m_is_used; }); + auto subparser_used = + std::any_of(m_subparser_used.cbegin(), m_subparser_used.cend(), + [](auto &it) { return it.second; }); + + return m_is_parsed && (arg_used || subparser_used); + } + + // Parameter packing + // Call add_argument with variadic number of string arguments + template Argument &add_argument(Targs... f_args) { + using array_of_sv = std::array; + auto argument = + m_optional_arguments.emplace(std::cend(m_optional_arguments), + m_prefix_chars, array_of_sv{f_args...}); + + if (!argument->m_is_optional) { + m_positional_arguments.splice(std::cend(m_positional_arguments), + m_optional_arguments, argument); + } + argument->set_usage_newline_counter(m_usage_newline_counter); + argument->set_group_idx(m_group_names.size()); + + index_argument(argument); + return *argument; + } + + class MutuallyExclusiveGroup { + friend class ArgumentParser; + + public: + MutuallyExclusiveGroup() = delete; + + explicit MutuallyExclusiveGroup(ArgumentParser &parent, + bool required = false) + : m_parent(parent), m_required(required), m_elements({}) {} + + MutuallyExclusiveGroup(const MutuallyExclusiveGroup &other) = delete; + MutuallyExclusiveGroup & + operator=(const MutuallyExclusiveGroup &other) = delete; + + MutuallyExclusiveGroup(MutuallyExclusiveGroup &&other) noexcept + : m_parent(other.m_parent), m_required(other.m_required), + m_elements(std::move(other.m_elements)) { + other.m_elements.clear(); + } + + template Argument &add_argument(Targs... f_args) { + auto &argument = m_parent.add_argument(std::forward(f_args)...); + m_elements.push_back(&argument); + argument.set_usage_newline_counter(m_parent.m_usage_newline_counter); + argument.set_group_idx(m_parent.m_group_names.size()); + return argument; + } + + private: + ArgumentParser &m_parent; + bool m_required{false}; + std::vector m_elements{}; + }; + + MutuallyExclusiveGroup &add_mutually_exclusive_group(bool required = false) { + m_mutually_exclusive_groups.emplace_back(*this, required); + return m_mutually_exclusive_groups.back(); + } + + // Parameter packed add_parents method + // Accepts a variadic number of ArgumentParser objects + template + ArgumentParser &add_parents(const Targs &... f_args) { + for (const ArgumentParser &parent_parser : {std::ref(f_args)...}) { + for (const auto &argument : parent_parser.m_positional_arguments) { + auto it = m_positional_arguments.insert( + std::cend(m_positional_arguments), argument); + index_argument(it); + } + for (const auto &argument : parent_parser.m_optional_arguments) { + auto it = m_optional_arguments.insert(std::cend(m_optional_arguments), + argument); + index_argument(it); + } + } + return *this; + } + + // Ask for the next optional arguments to be displayed on a separate + // line in usage() output. Only effective if set_usage_max_line_width() is + // also used. + ArgumentParser &add_usage_newline() { + ++m_usage_newline_counter; + return *this; + } + + // Ask for the next optional arguments to be displayed in a separate section + // in usage() and help (<< *this) output. + // For usage(), this is only effective if set_usage_max_line_width() is + // also used. + ArgumentParser &add_group(std::string group_name) { + m_group_names.emplace_back(std::move(group_name)); + return *this; + } + + ArgumentParser &add_description(std::string description) { + m_description = std::move(description); + return *this; + } + + ArgumentParser &add_epilog(std::string epilog) { + m_epilog = std::move(epilog); + return *this; + } + + // Add a un-documented/hidden alias for an argument. + // Ideally we'd want this to be a method of Argument, but Argument + // does not own its owing ArgumentParser. + ArgumentParser &add_hidden_alias_for(Argument &arg, std::string_view alias) { + for (auto it = m_optional_arguments.begin(); + it != m_optional_arguments.end(); ++it) { + if (&(*it) == &arg) { + m_argument_map.insert_or_assign(std::string(alias), it); + return *this; + } + } + throw std::logic_error( + "Argument is not an optional argument of this parser"); + } + + /* Getter for arguments and subparsers. + * @throws std::logic_error in case of an invalid argument or subparser name + */ + template T &at(std::string_view name) { + if constexpr (std::is_same_v) { + return (*this)[name]; + } else { + std::string str_name(name); + auto subparser_it = m_subparser_map.find(str_name); + if (subparser_it != m_subparser_map.end()) { + return subparser_it->second->get(); + } + throw std::logic_error("No such subparser: " + str_name); + } + } + + ArgumentParser &set_prefix_chars(std::string prefix_chars) { + m_prefix_chars = std::move(prefix_chars); + return *this; + } + + ArgumentParser &set_assign_chars(std::string assign_chars) { + m_assign_chars = std::move(assign_chars); + return *this; + } + + /* Call parse_args_internal - which does all the work + * Then, validate the parsed arguments + * This variant is used mainly for testing + * @throws std::runtime_error in case of any invalid argument + */ + void parse_args(const std::vector &arguments) { + parse_args_internal(arguments); + // Check if all arguments are parsed + for ([[maybe_unused]] const auto &[unused, argument] : m_argument_map) { + argument->validate(); + } + + // Check each mutually exclusive group and make sure + // there are no constraint violations + for (const auto &group : m_mutually_exclusive_groups) { + auto mutex_argument_used{false}; + Argument *mutex_argument_it{nullptr}; + for (Argument *arg : group.m_elements) { + if (!mutex_argument_used && arg->m_is_used) { + mutex_argument_used = true; + mutex_argument_it = arg; + } else if (mutex_argument_used && arg->m_is_used) { + // Violation + throw std::runtime_error("Argument '" + arg->get_usage_full() + + "' not allowed with '" + + mutex_argument_it->get_usage_full() + "'"); + } + } + + if (!mutex_argument_used && group.m_required) { + // at least one argument from the group is + // required + std::string argument_names{}; + std::size_t i = 0; + std::size_t size = group.m_elements.size(); + for (Argument *arg : group.m_elements) { + if (i + 1 == size) { + // last + argument_names += std::string("'") + arg->get_usage_full() + std::string("' "); + } else { + argument_names += std::string("'") + arg->get_usage_full() + std::string("' or "); + } + i += 1; + } + throw std::runtime_error("One of the arguments " + argument_names + + "is required"); + } + } + } + + /* Call parse_known_args_internal - which does all the work + * Then, validate the parsed arguments + * This variant is used mainly for testing + * @throws std::runtime_error in case of any invalid argument + */ + std::vector + parse_known_args(const std::vector &arguments) { + auto unknown_arguments = parse_known_args_internal(arguments); + // Check if all arguments are parsed + for ([[maybe_unused]] const auto &[unused, argument] : m_argument_map) { + argument->validate(); + } + return unknown_arguments; + } + + /* Main entry point for parsing command-line arguments using this + * ArgumentParser + * @throws std::runtime_error in case of any invalid argument + */ + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) + void parse_args(int argc, const char *const argv[]) { + parse_args({argv, argv + argc}); + } + + /* Main entry point for parsing command-line arguments using this + * ArgumentParser + * @throws std::runtime_error in case of any invalid argument + */ + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) + auto parse_known_args(int argc, const char *const argv[]) { + return parse_known_args({argv, argv + argc}); + } + + /* Getter for options with default values. + * @throws std::logic_error if parse_args() has not been previously called + * @throws std::logic_error if there is no such option + * @throws std::logic_error if the option has no value + * @throws std::bad_any_cast if the option is not of type T + */ + template T get(std::string_view arg_name) const { + if (!m_is_parsed) { + throw std::logic_error("Nothing parsed, no arguments are available."); + } + return (*this)[arg_name].get(); + } + + /* Getter for options without default values. + * @pre The option has no default value. + * @throws std::logic_error if there is no such option + * @throws std::bad_any_cast if the option is not of type T + */ + template + auto present(std::string_view arg_name) const -> std::optional { + return (*this)[arg_name].present(); + } + + /* Getter that returns true for user-supplied options. Returns false if not + * user-supplied, even with a default value. + */ + auto is_used(std::string_view arg_name) const { + return (*this)[arg_name].m_is_used; + } + + /* Getter that returns true if a subcommand is used. + */ + auto is_subcommand_used(std::string_view subcommand_name) const { + return m_subparser_used.at(std::string(subcommand_name)); + } + + /* Getter that returns true if a subcommand is used. + */ + auto is_subcommand_used(const ArgumentParser &subparser) const { + return is_subcommand_used(subparser.m_program_name); + } + + /* Indexing operator. Return a reference to an Argument object + * Used in conjunction with Argument.operator== e.g., parser["foo"] == true + * @throws std::logic_error in case of an invalid argument name + */ + Argument &operator[](std::string_view arg_name) const { + std::string name(arg_name); + auto it = m_argument_map.find(name); + if (it != m_argument_map.end()) { + return *(it->second); + } + if (!is_valid_prefix_char(arg_name.front())) { + const auto legal_prefix_char = get_any_valid_prefix_char(); + const auto prefix = std::string(1, legal_prefix_char); + + // "-" + arg_name + name = prefix + name; + it = m_argument_map.find(name); + if (it != m_argument_map.end()) { + return *(it->second); + } + // "--" + arg_name + name = prefix + name; + it = m_argument_map.find(name); + if (it != m_argument_map.end()) { + return *(it->second); + } + } + throw std::logic_error("No such argument: " + std::string(arg_name)); + } + + // Print help message + friend auto operator<<(std::ostream &stream, const ArgumentParser &parser) + -> std::ostream & { + stream.setf(std::ios_base::left); + + auto longest_arg_length = parser.get_length_of_longest_argument(); + + stream << parser.usage() << "\n\n"; + + if (!parser.m_description.empty()) { + stream << parser.m_description << "\n\n"; + } + + const bool has_visible_positional_args = std::find_if( + parser.m_positional_arguments.begin(), + parser.m_positional_arguments.end(), + [](const auto &argument) { + return !argument.m_is_hidden; }) != + parser.m_positional_arguments.end(); + if (has_visible_positional_args) { + stream << "Positional arguments:\n"; + } + + for (const auto &argument : parser.m_positional_arguments) { + if (!argument.m_is_hidden) { + stream.width(static_cast(longest_arg_length)); + stream << argument; + } + } + + if (!parser.m_optional_arguments.empty()) { + stream << (!has_visible_positional_args ? "" : "\n") + << "Optional arguments:\n"; + } + + for (const auto &argument : parser.m_optional_arguments) { + if (argument.m_group_idx == 0 && !argument.m_is_hidden) { + stream.width(static_cast(longest_arg_length)); + stream << argument; + } + } + + for (size_t i_group = 0; i_group < parser.m_group_names.size(); ++i_group) { + stream << "\n" << parser.m_group_names[i_group] << " (detailed usage):\n"; + for (const auto &argument : parser.m_optional_arguments) { + if (argument.m_group_idx == i_group + 1 && !argument.m_is_hidden) { + stream.width(static_cast(longest_arg_length)); + stream << argument; + } + } + } + + bool has_visible_subcommands = std::any_of( + parser.m_subparser_map.begin(), parser.m_subparser_map.end(), + [](auto &p) { return !p.second->get().m_suppress; }); + + if (has_visible_subcommands) { + stream << (parser.m_positional_arguments.empty() + ? (parser.m_optional_arguments.empty() ? "" : "\n") + : "\n") + << "Subcommands:\n"; + for (const auto &[command, subparser] : parser.m_subparser_map) { + if (subparser->get().m_suppress) { + continue; + } + + stream << std::setw(2) << " "; + stream << std::setw(static_cast(longest_arg_length - 2)) + << command; + stream << " " << subparser->get().m_description << "\n"; + } + } + + if (!parser.m_epilog.empty()) { + stream << '\n'; + stream << parser.m_epilog << "\n\n"; + } + + return stream; + } + + // Format help message + auto help() const -> std::stringstream { + std::stringstream out; + out << *this; + return out; + } + + // Sets the maximum width for a line of the Usage message + ArgumentParser &set_usage_max_line_width(size_t w) { + this->m_usage_max_line_width = w; + return *this; + } + + // Asks to display arguments of mutually exclusive group on separate lines in + // the Usage message + ArgumentParser &set_usage_break_on_mutex() { + this->m_usage_break_on_mutex = true; + return *this; + } + + // Format usage part of help only + auto usage() const -> std::string { + std::stringstream stream; + + std::string curline("Usage: "); + curline += this->m_parser_path; + const bool multiline_usage = + this->m_usage_max_line_width < (std::numeric_limits::max)(); + const size_t indent_size = curline.size(); + + const auto deal_with_options_of_group = [&](std::size_t group_idx) { + bool found_options = false; + // Add any options inline here + const MutuallyExclusiveGroup *cur_mutex = nullptr; + int usage_newline_counter = -1; + for (const auto &argument : this->m_optional_arguments) { + if (argument.m_is_hidden) { + continue; + } + if (multiline_usage) { + if (argument.m_group_idx != group_idx) { + continue; + } + if (usage_newline_counter != argument.m_usage_newline_counter) { + if (usage_newline_counter >= 0) { + if (curline.size() > indent_size) { + stream << curline << std::endl; + curline = std::string(indent_size, ' '); + } + } + usage_newline_counter = argument.m_usage_newline_counter; + } + } + found_options = true; + const std::string arg_inline_usage = argument.get_inline_usage(); + const MutuallyExclusiveGroup *arg_mutex = + get_belonging_mutex(&argument); + if ((cur_mutex != nullptr) && (arg_mutex == nullptr)) { + curline += ']'; + if (this->m_usage_break_on_mutex) { + stream << curline << std::endl; + curline = std::string(indent_size, ' '); + } + } else if ((cur_mutex == nullptr) && (arg_mutex != nullptr)) { + if ((this->m_usage_break_on_mutex && curline.size() > indent_size) || + curline.size() + 3 + arg_inline_usage.size() > + this->m_usage_max_line_width) { + stream << curline << std::endl; + curline = std::string(indent_size, ' '); + } + curline += " ["; + } else if ((cur_mutex != nullptr) && (arg_mutex != nullptr)) { + if (cur_mutex != arg_mutex) { + curline += ']'; + if (this->m_usage_break_on_mutex || + curline.size() + 3 + arg_inline_usage.size() > + this->m_usage_max_line_width) { + stream << curline << std::endl; + curline = std::string(indent_size, ' '); + } + curline += " ["; + } else { + curline += '|'; + } + } + cur_mutex = arg_mutex; + if (curline.size() != indent_size && + curline.size() + 1 + arg_inline_usage.size() > + this->m_usage_max_line_width) { + stream << curline << std::endl; + curline = std::string(indent_size, ' '); + curline += " "; + } else if (cur_mutex == nullptr) { + curline += " "; + } + curline += arg_inline_usage; + } + if (cur_mutex != nullptr) { + curline += ']'; + } + return found_options; + }; + + const bool found_options = deal_with_options_of_group(0); + + if (found_options && multiline_usage && + !this->m_positional_arguments.empty()) { + stream << curline << std::endl; + curline = std::string(indent_size, ' '); + } + // Put positional arguments after the optionals + for (const auto &argument : this->m_positional_arguments) { + if (argument.m_is_hidden) { + continue; + } + const std::string pos_arg = !argument.m_metavar.empty() + ? argument.m_metavar + : argument.m_names.front(); + if (curline.size() + 1 + pos_arg.size() > this->m_usage_max_line_width) { + stream << curline << std::endl; + curline = std::string(indent_size, ' '); + } + curline += " "; + if (argument.m_num_args_range.get_min() == 0 && + !argument.m_num_args_range.is_right_bounded()) { + curline += "["; + curline += pos_arg; + curline += "]..."; + } else if (argument.m_num_args_range.get_min() == 1 && + !argument.m_num_args_range.is_right_bounded()) { + curline += pos_arg; + curline += "..."; + } else { + curline += pos_arg; + } + } + + if (multiline_usage) { + // Display options of other groups + for (std::size_t i = 0; i < m_group_names.size(); ++i) { + stream << curline << std::endl << std::endl; + stream << m_group_names[i] << ":" << std::endl; + curline = std::string(indent_size, ' '); + deal_with_options_of_group(i + 1); + } + } + + stream << curline; + + // Put subcommands after positional arguments + if (!m_subparser_map.empty()) { + stream << " {"; + std::size_t i{0}; + for (const auto &[command, subparser] : m_subparser_map) { + if (subparser->get().m_suppress) { + continue; + } + + if (i == 0) { + stream << command; + } else { + stream << "," << command; + } + ++i; + } + stream << "}"; + } + + return stream.str(); + } + + // Printing the one and only help message + // I've stuck with a simple message format, nothing fancy. + [[deprecated("Use cout << program; instead. See also help().")]] std::string + print_help() const { + auto out = help(); + std::cout << out.rdbuf(); + return out.str(); + } + + void add_subparser(ArgumentParser &parser) { + parser.m_parser_path = m_program_name + " " + parser.m_program_name; + auto it = m_subparsers.emplace(std::cend(m_subparsers), parser); + m_subparser_map.insert_or_assign(parser.m_program_name, it); + m_subparser_used.insert_or_assign(parser.m_program_name, false); + } + + void set_suppress(bool suppress) { m_suppress = suppress; } + +protected: + const MutuallyExclusiveGroup *get_belonging_mutex(const Argument *arg) const { + for (const auto &mutex : m_mutually_exclusive_groups) { + if (std::find(mutex.m_elements.begin(), mutex.m_elements.end(), arg) != + mutex.m_elements.end()) { + return &mutex; + } + } + return nullptr; + } + + bool is_valid_prefix_char(char c) const { + return m_prefix_chars.find(c) != std::string::npos; + } + + char get_any_valid_prefix_char() const { return m_prefix_chars[0]; } + + /* + * Pre-process this argument list. Anything starting with "--", that + * contains an =, where the prefix before the = has an entry in the + * options table, should be split. + */ + std::vector + preprocess_arguments(const std::vector &raw_arguments) const { + std::vector arguments{}; + for (const auto &arg : raw_arguments) { + + const auto argument_starts_with_prefix_chars = + [this](const std::string &a) -> bool { + if (!a.empty()) { + + const auto legal_prefix = [this](char c) -> bool { + return m_prefix_chars.find(c) != std::string::npos; + }; + + // Windows-style + // if '/' is a legal prefix char + // then allow single '/' followed by argument name, followed by an + // assign char, e.g., ':' e.g., 'test.exe /A:Foo' + const auto windows_style = legal_prefix('/'); + + if (windows_style) { + if (legal_prefix(a[0])) { + return true; + } + } else { + // Slash '/' is not a legal prefix char + // For all other characters, only support long arguments + // i.e., the argument must start with 2 prefix chars, e.g, + // '--foo' e,g, './test --foo=Bar -DARG=yes' + if (a.size() > 1) { + return (legal_prefix(a[0]) && legal_prefix(a[1])); + } + } + } + return false; + }; + + // Check that: + // - We don't have an argument named exactly this + // - The argument starts with a prefix char, e.g., "--" + // - The argument contains an assign char, e.g., "=" + auto assign_char_pos = arg.find_first_of(m_assign_chars); + + if (m_argument_map.find(arg) == m_argument_map.end() && + argument_starts_with_prefix_chars(arg) && + assign_char_pos != std::string::npos) { + // Get the name of the potential option, and check it exists + std::string opt_name = arg.substr(0, assign_char_pos); + if (m_argument_map.find(opt_name) != m_argument_map.end()) { + // This is the name of an option! Split it into two parts + arguments.push_back(std::move(opt_name)); + arguments.push_back(arg.substr(assign_char_pos + 1)); + continue; + } + } + // If we've fallen through to here, then it's a standard argument + arguments.push_back(arg); + } + return arguments; + } + + /* + * @throws std::runtime_error in case of any invalid argument + */ + void parse_args_internal(const std::vector &raw_arguments) { + auto arguments = preprocess_arguments(raw_arguments); + if (m_program_name.empty() && !arguments.empty()) { + m_program_name = arguments.front(); + } + auto end = std::end(arguments); + auto positional_argument_it = std::begin(m_positional_arguments); + for (auto it = std::next(std::begin(arguments)); it != end;) { + const auto ¤t_argument = *it; + if (Argument::is_positional(current_argument, m_prefix_chars)) { + if (positional_argument_it == std::end(m_positional_arguments)) { + + // Check sub-parsers + auto subparser_it = m_subparser_map.find(current_argument); + if (subparser_it != m_subparser_map.end()) { + + // build list of remaining args + const auto unprocessed_arguments = + std::vector(it, end); + + // invoke subparser + m_is_parsed = true; + m_subparser_used[current_argument] = true; + return subparser_it->second->get().parse_args( + unprocessed_arguments); + } + + if (m_positional_arguments.empty()) { + + // Ask the user if they argument they provided was a typo + // for some sub-parser, + // e.g., user provided `git totes` instead of `git notes` + if (!m_subparser_map.empty()) { + throw std::runtime_error( + "Failed to parse '" + current_argument + "', did you mean '" + + std::string{details::get_most_similar_string( + m_subparser_map, current_argument)} + + "'"); + } + + // Ask the user if they meant to use a specific optional argument + if (!m_optional_arguments.empty()) { + for (const auto &opt : m_optional_arguments) { + if (!opt.m_implicit_value.has_value()) { + // not a flag, requires a value + if (!opt.m_is_used) { + throw std::runtime_error( + "Zero positional arguments expected, did you mean " + + opt.get_usage_full()); + } + } + } + + throw std::runtime_error("Zero positional arguments expected"); + } else { + throw std::runtime_error("Zero positional arguments expected"); + } + } else { + throw std::runtime_error("Maximum number of positional arguments " + "exceeded, failed to parse '" + + current_argument + "'"); + } + } + auto argument = positional_argument_it++; + + // Deal with the situation of ... + if (argument->m_num_args_range.get_min() == 1 && + argument->m_num_args_range.get_max() == (std::numeric_limits::max)() && + positional_argument_it != std::end(m_positional_arguments) && + std::next(positional_argument_it) == std::end(m_positional_arguments) && + positional_argument_it->m_num_args_range.get_min() == 1 && + positional_argument_it->m_num_args_range.get_max() == 1 ) { + if (std::next(it) != end) { + positional_argument_it->consume(std::prev(end), end); + end = std::prev(end); + } else { + throw std::runtime_error("Missing " + positional_argument_it->m_names.front()); + } + } + + it = argument->consume(it, end); + continue; + } + + auto arg_map_it = m_argument_map.find(current_argument); + if (arg_map_it != m_argument_map.end()) { + auto argument = arg_map_it->second; + it = argument->consume(std::next(it), end, arg_map_it->first); + } else if (const auto &compound_arg = current_argument; + compound_arg.size() > 1 && + is_valid_prefix_char(compound_arg[0]) && + !is_valid_prefix_char(compound_arg[1])) { + ++it; + for (std::size_t j = 1; j < compound_arg.size(); j++) { + auto hypothetical_arg = std::string{'-', compound_arg[j]}; + auto arg_map_it2 = m_argument_map.find(hypothetical_arg); + if (arg_map_it2 != m_argument_map.end()) { + auto argument = arg_map_it2->second; + it = argument->consume(it, end, arg_map_it2->first); + } else { + throw std::runtime_error("Unknown argument: " + current_argument); + } + } + } else { + throw std::runtime_error("Unknown argument: " + current_argument); + } + } + m_is_parsed = true; + } + + /* + * Like parse_args_internal but collects unused args into a vector + */ + std::vector + parse_known_args_internal(const std::vector &raw_arguments) { + auto arguments = preprocess_arguments(raw_arguments); + + std::vector unknown_arguments{}; + + if (m_program_name.empty() && !arguments.empty()) { + m_program_name = arguments.front(); + } + auto end = std::end(arguments); + auto positional_argument_it = std::begin(m_positional_arguments); + for (auto it = std::next(std::begin(arguments)); it != end;) { + const auto ¤t_argument = *it; + if (Argument::is_positional(current_argument, m_prefix_chars)) { + if (positional_argument_it == std::end(m_positional_arguments)) { + + // Check sub-parsers + auto subparser_it = m_subparser_map.find(current_argument); + if (subparser_it != m_subparser_map.end()) { + + // build list of remaining args + const auto unprocessed_arguments = + std::vector(it, end); + + // invoke subparser + m_is_parsed = true; + m_subparser_used[current_argument] = true; + return subparser_it->second->get().parse_known_args_internal( + unprocessed_arguments); + } + + // save current argument as unknown and go to next argument + unknown_arguments.push_back(current_argument); + ++it; + } else { + // current argument is the value of a positional argument + // consume it + auto argument = positional_argument_it++; + it = argument->consume(it, end); + } + continue; + } + + auto arg_map_it = m_argument_map.find(current_argument); + if (arg_map_it != m_argument_map.end()) { + auto argument = arg_map_it->second; + it = argument->consume(std::next(it), end, arg_map_it->first); + } else if (const auto &compound_arg = current_argument; + compound_arg.size() > 1 && + is_valid_prefix_char(compound_arg[0]) && + !is_valid_prefix_char(compound_arg[1])) { + ++it; + for (std::size_t j = 1; j < compound_arg.size(); j++) { + auto hypothetical_arg = std::string{'-', compound_arg[j]}; + auto arg_map_it2 = m_argument_map.find(hypothetical_arg); + if (arg_map_it2 != m_argument_map.end()) { + auto argument = arg_map_it2->second; + it = argument->consume(it, end, arg_map_it2->first); + } else { + unknown_arguments.push_back(current_argument); + break; + } + } + } else { + // current argument is an optional-like argument that is unknown + // save it and move to next argument + unknown_arguments.push_back(current_argument); + ++it; + } + } + m_is_parsed = true; + return unknown_arguments; + } + + // Used by print_help. + std::size_t get_length_of_longest_argument() const { + if (m_argument_map.empty()) { + return 0; + } + std::size_t max_size = 0; + for ([[maybe_unused]] const auto &[unused, argument] : m_argument_map) { + max_size = + std::max(max_size, argument->get_arguments_length()); + } + for ([[maybe_unused]] const auto &[command, unused] : m_subparser_map) { + max_size = std::max(max_size, command.size()); + } + return max_size; + } + + using argument_it = std::list::iterator; + using mutex_group_it = std::vector::iterator; + using argument_parser_it = + std::list>::iterator; + + void index_argument(argument_it it) { + for (const auto &name : std::as_const(it->m_names)) { + m_argument_map.insert_or_assign(name, it); + } + } + + std::string m_program_name; + std::string m_version; + std::string m_description; + std::string m_epilog; + bool m_exit_on_default_arguments = true; + std::string m_prefix_chars{"-"}; + std::string m_assign_chars{"="}; + bool m_is_parsed = false; + std::list m_positional_arguments; + std::list m_optional_arguments; + std::map m_argument_map; + std::string m_parser_path; + std::list> m_subparsers; + std::map m_subparser_map; + std::map m_subparser_used; + std::vector m_mutually_exclusive_groups; + bool m_suppress = false; + std::size_t m_usage_max_line_width = (std::numeric_limits::max)(); + bool m_usage_break_on_mutex = false; + int m_usage_newline_counter = 0; + std::vector m_group_names; +}; + +} // namespace argparse diff --git a/src/project3/include/classes.hpp b/src/project3/include/classes.hpp new file mode 100644 index 0000000..064093d --- /dev/null +++ b/src/project3/include/classes.hpp @@ -0,0 +1,85 @@ +#include +#include + +#ifndef CLASSES_HPP +#define CLASSES_HPP + +class PenningTrap; + +arma::vec standard_external_E_field(const arma::vec& r, double t, const PenningTrap& trap); +arma::vec oscillating_external_E_field(const arma::vec& r, double t, const PenningTrap& trap); +arma::vec standard_external_B_field(const arma::vec& r, double t, const PenningTrap& trap); +arma::vec limited_range_external_B_field(const arma::vec& r, double t, const PenningTrap& trap); + +class Particle { + public: + arma::vec position; + arma::vec velocity; + double mass; + double charge; + Particle(arma::vec pos, arma::vec vel, double m, double q); + Particle(double m, double q); + std::string info() const; + bool inside_trap(double d) const; + +}; + +class PenningTrap { + private: + std::vector particles; + bool coulomb_interaction = true; + bool modified_fields = false; + arma::vec (*_external_E_field)(const arma::vec& r, double t, const PenningTrap& trap) = standard_external_E_field; + arma::vec (*_external_B_field)(const arma::vec& r, double t, const PenningTrap& trap) = standard_external_B_field; + public: + double B0; + double V0; + double d; + double f = 0.0; // Amplitude of oscillating potential + double omega_V = 0.0; // Angular frequency of oscillating potential + PenningTrap(double B0_in, double V0_in, double d_in); + void add_particle(Particle& p); + void add_n_identical_particles(int n, double m, double q); + arma::vec external_E_field(const arma::vec& r, double t) const { + return _external_E_field(r, t, *this); + } + arma::vec external_B_field(const arma::vec& r, double t) const { + return _external_B_field(r, t, *this); + } + void set_external_E_field(arma::vec (*E_field_func)(const arma::vec&, double, const PenningTrap&)); + void set_external_B_field(arma::vec (*B_field_func)(const arma::vec&, double, const PenningTrap&)); + arma::vec force_particle(int i, int j) const; + arma::vec total_force_external(int i, double t) const; + arma::vec total_force_particles(int i) const; + arma::vec total_force(int i, double t) const; + double potential_energy(int i) const; + double total_potential_energy() const; + double kinetic_energy(int i) const; + double total_kinetic_energy() const; + double total_energy() const; + Particle& get_particle(int i); + const Particle& get_particle(int i) const; + int num_particles() const; + void enable_interactions() { + coulomb_interaction = true; + } + void disable_interactions() { + coulomb_interaction = false; + } + bool get_coulomb_interaction() const { + return coulomb_interaction; + } + bool get_modified_fields() const { + return modified_fields; + } + std::string info() const; + int num_inside_trap() const; +}; + + +std::ostream& operator<<(std::ostream& os, const Particle& p); + +std::ostream& operator<<(std::ostream& os, const PenningTrap& trap); + + +#endif \ No newline at end of file diff --git a/src/project3/include/constants.hpp b/src/project3/include/constants.hpp new file mode 100644 index 0000000..55fd7fb --- /dev/null +++ b/src/project3/include/constants.hpp @@ -0,0 +1,13 @@ +#ifndef CONSTANTS_HPP +#define CONSTANTS_HPP + +namespace constants { + const double k_e = 1.38935333e5; // Unit: u * um^3 / (us^2 * e^2), Coulomb's constant + const double tesla = 9.64852558e1; // Conversion factor from tesla to u/(us * e) + const double volt = 9.64852558e7; // Conversion factor from volt to u * um^2 / (us^2 * e) + const double meter = 1e6; // Conversion factor from meter to micrometer + const double second = 1e6; // Conversion factor from second to microsecond + const double amu = 1.0; // Atomic mass unit in terms of itself (u) + const double elementary_charge = 1.0; // Elementary charge in terms of itself (e) +} +#endif \ No newline at end of file diff --git a/src/project3/include/solvers.hpp b/src/project3/include/solvers.hpp new file mode 100644 index 0000000..32c11cc --- /dev/null +++ b/src/project3/include/solvers.hpp @@ -0,0 +1,92 @@ +#include "classes.hpp" +#include +#include + +#ifndef SOLVERS_HPP +#define SOLVERS_HPP + + +arma::cube to_cube(const std::vector& vec); + +void save_to_file(const std::string& filename, const arma::cube& data); +void save_to_file(const std::string& filename, const arma::vec& data); + + +class Solver { + protected: + PenningTrap& trap; + double dt; + int steps; + std::vector positions; + std::vector velocities; + std::vector inside_trap_count; + std::vector potential_energies; + std::vector kinetic_energies; + std::vector total_energies; + virtual void step() = 0; + void record_position(); + void record_velocity(); + void record_energies(); + void record_trap_count(); + public: + Solver(PenningTrap& trap_in, double dt_in); + void simulate(int num_steps); + void simulate_time(double total_time) { + int num_steps = total_steps(total_time); + simulate(num_steps); + } + std::vector get_positions(); + std::vector get_velocities(); + std::vector get_potential_energies(); + std::vector get_kinetic_energies(); + std::vector get_total_energies(); + std::vector get_inside_trap_count(); + int get_current_step(); + int total_steps(double total_time); + void save(std::string base_filename); + void save_counts(std::string base_filename); + void record_current_step() { + record_position(); + record_velocity(); + if (!trap.get_modified_fields()) { + record_energies(); + } + record_trap_count(); + } + bool record_positions_and_velocities = true; + bool record_inside_trap_count = true; +}; + +class EulerSolver : public Solver { + public: + EulerSolver(PenningTrap& trap_in, double dt_in); + void step() override; +}; +class RK4Solver : public Solver { + public: + RK4Solver(PenningTrap& trap_in, double dt_in); + void step() override; +}; +class VelocityVerletSolver : public Solver { + private: + std::vector accelerations; + public: + VelocityVerletSolver(PenningTrap& trap_in, double dt_in); + void step() override; +}; + +class AnalyticalSolver : public Solver { + private: + std::vector w_0; + std::vector w_z; + std::vector w_plus; + std::vector w_minus; + std::vector A_plus; + std::vector A_minus; + std::vector z_0; + public: + AnalyticalSolver(PenningTrap& trap_in, double dt_in); + void step() override; +}; + +#endif \ No newline at end of file diff --git a/src/project3/many_particles.cpp b/src/project3/many_particles.cpp new file mode 100644 index 0000000..19efa67 --- /dev/null +++ b/src/project3/many_particles.cpp @@ -0,0 +1,173 @@ +#include +#include "classes.hpp" +#include "solvers.hpp" +#include "constants.hpp" +#include "argparse/argparse.hpp" + +#include +#include + +using namespace std; + +void print_first_particles(PenningTrap& trap, int num_particles) { + for (int i = 0; i < num_particles && i < trap.num_particles(); ++i) { + cout << "Particle " << i + 1 << ": " << endl << trap.get_particle(i) << endl; + } +} + +void save_timing(clock_t start, clock_t end, const string& filename) { + double cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC; + ofstream file(filename); + if (file.is_open()) { + file << "CPU time used: " << cpu_time_used << " seconds" << endl; + file.close(); + } else { + cerr << "Unable to open file for writing timing information." << endl; + } +} + +int main(int argc, char* argv[]) { + argparse::ArgumentParser program("many_particles"); + program.add_argument("-v", "--verbose") + .help("Enable verbose output of first particles") + .flag(); + program.add_argument("-N", "--steps") + .help("Number of time steps") + .default_value(4000) + .scan<'i', int>(); + program.add_argument("-n", "--num_particles") + .help("Number of particles") + .default_value(100) + .scan<'i', int>(); + program.add_argument("-i", "--disable-interactions") + .help("Disable Coulomb interactions") + .default_value(true) + .implicit_value(false); + program.add_argument("-O", "--oscillating-potential") + .help("Enable oscillating potential") + .flag(); + program.add_argument("-f", "--amplitude") + .help("Amplitude of oscillating potential") + .default_value(0.0) + .scan<'f', double>(); + program.add_argument("-w", "--frequency") + .help("Angular frequency of oscillating potential") + .default_value(0.0) + .scan<'f', double>(); + program.add_argument("-r", "--reduced-output") + .help("Reduce output for oscillating potential to only final count") + .flag(); + program.add_argument("-E", "--euler") + .help("Use Euler solver instead of RK4") + .flag(); + program.add_argument("-V", "--velocity-verlet") + .help("Use Velocity Verlet solver instead of RK4") + .flag(); + program.add_argument("-t", "--timing") + .help("Enable timing of the simulation") + .flag(); + + try { + program.parse_args(argc, argv); + } catch (const std::runtime_error& err) { + std::cerr << err.what() << std::endl; + std::cerr << program.help().str() << std::endl; + exit(1); + } + + bool verbose = program.get("--verbose"); + + int N = program.get("--steps"); + int n_particles = program.get("--num_particles"); + bool interactions = program.get("--disable-interactions"); + bool oscillating_potential = program.get("--oscillating-potential"); + bool use_euler = program.get("--euler"); + bool use_velocity_verlet = program.get("--velocity-verlet"); + bool timing = program.get("--timing"); + + double B_0 = 1.0; // Tesla + double V_0 = 0.025; // Volt + double d = 500e-6; // meter + + PenningTrap trap(B_0, V_0, d); + if (interactions) { + trap.enable_interactions(); + } + else { + trap.disable_interactions(); + } + + + bool reduced_output = program.get("--reduced-output"); // Only relevant if oscillating potential is enabled + if (oscillating_potential) { + trap.set_external_E_field(oscillating_external_E_field); + trap.set_external_B_field(limited_range_external_B_field); + trap.f = program.get("--amplitude"); + trap.omega_V = program.get("--frequency"); + } + + trap.add_n_identical_particles(n_particles, 40.078 * constants::amu, 1 * constants::elementary_charge); + if (verbose) { + cout << trap.info() << endl; + print_first_particles(trap, 10); + } + + + double dt = 50e-6 / N; // seconds + + + unique_ptr solver; + string solver_name; + + if (use_euler) { + solver = make_unique(trap, dt); + solver_name = "Euler"; + } else if (use_velocity_verlet) { + solver = make_unique(trap, dt); + solver_name = "VelocityVerlet"; + } else { + solver = make_unique(trap, dt); + solver_name = "RK4"; + } + clock_t start, end; + start = clock(); + if (oscillating_potential) { + solver->record_positions_and_velocities = false; // Disable recording for performance + if (reduced_output) { + solver->record_inside_trap_count = false; // Disable recording for performance + } + solver->simulate(N); + end = clock(); + string folder = "results/" + solver_name + "/many_particles_" + to_string(trap.num_particles()) + "_particles_" + to_string(int(N)) + "_steps_" + (interactions ? "enabled" : "disabled") + "_interactions_oscillating_potential"; + string filename = "f" + to_string(trap.f) + "_w" + to_string(trap.omega_V); + filesystem::create_directories(folder); + + if (reduced_output) { + solver->record_current_step(); // Record only final step + } + solver->save_counts(folder + "/" + filename); + cout << "Final number of particles inside trap: " << trap.num_inside_trap() << " out of " << trap.num_particles() << endl; + if (timing) { + save_timing(start, end, folder + "/" + filename + "_timing.txt"); + } + return 0; + + } + solver->simulate(N); + end = clock(); + string folder = "results/" + solver_name; + filesystem::create_directories(folder); + string filename = "/many_particles_" + to_string(trap.num_particles()) + "_particles_" + to_string(int(N)) + "_steps_" + (interactions ? "enabled" : "disabled") + "_interactions"; + solver->save(folder + filename); + if (verbose) { + vector positions = solver->get_positions(); + cout << "Final positions of particles: " << endl; + print_first_particles(trap, 10); + } + if (timing) { + save_timing(start, end, folder + filename + "_timing.txt"); + } + + return 0; +} + diff --git a/src/project3/progress.sh b/src/project3/progress.sh new file mode 100755 index 0000000..e9155df --- /dev/null +++ b/src/project3/progress.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +interval=5 # seconds between updates + +while true; do + data=$(pueue status --json) + + queued=$(jq '.tasks | map(select(.status=="Queued")) | length' <<< "$data") + running=$(jq '.tasks | map(select(.status=="Running")) | length' <<< "$data") + total=$(jq '.tasks | length' <<< "$data") + + # average duration of finished tasks (seconds) + avg=$(jq '.tasks + | map(select(.start != null and .end != null) + | ((.end[0:19] + "Z") | fromdate) - ((.start[0:19] + "Z") | fromdate)) + | if length > 0 then add / length else 0 end' <<< "$data") + + clear + echo "Queued: $queued" + echo "Running: $running" + echo "Total: $total" + + # Only calculate ETA if avg > 0 + if (( $(echo "$avg > 0" | bc -l) )); then + remaining=$((queued + running)) + eta_seconds=$(echo "$remaining * $avg" | bc -l) + finish_time=$(date -d "@$(($(date +%s) + ${eta_seconds%.*}))" +"%Y-%m-%d %H:%M:%S") + printf "Average duration: %.2fs\n" "$avg" + printf "ETA: ~%.0fs (finishing around %s)\n" "$eta_seconds" "$finish_time" + else + echo "ETA: Not enough finished jobs in history yet." + fi + + sleep $interval +done + diff --git a/src/project3/python/plot_energies.py b/src/project3/python/plot_energies.py new file mode 100644 index 0000000..0b7b959 --- /dev/null +++ b/src/project3/python/plot_energies.py @@ -0,0 +1,35 @@ +import matplotlib.pyplot as plt +import numpy as np +import os +import typer + +app = typer.Typer() + +def load_data(total_energy_file): + total_energy = np.loadtxt(total_energy_file) + kin_file = total_energy_file.replace("total_energies", "kinetic_energies") + pot_file = total_energy_file.replace("total_energies", "potential_energies") + kinetic_energy = np.loadtxt(kin_file) + potential_energy = np.loadtxt(pot_file) + step_count = len(total_energy) + return total_energy, kinetic_energy, potential_energy, step_count + +@app.command() +def plot_kinetic_energy(energy_files: list[str]=[], labels: list[str]=[], mass: float=1.0): + """Plot kinetic energy from velocity files.""" + for i, energy_file in enumerate(energy_files): + total_energy, kinetic_energy, potential_energy, step_count = load_data(energy_file) + time = np.linspace(0, 50e-6, step_count) + color = f"C{i % 10}" + plt.plot(time, total_energy, label=labels[i], color=color, linestyle="-") + plt.plot(time, potential_energy, color=color, linestyle="--") + plt.plot(time, kinetic_energy, color=color, linestyle=":") + plt.xlabel('Time (s)') + plt.ylabel('Energy (J)') + plt.title('Energy Evolution') + plt.legend() + plt.show() + + +if __name__ == "__main__": + app() \ No newline at end of file diff --git a/src/project3/python/plot_resonances.py b/src/project3/python/plot_resonances.py new file mode 100644 index 0000000..359acbb --- /dev/null +++ b/src/project3/python/plot_resonances.py @@ -0,0 +1,49 @@ +import matplotlib.pyplot as plt +import numpy as np +import os +import argparse + +argparser = argparse.ArgumentParser() +argparser.add_argument("directory", type=str, help="Directory containing the data files") +args = argparser.parse_args() +directory = args.directory + +def get_filenames(directory): + filenames = [os.path.join(directory, f) for f in os.listdir(directory) if f.endswith(".red")] + return filenames + +def get_pars(filename): + amplitude = float(filename.split("_")[0][1:]) + omega = float(filename.split("_")[1][1:]) + return amplitude, omega + +def load_data(filename): + with open(filename, "r") as file: + x = int(file.readline().split()[1]) + return x + +def plot_resonances(amplitudes, omegas, counts): + plt.figure(figsize=(8, 6)) + unique_amps = sorted(set(amplitudes)) + for amp in unique_amps: + mask = np.array(amplitudes) == amp + omegas_subset = np.array(omegas)[mask] + counts_subset = np.array(counts)[mask] + omegas_sorted, counts_sorted = zip(*sorted(zip(omegas_subset, counts_subset))) + plt.plot(omegas_sorted, counts_sorted, label=f'Amplitude {amp}') + plt.xlabel('Omega') + plt.ylabel('Count inside trap') + plt.legend() + plt.show() + +if __name__ == "__main__": + filenames = get_filenames(directory) + amplitudes, omegas, counts = [], [], [] + for filename in filenames: + amplitude, omega = get_pars(os.path.basename(filename)) + count = load_data(filename) + amplitudes.append(amplitude) + omegas.append(omega) + counts.append(count) + plot_resonances(amplitudes, omegas, counts) + diff --git a/src/project3/python/plot_trajectories.py b/src/project3/python/plot_trajectories.py new file mode 100644 index 0000000..620924d --- /dev/null +++ b/src/project3/python/plot_trajectories.py @@ -0,0 +1,93 @@ +import matplotlib.pyplot as plt +import numpy as np +import os +import typer +from typing import Literal + +app = typer.Typer() + +def load_trajectory_data(filename): + data = np.loadtxt(filename) + step_count = int(float(filename.split("/")[-1].split("_")[5])) + particle_count = int(float(filename.split("/")[-1].split("_")[2])) + single_particle = particle_count == 1 + if single_particle: + data = data.reshape((data.shape[0], 1)) + data = data.reshape(step_count, 3, particle_count).transpose(1, 2, 0) + return data, step_count, particle_count + +@app.command() +def plot_z_evolution(trajectory_file: str): + """Plot the z-coordinate evolution from a trajectory file.""" + data, step_count, particle_count = load_trajectory_data(trajectory_file) + time = np.linspace(0, 50e-6, step_count) + for i in range(particle_count): + plt.plot(time, data[2, i, :] * 1e-6, label=f'Particle {i+1}') + plt.xlabel('Time (s)') + plt.ylabel('Z Position (m)') + plt.title('Z Coordinate Evolution') + plt.legend() + plt.show() + +@app.command() +def plot_xy_trajectory(trajectory_file: str, plot_start_end: bool = True, plot_time: bool = False): + """Plot the XY trajectory from a trajectory file.""" + data, step_count, particle_count = load_trajectory_data(trajectory_file) + for i in range(particle_count): + if plot_start_end: + plt.scatter(data[0, i, 0] * 1e-6, data[1, i, 0] * 1e-6, marker="o", color="black", label="Start" if i == 0 else "") + plt.scatter(data[0, i, -1] * 1e-6, data[1, i, -1] * 1e-6, marker="x", color="red", label="End" if i == 0 else "") + if plot_time: + marker = [".", ",", "o", "v", "^", "<", ">", "1", "2", "3", "4", "8"][i % 12] + cm = plt.get_cmap('viridis') + c = cm(np.linspace(0, 1, step_count)) + plt.scatter(data[0, i, :] * 1e-6, data[1, i, :] * 1e-6, label=f'Particle {i+1}', marker=marker, c=c) + else: + ls = "-" + c = f"C{i % 10}" + plt.plot(data[0, i, :] * 1e-6, data[1, i, :] * 1e-6, label=f'Particle {i+1}', linestyle=ls, color=c) + plt.xlabel('X Position (m)') + plt.ylabel('Y Position (m)') + plt.title('XY Trajectory') + plt.axis('equal') + if plot_time: + #sm = plt.cm.ScalarMappable(cmap=cm, norm=plt.Normalize(vmin=0, vmax=50e-6)) + #sm.set_array([]) + #cbar = plt.colorbar(sm) + #cbar.set_label('Time') + pass + plt.legend() + plt.show() + +@app.command() +def phase_space_plot(trajectory_file: str, velocity_file: str, axis: Literal['x', 'y', 'z'] = 'z'): + """Plot phase space (Z vs Vz) from trajectory and velocity files.""" + axis_index = {'x': 0, 'y': 1, 'z': 2}[axis] + traj_data, step_count, particle_count = load_trajectory_data(trajectory_file) + vel_data, _, _ = load_trajectory_data(velocity_file) + for i in range(particle_count): + plt.plot(traj_data[axis_index, i, :] * 1e-6, vel_data[axis_index, i, :] * 1e-6, label=f'Particle {i+1}') + plt.xlabel(f'{axis.upper()} Position (m)') + plt.ylabel(f'{axis.upper()} Velocity (m/s)') + plt.title(f'Phase Space Plot ({axis.upper()} vs V{axis.upper()})') + plt.legend() + plt.show() + +@app.command() +def plot_error(trajectory_files: list[str], analytical_file: str): + """Plot error between numerical and analytical trajectories.""" + analytical_data, step_count, particle_count = load_trajectory_data(analytical_file) + time = np.linspace(0, 50e-6, step_count) + for traj_file in trajectory_files: + numerical_data, _, _ = load_trajectory_data(traj_file) + error = numerical_data - analytical_data + relative_error = np.mean(np.linalg.norm(error, axis=0) / np.linalg.norm(analytical_data, axis=0), axis=0) + plt.plot(time, relative_error, label=os.path.basename(traj_file)) + plt.xlabel('Time (s)') + plt.ylabel('Relative Error') + plt.title('Relative Error between Numerical and Analytical Trajectories') + plt.legend() + plt.show() + +if __name__ == "__main__": + app() \ No newline at end of file diff --git a/src/project3/src/classes.cpp b/src/project3/src/classes.cpp new file mode 100644 index 0000000..da678f4 --- /dev/null +++ b/src/project3/src/classes.cpp @@ -0,0 +1,223 @@ +#include "classes.hpp" +#include "constants.hpp" +#include + +// Initialize particle with position and velocity +// Mass in atomic mass units (u), charge in elementary charges (e) +// Positions in meters, velocities in meters/second +Particle::Particle(arma::vec pos, arma::vec vel, double m, double q) + : position(pos * constants::meter), velocity(vel * constants::meter / constants::second), mass(m * constants::amu), charge(q * constants::elementary_charge) {} + +// Initialize particle at origin with zero velocity +Particle::Particle(double m, double q) + : position(arma::vec({0,0,0})), velocity(arma::vec({0,0,0})), mass(m * constants::amu), charge(q * constants::elementary_charge) {} + +std::string Particle::info() const { + std::string info_str = "Particle (m = " + std::to_string(mass) + " u, q = " + std::to_string(charge) + " e)\n"; + info_str += "Position (um): [" + std::to_string(position(0)) + ", " + std::to_string(position(1)) + ", " + std::to_string(position(2)) + "]\n"; + info_str += "Velocity (um/us): [" + std::to_string(velocity(0)) + ", " + std::to_string(velocity(1)) + ", " + std::to_string(velocity(2)) + "]\n"; + return info_str; +} + +bool Particle::inside_trap(double d) const { + return arma::norm(position) <= d; +} + +// Empty Penning Trap with specified field parameters +// B0 in tesla, V0 in volt, d in meters +PenningTrap::PenningTrap(double B0_in, double V0_in, double d_in) + : B0(B0_in * constants::tesla), V0(V0_in * constants::volt), d(d_in * constants::meter) {} + +// Add particle to trap +void PenningTrap::add_particle(Particle& p) { + particles.push_back(p); +} + +// Add n identical particles with mass m and charge q +void PenningTrap::add_n_identical_particles(int n, double m, double q) { + for (int i = 0; i < n; ++i) { + arma::vec pos = arma::vec(3).randn() * 0.1 * d; // Random position within 10% of d (unit: um) + arma::vec vel = arma::vec(3).randn() * 0.1 * d; // Random velocity within 10% of d/s (unit: um/us) + Particle p(pos / constants::meter, vel, m, q); + add_particle(p); + } +} + +void PenningTrap::set_external_E_field(arma::vec (*E_field_func)(const arma::vec&, double, const PenningTrap&)) { + _external_E_field = E_field_func; + modified_fields = true; +} + +void PenningTrap::set_external_B_field(arma::vec (*B_field_func)(const arma::vec&, double, const PenningTrap&)) { + _external_B_field = B_field_func; + modified_fields = true; +} + + +// Force on particle i from particle j due to Coulomb interaction +// Neglecting magnetic fields from moving charges +arma::vec PenningTrap::force_particle(int i, int j) const { + if (!coulomb_interaction) { + return arma::vec({0, 0, 0}); + } + arma::vec r_i = particles[i].position; + arma::vec r_j = particles[j].position; + arma::vec r_ij = r_i - r_j; + double distance = arma::norm(r_ij); + if (distance == 0) { + return arma::vec({0, 0, 0}); // Avoid division by zero + } + double force_magnitude_per_dist = (constants::k_e * particles[i].charge * particles[j].charge) / (distance * distance * distance); + return force_magnitude_per_dist * r_ij; +} + +// Total force on particle i from external fields +// Sum of electric and magnetic forces +arma::vec PenningTrap::total_force_external(int i, double t) const { + arma::vec E = external_E_field(get_particle(i).position, t); + arma::vec B = external_B_field(get_particle(i).position, t); + arma::vec v = get_particle(i).velocity; + arma::vec F_electric = get_particle(i).charge * E; + arma::vec F_magnetic = get_particle(i).charge * arma::cross(v, B); + return F_electric + F_magnetic; +} + +// Total force on particle i from all other particles +arma::vec PenningTrap::total_force_particles(int i) const { + arma::vec total_force = arma::vec({0, 0, 0}); + if (!coulomb_interaction) { // Add the check here as well to avoid unnecessary calls to force_particle + return total_force; + } + for (size_t j = 0; j < particles.size(); ++j) { + if (j != i) { + total_force += force_particle(i, j); + } + } + return total_force; +} + +// Total force on particle i from all other particles and external fields +arma::vec PenningTrap::total_force(int i, double t) const { + return total_force_external(i, t) + total_force_particles(i); +} + +// Potential energy of particle i in the trap +double PenningTrap::potential_energy(int i) const { + if (modified_fields) { + throw std::runtime_error("Potential energy calculation not valid with modified external fields."); + } + double q = particles[i].charge; + arma::vec r = particles[i].position; + double V = (V0 / (d * d)) * (r(2) * r(2) - 0.5 * (r(0) * r(0) + r(1) * r(1))); + if (coulomb_interaction) { + // Add contributions from other particles + for (size_t j = 0; j < particles.size(); ++j) { + if (j != i) { + arma::vec r_j = particles[j].position; + double distance = arma::norm(r - r_j); + if (distance != 0) { + V += (constants::k_e * particles[j].charge) / distance; + } + } + } + } + return q * V; +} + +// Total potential energy of all particles in the trap +double PenningTrap::total_potential_energy() const { + if (modified_fields) { + throw std::runtime_error("Potential energy calculation not valid with modified external fields."); + } + double total_U = 0.0; + for (size_t i = 0; i < particles.size(); ++i) { + total_U += potential_energy(i); + } + return total_U; +} + +// Kinetic energy of particle i +double PenningTrap::kinetic_energy(int i) const { + double m = particles[i].mass; + arma::vec v = particles[i].velocity; + return 0.5 * m * arma::dot(v, v); +} +// Total kinetic energy of all particles in the trap +double PenningTrap::total_kinetic_energy() const { + double total_K = 0.0; + for (size_t i = 0; i < particles.size(); ++i) { + total_K += kinetic_energy(i); + } + return total_K; +} + +// Total energy of all particles in the trap +double PenningTrap::total_energy() const { + return total_kinetic_energy() + total_potential_energy(); +} + + +// Getter function for particles +Particle& PenningTrap::get_particle(int i) { + return particles[i]; +} + +const Particle& PenningTrap::get_particle(int i) const { + return particles[i]; +} + +// Number of particles in trap +int PenningTrap::num_particles() const{ + return particles.size(); +} + + +std::string PenningTrap::info() const { + std::string info_str = "Penning Trap (B0 = " + std::to_string(B0) + " u/(us*e), V0 = " + std::to_string(V0) + " u*um^2/(us^2*e), d = " + std::to_string(d) + " um)\n"; + info_str += "Number of particles: " + std::to_string(num_particles()) + "\n"; + info_str += "Coulomb interactions: " + std::string(coulomb_interaction ? "enabled" : "disabled") + "\n"; + return info_str; +} + +int PenningTrap::num_inside_trap() const { + int count = 0; + for (int i = 0; i < num_particles(); ++i) { + if (particles[i].inside_trap(d)) { + count++; + } + } + return count; +} + +// Electric field at position r and time t +// Electric field from V = V0 * (z^2 - (x^2 + y^2)/2) / d^2 +arma::vec standard_external_E_field(const arma::vec& r, double t, const PenningTrap& trap) { + return (trap.V0 / (trap.d * trap.d)) * arma::vec({r(0), r(1), -2 * r(2)}); +} + +// Magnetic field at position r and time t +// Constant magnetic field in z-direction +arma::vec standard_external_B_field(const arma::vec& r, double t, const PenningTrap& trap) { + return arma::vec({0, 0, trap.B0}); +} + +arma::vec oscillating_external_E_field(const arma::vec& r, double t, const PenningTrap& trap) { + if (arma::norm(r) > trap.d) { + return arma::vec({0, 0, 0}); // No electric field outside the trap + } + return standard_external_E_field(r, t, trap) * (1 + trap.f * cos(trap.omega_V * t)); +} + +arma::vec limited_range_external_B_field(const arma::vec& r, double t, const PenningTrap& trap) { + if (arma::norm(r) > trap.d) { + return arma::vec({0, 0, 0}); // No magnetic field outside the trap + } + return standard_external_B_field(r, t, trap); +} + +std::ostream& operator<<(std::ostream& os, const Particle& p) { + return os << p.info(); +} +std::ostream& operator<<(std::ostream& os, const PenningTrap& trap) { + return os << trap.info(); +} \ No newline at end of file diff --git a/src/project3/src/solvers.cpp b/src/project3/src/solvers.cpp new file mode 100644 index 0000000..5a88cdc --- /dev/null +++ b/src/project3/src/solvers.cpp @@ -0,0 +1,340 @@ +#include "classes.hpp" +#include "solvers.hpp" +#include "constants.hpp" + + +// Initialize base solver class +// dt in seconds +Solver::Solver(PenningTrap& trap_in, double dt_in) + : trap(trap_in), dt(dt_in * constants::second), steps(0) {} + +// Simulate the system for a given number of steps +void Solver::simulate(int num_steps) { + for (int i = 0; i < num_steps; i++) { + step(); + if (record_positions_and_velocities) { // Allow disabling of recording for performance + // Store positions of all particles after each step + record_position(); + // Store velocities of all particles after each step + record_velocity(); + if (!trap.get_modified_fields()) { + record_energies(); + } + } + if (record_inside_trap_count) { + record_trap_count(); + } + steps++; + } +} + +void Solver::record_position() { + arma::mat current_positions(3, trap.num_particles()); + for (int j = 0; j < trap.num_particles(); j++) { + current_positions.col(j) = trap.get_particle(j).position; + } + positions.push_back(current_positions); +} +void Solver::record_velocity() { + arma::mat current_velocities(3, trap.num_particles()); + for (int j = 0; j < trap.num_particles(); j++) { + current_velocities.col(j) = trap.get_particle(j).velocity; + } + velocities.push_back(current_velocities); +} + +void Solver::record_energies() { + double U = trap.total_potential_energy(); + double K = trap.total_kinetic_energy(); + double E = trap.total_energy(); + potential_energies.push_back(U); + kinetic_energies.push_back(K); + total_energies.push_back(E); +} + +void Solver::record_trap_count() { + inside_trap_count.push_back(trap.num_inside_trap()); +} + +// Get recorded positions of particles +std::vector Solver::get_positions() { + return positions; +} + +// Get recorded velocities of particles +std::vector Solver::get_velocities() { + return velocities; +} +std::vector Solver::get_potential_energies() { + return potential_energies; +} +std::vector Solver::get_kinetic_energies() { + return kinetic_energies; +} +std::vector Solver::get_total_energies() { + return total_energies; +} + +std::vector Solver::get_inside_trap_count() { + return inside_trap_count; +} + +// Get the current step count +int Solver::get_current_step() { + return steps; +} + +// Calculate total steps for a given total time +// total_time in seconds +int Solver::total_steps(double total_time) { + return static_cast(total_time * constants::second / dt); +} + +void Solver::save(std::string base_filename) { + arma::cube pos_cube = to_cube(positions); + save_to_file(base_filename + "_positions.dat", pos_cube); + arma::cube vel_cube = to_cube(velocities); + save_to_file(base_filename + "_velocities.dat", vel_cube); + if (!trap.get_modified_fields()) { + arma::vec U = arma::vec(potential_energies); + save_to_file(base_filename + "_potential_energies.dat", U); + arma::vec K = arma::vec(kinetic_energies); + save_to_file(base_filename + "_kinetic_energies.dat", K); + arma::vec E = arma::vec(total_energies); + save_to_file(base_filename + "_total_energies.dat", E); + } +} + +void Solver::save_counts(std::string base_filename) { + std::string extension = ".dat"; + if (inside_trap_count.size() == 1) { + // Reduced to last element if only one entry + extension = ".red"; + } + std::ofstream file(base_filename + "_inside_trap_count" + extension); + for (size_t i = 0; i < inside_trap_count.size(); i++) { + file << i << " " << inside_trap_count[i] << "\n"; + } + file.close(); +} + +// Initialize Euler solver +EulerSolver::EulerSolver(PenningTrap& trap_in, double dt_in) + : Solver(trap_in, dt_in) {} + +// Perform a single Euler integration step +void EulerSolver::step() { + int n = trap.num_particles(); + for (int i = 0; i < n; i++) { + Particle& p = trap.get_particle(i); + arma::vec F = trap.total_force(i, steps * dt); + arma::vec a = F / p.mass; + p.position += p.velocity * dt; + p.velocity += a * dt; + } +} + +// Initialize Runge-Kutta 4 solver +RK4Solver::RK4Solver(PenningTrap& trap_in, double dt_in) + : Solver(trap_in, dt_in) {} + + +// Perform a single RK4 integration step +void RK4Solver::step() { + int n = trap.num_particles(); + std::vector k1_v(n), k1_r(n); + std::vector k2_v(n), k2_r(n); + std::vector k3_v(n), k3_r(n); + std::vector k4_v(n), k4_r(n); + + std::vector current_positions(n); + std::vector current_velocities(n); + + for (int i = 0; i < n; i++) { + current_positions[i] = trap.get_particle(i).position; + current_velocities[i] = trap.get_particle(i).velocity; + } + double t = steps * dt; + // Calculate k1 + for (int i = 0; i < n; i++) { + Particle& p = trap.get_particle(i); + arma::vec F = trap.total_force(i, t); + arma::vec a = F / p.mass; + k1_v[i] = a * dt; + k1_r[i] = p.velocity * dt; + p.position += k1_r[i] / 2; + p.velocity += k1_v[i] / 2; + } + // Calculate k2 + for (int i = 0; i < n; i++) { + Particle& p = trap.get_particle(i); + arma::vec F = trap.total_force(i, t + dt / 2); + arma::vec a = F / p.mass; + k2_v[i] = a * dt; + k2_r[i] = p.velocity * dt; + p.position = current_positions[i] + k2_r[i] / 2; + p.velocity = current_velocities[i] + k2_v[i] / 2; + } + // Calculate k3 + for (int i = 0; i < n; i++) { + Particle& p = trap.get_particle(i); + arma::vec F = trap.total_force(i, t + dt / 2); + arma::vec a = F / p.mass; + k3_v[i] = a * dt; + k3_r[i] = p.velocity * dt; + p.position = current_positions[i] + k3_r[i]; + p.velocity = current_velocities[i] + k3_v[i]; + } + // Calculate k4 + for (int i = 0; i < n; i++) { + Particle& p = trap.get_particle(i); + arma::vec F = trap.total_force(i, t + dt); + arma::vec a = F / p.mass; + k4_v[i] = a * dt; + k4_r[i] = p.velocity * dt; + p.position = current_positions[i]; + p.velocity = current_velocities[i]; + } + // Update positions and velocities + for (int i = 0; i < n; i++) { + Particle& p = trap.get_particle(i); + p.position = current_positions[i] + (k1_r[i] + 2.0 * k2_r[i] + 2.0 * k3_r[i] + k4_r[i]) / 6.0; + p.velocity = current_velocities[i] + (k1_v[i] + 2.0 * k2_v[i] + 2.0 * k3_v[i] + k4_v[i]) / 6.0; + } +} + +VelocityVerletSolver::VelocityVerletSolver(PenningTrap& trap_in, double dt_in) + : Solver(trap_in, dt_in) { + // Initialize accelerations + int n = trap.num_particles(); + accelerations.resize(n); + for (int i = 0; i < n; i++) { + Particle& p = trap.get_particle(i); + arma::vec F = trap.total_force(i, 0.0); + accelerations[i] = F / p.mass; + } +} + +// Perform a single Velocity Verlet integration step +void VelocityVerletSolver::step() { + int n = trap.num_particles(); + for (int i = 0; i < n; i++) { + Particle& p = trap.get_particle(i); + p.position += p.velocity * dt + 0.5 * accelerations[i] * dt * dt; + arma::vec new_acceleration = trap.total_force(i, steps * dt) / p.mass; + p.velocity += 0.5 * (accelerations[i] + new_acceleration) * dt; + accelerations[i] = new_acceleration; + } +} + + +// Initialize Analytical solver +AnalyticalSolver::AnalyticalSolver(PenningTrap& trap_in, double dt_in) + : Solver(trap_in, dt_in) { + // Check for validity of analytical solution + if (trap_in.get_coulomb_interaction()) { + throw std::runtime_error("Analytical solution not valid with Coulomb interactions enabled."); + } + if (trap_in.get_modified_fields()) { + throw std::runtime_error("Analytical solution not valid with modified external fields."); + } + for (int i = 0; i < trap_in.num_particles(); i++) { + if (trap_in.get_particle(i).velocity(0) != 0 || trap_in.get_particle(i).velocity(2) != 0) { + throw std::runtime_error("Analytical solution not valid for non-zero initial velocity in x or z direction."); + } + if (trap_in.get_particle(i).position(1) != 0) { + throw std::runtime_error("Analytical solution not valid for non-zero initial position in y direction."); + } + } + + trap = trap_in; + dt = dt_in * constants::second; + steps = 0; + int n = trap.num_particles(); + w_0.resize(n); + w_z.resize(n); + w_plus.resize(n); + w_minus.resize(n); + A_plus.resize(n); + A_minus.resize(n); + z_0.resize(n); + + for (int i = 0; i < n; i++) { + Particle& p = trap.get_particle(i); + double q = p.charge; + double m = p.mass; + double B0 = trap.B0; + double V0 = trap.V0; + double d = trap.d; + + w_0[i] = q * B0 / m; + w_z[i] = std::sqrt(2 * q * V0 / (m * d * d)); + double discriminant = w_0[i] * w_0[i] - 2 * w_z[i] * w_z[i]; + if (discriminant < 0) { + throw std::runtime_error("Analytical solution not valid: discriminant is negative."); + } + w_plus[i] = (w_0[i] + std::sqrt(discriminant)) / 2.0; + w_minus[i] = (w_0[i] - std::sqrt(discriminant)) / 2.0; + + arma::vec r = p.position; + arma::vec v = p.velocity; + + // Initial conditions + double x0 = r(0); + double y0 = r(1); + double z0 = r(2); + double vx0 = v(0); + double vy0 = v(1); + double vz0 = v(2); + + // Calculate amplitudes + A_plus[i] = (vy0 + w_minus[i] * x0) / (w_plus[i] - w_minus[i]); + A_minus[i] = -(vy0 + w_plus[i] * x0) / (w_plus[i] - w_minus[i]); + z_0[i] = z0; + } +} + +// Perform a single Analytical "integration" step +void AnalyticalSolver::step() { + int n = trap.num_particles(); + double t = steps * dt; + for (int i = 0; i < n; i++) { + Particle& p = trap.get_particle(i); + double x = -A_plus[i] * std::cos(w_plus[i] * t) - A_minus[i] * std::cos(w_minus[i] * t); + double y = A_plus[i] * std::sin(w_plus[i] * t) + A_minus[i] * std::sin(w_minus[i] * t); + double z = z_0[i] * std::cos(w_z[i] * t); + + double vx = +A_plus[i] * w_plus[i] * std::sin(w_plus[i] * t) + A_minus[i] * w_minus[i] * std::sin(w_minus[i] * t); + double vy = A_plus[i] * w_plus[i] * std::cos(w_plus[i] * t) + A_minus[i] * w_minus[i] * std::cos(w_minus[i] * t); + double vz = -z_0[i] * w_z[i] * std::sin(w_z[i] * t); + + p.position = arma::vec({x, y, z}); + p.velocity = arma::vec({vx, vy, vz}); + } +} + + +// Convert vector of matrices to a 3D cube for easier data handling +arma::cube to_cube(const std::vector& vec) { + if (vec.empty()) { + return arma::cube(); + } + int rows = vec[0].n_rows; + int cols = vec[0].n_cols; + int slices = vec.size(); + arma::cube cube_data(rows, cols, slices); + for (size_t i = 0; i < vec.size(); ++i) { + cube_data.slice(i) = vec[i]; + } + return cube_data; +} + +// Save cube data to a file +void save_to_file(const std::string& filename, const arma::cube& data) { + data.save(filename, arma::raw_ascii); +} + +void save_to_file(const std::string& filename, const arma::vec& data) { + arma::mat mat_data = arma::conv_to::from(data); + mat_data.save(filename, arma::raw_ascii); +} \ No newline at end of file diff --git a/src/project3/two_particles.cpp b/src/project3/two_particles.cpp new file mode 100644 index 0000000..f247d2d --- /dev/null +++ b/src/project3/two_particles.cpp @@ -0,0 +1,126 @@ +#include +#include "classes.hpp" +#include "solvers.hpp" +#include "constants.hpp" +#include "argparse/argparse.hpp" + +#include + +using namespace std; + +int main(int argc, char* argv[]) { + argparse::ArgumentParser program("two_particles"); + program.add_argument("-N", "--steps") + .help("Number of time steps") + .default_value(4000) + .scan<'i', int>(); + program.add_argument("-n", "--num_particles") + .help("Number of particles (either 1 or 2)") + .default_value(2) + .scan<'i', int>(); + program.add_argument("-i", "--disable-interactions") + .help("Disable Coulomb interactions") + .default_value(true) + .implicit_value(false); + program.add_argument("-E", "--euler") + .help("Use Euler solver instead of RK4") + .flag(); + program.add_argument("-A", "--analytical") + .help("Use Analytical solver instead of RK4 (only valid for particles without interactions and specific initial conditions)") + .flag(); + program.add_argument("-V", "--velocity-verlet") + .help("Use Velocity Verlet solver instead of RK4") + .flag(); + + try { + program.parse_args(argc, argv); + } catch (const runtime_error& err) { + cerr << err.what() << endl; + cerr << program.help().str() << endl; + exit(1); + } + + double N = program.get("--steps"); + int n_particles = program.get("--num_particles"); + bool interactions = program.get("--disable-interactions"); + bool use_euler = program.get("--euler"); + bool use_analytical = program.get("--analytical"); + bool use_velocity_verlet = program.get("--velocity-verlet"); + + double B_0 = 1.0; // Tesla + double V_0 = 0.025; // Volt + double d = 500e-6; // meter + + PenningTrap trap(B_0, V_0, d); + if (interactions) { + trap.enable_interactions(); + } + else { + trap.disable_interactions(); + } + cout << trap << endl; + + + Particle p1(arma::vec({20e-6, 0, 20e-6}), arma::vec({0, 25, 0}), 40.078 * constants::amu, 1 * constants::elementary_charge); + Particle p2(arma::vec({25e-6, 25e-6, 0}), arma::vec({0, 40, 5}), 40.078 * constants::amu, 1 * constants::elementary_charge); + + trap.add_particle(p1); + if (n_particles > 1) { + trap.add_particle(p2); + } + + double dt = 50e-6 / N; // seconds + + if (use_euler) { + EulerSolver solver(trap, dt); + solver.simulate(N); + solver.save("results/two_particles_" + std::to_string(n_particles) + (interactions ? "_with_interactions_" : "_no_interactions_") + std::to_string(N) + "_steps_euler"); + vector positions = solver.get_positions(); + cout << "Final position of particle 1: " << endl; + cout << positions.back().col(0) << endl; + if (n_particles > 1) { + cout << "Final position of particle 2: " << endl; + cout << positions.back().col(1) << endl; + } + return 0; + } + + if (use_analytical) { + AnalyticalSolver solver(trap, dt); + solver.simulate(N); + solver.save("results/two_particles_" + std::to_string(n_particles) + (interactions ? "_with_interactions_" : "_no_interactions_") + std::to_string(N) + "_steps_analytical"); + vector positions = solver.get_positions(); + cout << "Final position of particle 1: " << endl; + cout << positions.back().col(0) << endl; + if (n_particles > 1) { + cout << "Final position of particle 2: " << endl; + cout << positions.back().col(1) << endl; + } + return 0; + } + + if (use_velocity_verlet) { + VelocityVerletSolver solver(trap, dt); + solver.simulate(N); + solver.save("results/two_particles_" + std::to_string(n_particles) + (interactions ? "_with_interactions_" : "_no_interactions_") + std::to_string(N) + "_steps_velocity_verlet"); + vector positions = solver.get_positions(); + cout << "Final position of particle 1: " << endl; + cout << positions.back().col(0) << endl; + if (n_particles > 1) { + cout << "Final position of particle 2: " << endl; + cout << positions.back().col(1) << endl; + } + return 0; + } + + RK4Solver solver(trap, dt); + solver.simulate(N); + solver.save("results/two_particles_" + std::to_string(n_particles) + (interactions ? "_with_interactions_" : "_no_interactions_") + std::to_string(N) + "_steps_rk4"); + vector positions = solver.get_positions(); + cout << "Final position of particle 1: " << endl; + cout << positions.back().col(0) << endl; + if (n_particles > 1) { + cout << "Final position of particle 2: " << endl; + cout << positions.back().col(1) << endl; + } +} \ No newline at end of file diff --git a/uv.lock b/uv.lock index ce9600a..c211472 100644 --- a/uv.lock +++ b/uv.lock @@ -42,6 +42,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" }, ] +[[package]] +name = "click" +version = "8.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/61/de6cd827efad202d7057d93e0fed9294b96952e188f7384832791c7b2254/click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4", size = 276943, upload-time = "2025-09-18T17:32:23.696Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", size = 107295, upload-time = "2025-09-18T17:32:22.42Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -198,6 +210,7 @@ dependencies = [ { name = "numpy" }, { name = "pandas" }, { name = "scipy" }, + { name = "typer" }, ] [package.metadata] @@ -207,6 +220,7 @@ requires-dist = [ { name = "numpy", specifier = ">=2.3.2" }, { name = "pandas", specifier = ">=2.3.2" }, { name = "scipy", specifier = ">=1.16.1" }, + { name = "typer", specifier = ">=0.19.2" }, ] [[package]] @@ -367,6 +381,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, ] +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + [[package]] name = "matplotlib" version = "3.10.5" @@ -426,6 +452,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca", size = 9899, upload-time = "2024-04-15T13:44:43.265Z" }, ] +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + [[package]] name = "nest-asyncio" version = "1.6.0" @@ -757,6 +792,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/69/a4/7ee652ea1c77d872f5d99ed937fa8bbd1f6f4b7a39a6d3a0076c286e0c3e/pyzmq-27.0.2-cp314-cp314t-win_arm64.whl", hash = "sha256:4108785f2e5ac865d06f678a07a1901e3465611356df21a545eeea8b45f56265", size = 574901, upload-time = "2025-08-21T04:22:17.423Z" }, ] +[[package]] +name = "rich" +version = "14.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fe/75/af448d8e52bf1d8fa6a9d089ca6c07ff4453d86c65c145d0a300bb073b9b/rich-14.1.0.tar.gz", hash = "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8", size = 224441, upload-time = "2025-07-25T07:32:58.125Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/30/3c4d035596d3cf444529e0b2953ad0466f6049528a879d27534700580395/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", size = 243368, upload-time = "2025-07-25T07:32:56.73Z" }, +] + [[package]] name = "scipy" version = "1.16.1" @@ -804,6 +852,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6e/6c/a76329897a7cae4937d403e623aa6aaea616a0bb5b36588f0b9d1c9a3739/scipy-1.16.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c0c804d60492a0aad7f5b2bb1862f4548b990049e27e828391ff2bf6f7199998", size = 39427705, upload-time = "2025-07-27T16:31:53.96Z" }, ] +[[package]] +name = "shellingham" +version = "1.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, +] + [[package]] name = "six" version = "1.17.0" @@ -855,6 +912,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" }, ] +[[package]] +name = "typer" +version = "0.19.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "rich" }, + { name = "shellingham" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/21/ca/950278884e2ca20547ff3eb109478c6baf6b8cf219318e6bc4f666fad8e8/typer-0.19.2.tar.gz", hash = "sha256:9ad824308ded0ad06cc716434705f691d4ee0bfd0fb081839d2e426860e7fdca", size = 104755, upload-time = "2025-09-23T09:47:48.256Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/22/35617eee79080a5d071d0f14ad698d325ee6b3bf824fc0467c03b30e7fa8/typer-0.19.2-py3-none-any.whl", hash = "sha256:755e7e19670ffad8283db353267cb81ef252f595aa6834a0d1ca9312d9326cb9", size = 46748, upload-time = "2025-09-23T09:47:46.777Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + [[package]] name = "tzdata" version = "2025.2"