1
+ /* CrabCavityPass.c
2
+ for Accelerator Toolbox
3
+ Xiaobiao Huang, created 11/1/2016
4
+ */
5
+
6
+ #include "mex.h"
7
+ #include "elempass.h"
8
+ #include <math.h>
9
+ #define TWOPI 6.28318530717959
10
+ #define C0 2.99792458e8
11
+ #include <omp.h>
12
+ #include <float.h>
13
+ /*#define isnan(x) ((x) != (x))
14
+ #define isinf(x) (isnan(x-x))
15
+ */
16
+ double grandn ()
17
+ {
18
+ const double epsilon = DBL_EPSILON ;
19
+
20
+ static double z0 , z1 ;
21
+ static bool generate ;
22
+ generate = !generate ;
23
+
24
+ if (!generate )
25
+ return z1 ;
26
+
27
+ double u1 , u2 ;
28
+ do
29
+ {
30
+ u1 = rand () * (1.0 / RAND_MAX );
31
+ u2 = rand () * (1.0 / RAND_MAX );
32
+ }
33
+ while ( u1 <= epsilon );
34
+
35
+ z0 = sqrt (-2.0 * log (u1 )) * cos (TWOPI * u2 );
36
+ z1 = sqrt (-2.0 * log (u1 )) * sin (TWOPI * u2 );
37
+ return z0 ;
38
+
39
+ }
40
+ /*CrabCavityPass(r_in, le, vx/energy,vy/energy, freq, phi,sigphi,sigvv, n);*/
41
+ void CrabCavityPass (double * r_in , double le , double nvx , double nvy , double freq , double phi , double sigphi , double sigvv , int num_particles )
42
+ /* le - physical length
43
+ nv - peak voltage (V) normalized to the design enegy (eV)
44
+ r is a 6-by-N matrix of initial conditions reshaped into
45
+ 1-d array of 6*N elements
46
+ */
47
+ { int c , c6 ;
48
+ double halflength , p_norm , NormL ;
49
+ double nvxa ,nvya , ddpp ,omega_t ,k ;
50
+
51
+ /* move the random number outside of the for loop, 11/29/2017 */
52
+ double rndph , rndx , rndy ;
53
+ rndph = grandn ();
54
+ rndx = grandn ();
55
+ rndy = grandn ();
56
+
57
+ k = TWOPI * freq /C0 ;
58
+ if (le == 0 )
59
+ {
60
+
61
+ for (c = 0 ;c < num_particles ;c ++ )
62
+ { c6 = c * 6 ;
63
+ if (!mxIsNaN (r_in [c6 ]))
64
+ {
65
+ if (sigphi > 0 )
66
+ omega_t = k * r_in [c6 + 5 ] + phi + sigphi * rndph ;
67
+ else
68
+ omega_t = k * r_in [c6 + 5 ] + phi ;
69
+ if (sigvv > 0 )
70
+ {
71
+ nvxa = nvx * (1.0 + sigvv * rndx );
72
+ nvya = nvy * (1.0 + sigvv * rndy );
73
+ }
74
+ else
75
+ {
76
+ nvxa = nvx ;
77
+ nvya = nvy ;
78
+ }
79
+ ddpp = - (nvya * r_in [c6 + 2 ]+ nvxa * r_in [c6 + 0 ])* k * cos (omega_t )/(1 + r_in [c6 + 4 ]);
80
+
81
+ r_in [c6 + 1 ] += nvxa * sin (omega_t );
82
+ r_in [c6 + 3 ] += nvya * sin (omega_t );
83
+ r_in [c6 + 4 ] += ddpp ;
84
+ }
85
+ }
86
+ }
87
+ else
88
+ { halflength = le /2 ;
89
+
90
+
91
+ for (c = 0 ;c < num_particles ;c ++ )
92
+ { c6 = c * 6 ;
93
+ /*if(!mxIsNaN(r_in[c6])) */
94
+ if (!isnan (r_in [c6 ]))
95
+ { p_norm = 1 /(1 + r_in [c6 + 4 ]);
96
+ NormL = halflength * p_norm ;
97
+ /* Propagate through a drift equal to half cavity length */
98
+ r_in [c6 + 0 ]+= NormL * r_in [c6 + 1 ];
99
+ r_in [c6 + 2 ]+= NormL * r_in [c6 + 3 ];
100
+ r_in [c6 + 5 ]+= NormL * p_norm * (r_in [c6 + 1 ]* r_in [c6 + 1 ]+ r_in [c6 + 3 ]* r_in [c6 + 3 ])/2 ;
101
+
102
+ /* Apply kicks */
103
+ if (sigphi > 0 )
104
+ omega_t = k * r_in [c6 + 5 ] + phi + sigphi * rndph ;
105
+ else
106
+ omega_t = k * r_in [c6 + 5 ] + phi ;
107
+ if (sigvv > 0 )
108
+ {
109
+ nvxa = nvx * (1.0 + sigvv * rndx );
110
+ nvya = nvy * (1.0 + sigvv * rndy );
111
+ }
112
+ else
113
+ {
114
+ nvxa = nvx ;
115
+ nvya = nvy ;
116
+ }
117
+ ddpp = - (nvya * r_in [c6 + 2 ]+ nvxa * r_in [c6 + 0 ])* k * cos (omega_t )/(1 + r_in [c6 + 4 ]);
118
+
119
+ r_in [c6 + 1 ] += nvxa * sin (omega_t );
120
+ r_in [c6 + 3 ] += nvya * sin (omega_t );
121
+ r_in [c6 + 4 ] += ddpp ;
122
+
123
+
124
+ p_norm = 1 /(1 + r_in [c6 + 4 ]);
125
+ NormL = halflength * p_norm ;
126
+ /* Propagate through a drift equal to half cavity length */
127
+ r_in [c6 + 0 ]+= NormL * r_in [c6 + 1 ];
128
+ r_in [c6 + 2 ]+= NormL * r_in [c6 + 3 ];
129
+ r_in [c6 + 5 ]+= NormL * p_norm * (r_in [c6 + 1 ]* r_in [c6 + 1 ]+ r_in [c6 + 3 ]* r_in [c6 + 3 ])/2 ;
130
+ }
131
+ }
132
+ }
133
+
134
+ }
135
+
136
+
137
+ ExportMode int * passFunction (const mxArray * ElemData ,int * FieldNumbers ,
138
+ double * r_in , int num_particles , int mode )
139
+
140
+
141
+ #define NUM_FIELDS_2_REMEMBER 5
142
+
143
+ { double le , * volt , freq , energy , phi , vx , vy ,sigphi , sigvv ;
144
+ int * returnptr ;
145
+ int * NewFieldNumbers , fnum ;
146
+
147
+
148
+ switch (mode )
149
+ { case NO_LOCAL_COPY : /* Obsolete in AT1.3 */
150
+ {
151
+
152
+ } break ;
153
+
154
+ case MAKE_LOCAL_COPY : /* Find field numbers first
155
+ Save a list of field number in an array
156
+ and make returnptr point to that array
157
+ */
158
+ {
159
+ NewFieldNumbers = (int * )mxCalloc (NUM_FIELDS_2_REMEMBER ,sizeof (int ));
160
+
161
+ fnum = mxGetFieldNumber (ElemData ,"Length" );
162
+ if (fnum < 0 )
163
+ mexErrMsgTxt ("Required field 'Length' was not found in the element data structure" );
164
+ NewFieldNumbers [0 ] = fnum ;
165
+
166
+ fnum = mxGetFieldNumber (ElemData ,"Voltages" );
167
+ if (fnum < 0 )
168
+ mexErrMsgTxt ("Required field 'Voltages' was not found in the element data structure" );
169
+ NewFieldNumbers [1 ] = fnum ;
170
+
171
+ fnum = mxGetFieldNumber (ElemData ,"Energy" );
172
+ if (fnum < 0 )
173
+ mexErrMsgTxt ("Required field 'Energy' was not found in the element data structure" );
174
+ NewFieldNumbers [2 ] = fnum ;
175
+
176
+
177
+ fnum = mxGetFieldNumber (ElemData ,"Frequency" );
178
+ if (fnum < 0 )
179
+ mexErrMsgTxt ("Required field 'Frequency' was not found in the element data structure" );
180
+ NewFieldNumbers [3 ] = fnum ;
181
+
182
+ /* Optional field TimeLag */
183
+ fnum = mxGetFieldNumber (ElemData ,"Phase" );
184
+ NewFieldNumbers [4 ] = fnum ;
185
+ if (fnum < 0 )
186
+ phi = 0 ;
187
+ else
188
+ phi = mxGetScalar (mxGetFieldByNumber (ElemData ,0 ,fnum ));
189
+
190
+ fnum = mxGetFieldNumber (ElemData ,"SigPhi" );
191
+ NewFieldNumbers [5 ] = fnum ;
192
+ if (fnum < 0 )
193
+ sigphi = 0 ;
194
+ else
195
+ sigphi = mxGetScalar (mxGetFieldByNumber (ElemData ,0 ,fnum ));
196
+
197
+ fnum = mxGetFieldNumber (ElemData ,"SigVV" );
198
+ NewFieldNumbers [6 ] = fnum ;
199
+ if (fnum < 0 )
200
+ sigvv = 0 ;
201
+ else
202
+ sigvv = mxGetScalar (mxGetFieldByNumber (ElemData ,0 ,fnum ));
203
+
204
+
205
+ le = mxGetScalar (mxGetFieldByNumber (ElemData ,0 ,NewFieldNumbers [0 ]));
206
+ volt = mxGetPr (mxGetFieldByNumber (ElemData ,0 ,NewFieldNumbers [1 ]));
207
+ vx = volt [0 ];
208
+ vy = volt [1 ];
209
+ energy = mxGetScalar (mxGetFieldByNumber (ElemData ,0 ,NewFieldNumbers [2 ]));
210
+ freq = mxGetScalar (mxGetFieldByNumber (ElemData ,0 ,NewFieldNumbers [3 ]));
211
+
212
+ returnptr = NewFieldNumbers ;
213
+ } break ;
214
+
215
+ case USE_LOCAL_COPY : /* Get fields from MATLAB using field numbers
216
+ The second argument ponter to the array of field
217
+ numbers is previously created with
218
+ QuadLinPass( ..., MAKE_LOCAL_COPY)
219
+ */
220
+
221
+ { le = mxGetScalar (mxGetFieldByNumber (ElemData ,0 ,FieldNumbers [0 ]));
222
+ volt = mxGetPr (mxGetFieldByNumber (ElemData ,0 ,FieldNumbers [1 ]));
223
+ vx = volt [0 ];
224
+ vy = volt [1 ];
225
+ energy = mxGetScalar (mxGetFieldByNumber (ElemData ,0 ,FieldNumbers [2 ]));
226
+ freq = mxGetScalar (mxGetFieldByNumber (ElemData ,0 ,FieldNumbers [3 ]));
227
+ /* Optional field TimeLag */
228
+ if (FieldNumbers [4 ]< 0 )
229
+ phi = 0 ;
230
+ else
231
+ phi = mxGetScalar (mxGetFieldByNumber (ElemData ,0 ,FieldNumbers [4 ]));
232
+
233
+ if (FieldNumbers [5 ]< 0 )
234
+ sigphi = 0 ;
235
+ else
236
+ sigphi = mxGetScalar (mxGetFieldByNumber (ElemData ,0 ,FieldNumbers [5 ]));
237
+
238
+ if (FieldNumbers [6 ]< 0 )
239
+ sigvv = 0 ;
240
+ else
241
+ sigvv = mxGetScalar (mxGetFieldByNumber (ElemData ,0 ,FieldNumbers [6 ]));
242
+
243
+ returnptr = FieldNumbers ;
244
+ } break ;
245
+
246
+ default :
247
+ { mexErrMsgTxt ("No match found for calling mode in function CavityPass\n" );
248
+ }
249
+ }
250
+
251
+
252
+ CrabCavityPass (r_in , le , vx /energy ,vy /energy , freq , phi ,sigphi ,sigvv , num_particles );
253
+ return (returnptr );
254
+ }
255
+
256
+
257
+
258
+ void mexFunction ( int nlhs , mxArray * plhs [], int nrhs , const mxArray * prhs [])
259
+ { double * volt ,freq , energy ,vx ,vy ;
260
+ int m ,n ;
261
+ double * r_in , le , phi , sigphi , sigvv ;
262
+ mxArray * tmpmxptr ;
263
+
264
+ if (nrhs )
265
+ {
266
+
267
+ /* ALLOCATE memory for the output array of the same size as the input */
268
+ m = mxGetM (prhs [1 ]);
269
+ n = mxGetN (prhs [1 ]);
270
+ if (m != 6 )
271
+ mexErrMsgTxt ("Second argument must be a 6 x N matrix" );
272
+
273
+
274
+ tmpmxptr = mxGetField (prhs [0 ],0 ,"Length" );
275
+ if (tmpmxptr )
276
+ le = mxGetScalar (tmpmxptr );
277
+ else
278
+ mexErrMsgTxt ("Required field 'Length' was not found in the element data structure" );
279
+
280
+ tmpmxptr = mxGetField (prhs [0 ],0 ,"Phase" );
281
+ if (tmpmxptr )
282
+ phi = mxGetScalar (tmpmxptr );
283
+ else
284
+ phi = 0 ;
285
+
286
+ tmpmxptr = mxGetField (prhs [0 ],0 ,"SigPhi" );
287
+ if (tmpmxptr )
288
+ sigphi = mxGetScalar (tmpmxptr );
289
+ else
290
+ sigphi = 0 ;
291
+
292
+ tmpmxptr = mxGetField (prhs [0 ],0 ,"SigVV" );
293
+ if (tmpmxptr )
294
+ sigvv = mxGetScalar (tmpmxptr );
295
+ else
296
+ sigvv = 0 ;
297
+
298
+ tmpmxptr = mxGetField (prhs [0 ],0 ,"Voltages" );
299
+ if (tmpmxptr )
300
+ {
301
+ volt = mxGetPr (tmpmxptr );/* two numbers in [Vx, Vy] */
302
+ vx = volt [0 ];
303
+ vy = volt [1 ];
304
+ }
305
+ else
306
+ mexErrMsgTxt ("Required field 'Voltages' was not found in the element data structure" );
307
+
308
+ tmpmxptr = mxGetField (prhs [0 ],0 ,"Energy" );
309
+ if (tmpmxptr )
310
+ energy = mxGetScalar (tmpmxptr );
311
+ else
312
+ mexErrMsgTxt ("Required field 'Energy' was not found in the element data structure" );
313
+
314
+ tmpmxptr = mxGetField (prhs [0 ],0 ,"Frequency" );
315
+ if (tmpmxptr )
316
+ freq = mxGetScalar (tmpmxptr );
317
+ else
318
+ mexErrMsgTxt ("Required field 'Frequency' was not found in the element data structure" );
319
+
320
+ plhs [0 ] = mxDuplicateArray (prhs [1 ]);
321
+ r_in = mxGetPr (plhs [0 ]);
322
+ CrabCavityPass (r_in , le , vx /energy ,vy /energy , freq , phi ,sigphi ,sigvv , n );
323
+ }
324
+ else
325
+ { /* return list of required fields */
326
+ plhs [0 ] = mxCreateCellMatrix (4 ,1 );
327
+ mxSetCell (plhs [0 ],0 ,mxCreateString ("Length" ));
328
+ mxSetCell (plhs [0 ],1 ,mxCreateString ("Voltages" ));
329
+ mxSetCell (plhs [0 ],2 ,mxCreateString ("Energy" ));
330
+ mxSetCell (plhs [0 ],3 ,mxCreateString ("Frequency" ));
331
+ if (nlhs > 1 ) /* optional fields */
332
+ { plhs [1 ] = mxCreateCellMatrix (3 ,1 );
333
+ mxSetCell (plhs [1 ],0 ,mxCreateString ("Phase" ));
334
+ mxSetCell (plhs [1 ],1 ,mxCreateString ("SigPhi" ));
335
+ mxSetCell (plhs [1 ],2 ,mxCreateString ("SigVV" ));
336
+ }
337
+ }
338
+
339
+ }
0 commit comments