Computational Physics

This document explains the computational physics methods used in Picht. There’s a lot of code whose purpose isn’t for software-related modularity but the physics, and this exists to clear it up.

Physics

The main two equations Picht uses behind the scenes to calculate electrodynamics are the Lorentz force equation and the Paraxial Ray equation.

Electric Lenses

For electrostatic lenses (like electrodes and einzel lenses), the PotentialField class calculates the electric field by solving the Laplacian:

\[\nabla^2 V = 0\]

where V is the electrostatic potential (voltage). It uses multigrid methods using PyAMG to solve the system of equations generated by the Laplacian, which has a roughly O(n) complexity when the amount of discretizations increase. So a jump from a 100x100 grid to a 1000x1000 grid is only ~10 times more computational power. Systems using the previous SOR solver that pre-2.0.0 releases had, will calculate 100x100 grids slower and less accurately than our current PyAMG-based multgrid solver can do for 1000x1000 grids. So, feel free to use much finer meshes.

After the electrostatic potential field (voltage field) V is solved, we use np.gradient and solve:

\[E = -\nabla V\]

To find the electric field from the potential field. This is relatively straightforward. At every point, thus, we have Ez and Er stored for the electric field components in different directions.

Finally, when calculating particle trajectories, the Lorentz force equation for electrostatics is used:

\[\mathbf{F} = qE\]

We use this instead of the paraxial ray equation because, quite honestly, we can get away with it. The speeds are sufficient, it’s more accurate, and calculating electrostatics at high-divergence angles is more important than for magnetostatics, because we can more accurately simulate electron and ion guns, which are electric in nature.

Magnetic Lenses

For magnetic lenses, we first solve Poisson’s equation:

\[\nabla^2 A = -\mu_0 \mu_r J\]

Where A is the vector potential, $mu_0$ is the permeability of free space, $mu_r$ is the relative permeability, and J is current density. This also uses PyAMG with its benefits, but it takes ~2-3 times longer than the electric potential field calculations, which are scalar. Still, if there are no electric lenses, electric fields aren’t calculated and the same here, so there’s no overhead with the addition of magnetic lenses into the codebase if you don’t add them to your IonOpticsSystem.

Then, we calculate the magnetic field using:

\[B = \nabla \times A\]

Which is not computationally intensive. Then, instead of using the Lorentz equation (which requires azimuthal components to work + is much slower and more complex for B-fields) we use the small-angle approximation which is paraxial ray equation. More specifically we use:

\[F_r = -\frac{q^2 B_z^2}{4m} r\]

Where $F_r$ is the radial component of focusing, r is the distance from the center axis of the magnetic lens, $q^2$ is of course the square of the charge and $B_z$ is the axial component of the magnetic field, and m is the mass of the particle.