Skip to content

Commit 5ed18fe

Browse files
authored
More lcavity devel. (bmad-sim#1600)
* More lcavity devel.
1 parent 2ab4325 commit 5ed18fe

File tree

15 files changed

+728
-646
lines changed

15 files changed

+728
-646
lines changed

bmad/code/em_field_calc.f90

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ recursive subroutine em_field_calc (ele, param, s_pos, orbit, local_ref_frame, f
322322
if (present(rf_time)) then
323323
time = rf_time
324324
else
325-
time = particle_rf_time(orbit, ele, .false., s_body)
325+
time = particle_rf_time(orbit, ele, .false., s_body, rf_freq = ele%value(rf_frequency$))
326326
endif
327327
phase = twopi * (ele%value(phi0$) + ele%value(phi0_multipass$) + ele%value(phi0_autoscale$) - &
328328
(time - rf_ref_time_offset(ele) - s_body/c_light) * ele%value(rf_frequency$))
@@ -347,7 +347,7 @@ recursive subroutine em_field_calc (ele, param, s_pos, orbit, local_ref_frame, f
347347
if (present(rf_time)) then
348348
time = rf_time
349349
else
350-
time = particle_rf_time(orbit, ele, .true., s_body)
350+
time = particle_rf_time(orbit, ele, .true., s_body, rf_freq = ele%value(rf_frequency$))
351351
endif
352352
phase = (ele%value(phi0$) + ele%value(phi0_multipass$) + ele%value(phi0_err$) + ele%value(phi0_autoscale$))
353353
field%e(3) = e_accel_field (ele, gradient$) * cos(twopi * (time * ele%value(rf_frequency$) + phase)) / ref_charge
@@ -425,7 +425,7 @@ recursive subroutine em_field_calc (ele, param, s_pos, orbit, local_ref_frame, f
425425
if (present(rf_time)) then
426426
time = rf_time
427427
else
428-
time = particle_rf_time(orbit, ele, .true., s_body)
428+
time = particle_rf_time(orbit, ele, .true., s_body, rf_freq = ele%value(rf_frequency$))
429429
endif
430430

431431
if (nint(ele%value(cavity_type$)) == traveling_wave$) then
@@ -782,13 +782,6 @@ recursive subroutine em_field_calc (ele, param, s_pos, orbit, local_ref_frame, f
782782
! FieldMap
783783

784784
case(fieldmap$)
785-
786-
if (present(rf_time)) then
787-
time = rf_time
788-
else
789-
time = particle_rf_time(orbit, ele, .false., s_body)
790-
endif
791-
792785
if (.not. associated(ele%cylindrical_map) .and. .not. associated(ele%cartesian_map) .and. &
793786
.not. associated(ele%gen_grad_map) .and. .not. associated(ele%grid_field)) then
794787
call out_io (s_fatal$, r_name, 'No associated fieldmap (cartesican_map, grid_field, etc) FOR: ' // ele%name)
@@ -1108,6 +1101,12 @@ recursive subroutine em_field_calc (ele, param, s_pos, orbit, local_ref_frame, f
11081101
freq0 = ele%value(rf_frequency$)
11091102
freq = ele%value(rf_frequency$) * cl_map%harmonic
11101103

1104+
if (present(rf_time)) then
1105+
time = rf_time
1106+
else
1107+
time = particle_rf_time(orbit, ele, .false., s_body, rf_freq = freq0)
1108+
endif
1109+
11111110
if (freq0 == 0) then
11121111
call out_io (s_fatal$, r_name, 'Element frequency is zero but cylindrical_map harmonic is not in: ' // ele%name)
11131112
if (global_com%exit_on_error) call err_exit
@@ -1314,6 +1313,12 @@ recursive subroutine em_field_calc (ele, param, s_pos, orbit, local_ref_frame, f
13141313
return
13151314
endif
13161315

1316+
if (present(rf_time)) then
1317+
time = rf_time
1318+
else
1319+
time = particle_rf_time(orbit, ele, .false., s_body, rf_freq = freq0)
1320+
endif
1321+
13171322
t_ref = (ele%value(phi0$) + ele%value(phi0_multipass$) + ele%value(phi0_err$) + &
13181323
phi0_autoscale + g_field%phi0_fieldmap) / freq0
13191324
if (ele%key == rfcavity$) t_ref = 0.25/freq0 - t_ref

bmad/code/particle_rf_time.f90

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
!+
2-
! Function particle_rf_time (orbit, ele, reference_active_edge, s_rel, time_coords, rf_freq, rf_clock_harmonic, abs_time) result (time)
2+
! Function particle_rf_time (orbit, ele, reference_active_edge, s_rel, time_coords, rf_freq, abs_time) result (time)
33
!
44
! Routine to return the reference time used to calculate the phase of
55
! time-dependent EM fields.
@@ -19,17 +19,18 @@
1919
! s_rel -- real(rp), optional: Longitudinal position relative to the upstream edge of the element.
2020
! Needed for relative time tracking when the particle is inside the element. Default is 0.
2121
! time_coords -- logical, optional: Default False. If True then orbit is using time based phase space coordinates.
22-
! rf_freq -- real(rp), optional: If present and non-zero, the returned time shifted by an integer multiple
23-
! of 1/rf_freq to be in the range [-1/2*rf_freq, 1/2*rf_freq].
2422
! rf_clock_harmonic -- integer, optional: Used with the rf clock in cases where an element has multiple frequencies.
23+
! rf_freq -- real(rp), optional: If present, the returned time shifted by an integer multiple
24+
! of 1/rf_freq to be in the range [-1/2*rf_freq, 1/2*rf_freq]. This is useful to
25+
! avoid round-off errors.
2526
! abs_time -- real(rp), optional: If False (default) use setting of bmad_com%absolute_time_tracking.
2627
! If True, use absolute time instead of relative time.
2728
!
2829
! Ouput:
2930
! time -- Real(rp): Current time.
3031
!-
3132

32-
function particle_rf_time (orbit, ele, reference_active_edge, s_rel, time_coords, rf_freq, rf_clock_harmonic, abs_time) result (time)
33+
function particle_rf_time (orbit, ele, reference_active_edge, s_rel, time_coords, rf_freq, abs_time) result (time)
3334

3435
use bmad_routine_interface, dummy_except => particle_rf_time
3536
use attribute_mod, only: has_attribute
@@ -42,8 +43,8 @@ function particle_rf_time (orbit, ele, reference_active_edge, s_rel, time_coords
4243
type (ele_pointer_struct), allocatable :: chain(:)
4344

4445
real(rp), optional :: s_rel, rf_freq
45-
real(rp) time, s_hard_offset, beta0, freq
46-
integer, optional :: rf_clock_harmonic
46+
real(qp) time
47+
real(rp) s_hard_offset, beta0, freq
4748
integer n, ix_pass, n_links, harmonic
4849
logical, optional :: reference_active_edge, time_coords, abs_time
4950

@@ -113,10 +114,9 @@ function particle_rf_time (orbit, ele, reference_active_edge, s_rel, time_coords
113114
time = time - s_hard_offset / (c_light * beta0)
114115
endif
115116

116-
!
117-
118-
freq = real_option(0.0_rp, rf_freq)
119-
if (freq /= 0) time = modulo2(time, 0.5_rp/freq)
117+
if (present(rf_freq)) then
118+
if (rf_freq /= 0) time = modulo2(time, 0.5_qp/rf_freq)
119+
endif
120120

121121
end function particle_rf_time
122122

bmad/code/track1.f90

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,17 @@ recursive subroutine track1 (start_orb, ele, param, end_orb, track, err_flag, ig
226226
case (bmad_standard$)
227227
if (end_orb%species == photon$) then
228228
call track1_bmad_photon (end_orb, ele, param, err)
229+
if (err) return
230+
229231
else
230232
call track1_bmad (end_orb, ele, param, err, track, mat6 = ele%mat6, make_matrix = make_map1)
233+
if (err) return
231234

232235
select case (ele%key)
233236
case (beambeam$, crab_cavity$, patch$); do_spin_tracking = .false.
237+
case (lcavity$); do_spin_tracking = (do_spin_tracking .and. nint(ele%value(n_rf_steps$)) < 1)
234238
end select
235239
endif
236-
if (err) return
237240

238241
case (runge_kutta$, fixed_step_runge_kutta$)
239242
call track1_runge_kutta (end_orb, ele, param, err, track, mat6 = ele%mat6, make_matrix = make_map1)

bmad/doc/charged-tracking.tex

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,7 +1172,8 @@ \subsection{drift-kick model}
11721172
kicks are applied at the ends of the element and in between sections with the kicks at the ends
11731173
being half that of the kicks applied in the interior. The voltage at a kick point is:
11741174
\begin{equation}
1175-
V_{kick} = \frac{r_q \, \kappa \, V_{tot}}{N_s} \, \cos(2 \pi \, (\phi_t + \phi_\REF))
1175+
V_txt{kick} = \frac{r_q \, \kappa \, V_{tot}}{N_s} \, \cos(2 \pi \, (\phi_t + \phi_\REF))
1176+
\label{vkick}
11761177
\end{equation}
11771178
See \Eq{dergl} for a description of the parameters in the equation. Here $\kappa$ is 0.5 for the end
11781179
kick points and is unity for interior kick points.
@@ -1193,6 +1194,9 @@ \subsection{drift-kick model}
11931194
in each section will affect the plotting of phase space momentum coordinates since these
11941195
are normalized to $P_0$ (\sref{s:phase.space}).
11951196

1197+
For spin tracking through the energy kick, the BMT equation is used with the integrated kick field
1198+
given by Eq.~{vkick} modeled as an electric field in the $z$-direction.
1199+
11961200
%---------------------------------------------------------------------------------
11971201
\subsection{Edge kick}
11981202

@@ -1205,7 +1209,7 @@ \subsection{Edge kick}
12051209
H_f = \mp \frac{q}{2 \, P_0 \, c} G_t \, \cos(\phi_t + \phi_\REF) \, (x^2 + y^2)
12061210
\end{equation}
12071211
where the minus sign is for the entrance end and the plus sign is for the exit end, $q$ is the
1208-
particle charge, $P_0$ is the reference momentum. Since $\phi_t = 2 \pi f_\txt{rf} \, t$ is time
1212+
particle charge, $P_0$ is the reference momentum. Since $\phi_t = 2 \pi f_\txt{rf} \, t$ is time
12091213
dependent, it is easiest to use this Hamiltonian in energy-time phase space coordinates
12101214
(\sref{energy.phase.space}) to give the fringe kicks:
12111215
\begin{align}
@@ -1223,7 +1227,8 @@ \subsection{Edge kick}
12231227
oscillation also delays the particle in time compared to the case where there is no oscillation
12241228
conponent.
12251229

1226-
For spin tracking, the BMT equation is used with the integrated edge field (voltage) $\bfV_f$:
1230+
For spin tracking through the edge field, the BMT equation is used with the integrated edge field
1231+
(voltage) $\bfV_f$ parallel to the radius vector $\bfr$:
12271232
\begin{equation}
12281233
\bfV_f = -G_t \, \bfr
12291234
\end{equation}
@@ -1267,10 +1272,12 @@ \subsection{Standing wave focusing: the pondermotive force}
12671272
forward propagating particle is rapidly varying. The formulas above are for the kick averaged over
12681273
all phases and therefore the phase dependence has been eliminated.
12691274

1270-
For spin tracking, the focusing kick is modeled as a radial integrated field (voltage) $\bfV_f$
1271-
\begin{equation}
1272-
\bfV_f = -G_t \, \bfr
1273-
\end{equation}
1275+
For spin tracking, to zeroth order, the averaged field is zero for the backwards wave so no spin
1276+
kick is applied for the backwards wave.
1277+
\begin{align}
1278+
\bfE(\bfr) &= \CRNO
1279+
\bfB(\theta) &=
1280+
\end{align}
12741281

12751282
%-----------------------------------------------------------------------------------------
12761283
%-----------------------------------------------------------------------------------------

bmad/doc/methods.tex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -528,14 +528,14 @@ \section{Spin Tracking Methods}
528528
\begin{sideways}\vn{Magnus}\end{sideways} &
529529
\begin{sideways}\vn{Sprint}\end{sideways} &
530530
\begin{sideways}\vn{Symp_Lie_PTC}\end{sideways} &
531-
\begin{sideways}\vn{Tracking}\end{sideways}
531+
\begin{sideways}\vn{Tracking}\end{sideways} &
532532
\begin{sideways}\vn{Transverse_Kick}\end{sideways} &
533533
\\ \midrule
534534
% O C M Spt SLP Trk TK
535535
\vn{ab_multipole and multipole} & X & X & & & & D & \\
536536
\vn{ac_kicker} & X & X & & & & D & \\
537537
\vn{beambeam} & X & X & & & & D & \\
538-
\vn{bends: rbend and sbend} & X & X & X & X & X & D & \\
538+
\vn{bends: rbend and sbend} & X & X & X & X & X & D & \\
539539
\vn{converter} & X & X & & & & D & \\
540540
\vn{crab_cavity} & X & X & & & & D & \\
541541
\vn{custom} & X & D & & & & X & \\
@@ -547,10 +547,10 @@ \section{Spin Tracking Methods}
547547
\vn{fiducial} & X & X & & & X & D & \\
548548
\vn{floor_shift} & X & X & & & X & D & \\
549549
\vn{hkicker} & X & X & X & X & X & D & \\
550-
\vn{instrument, monitor and pipe} & X & X & X & X & X & D & \\
550+
\vn{instrument, monitor and pipe} & X & X & X & X & X & D & \\
551551
\vn{kicker} & X & X & X & X & X & D & \\
552-
\vn{lcavity and rfcavity} & X & X & X & & X & D & \\
553-
\vn{marker} & X & X & X & & X & D & \\
552+
\vn{lcavity and rfcavity} & X & X & & & X & D & \\
553+
\vn{marker} & X & X & & & & D & \\
554554
\vn{match} & D & & & & & & X \\
555555
\vn{octupole} & X & X & & X & X & D & \\
556556
\vn{patch} & X & X & & & X & D & \\

bmad/low_level/ac_kicker_amp.f90

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ function ac_kicker_amp(ele, orbit, true_time) result (ac_amp)
3737
!
3838

3939
ref_ele => ele
40-
if (ref_ele%slave_status == super_slave$ .or. ele%slave_status == slice_slave$) ref_ele => pointer_to_super_lord (ref_ele)
40+
if (ref_ele%slave_status == super_slave$ .or. ele%slave_status == slice_slave$) &
41+
ref_ele => pointer_to_super_lord (ref_ele)
4142

4243
ac_amp = 1
4344
if (ele%key /= ac_kicker$) return
@@ -55,12 +56,12 @@ function ac_kicker_amp(ele, orbit, true_time) result (ac_amp)
5556
if (allocated(ac%frequency)) then
5657
ac_amp = 0
5758
do i = 1, size(ac%frequency)
58-
t = real_option(particle_rf_time(orbit, ele, rf_clock_harmonic = ac%frequency(i)%rf_clock_harmonic), true_time)
59+
t = real_option(real(particle_rf_time(orbit, ele, rf_freq = ac%frequency(i)%f), rp), true_time)
5960
ac_amp = ac_amp + ac%frequency(i)%amp * cos(twopi*(ac%frequency(i)%f * t + ac%frequency(i)%phi))
6061
enddo
6162

6263
else
63-
t = real_option(particle_rf_time(orbit, ele), true_time)
64+
t = real_option(real(particle_rf_time(orbit, ele), rp), true_time)
6465
ac_amp = knot_interpolate(ac%amp_vs_time%time, ac%amp_vs_time%amp, t, nint(ele%value(interpolation$)), err_flag)
6566
if (err_flag) then
6667
call out_io (s_fatal$, r_name, 'INTERPOLATION PROBLEM FOR AC_KICKER: ' // ele%name)

bmad/low_level/track_a_crab_cavity.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ subroutine track_a_crab_cavity (orbit, ele, param, mat6, make_matrix)
8181
s_here = (i - 0.5_rp) * dl
8282

8383
phase0 = twopi * (ele%value(phi0$) + ele%value(phi0_multipass$) + ele%value(phi0_autoscale$) - &
84-
(particle_rf_time (orbit, ele, .false.) - rf_ref_time_offset(ele, s_here)) * &
84+
(particle_rf_time (orbit, ele, .false., rf_freq = ele%value(rf_frequency$)) - rf_ref_time_offset(ele, s_here)) * &
8585
ele%value(rf_frequency$))
8686
if (ele%orientation == -1) phase0 = phase0 + twopi * ele%value(rf_frequency$) * dt_length
8787
phase = phase0

0 commit comments

Comments
 (0)