Skip to content

Commit c1cd7bb

Browse files
committed
Merge remote-tracking branch 'hannes-bartosik/master' into develop
2 parents 884f383 + 550f8a4 commit c1cd7bb

File tree

4 files changed

+144
-22
lines changed

4 files changed

+144
-22
lines changed

pysixtrack/be_beamfields/spacecharge.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ class SpaceChargeCoasting(Element):
66
"""Space charge for a coasting beam"""
77

88
_description = [
9-
("line_density", "1/m", "Desc...", 0.0),
10-
("sigma_x", "m", "Desc...", 1.0),
11-
("sigma_y", "m", "Desc...", 1.0),
12-
("length", "m", "Desc...", 0.0),
13-
("x_co", "m", "Desc...", 0.0),
14-
("y_co", "m", "Desc...", 0),
9+
("line_density", "1/m", "Number of particles per unit length", 0.0),
10+
("sigma_x", "m", "Horizontal size of the beam (r.m.s.)", 1.0),
11+
("sigma_y", "m", "Vertical size of the beam (r.m.s.)", 1.0),
12+
("length", "m", "Integration length of space charge kick", 0.0),
13+
("x_co", "m", "Horizontal closed orbit offset", 0.0),
14+
("y_co", "m", "Vertical closed orbit offset", 0),
1515
]
1616
_extra = [
17-
("min_sigma_diff", "m", "Desc...", 1e-30),
18-
("enabled", "", "Desc...", True),
17+
("min_sigma_diff", "m", "Threshold to detect round beam", 1e-30),
18+
("enabled", "", "Switch to disable space charge effect", True),
1919
]
2020

2121
def track(self, p):
@@ -64,17 +64,17 @@ def track(self, p):
6464

6565
class SpaceChargeBunched(Element):
6666
_description = [
67-
("number_of_particles", "", "Desc...", 0.0),
68-
("bunchlength_rms", "m", "Desc...", 1.0),
69-
("sigma_x", "m", "Desc...", 1.0),
70-
("sigma_y", "m", "Desc...", 1.0),
71-
("length", "m", "Desc...", 0.0),
72-
("x_co", "m", "Desc...", 0.0),
73-
("y_co", "m", "Desc...", 0),
67+
("number_of_particles", "", "Number of particles in the bunch", 0.0),
68+
("bunchlength_rms", "m", "Length of the bunch (r.m.s.)", 1.0),
69+
("sigma_x", "m", "Horizontal size of the beam (r.m.s.)", 1.0),
70+
("sigma_y", "m", "Vertical size of the beam (r.m.s.)", 1.0),
71+
("length", "m", "Integration length of space charge kick", 0.0),
72+
("x_co", "m", "Horizontal closed orbit offset", 0.0),
73+
("y_co", "m", "Vertical closed orbit offset", 0),
7474
]
7575
_extra = [
76-
("min_sigma_diff", "m", "Desc...", 1e-30),
77-
("enabled", "", "Desc...", True),
76+
("min_sigma_diff", "m", "Threshold to detect round beam", 1e-30),
77+
("enabled", "", "Switch to disable space charge effect", True),
7878
]
7979

8080
def track(self, p):

pysixtrack/elements.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ def track(self, particle):
309309
and y <= self.max_y
310310
)
311311
if particle.state != 1:
312-
return particle.state
312+
return "Particle lost"
313313
else:
314314
particle.state = np.int_(
315315
(x >= self.min_x)
@@ -319,13 +319,13 @@ def track(self, particle):
319319
)
320320
particle.remove_lost_particles()
321321
if len(particle.state) == 0:
322-
return -1
322+
return "All particles lost"
323323

324324

325325
class LimitEllipse(Element):
326326
_description = [
327-
("a", "m^2", "Horizontal semiaxis", 1.0),
328-
("b", "m^2", "Vertical semiaxis", 1.0),
327+
("a", "m", "Horizontal semiaxis", 1.0),
328+
("b", "m", "Vertical semiaxis", 1.0),
329329
]
330330

331331
def track(self, particle):
@@ -345,7 +345,7 @@ def track(self, particle):
345345
)
346346
particle.remove_lost_particles()
347347
if len(particle.state) == 0:
348-
return "All particle lost"
348+
return "All particles lost"
349349

350350

351351
class BeamMonitor(Element):

