Skip to content

Commit 3fbc89f

Browse files
cleanup and docs
1 parent 8f0c9df commit 3fbc89f

File tree

3 files changed

+268
-13
lines changed

3 files changed

+268
-13
lines changed
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "892a58d5-2d7f-4053-9bd0-1a02d3b7d455",
6+
"metadata": {},
7+
"source": [
8+
"# Resistive Wall Wakefield\n",
9+
"\n",
10+
"The `ResistiveWallWakefield` object implements the pseudomode (damped oscillator) fits from SLAC-PUB-10707 to efficiently calculate the resistive wall wakefield from round and flat geometries, for arbitrary conductivities and relaxation times."
11+
]
12+
},
13+
{
14+
"cell_type": "code",
15+
"execution_count": null,
16+
"id": "fee8faee-1f31-4e4d-a2af-18bfb25fa0cc",
17+
"metadata": {},
18+
"outputs": [],
19+
"source": [
20+
"from pmd_beamphysics.wakefields.resistive_wall import ResistiveWallWakefield\n",
21+
"\n",
22+
"from pmd_beamphysics import ParticleGroup\n",
23+
"from pmd_beamphysics.units import epsilon_0\n",
24+
"import numpy as np\n",
25+
"import matplotlib.pyplot as plt"
26+
]
27+
},
28+
{
29+
"cell_type": "code",
30+
"execution_count": null,
31+
"id": "393a7b50-478f-47a0-acf8-268a34b2af45",
32+
"metadata": {},
33+
"outputs": [],
34+
"source": [
35+
"?ResistiveWallWakefield"
36+
]
37+
},
38+
{
39+
"cell_type": "markdown",
40+
"id": "c36da92f-d4a6-46c5-a0ff-307d5d69bde7",
41+
"metadata": {},
42+
"source": [
43+
"# Basic ins"
44+
]
45+
},
46+
{
47+
"cell_type": "code",
48+
"execution_count": null,
49+
"id": "d045a156-5b8d-439c-b3a0-0434f01657ba",
50+
"metadata": {},
51+
"outputs": [],
52+
"source": [
53+
"wake = ResistiveWallWakefield(\n",
54+
" radius=0.0025, geometry=\"round\", conductivity=6.5e7, relaxation_time=27e-15\n",
55+
")\n",
56+
"\n",
57+
"wake.plot()"
58+
]
59+
},
60+
{
61+
"cell_type": "code",
62+
"execution_count": null,
63+
"id": "47eb70ea-ff85-4b1d-8de0-f9b9f44b5f9b",
64+
"metadata": {},
65+
"outputs": [],
66+
"source": [
67+
"print(wake.to_bmad())"
68+
]
69+
},
70+
{
71+
"cell_type": "markdown",
72+
"id": "ad1249db-19e5-42a2-a976-2ff48843a91d",
73+
"metadata": {},
74+
"source": [
75+
"# Compare with SLAC-PUB-10707\n",
76+
"\n",
77+
"Here we check the function against the plots in SLAC-PUB-10707."
78+
]
79+
},
80+
{
81+
"cell_type": "code",
82+
"execution_count": null,
83+
"id": "56a82d9d-9079-45d5-8bcd-6c8f5f2bdd32",
84+
"metadata": {},
85+
"outputs": [],
86+
"source": [
87+
"radius_ref = 2.5e-3\n",
88+
"\n",
89+
"wake = ResistiveWallWakefield.from_material(\n",
90+
" material=\"copper-slac-pub-10707\", radius=radius_ref, geometry=\"round\"\n",
91+
")\n",
92+
"\n",
93+
"wake.plot()"
94+
]
95+
},
96+
{
97+
"cell_type": "code",
98+
"execution_count": null,
99+
"id": "19cff809-238b-4cbc-90d4-1cbac8032022",
100+
"metadata": {},
101+
"outputs": [],
102+
"source": [
103+
"raw_data = np.loadtxt(\"../data/SLAC-PUB-10707-digitized-Fig4-AC-Cu.csv\", delimiter=\",\")\n",
104+
"\n",
105+
"# Convert to SI\n",
106+
"zref, Wref = (\n",
107+
" raw_data[:, 0] * 1e-6,\n",
108+
" raw_data[:, 1] * 4 / radius_ref**2 / (4 * np.pi * epsilon_0),\n",
109+
")\n",
110+
"plt.plot(zref, Wref)"
111+
]
112+
},
113+
{
114+
"cell_type": "code",
115+
"execution_count": null,
116+
"id": "eabb80d7-969c-45e6-bd56-60cd05b8d494",
117+
"metadata": {},
118+
"outputs": [],
119+
"source": [
120+
"zlist = np.linspace(0, 300e-6, 200)\n",
121+
"Wz = wake.pseudomode(-zlist)\n",
122+
"\n",
123+
"fig, ax = plt.subplots()\n",
124+
"ax.plot(zlist * 1e6, Wz * 1e-12, label=f\"ResistiveWallWakefield {wake.geometry}\")\n",
125+
"\n",
126+
"ax.plot(zref * 1e6, Wref * 1e-12, \"--\", label=\"Fig. 4 AC-Cu from SLAC-PUB-10707 2004\")\n",
127+
"plt.legend()\n",
128+
"\n",
129+
"ax.set_xlabel(r\"$-z$ (µm)\")\n",
130+
"ax.set_ylabel(r\"$W_z$ (V/pC/m)\")"
131+
]
132+
},
133+
{
134+
"cell_type": "markdown",
135+
"id": "5d112e6f-839f-4d62-bc24-3130c91b2e9d",
136+
"metadata": {},
137+
"source": [
138+
"# Integrated wake from particles\n"
139+
]
140+
},
141+
{
142+
"cell_type": "code",
143+
"execution_count": null,
144+
"id": "ca47a277-7b06-4207-a2cf-79bc98a7bb3d",
145+
"metadata": {},
146+
"outputs": [],
147+
"source": [
148+
"P = ParticleGroup(\"../data/bmad_particles2.h5\")\n",
149+
"P.drift_to_t()"
150+
]
151+
},
152+
{
153+
"cell_type": "code",
154+
"execution_count": null,
155+
"id": "e2478b38-e658-40fb-95bb-a1574e784d50",
156+
"metadata": {},
157+
"outputs": [],
158+
"source": [
159+
"z = P.z\n",
160+
"weight = P.weight"
161+
]
162+
},
163+
{
164+
"cell_type": "markdown",
165+
"id": "5e8c504c-d5c2-4cb4-b747-eb64dc3e1bcc",
166+
"metadata": {},
167+
"source": [
168+
"`wake.pseudomode` gives the per particle kicks"
169+
]
170+
},
171+
{
172+
"cell_type": "code",
173+
"execution_count": null,
174+
"id": "933f4897-7be8-4b68-8988-337e66fe87ae",
175+
"metadata": {},
176+
"outputs": [],
177+
"source": [
178+
"zwake = wake.pseudomode.particle_kicks(z, weight)\n",
179+
"len(zwake)"
180+
]
181+
},
182+
{
183+
"cell_type": "code",
184+
"execution_count": null,
185+
"id": "34bf0eb3-7543-4da1-90ee-a426e26e5740",
186+
"metadata": {},
187+
"outputs": [],
188+
"source": [
189+
"plt.scatter(z, zwake)"
190+
]
191+
},
192+
{
193+
"cell_type": "code",
194+
"execution_count": null,
195+
"id": "951358f0-f4eb-4771-98eb-e48b9cfd05a1",
196+
"metadata": {},
197+
"outputs": [],
198+
"source": [
199+
"zscale = 1e6\n",
200+
"fig, ax = plt.subplots()\n",
201+
"ax.scatter(z * zscale, zwake, label=\"Python\", color=\"black\")\n",
202+
"ax.legend()\n",
203+
"ax.set_xlabel(r\"$z$ (µm)\")\n",
204+
"ax.set_ylabel(r\"$W_z$ (eV/m)\")"
205+
]
206+
},
207+
{
208+
"cell_type": "markdown",
209+
"id": "5d6d054a-3635-4072-82f2-203fd706c171",
210+
"metadata": {},
211+
"source": [
212+
"# ParticleGroup.wakefield_plot\n",
213+
"\n",
214+
"Wakefields can be autmoatically integrated and plotted from a ParticlGroup. The function automatically determintes the horizontal axis."
215+
]
216+
},
217+
{
218+
"cell_type": "code",
219+
"execution_count": null,
220+
"id": "00bf79b7-2563-4935-9027-5065267958d4",
221+
"metadata": {},
222+
"outputs": [],
223+
"source": [
224+
"P.wakefield_plot(wake, figsize=(12, 4))"
225+
]
226+
},
227+
{
228+
"cell_type": "code",
229+
"execution_count": null,
230+
"id": "d4792846-1230-4ff6-88c3-905388e86776",
231+
"metadata": {},
232+
"outputs": [],
233+
"source": [
234+
"P.drift_to_z()\n",
235+
"P.wakefield_plot(wake, figsize=(12, 4))"
236+
]
237+
}
238+
],
239+
"metadata": {
240+
"kernelspec": {
241+
"display_name": "Python 3 (ipykernel)",
242+
"language": "python",
243+
"name": "python3"
244+
},
245+
"language_info": {
246+
"codemirror_mode": {
247+
"name": "ipython",
248+
"version": 3
249+
},
250+
"file_extension": ".py",
251+
"mimetype": "text/x-python",
252+
"name": "python",
253+
"nbconvert_exporter": "python",
254+
"pygments_lexer": "ipython3",
255+
"version": "3.13.3"
256+
}
257+
},
258+
"nbformat": 4,
259+
"nbformat_minor": 5
260+
}

