Skip to content
Snippets Groups Projects
test_bunch.py 4.99 KiB
import numpy as np
import pytest
from scipy.constants import e

from mbtrack2 import Bunch


def test_bunch_values(demo_ring):
    mp_number = 10
    current = 20e-3
    mybunch = Bunch(demo_ring, mp_number=mp_number, current=current,
                    track_alive=True)

    assert mybunch.mp_number == mp_number
    assert pytest.approx(mybunch.current) == current
    assert len(mybunch) == mp_number
    np.testing.assert_allclose(mybunch.alive, np.ones((mp_number,), dtype=bool))
    assert pytest.approx(mybunch.charge) == current * demo_ring.T0
    assert pytest.approx(mybunch.charge_per_mp) == current * demo_ring.T0 / mp_number
    assert pytest.approx(mybunch.particle_number) == current * demo_ring.T0 / e
    assert mybunch.is_empty == False

def test_bunch_magic(mybunch):
    for label in mybunch:
        np.testing.assert_allclose(mybunch[label], np.zeros(len(mybunch)))
        mybunch[label] = np.ones(len(mybunch))
        np.testing.assert_allclose(mybunch[label], np.ones(len(mybunch)))

def test_bunch_losses(mybunch):
    charge_init = mybunch.charge
    mybunch.alive[0] = False
    assert len(mybunch) == mybunch.mp_number - 1
    assert pytest.approx(mybunch.charge) == charge_init * len(mybunch) / mybunch.mp_number

def test_bunch_init_gauss(large_bunch):
    large_bunch.init_gaussian(mean=np.ones((6,)))
    np.testing.assert_allclose(large_bunch.mean, np.ones((6,)), rtol=1e-2)

def test_bunch_save_load(mybunch, demo_ring, tmp_path):
    mybunch["x"] += 1
    mybunch.save(str(tmp_path / "test"))

    mybunch2 = Bunch(demo_ring, mp_number=1, current=1e-5)
    mybunch2.load(str(tmp_path / "test.hdf5"))

    assert mybunch.mp_number == mybunch2.mp_number
    assert pytest.approx(mybunch.charge) == mybunch2.charge
    for label in mybunch:
        np.testing.assert_allclose(mybunch[label], mybunch2[label])

def test_bunch_stats(demo_ring, large_bunch):
    large_bunch.init_gaussian()
    np.testing.assert_array_almost_equal(large_bunch.mean, np.zeros((6,)), decimal=5)
    sig = np.concatenate((demo_ring.sigma(), [demo_ring.sigma_0, demo_ring.sigma_delta]))
    np.testing.assert_allclose(large_bunch.std, sig, rtol=1e-2)
    np.testing.assert_allclose(large_bunch.emit[:2], demo_ring.emit, rtol=1e-2)
    np.testing.assert_allclose(large_bunch.cs_invariant[:2], demo_ring.emit*2, rtol=1e-2)

def test_bunch_binning(mybunch):
    mybunch.init_gaussian()
    (bins, sorted_index, profile, center) = mybunch.binning()
    profile0 = np.zeros((len(bins)-1,))
    for i, val in enumerate(sorted_index):
        assert bins[val] <= mybunch["tau"][i] <= bins[val+1]
        profile0[val] += 1
    np.testing.assert_allclose(profile0, profile)

def test_bunch_plots(mybunch):
    mybunch.init_gaussian()
    mybunch.plot_phasespace()
    mybunch.plot_profile()
    assert True
def test_bunch_emittance(demo_ring):
    mp_number = 1_000_000
    current = 1.2e-3
    mybunch = Bunch(demo_ring, mp_number=mp_number, current=current,
                    track_alive=False)
    mybunch.init_gaussian()
    np.testing.assert_allclose(mybunch.emit[0], demo_ring.emit[0], rtol=1e-2, atol=0,
     err_msg=f'Emittances do not match. {demo_ring.emit[0]} initialised, {mybunch.emit[0]:} calculated')
    np.testing.assert_allclose(mybunch.emit[1], demo_ring.emit[1], rtol=1e-2, atol=0,
     err_msg=f'Emittances do not match. {demo_ring.emit[1]} initialised, {mybunch.emit[1]:} calculated')

    np.testing.assert_allclose(mybunch.emit[0], mybunch.cs_invariant[0]/2, rtol=1e-2, atol=0,
     err_msg=f'Emittances do not match. {mybunch.cs_invariant[0]/2} calculated with optics functions, {mybunch.emit[0]:} calculated with coordinates only')
    np.testing.assert_allclose(mybunch.emit[1], mybunch.cs_invariant[1]/2, rtol=1e-2, atol=0,
     err_msg=f'Emittances do not match. {mybunch.cs_invariant[1]/2} calculated with optics functions, {mybunch.emit[1]:} calculated with coordinates only')


def test_bunch_emittance_with_dispersion(demo_ring):
    mp_number = 1_000_000
    current = 1.2e-3
    demo_ring.optics.local_dispersion = np.array([1e-2, 1e-3, 1e-2, 1e-3])
    mybunch = Bunch(demo_ring, mp_number=mp_number, current=current,
                    track_alive=False)
    mybunch.init_gaussian()
    np.testing.assert_allclose(mybunch.emit[0], demo_ring.emit[0], rtol=1e-2, atol=0,
     err_msg=f'Emittances do not match. {demo_ring.emit[0]} initialised, {mybunch.emit[0]:} calculated')
    np.testing.assert_allclose(mybunch.emit[1], demo_ring.emit[1], rtol=1e-2, atol=0,
     err_msg=f'Emittances do not match. {demo_ring.emit[1]} initialised, {mybunch.emit[1]:} calculated')

    np.testing.assert_allclose(mybunch.emit[0], mybunch.cs_invariant[0]/2, rtol=1e-2, atol=0,
     err_msg=f'Emittances do not match. {mybunch.cs_invariant[0]/2} calculated with optics functions, {mybunch.emit[0]:} calculated with coordinates only')
    np.testing.assert_allclose(mybunch.emit[1], mybunch.cs_invariant[1]/2, rtol=1e-2, atol=0,
     err_msg=f'Emittances do not match. {mybunch.cs_invariant[1]/2} calculated with optics functions, {mybunch.emit[1]:} calculated with coordinates only')