ocelot-collab / ocelot

OCELOT is a multiphysics simulation toolkit designed for studying FEL and storage ring-based light sources.
GNU General Public License v3.0
86 stars 58 forks source link

Undulator magnetic field expression seems wrong #261

Open delaossa opened 9 hours ago

delaossa commented 9 hours ago

Hello,

I have been revising the UndulatorAtom class and have noticed that there seems to be a couple of inconsistencies:

  1. The general expression for the magnetic field seems to be wrong. In the code this is written:

    Bx = -B0 * (kx / ky) * np.sin(kx_x) * np.sinh(ky_y) * np.cos(kz_z)
    By = B0 * np.cos(kx_x) * np.cosh(ky_y) * np.cos(kz_z)
    Bz = -B0 * (kz / ky) * np.cos(kx_x) * np.sinh(ky_y) * np.sin(kz_z)

    But, from S. Reiche's thesis, Eq. (2.1), I get:

    Bx = B0 * (kx / ky) * np.sinh(kx_x) * np.sinh(ky_y) * np.cos(kz_z)
    By = B0 * np.cosh(kx_x) * np.cosh(ky_y) * np.cos(kz_z)
    Bz = -B0 * (kz / ky) * np.cosh(kx_x) * np.sinh(ky_y) * np.sin(kz_z)

    See here: https://github.com/ocelot-collab/ocelot/blob/39bda2607853c23abee02cde31521d8b4186c0c6/ocelot/cpbd/elements/undulator_atom.py#L124 In this piece of code kx is always set to zero and, in this case, the two expressions yield the same result. However, for consistency, I think that this should be fixed.

  2. Depending on the end_poles parameter, a phase shift is introduced: np.cos(kz_z + ph_shift). However, this phase shift is only applied to the np.cos(kz_z) part in By, but not to the np.sin(kz_z) part in Bz. This would certainly lead to a wrong focusing effect when using the RK method.

Perhaps is easier to explain the issue through this PR #262.

sergey-tomin commented 6 hours ago

Hi,

  1. Both sets of formulas are correct. However, one should not forget that, in reality, the field in the horizontal direction should decay; for that, $k_x$ must be an imaginary number. In that case, we have $\cosh(i x) = \cos(x)$. For the $B_x$ component, it is a bit different. We have originally:

$$ B_x = B_0 \frac{k_x}{k_y} \sin(k_x x) ...., $$

which will transform to:

$$ B_x = B_0 \frac{i k_x}{k_y} \sinh(i k_x x)... = -B_0 \frac{k_x}{k_y} \sin(k_x x)... $$

As you can see, now we have the same formulas as in Ocelot. By the way, apparently I tried to provide a hint (to myself) with the comment "# // here kx is only real.". I will include an explanation in the doc string.

  1. Regarding the issue with $\sin(k_z z)$, it seems you are right. This shift also has to be in the $B_z$ field. Thanks for the tip.

I see you submitted a PR, so you have a choice: either you modify your PR and remove the changes regarding point 1 and leave the changes regarding point 2, or I can do it. Please let me know.

Cheers, Sergey.

delaossa commented 4 hours ago

Hi Sergey,

Oh I see! I missed that... Thanks a lot for the explanation!

About the PR, I only did it so one could see better the issue by comparing the two versions. I think that it is better if you take care of point 2. I am not very satisfied how the phase shift is implemented anyway...