source: MML/trunk/at/simulator/element/user/gwig.c @ 4

Last change on this file since 4 was 4, checked in by zhangj, 11 years ago

Initial import--MML version from SOLEIL@2013

File size: 7.2 KB
Line 
1/*
2 *----------------------------------------------------------------------------
3 * Modification Log:
4 * -----------------
5 * .04  2003-04-29      YK Wu, Duke University, wu@fel.duke.edu
6 *                      using scientific notation for constants.
7 *                      Checked with TRACY pascal code.
8 *                      Computing differential pathlength only.
9 *
10 * .03  2003-04-28      YK Wu, Duke University, wu@fel.duke.edu
11 *                      Convert to C code and cross-checked with the pascal version;
12 *
13 * .02  2001-12-xx      Y. K. Wu, Duke University, wu@fel.duke.edu
14 *                      Implementing DA version of the wiggler integrator for Pascal.
15 *                      Gauge is disabled !!! (Dec. 4, 2001)
16 * 
17 * .01  2001-02-12      Y. K. Wu, LBNL
18 *                      Implementing a generic wiggler integrator
19 *                      for paraxial-ray Hamiltonian approximation.
20 *
21 *                   
22 *----------------------------------------------------------------------------
23 *  Accelerator Physics Group, Duke FEL Lab, www.fel.duke.edu 
24 */
25
26#ifndef  GWIG
27#include "gwig.h"
28#include <stdlib.h>
29#include <math.h>
30#include <stdio.h>
31#endif
32
33void GWigGauge(struct gwig *pWig, double *X, int flag);
34void GWigPass_2nd(struct gwig *pWig, double *X);
35void GWigPass_4th(struct gwig *pWig, double *X);
36void GWigMap_2nd(struct gwig *pWig, double *X, double dl);
37void GWigAx(struct gwig *pWig, double *Xvec, double *pax, double *paxpy);
38void GWigAy(struct gwig *pWig, double *Xvec, double *pay, double *paypx);
39double sinc(double x );
40void GWigGauge(struct gwig *pWig, double *X, int flag)
41
42{
43  double ax, ay, axpy, aypx;
44
45  GWigAx(pWig, X, &ax, &axpy);
46  GWigAy(pWig, X, &ay, &aypx);
47 
48  if (flag = Elem_Entrance) {
49    /* At the entrance of the wiggler */
50    X[1] = X[1] + ax;
51    X[3] = X[3] + ay;
52  } else if (flag = Elem_Exit) {
53    /* At the exit of the wiggler */
54    X[1] = X[1] - ax;
55    X[3] = X[3] - ay;
56  } else {
57    printf("  GWigGauge: Unknown flag = %i\n", flag);
58  }
59}
60
61
62void GWigPass_2nd(struct gwig *pWig, double *X) 
63{
64  int    i, Nstep;
65  double dl;
66 
67  Nstep = pWig->PN*(pWig->Nw);
68  dl    = pWig->Lw/(pWig->PN);
69
70  for (i = 1; i <= Nstep; i++) {
71    GWigMap_2nd(pWig, X, dl);
72  }
73}
74
75
76void GWigPass_4th(struct gwig *pWig, double *X)
77{
78
79  const double x1 = 1.3512071919596576340476878089715e0;
80  const double x0 =-1.7024143839193152680953756179429e0;
81
82  int    i, Nstep;
83  double dl, dl1, dl0;
84 
85  Nstep = pWig->PN*(pWig->Nw);
86  dl = pWig->Lw/(pWig->PN);
87
88  dl1 = x1*dl;
89  dl0 = x0*dl;
90
91  for (i = 1; i <= Nstep; i++ ) {
92    GWigMap_2nd(pWig, X, dl1);
93    GWigMap_2nd(pWig, X, dl0);
94    GWigMap_2nd(pWig, X, dl1);
95  }
96}
97
98
99void GWigMap_2nd(struct gwig *pWig, double *X, double dl) 
100{
101
102  double dld, dl2, dl2d;
103  double ax, ay, axpy, aypx;
104 
105  dld  = dl/(1.0e0 + X[4]);
106  dl2  = 0.5e0 * dl;
107  dl2d = dl2/(1.0e0 + X[4]);
108
109  /* Step1: increase a half step in z */
110  pWig->Zw = pWig->Zw + dl2;
111
112  /* Step2: a half drift in y */
113  GWigAy(pWig, X, &ay, &aypx);
114  X[1] = X[1] - aypx;
115  X[3] = X[3] - ay;
116
117  X[2] = X[2] + dl2d*X[3];
118  X[5] = X[5] + 0.5e0*dl2d*(X[3]*X[3])/(1.0e0+X[4]);
119   
120  GWigAy(pWig, X, &ay, &aypx);
121  X[1] = X[1] + aypx;
122  X[3] = X[3] + ay;
123
124  /* Step3: a full drift in x */
125  GWigAx(pWig, X, &ax, &axpy);
126  X[1] = X[1] - ax;
127  X[3] = X[3] - axpy;
128
129  X[0] = X[0] + dld*X[1];
130/* Full path length
131  X[5] = X[5] + dl + 0.5e0*dld*(X[1]*X[1])/(1.0e0+X[4]);
132*/
133  /* Differential path length only */
134  X[5] = X[5] + 0.5e0*dld*(X[1]*X[1])/(1.0e0+X[4]);
135   
136  GWigAx(pWig, X, &ax, &axpy);
137  X[1] = X[1] + ax;
138  X[3] = X[3] + axpy;
139
140  /* Step4: a half drift in y */
141  GWigAy(pWig, X, &ay, &aypx);
142  X[1] = X[1] - aypx;
143  X[3] = X[3] - ay;
144
145  X[2] = X[2] + dl2d*X[3];
146  X[5] = X[5] + 0.5e0*dl2d*(X[3]*X[3])/(1.0e0+X[4]);
147   
148  GWigAy(pWig, X, &ay, &aypx);
149  X[1] = X[1] + aypx;
150  X[3] = X[3] + ay;
151
152  /* Step5: increase a half step in z */
153  pWig->Zw = pWig->Zw + dl2;
154 
155}
156
157
158void GWigAx(struct gwig *pWig, double *Xvec, double *pax, double *paxpy) 
159{
160
161  int    i;
162  double x, y, z;
163  double kx, ky, kz, tz, kw;
164  double cx, sxkx, chx, shx;
165  double cy, sy, chy, shy, sz;
166  double gamma0, beta0;
167  double ax, axpy;
168
169  x = Xvec[0];
170  y = Xvec[2];
171  z = pWig->Zw;
172 
173  kw   = 2e0*PI/(pWig->Lw);
174  ax   = 0e0;
175  axpy = 0e0;
176
177  gamma0   = pWig->E0/XMC2;
178  beta0    = sqrt(1e0 - 1e0/(gamma0*gamma0));
179  pWig->Aw = (q_e/m_e/clight)/(2e0*PI) * (pWig->Lw) * (pWig->PB0);
180
181  /* Horizontal Wiggler: note that one potentially could have: kx=0 */
182  for (i = 0; i < pWig->NHharm; i++) {
183    pWig->HCw[i] = pWig->HCw_raw[i]*(pWig->Aw)/(gamma0*beta0);
184    kx = pWig->Hkx[i];
185    ky = pWig->Hky[i];
186    kz = pWig->Hkz[i];
187    tz = pWig->Htz[i];
188
189    cx  = cos(kx*x);
190    chy = cosh(ky * y);
191    sz  = sin(kz * z + tz);
192    ax  = ax + (pWig->HCw[i])*(kw/kz)*cx*chy*sz;
193
194    shy = sinh(ky * y);
195    if ( abs(kx/kw) > GWIG_EPS ) {
196      sxkx = sin(kx * x)/kx;   
197    } else {
198      sxkx = x*sinc(kx*x);
199    }
200
201    axpy = axpy + pWig->HCw[i]*(kw/kz)*ky*sxkx*shy*sz;
202  }
203
204
205  /* Vertical Wiggler: note that one potentially could have: ky=0 */
206  for (i = 0; i < pWig->NVharm; i++ ) {
207    pWig->VCw[i] = pWig->VCw_raw[i]*(pWig->Aw)/(gamma0*beta0);
208    kx = pWig->Vkx[i];
209    ky = pWig->Vky[i];
210    kz = pWig->Vkz[i];
211    tz = pWig->Vtz[i];
212
213    shx = sinh(kx * x);
214    sy  = sin(ky * y);
215    sz  = sin(kz * z + tz);
216    ax  = ax + pWig->VCw[i]*(kw/kz)*(ky/kx)*shx*sy*sz;
217
218    chx = cosh(kx * x);
219    cy  = cos(ky * y);
220    axpy = axpy + pWig->VCw[i]*(kw/kz)* pow(ky/kx,2) *chx*cy*sz;     
221  }
222
223  *pax   = ax;
224  *paxpy = axpy;
225}
226
227
228void GWigAy(struct gwig *pWig, double *Xvec, double *pay, double *paypx)
229{
230  int    i;
231  double x, y, z;
232  double kx, ky, kz, tz, kw;
233  double cx, sx, chx, shx;
234  double cy, syky, chy, shy, sz;
235  double gamma0, beta0;
236  double ay, aypx;
237
238  x = Xvec[0];
239  y = Xvec[2];
240  z = pWig->Zw;
241   
242  kw   = 2e0*PI/(pWig->Lw);
243  ay   = 0e0;
244  aypx = 0e0;
245
246  gamma0  = pWig->E0/XMC2;
247  beta0   = sqrt(1e0 - 1e0/(gamma0*gamma0));
248  pWig->Aw = (q_e/m_e/clight)/(2e0*PI) * (pWig->Lw) * (pWig->PB0);
249     
250  /* Horizontal Wiggler: note that one potentially could have: kx=0 */
251  for ( i = 0; i < pWig->NHharm; i++ ){
252    pWig->HCw[i] = (pWig->HCw_raw[i])*(pWig->Aw)/(gamma0*beta0);
253    kx = pWig->Hkx[i];
254    ky = pWig->Hky[i];
255    kz = pWig->Hkz[i];
256    tz = pWig->Htz[i];
257 
258    sx = sin(kx * x);
259    shy = sinh(ky * y);
260    sz  = sin(kz * z + tz);
261    ay  = ay + (pWig->HCw[i])*(kw/kz)*(kx/ky)*sx*shy*sz;
262 
263    cx  = cos(kx * x);
264    chy = cosh(ky * y);
265   
266    aypx = aypx + (pWig->HCw[i])*(kw/kz)*pow(kx/ky,2) * cx*chy*sz;
267  }
268
269  /* Vertical Wiggler: note that one potentially could have: ky=0 */
270  for (i = 0; i < pWig->NVharm; i++) {
271    pWig->VCw[i] = (pWig->VCw_raw[i])*(pWig->Aw)/(gamma0*beta0);       
272    kx = pWig->Vkx[i];
273    ky = pWig->Vky[i];
274    kz = pWig->Vkz[i];
275    tz = pWig->Vtz[i];
276
277    chx = cosh(kx * x);
278    cy  = cos(ky * y);
279    sz  = sin(kz * z + tz);
280    ay  = ay + (pWig->VCw[i])*(kw/kz)*chx*cy*sz;
281
282    shx = sinh(kx * x);
283    if (abs(ky/kw) > GWIG_EPS) {
284      syky  = sin(ky * y)/ky;
285    } else {
286      syky = y * sinc(ky * y);
287      aypx = aypx + (pWig->VCw[i])*(kw/kz)* kx*shx*syky*sz;
288    }
289  }
290 
291  *pay = ay;
292  *paypx = aypx;
293}
294
295
296double sinc(double x)
297{
298  double x2, result;
299/* Expand sinc(x) = sin(x)/x to x^8 */
300  x2 = x*x;
301  result = 1e0 - x2/6e0*(1e0 - x2/20e0 *(1e0 - x2/42e0*(1e0-x2/72e0) ) );
302  return result;
303}
304
Note: See TracBrowser for help on using the repository browser.