tests/test_beamfields.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import numpy as np
2+
3+
import pysixtrack
4+
5+
6+
def test_track_spacecharge():
7+
x_co = 0.1
8+
y_co = -0.5
9+
sigma_x = 0.5
10+
sigma_y = 0.1
11+
el1 = pysixtrack.elements.SpaceChargeBunched(
12+
number_of_particles=1e11,
13+
bunchlength_rms=0.22,
14+
sigma_x=sigma_x,
15+
sigma_y=sigma_y,
16+
length=2.0,
17+
x_co=x_co,
18+
y_co=y_co,
19+
)
20+
line_density = el1.number_of_particles / (
21+
el1.bunchlength_rms * np.sqrt(2 * np.pi)
22+
)
23+
el2 = pysixtrack.elements.SpaceChargeCoasting(
24+
line_density=line_density,
25+
sigma_x=el1.sigma_x,
26+
sigma_y=el1.sigma_y,
27+
length=el1.length,
28+
x_co=el1.x_co,
29+
y_co=el1.y_co,
30+
)
31+
32+
# test absolute kick for sigma_x > sigma_y
33+
x_offset = 0.2
34+
y_offset = -0.5
35+
p1 = pysixtrack.Particles()
36+
p1.x = x_co + x_offset
37+
p1.y = y_co + y_offset
38+
p2 = p1.copy()
39+
el1.track(p1)
40+
el2.track(p2)
41+
assert np.isclose(p1.px, 1.33671170365656e-07, atol=1e-15)
42+
assert np.isclose(p1.py, -6.228154616877465e-07, atol=1e-15)
43+
assert p1.compare(p2, abs_tol=1e-15)
44+
45+
# test absolute kick for sigma_y > sigma_x
46+
el1.sigma_x = sigma_y
47+
el1.sigma_y = sigma_x
48+
el2.sigma_x = sigma_y
49+
el2.sigma_y = sigma_x
50+
p1 = pysixtrack.Particles()
51+
p1.x = x_co + y_offset
52+
p1.y = y_co + x_offset
53+
p2 = p1.copy()
54+
el1.track(p1)
55+
el2.track(p2)
56+
assert np.isclose(p1.px, -6.228154616877465e-07, atol=1e-15)
57+
assert np.isclose(p1.py, 1.33671170365656e-07, atol=1e-15)
58+
assert p1.compare(p2, abs_tol=1e-15)
59+
60+
# test no kick for particle on closed orbit
61+
p1 = pysixtrack.Particles()
62+
p1.x = el1.x_co
63+
p1.y = el1.y_co
64+
p2 = p1.copy()
65+
el1.track(p1)
66+
el2.track(p2)
67+
assert np.isclose(p1.px, 0.0, atol=1e-15)
68+
assert np.isclose(p1.py, 0.0, atol=1e-15)
69+
assert p1.compare(p2, abs_tol=1e-15)

tests/test_track.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import numpy as np
2+
13
import pysixtrack
24

35
element_list = [
46
pysixtrack.elements.Drift,
57
pysixtrack.elements.DriftExact,
68
pysixtrack.elements.Multipole,
79
pysixtrack.elements.Cavity,
10+
pysixtrack.elements.SawtoothCavity,
811
pysixtrack.elements.XYShift,
912
pysixtrack.elements.SRotation,
1013
pysixtrack.elements.RFMultipole,
@@ -15,6 +18,8 @@
1518
pysixtrack.elements.LimitEllipse,
1619
pysixtrack.elements.BeamBeam4D,
1720
pysixtrack.elements.BeamBeam6D,
21+
pysixtrack.elements.SpaceChargeCoasting,
22+
pysixtrack.elements.SpaceChargeBunched,
1823
]
1924

2025

@@ -37,3 +42,51 @@ def test_track_rfmultipole():
3742
el2.track(p2)
3843

3944
assert p1.compare(p2, abs_tol=1e-15)
45+
46+
47+
def test_track_LimitRect():
48+
min_x = -0.1
49+
max_x = 0.3
50+
min_y = -0.5
51+
max_y = 0.1
52+
el = pysixtrack.elements.LimitRect(
53+
min_x=min_x, max_x=max_x, min_y=min_y, max_y=max_y
54+
)
55+
56+
p1 = pysixtrack.Particles()
57+
p1.x = 1
58+
p1.y = 1
59+
ret = el.track(p1)
60+
assert ret == "Particle lost"
61+
62+
arr = np.arange(0, 1, 0.001)
63+
p2 = pysixtrack.Particles(x=arr, y=arr)
64+
ret = el.track(p2)
65+
66+
p2.x += max_x + 1e-6
67+
ret = el.track(p2)
68+
assert ret == "All particles lost"
69+
70+
71+
def test_track_LimitEllipse():
72+
limit_a = 0.1
73+
limit_b = 0.2
74+
el = pysixtrack.elements.LimitEllipse(a=limit_a, b=limit_b)
75+
76+
p1 = pysixtrack.Particles()
77+
p1.x = 1
78+
p1.y = 1
79+
ret = el.track(p1)
80+
assert ret == "Particle lost"
81+
82+
arr = np.arange(0, 1, 0.001)
83+
p2 = pysixtrack.Particles(x=arr, y=arr)
84+
ret = el.track(p2)
85+
survived = np.where(
86+
(p2.x ** 2 / limit_a ** 2 + p2.y ** 2 / limit_b ** 2 <= 1.0)
87+
)
88+
assert len(p2.state) == len(survived[0])
89+
90+
p2.x += limit_a + 1e-6
91+
ret = el.track(p2)
92+
assert ret == "All particles lost"

0 commit comments

Comments
 (0)