mkdocs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ nav:
2020
- examples/fields/field_conversion.ipynb
2121
- examples/fields/corrector_modeling.ipynb
2222
- examples/fields/solenoid_modeling.ipynb
23+
- Wakefields:
24+
- examples/wakefields/resistive_wall_wakefield.ipynb
2325
- Utilities:
2426
- examples/units.ipynb
2527
- examples/labels.ipynb

pmd_beamphysics/wakefields/resistive_wall.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,9 @@
22
import numpy as np
33
import matplotlib.pyplot as plt
44

5-
from ..units import mu_0, c_light
5+
from ..units import c_light, epsilon_0, Z0
66
from scipy.signal import fftconvolve
77

8-
# Calculate these here for consistency
9-
epsilon_0 = 1 / (mu_0 * c_light**2)
10-
Z0 = mu_0 * c_light # Ohm
11-
128
# AC wake Fitting Formula Polynomial coefficients
139
# found by fitting digitized plots in SLAC-PUB-10707 Fig. 14
1410
_krs0_round_poly = np.poly1d(
@@ -108,14 +104,6 @@ def Gammaf(relaxation_time, radius, conductivity):
108104
return c_light * relaxation_time / s0f(radius, conductivity)
109105

110106

111-
# Bmad strings formatting
112-
def str_bool(x):
113-
if x:
114-
return "T"
115-
else:
116-
return "F"
117-
118-
119107
@dataclass(slots=True)
120108
class pseudomode:
121109
"""
@@ -270,11 +258,15 @@ class ResistiveWallWakefield:
270258
based on digitized data from SLAC-PUB-10707 Fig. 14.
271259
- Wakefield output supports evaluation, convolution, and export in Bmad format.
272260
- Materials with known conductivity and τ values are available via `from_material()`.
261+
- Relaxation times for materials have a large uncertainty in this model. See Bane, Stupakov, Tu (2006).
273262
274263
References
275264
----------
276265
Bane & Stupakov, SLAC-PUB-10707 (2004)
277266
https://www.slac.stanford.edu/cgi-wrap/getdoc/slac-pub-10707.pdf
267+
268+
Bane, Stupakov, Tu, Proceedings of EPAC 2006, Edinburgh, Scotland THPCH073 (2006)
269+
https://accelconf.web.cern.ch/e06/PAPERS/THPCH073.PDF
278270
"""
279271

280272
radius: float
@@ -478,6 +470,7 @@ def pseudomode(self):
478470
Single pseudomode representing this wakefield
479471
"""
480472

473+
# Conversion from cgs units
481474
A = 1 / (4 * np.pi * epsilon_0) * 4 / self.radius**2
482475
if self.geometry == "flat":
483476
A *= np.pi**2 / 16

0 commit comments

Comments
 (0)