Skip to content

Commit 78f78e0

Browse files
committed
fix:'replace_spacecharge_with_PIC' now creates 'PICCollection' with longitudinal kick for 'FFTSolver3D'
Added 'apply_z_kick' parameter to 'replace_spacecharge_with_PIC'. Added logic so that if solver is 'FFTSolver3D' and no 'apply_z_kick' parameter value is specified, 'apply_z_kick' is set to True when creating 'PICCollection'. Previously, PICCollection would always be created with 'apply_z_kick' as False even when using 'FFTSolver3D', and therefore no longitudinal kick would be deposited.
1 parent b02664d commit 78f78e0

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import pytest
2+
3+
import xtrack as xt
4+
import xpart as xp
5+
import xfields as xf
6+
7+
from xobjects.test_helpers import for_all_test_contexts
8+
from xfields.config_tools import replace_spacecharge_with_PIC
9+
10+
11+
@pytest.mark.parametrize(
12+
"solver, user_apply, expected",
13+
[
14+
("FFTSolver2p5D", None, False),
15+
("FFTSolver3D", None, True),
16+
("FFTSolver2p5D", True, True),
17+
("FFTSolver3D", False, False),
18+
]
19+
)
20+
@for_all_test_contexts
21+
def test_replace_spacecharge_with_PIC_apply_z_kick_logic(
22+
solver, user_apply, expected, test_context):
23+
bunch_intensity = 2.5e11
24+
sigma_x = 3e-3
25+
sigma_y = 2e-3
26+
sigma_z = 0.30
27+
p0c = 25.92e9
28+
29+
lprof = xf.LongitudinalProfileQGaussian(
30+
_context=test_context,
31+
number_of_particles=bunch_intensity,
32+
sigma_z=sigma_z,
33+
z0=0.0,
34+
q_parameter=1.0
35+
)
36+
37+
sc1 = xf.SpaceChargeBiGaussian(
38+
_context=test_context,
39+
update_on_track=False,
40+
length=1.0,
41+
longitudinal_profile=lprof,
42+
mean_x=0.0, mean_y=0.0,
43+
sigma_x=sigma_x, sigma_y=sigma_y,
44+
min_sigma_diff=1e-12,
45+
)
46+
sc2 = xf.SpaceChargeBiGaussian(
47+
_context=test_context,
48+
update_on_track=False,
49+
length=2.0,
50+
longitudinal_profile=lprof,
51+
mean_x=0.0, mean_y=0.0,
52+
sigma_x=sigma_x, sigma_y=sigma_y,
53+
min_sigma_diff=1e-12,
54+
)
55+
56+
line = xt.Line(elements=[
57+
xt.Drift(length=0.1),
58+
sc1,
59+
xt.Drift(length=0.2),
60+
sc2,
61+
xt.Drift(length=0.1),
62+
])
63+
64+
line.build_tracker(_context=test_context, compile=False)
65+
line.particle_ref = xp.Particles(_context=test_context, p0c=p0c)
66+
67+
n_sigmas_range_pic_x = 4.0
68+
n_sigmas_range_pic_y = 4.0
69+
nx_grid = 16
70+
ny_grid = 16
71+
nz_grid = 16
72+
n_lims_x = 3
73+
n_lims_y = 3
74+
z_range = (-3 * sigma_z, 3 * sigma_z)
75+
76+
kwargs = dict(
77+
line=line,
78+
n_sigmas_range_pic_x=n_sigmas_range_pic_x,
79+
n_sigmas_range_pic_y=n_sigmas_range_pic_y,
80+
nx_grid=nx_grid, ny_grid=ny_grid, nz_grid=nz_grid,
81+
n_lims_x=n_lims_x, n_lims_y=n_lims_y,
82+
z_range=z_range,
83+
solver=solver,
84+
)
85+
if user_apply is not None:
86+
kwargs["apply_z_kick"] = user_apply
87+
88+
pic_collection, all_pics = replace_spacecharge_with_PIC(**kwargs)
89+
90+
assert pic_collection.apply_z_kick == expected, (
91+
f"PICCollection.apply_z_kick mismatch for solver={solver}, "
92+
f"user_apply={user_apply}; expected {expected}"
93+
)

xfields/config_tools/spacecharge_config_tools.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ def replace_spacecharge_with_PIC(
277277
n_sigmas_range_pic_x, n_sigmas_range_pic_y,
278278
nx_grid, ny_grid, nz_grid, n_lims_x, n_lims_y, z_range,
279279
solver='FFTSolver2p5D',
280+
apply_z_kick=None,
280281
_context=None,
281282
_buffer=None):
282283

@@ -303,6 +304,10 @@ def replace_spacecharge_with_PIC(
303304
Number different limits in y for which PIC need to be generated.
304305
z_range : float
305306
Range of the longitudinal grid.
307+
apply_z_kick : bool, optional
308+
If ``True``, the longitudinal kick on the particles is applied.
309+
Defaults to ``True`` when ``solver`` is ``FFTSolver3D``,
310+
otherwise ``False``.
306311
_context : xtrack.Context (optional)
307312
Context in which the PIC elements are created.
308313
_buffer : xtrack.Buffer (optional)
@@ -338,6 +343,9 @@ def replace_spacecharge_with_PIC(
338343
y_lim_min = np.min(all_sigma_y) * (n_sigmas_range_pic_y - 0.5)
339344
y_lim_max = np.max(all_sigma_y) * (n_sigmas_range_pic_y + 0.5)
340345

346+
if apply_z_kick is None:
347+
apply_z_kick = (solver == "FFTSolver3D")
348+
341349
pic_collection = PICCollection(
342350
_context=_context,
343351
_buffer=_buffer,
@@ -346,6 +354,7 @@ def replace_spacecharge_with_PIC(
346354
y_lim_min=y_lim_min, y_lim_max=y_lim_max, n_lims_y=n_lims_y,
347355
z_range=z_range,
348356
solver=solver,
357+
apply_z_kick=apply_z_kick,
349358
gamma0=line.particle_ref.gamma0[0])
350359

351360
all_pics = []

0 commit comments

Comments
 (0)