Skip to content
Snippets Groups Projects
Commit ebd806ea authored by Alexis GAMELIN's avatar Alexis GAMELIN
Browse files

Add the interface for FB/loops in CavityResonator

Add an interface in CavityResonator to allow for external FB and loops.
Add the ProportionalLoop and TunerLoop using what was already done in the RF-FB branch.
parent 4d2d1fd5
Branches
Tags
No related merge requests found
......@@ -6,7 +6,9 @@ from mbtrack2.tracking.particles import (Electron,
Particle)
from mbtrack2.tracking.synchrotron import Synchrotron
from mbtrack2.tracking.rf import (RFCavity,
CavityResonator)
CavityResonator,
ProportionalLoop,
TunerLoop)
from mbtrack2.tracking.parallel import Mpi
from mbtrack2.tracking.element import (Element,
LongitudinalMap,
......
......@@ -58,6 +58,9 @@ class CavityResonator():
If used with mpi, beam.mpi.share_distributions must be called before the
track method call.
Different kind of RF feeback and loops can be added using:
cavity_resonator.feedback.append(loop)
Parameters
----------
ring : Synchrotron object
......@@ -212,6 +215,7 @@ class CavityResonator():
self.theta_gr = 0
self.Pg = 0
self.n_bin = int(n_bin)
self.feedback = []
def init_tracking(self, beam):
"""
......@@ -319,8 +323,11 @@ class CavityResonator():
# phasor decay to be at t=0 of the next bunch
self.phasor_decay(self.ring.T1, ref_frame="beam")
self.nturn += 1
# apply different kind of RF feedback
for fb in self.feedback:
fb.track(self)
self.nturn += 1
def init_phasor_track(self, beam):
"""
......@@ -895,3 +902,112 @@ class CavityResonator():
def deltaVRF(self, z, I0, F = 1, PHI = 0):
"""Return the generator voltage minus beam loading voltage taking into account form factor amplitude F and form factor phase PHI"""
return -1*self.Vg*(self.ring.k1*self.m)**2*np.cos(self.ring.k1*self.m*z + self.theta_g) - self.Vb(I0)*F*(self.ring.k1*self.m)**2*np.cos(self.ring.k1*self.m*z + self.psi - PHI)
class ProportionalLoop():
"""
Proportional feedback loop to control a CavityResonator amplitude and phase.
Feedback setpoints are cavity_resonator.Vc and cavity_resonator.theta.
The loop must be added to the CavityResonator object using:
cavity_resonator.feedback.append(loop)
Parameters
----------
ring : Synchrotron object
cavity_resonator : CavityResonator
The CavityResonator which is to be controlled.
gain_A : float
Amplitude (voltage) gain of the feedback.
gain_P : float
Phase gain of the feedback.
delay : int
Feedback delay in unit of turns.
"""
def __init__(self, ring, cavity_resonator, gain_A, gain_P, delay):
self.ring = ring
self.gain_A = gain_A
self.gain_P = gain_P
self.delay = int(delay)
self.volt_delay = np.ones(self.delay)*cavity_resonator.Vc
self.phase_delay = np.ones(self.delay)*cavity_resonator.theta
def track(self, cavity_resonator):
"""
Tracking method for the amplitude and phase loop.
Returns
-------
None.
"""
diff_A = self.volt_delay[-1] - cavity_resonator.Vc
diff_P = self.phase_delay[-1] - cavity_resonator.theta
cavity_resonator.Vg -= self.gain_A*diff_A
cavity_resonator.theta_g -= self.gain_P*diff_P
cavity_resonator.generator_phasor_record = np.ones(self.ring.h)*cavity_resonator.generator_phasor
self.volt_delay = np.roll(self.volt_delay, 1)
self.phase_delay = np.roll(self.phase_delay, 1)
self.volt_delay[0] = cavity_resonator.cavity_voltage
self.phase_delay[0] = cavity_resonator.cavity_phase
class TunerLoop():
"""
Cavity tuner loop used to control a CavityResonator tuning (psi or detune)
in order to keep the phase between cavity and generator current constant.
Only a proportional controller is assumed.
The loop must be added to the CavityResonator object using:
cavity_resonator.feedback.append(loop)
Parameters
----------
ring : Synchrotron object
cavity_resonator : CavityResonator
The CavityResonator which is to be controlled.
gain : float
Proportional gain of the tuner loop.
If not specified, 0.01 is used.
avering_period:
Period during which the phase difference is monitored and averaged.
Then the feedback correction is applied every avering_period turn.
Unit is turn number.
A value longer than one synchrotron period (1/fs) is recommended.
If not specified, 2-synchrotron period (2/fs) is used, although it is
too fast compared to the actual situation.
offset : float
Tuning offset in [rad].
"""
def __init__(self, ring, cavity_resonator, gain=0.01, avering_period=0,
offset=0):
self.ring = ring
if avering_period == 0:
fs = self.ring.synchrotron_tune(cavity_resonator.Vc)*self.ring.f1/self.ring.h
avering_period = 2/fs/self.ring.T0
self.Pgain = gain
self.offset = offset
self.avering_period = int(avering_period)
self.diff = 0
self.count = 0
def track(self, cavity_resonator):
"""
Tracking method for the tuner loop.
Returns
-------
None.
"""
if self.count == self.avering_period:
diff = self.diff/self.avering_period - self.offset
cavity_resonator.psi -= diff * self.Pgain
self.count = 0
self.diff = 0
else:
self.diff += cavity_resonator.cavity_phase - cavity_resonator.theta_g + cavity_resonator.psi
self.count += 1
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment