/**
   * prepare method for bringing the velocity in the desired half step
   *
   * @param p before the update: v(t); after the update: v(t-dt/2)
   */
  public void prepare(Particle2D p, Force f, double dt) {
    // a(t) = F(v(t), x(t)) / m
    p.ax = f.getForceX(p) / p.mass;
    p.ay = f.getForceY(p) / p.mass;

    // v(t - dt / 2) = v(t) - a(t)*dt / 2
    p.vx -= p.ax * dt / 2;
    p.vy -= p.ay * dt / 2;
  }
  /**
   * Boris algorithm for implementing the electric and magnetic field. The damping is implemented
   * with an linear error O(dt). Warning: the velocity is stored half a time step before of the
   * position.
   *
   * @param p before the update: x(t), v(t-dt/2); after the update: x(t+dt), v(t+dt/2)
   */
  public void step(Particle2D p, Force f, double step) {

    // remember for complete()
    // a(t) = F(v(t), x(t)) / m
    p.ax = f.getForceX(p) / p.mass;
    p.ay = f.getForceY(p) / p.mass;

    double vxminus = p.vx + f.getPositionComponentofForceX(p) * step / (2.0 * p.mass);
    double vxplus;
    double vxprime;

    double vyminus = p.vy + f.getPositionComponentofForceY(p) * step / (2.0 * p.mass);
    double vyplus;
    double vyprime;

    double t_z = p.charge * f.getBz(p) * step / (2.0 * p.mass); // t vector

    double s_z = 2 * t_z / (1 + t_z * t_z); // s vector

    vxprime = vxminus + vyminus * t_z;
    vyprime = vyminus - vxminus * t_z;

    vxplus = vxminus + vyprime * s_z;
    vyplus = vyminus - vxprime * s_z;

    p.vx =
        vxplus
            + f.getPositionComponentofForceX(p) * step / (2.0 * p.mass)
            + f.getTangentVelocityComponentOfForceX(p) * step / p.mass;
    p.vy =
        vyplus
            + f.getPositionComponentofForceY(p) * step / (2.0 * p.mass)
            + f.getTangentVelocityComponentOfForceY(p) * step / p.mass;

    p.x += p.vx * step;
    p.y += p.vy * step;
  }