1010from PyHEADTAIL .trackers .simple_long_tracking import LinearMap , RFSystems
1111
1212
13- class synchrotron (Element ):
13+ class Synchrotron (Element ):
1414
1515 def __init__ (self , * args , ** kwargs ):
1616
@@ -77,6 +77,14 @@ def Q_s(self):
7777 return np .sqrt ( e * np .abs (self .eta )* (self .h1 * self .V1 + self .h2 * self .V2 )
7878 / (2 * np .pi * self .p0 * self .beta * c ) )
7979
80+ @property
81+ def beta_z (self ):
82+ return np .abs (self .eta )* self .circumference / 2. / np .pi / self .Q_s
83+
84+ @property
85+ def R (self ):
86+ return self .circumference / (2 * np .pi )
87+
8088 def track (self , bunch , verbose = False ):
8189 for m in self .one_turn_map :
8290 if verbose :
@@ -85,11 +93,8 @@ def track(self, bunch, verbose = False):
8593 m .track (bunch )
8694
8795 def create_transverse_map (self ):
88- try :
89- chromaticity = Chromaticity (self .Qp_x , self .Qp_y )
90- except TypeError as error :
91- chromaticity = Chromaticity ([self .Qp_x ], [self .Qp_y ])
92- self .warns ('Converted to new interface - takes chromaticities as lists.' )
96+
97+ chromaticity = Chromaticity (self .Qp_x , self .Qp_y )
9398 amplitude_detuning = AmplitudeDetuning (self .app_x , self .app_y , self .app_xy )
9499
95100 self .transverse_map = TransverseMap (
@@ -102,17 +107,19 @@ def create_transverse_map(self):
102107 def create_longitudinal_map (self ):
103108
104109 if self .longitudinal_focusing == 'linear' :
105- self .longitudinal_map = LinearMap ([self .alpha ], self .circumference , self .Q_s )
110+ self .longitudinal_map = LinearMap ([self .alpha ], self .circumference ,
111+ self .Q_s , D_x = self .D_x [0 ], D_y = self .D_y [0 ])
106112 elif self .longitudinal_focusing == 'non-linear' :
107113 self .longitudinal_map = RFSystems (self .circumference , [self .h1 , self .h2 ], [self .V1 , self .V2 ], [self .dphi1 , self .dphi2 ],
108- [self .alpha ], self .gamma , self .p_increment )
114+ [self .alpha ], self .gamma , self .p_increment ,
115+ D_x = self .D_x [0 ], D_y = self .D_y [0 ])
109116 else :
110117 raise ValueError ('ERROR: unknown focusing' , self .longitudinal_focusing )
111118
112119 def generate_6D_Gaussian_bunch (self , n_macroparticles , intensity , epsn_x , epsn_y , sigma_z ):
113120 '''
114121 Generates a 6D Gaussian distribution of particles which is transversely
115- matched to the synchrotron . Longitudinally, the distribution is matched
122+ matched to the Synchrotron . Longitudinally, the distribution is matched
116123 only in terms of linear focusing. For a non-linear bucket, the Gaussian
117124 distribution is cut along the separatrix (with some margin) and will
118125 gradually filament into the bucket. This will change the specified bunch
@@ -121,42 +128,50 @@ def generate_6D_Gaussian_bunch(self, n_macroparticles, intensity, epsn_x, epsn_y
121128 if self .longitudinal_focusing == 'linear' :
122129 check_inside_bucket = lambda z ,dp : np .array (len (z )* [True ])
123130 elif self .longitudinal_focusing == 'non-linear' :
124- check_inside_bucket = self .longitudinal_map .get_bucket (self .gamma ).make_is_accepted (margin = 0.05 )
131+ check_inside_bucket = self .longitudinal_map .get_bucket (gamma = self .gamma ).make_is_accepted (margin = 0.05 )
125132 else :
126133 raise ValueError ('Longitudinal_focusing not recognized!!!' )
127134
128- beta_z = self .eta * self .circumference / 2. / np .pi / self .Q_s
135+ beta_z = np . abs ( self .eta ) * self .circumference / 2. / np .pi / self .Q_s
129136 sigma_dp = sigma_z / beta_z
130137
131138 bunch = CutRFBucket6D (macroparticlenumber = n_macroparticles , intensity = intensity , charge = self .charge , mass = self .mass ,
132- circumference = self .circumference , gamma_reference = self .gamma ,
139+ circumference = self .circumference , gamma = self .gamma ,
133140 transverse_map = self .transverse_map , epsn_x = epsn_x , epsn_y = epsn_y ,
134141 sigma_z = sigma_z , sigma_dp = sigma_dp ,
135142 is_accepted = check_inside_bucket ).generate ()
136143
137144 if self .D_x [0 ] != 0 :
138145 self .warns (('Correcting for (horizontal) dispersion {:g} m at first segment!\n ' ).format (self .D_x [0 ]))
139146 bunch .x += bunch .dp * self .D_x [0 ]
147+ if self .D_y [0 ] != 0 :
148+ self .warns (('Correcting for (vertical) dispersion {:g} m at first segment!\n ' ).format (self .D_y [0 ]))
149+ bunch .y += bunch .dp * self .D_y [0 ]
150+
140151
141152 return bunch
142153
143- def generate_6D_Gaussian_bunch_matched (self , n_macroparticles , intensity , epsn_x , epsn_y , sigma_z ):
154+ def generate_6D_Gaussian_bunch_matched (self , n_macroparticles , intensity , epsn_x , epsn_y , sigma_z = None , epsn_z = None ):
144155 '''
145156 Generates a 6D Gaussian distribution of particles which is transversely
146157 as well as longitudinally matched. The distribution is found iteratively
147158 to exactly yield the given bunch length while at the same time being
148159 stationary in the non-linear bucket. Thus, the bunch length should amount
149160 to the one specificed and should not change significantly during the
150- synchrotron motion.
161+ Synchrotron motion.
151162 '''
152163 bunch = MatchRFBucket6D (macroparticlenumber = n_macroparticles , intensity = intensity ,
153164 charge = self .charge , mass = self .mass ,
154- circumference = self .circumference , gamma_reference = self .gamma ,
155- epsn_x = epsn_x , epsn_y = epsn_y , sigma_z = sigma_z ,
165+ circumference = self .circumference , gamma = self .gamma ,
166+ epsn_x = epsn_x , epsn_y = epsn_y , epsn_z = epsn_z , sigma_z = sigma_z ,
156167 transverse_map = self .transverse_map ,
157- rf_bucket = self .longitudinal_map .get_bucket (self .gamma )).generate ()
168+ rf_bucket = self .longitudinal_map .get_bucket (gamma = self .gamma )).generate ()
158169 if self .D_x [0 ] != 0 :
159170 self .warns (('Correcting for (horizontal) dispersion {:g} m at first segment!\n ' ).format (self .D_x [0 ]))
160171 bunch .x += bunch .dp * self .D_x [0 ]
172+ if self .D_y [0 ] != 0 :
173+ self .warns (('Correcting for (vertical) dispersion {:g} m at first segment!\n ' ).format (self .D_y [0 ]))
174+ bunch .y += bunch .dp * self .D_y [0 ]
175+
161176
162177 return bunch
0 commit comments