Skip to content

Commit dc163e0

Browse files
committed
add crab cavity passmethod
1 parent c8c5844 commit dc163e0

File tree

1 file changed

+339
-0
lines changed

1 file changed

+339
-0
lines changed

atintegrators/CrabCavityPass.c

+339
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
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

Comments
 (0)