source: ZHANGProjects/ICOSIM/CPP/trunk/source/MagneticCollimator.cc @ 2

Last change on this file since 2 was 2, checked in by zhangj, 10 years ago

Initial import

File size: 14.7 KB
Line 
1#include <iostream>
2#include <vector>
3#include <string>
4#include <cmath>
5#include "MagneticCollimator.h"
6using namespace std;
7
8
9MagneticCollimator::MagneticCollimator(const double& ALFX, const double& ALFY, const double& APER_1, const double& APER_2, const double& APER_3, const double& APER_4, const string& APERTYPE, const double& BETX, const double& BETY, const double& DPX, const double& DPY, const double& DX, const double& DY, const string& KEYWORD, const double& L, const double& MUX, const double& MUY, const string& NAME, const double& PTC, const double& PXC, const double& PYC, const double& S, const double& TC, const double& XC, const double& YC, const double& K0L, const double& K0SL, const double& K1L, const double& K1SL, const double& K2L, const double& K2SL, const string& PARENT, const string& meth, const long double& hgap, const long double& hgap2, const double& collang, const long double& pdepth, const long double& pdepth2, const double& tcang, const double& nsig, const double& Bmax, const double& thicknessMagneticField, const double& energyPerIon, const double& mass)
10    : Collimator(ALFX, ALFY, APER_1, APER_2, APER_3, APER_4, APERTYPE, BETX, BETY, DPX, DPY, DX, DY, KEYWORD, L, MUX, MUY, NAME, PTC, PXC, PYC, S, TC, XC, YC, K0L, K0SL, K1L, K1SL, K2L, K2SL, PARENT, meth, hgap, hgap2, collang, pdepth, pdepth2, tcang, nsig, Bmax, thicknessMagneticField, energyPerIon, mass)
11{};
12
13MagneticCollimator:: MagneticCollimator(Element elt, const double& tcang, const double& nsig, const string& meth, const string& material)
14    : Collimator(elt, tcang, nsig, meth, material)
15{
16};
17
18
19MagneticCollimator::MagneticCollimator(const MagneticCollimator& obj)
20    : Collimator(obj)
21{};
22
23void MagneticCollimator::affiche()
24{
25
26    cout << "Magnetic collimator: " << endl;
27
28    this->Collimator::affiche();
29};
30
31double MagneticCollimator::Bcalc(const double& x, const double& y, const double& z, const double& w)
32{
33
34    double percent, n;
35
36    int nn;
37
38    percent = 0.1;
39    double a(log(percent));
40    double b(log((y - z) / y));
41    n = a / b;
42    nn = (int)floor(n);
43    if ((nn % 2) == 1) {
44        n = floor(n);
45    } else {
46        n = ceil(n);
47    }
48
49    return (w * pow((x / y), n)); //in Tesla
50};
51
52void MagneticCollimator::collipass(Particle& p1, double& dpopeff, const double& scaleorbit, const double& R11X, const double& R12X, const double& R21X, const double& R22X, const double& R11Y, const double& R12Y, const double& R21Y, const double& R22Y, const double& dx1, const double& dpx1, const double& dy1, const double& dpy1, const double& delta_s, const double& Apr, const double& Zpr, const double& betgam)
53{
54
55    double sa, ca;
56
57    sa = sin(this->tcang);
58    ca = cos(this->tcang);
59
60
61    //account for positioning of collimators on orbit:
62    p1.coordonnees[0][0] = p1.coordonnees[0][0] - scaleorbit * this->XC;
63    p1.coordonnees[0][2] = p1.coordonnees[0][2] - scaleorbit * this->YC;
64
65    double xl, xsl, pdepthStart, pdepthHalf, pdepthEnd, alf, lcolleff, z, B, BLength;
66
67
68    //Calculate effective x and x' in the rotated collimator coordinate system
69    //transforming to rotated system: [xl; yl]=[cos sin; -sin cos][x;y]
70    //transforming back: [x;y]=[cos -sin; sin cos][xl;yl]
71
72    xl = p1.coordonnees[0][0] * ca + p1.coordonnees[0][2] * sa;
73    xsl = p1.coordonnees[0][1] * ca + p1.coordonnees[0][3] * sa;
74    pdepthStart = abs(xl) - this->hgap; //the depth in the collimator at the beginning of the collimator
75    pdepthHalf = abs(xl + this->L * xsl / 2) - (this->hgap2 + this->hgap) / 2; //depth in collimator at the middle of the collimator
76    pdepthEnd = abs(xl + this->L * xsl) - this->hgap2; //depth in the collimator at the end of the collimator
77
78    if (pdepthStart > 0) { //particle impacting on the front end of the collimator
79
80        this->first.push_back(2);
81
82
83        //impact angle on collimator
84        if (xl < 0) {
85            alf = this->phi + xsl;
86        } else {
87            alf = this->phi - xsl;
88        }
89
90        lcolleff = pdepthStart / alf; //alpha is negative for particles hitting on the face
91
92        if ((lcolleff > this->L) || (lcolleff < 0)) {
93            lcolleff = this->L;
94        }
95
96        //Apply a thin collimator at the entrance
97
98        collipassInteraction(p1, Apr, Zpr, betgam, lcolleff);
99
100        p1.coordonnees[0][0] = p1.coordonnees[1][0];
101        p1.coordonnees[0][1] = p1.coordonnees[1][1];
102        p1.coordonnees[0][2] = p1.coordonnees[1][2];
103        p1.coordonnees[0][3] = p1.coordonnees[1][3];
104        p1.coordonnees[0][4] = p1.coordonnees[1][4];
105
106        dpopeff = (p1.Ap0 * Zpr) / (p1.Zp0 * Apr) * (1 + p1.coordonnees[0][4]) - 1;
107
108        xsl = p1.coordonnees[0][1] * ca + p1.coordonnees[0][3] * sa;
109        xl = p1.coordonnees[0][0] * ca + p1.coordonnees[0][2] * sa;
110        pdepthEnd = abs(xl + this->L * xsl) - this->hgap2;
111        p1.coordonnees[0][0] = p1.coordonnees[0][0] + scaleorbit * this->XC;
112        p1.coordonnees[0][2] = p1.coordonnees[0][2] + scaleorbit * this->YC;
113
114        if ((p1.Ap0 == 0) || (pdepthEnd >= 0)) { //particle lost, or stays inside the collimator's 2nd half
115            p1.coordonnees[1][0] = p1.coordonnees[0][0] + p1.coordonnees[0][1] * delta_s;
116            p1.coordonnees[1][2] = p1.coordonnees[0][2] + p1.coordonnees[0][3] * delta_s;
117            p1.coordonnees[1][1] = p1.coordonnees[0][1];
118            p1.coordonnees[1][3] = p1.coordonnees[0][3];
119            this->second.push_back(-1);
120            return;
121        } else {//particle gets out of the collimator
122            if (xl < 0) {
123                alf = this->phi + xsl;
124            } else {
125                alf = this->phi - xsl;
126            }
127            z = pdepthStart / alf; //where particle comes out of the collimator
128            z = (z + this->L) / 2; //midpoint between where particle gets out and the end of the collimator
129            p1.coordonnees[1][0] = p1.coordonnees[0][0] + p1.coordonnees[0][1] * z;
130            p1.coordonnees[1][2] = p1.coordonnees[0][2] + p1.coordonnees[0][3] * z;
131            p1.coordonnees[1][1] = p1.coordonnees[0][1];
132            p1.coordonnees[1][3] = p1.coordonnees[0][3];
133
134            if (xl > 0) {
135                B = this->Bmax;
136            } else {
137                B = -this->Bmax;
138            }
139            BLength = this->L - pdepthStart / alf;
140        }
141
142    }//end if(pdepthStart > 0)
143
144    else if (pdepthHalf >= 0) { //particle enters the collimator in the first half
145
146        double sImp, xint, yint, xsint, ysint;
147
148        this->first.push_back(1);
149
150        //Particles impacting along the jaw (outside the gap at the end but inside in beginning)
151
152        if ((xl + this->L * xsl / 2) < 0) {
153            alf = - this->phi - xsl;
154        } else {
155            alf = -this->phi + xsl;
156        }
157
158        //impact angle on collimator; the sign determines which jaw is hit and therefore if the jaw angle should be added or subtracted.
159
160        lcolleff = pdepthEnd / alf; //effective length of orbit inside collimator
161
162        if ((lcolleff > this->L) || (lcolleff < 0)) {
163            lcolleff = this->L;
164        }
165        sImp = -pdepthStart / alf; //distance from beginning of collimator to impact
166
167
168        //Move particle to this point. Drift => angles don't change, x,y change as straight line
169        xint = p1.coordonnees[0][0] + p1.coordonnees[0][1] * sImp;
170        yint = p1.coordonnees[0][2] + p1.coordonnees[0][3] * sImp;
171        xsint = p1.coordonnees[0][1];
172        ysint = p1.coordonnees[0][3];
173
174        double p1xtemp, p1ytemp, p1x0temp, p1xs0temp, p1y0temp, p1ys0temp;;
175
176        p1xtemp = p1.coordonnees[0][0];
177        p1ytemp = p1.coordonnees[0][2];
178        p1x0temp = p1.coordonnees[0][0];
179        p1xs0temp = p1.coordonnees[0][1];
180        p1y0temp = p1.coordonnees[0][2];
181        p1ys0temp = p1.coordonnees[0][3];
182
183        p1.coordonnees[0][0] = xint;
184        p1.coordonnees[0][1] = xsint;
185        p1.coordonnees[0][2] = yint;
186        p1.coordonnees[0][3] = ysint;
187
188        //Apply thin collimator at impact position
189
190        collipassInteraction(p1, Apr, Zpr, betgam, lcolleff);
191
192        xint = p1.coordonnees[1][0];
193        xsint = p1.coordonnees[1][1];
194        yint = p1.coordonnees[1][2];
195        ysint = p1.coordonnees[1][3];
196        p1.coordonnees[0][4] = p1.coordonnees[1][4];
197
198        dpopeff = (p1.Ap0 * Zpr) / (p1.Zp0 * Apr) * (1 + p1.coordonnees[0][4]) - 1;
199
200        xl = (xint + xsint * (this->L - sImp)) * ca + (yint + ysint * (this->L - sImp)) * sa;
201        pdepthEnd = abs(xl) - this->hgap2;
202
203        xint = xint + scaleorbit * this->XC; //coordinates not relative to reference particle/middle point between collimators
204        yint = yint + scaleorbit * this->YC;
205        p1.coordonnees[0][0] = p1x0temp + scaleorbit * this->XC;
206        p1.coordonnees[0][2] = p1y0temp + scaleorbit * this->YC;
207        p1.coordonnees[0][1] = p1xs0temp;
208        p1.coordonnees[0][3] = p1ys0temp;
209
210        if ((pdepthEnd >= 0) || (p1.Ap0 == 0)) {
211            p1.coordonnees[1][0] = xint + xsint * (delta_s - sImp);
212            p1.coordonnees[1][2] = yint + ysint * (delta_s - sImp);
213            p1.coordonnees[1][1] = xsint;
214            p1.coordonnees[1][3] = ysint;
215            this->second.push_back(-1);
216            return;
217        } else {
218
219            //Move particle as defined in MADX.
220            //Drift => angles don't change, x,y change as straight line
221            p1.coordonnees[1][0] = xint + xsint * (this->L - sImp) / 2;
222            p1.coordonnees[1][2] = yint + ysint * (this->L - sImp) / 2;
223            p1.coordonnees[1][1] = xsint;
224            p1.coordonnees[1][3] = ysint;
225
226            if (xl > 0) {
227                B = this->Bmax;
228            } else {
229                B = -this->Bmax;
230            }
231            BLength = this->L;
232            z = (this->L + sImp) / 2;
233        }
234
235    }//end if(pdepthHalf >=0)
236    else {//particles that don't hit the first half of the collimator: drift to the middle of the collimator
237
238        this->first.push_back(0);
239        p1.coordonnees[0][0] = p1.coordonnees[0][0] + scaleorbit * this->XC;
240        p1.coordonnees[0][2] = p1.coordonnees[0][2] + scaleorbit * this->YC;
241        p1.coordonnees[1][0] = p1.coordonnees[0][0] + p1.coordonnees[0][1] * this->L / 2;
242        p1.coordonnees[1][2] = p1.coordonnees[0][2] + p1.coordonnees[0][3] * this->L / 2;
243        xl = (p1.coordonnees[1][0] - scaleorbit * this->XC) * ca + (p1.coordonnees[1][2] - scaleorbit * this->YC) * sa;
244        p1.coordonnees[1][1] = p1.coordonnees[0][1];
245        p1.coordonnees[1][3] = p1.coordonnees[0][3];
246        p1.coordonnees[1][4] = p1.coordonnees[0][4];
247        BLength = this->L;
248        B = Bcalc(xl, (this->hgap + this->hgap2) / 2, this->thicknessMagneticField, this->Bmax);
249        z = this->L / 2;
250
251    }//end dernier else
252
253
254    //applying kick
255
256    double Preference, p, delta_angle, pdepthZ, sImp, xint, xsint, yint, ysint;
257
258    Preference = sqrt(this->energyPerIon * this->energyPerIon - this->mass * this->mass) / Apr; //momentum per nucleon for reference particle. unit: GeV/c
259    p = (1 + p1.coordonnees[0][4]) * Preference * p1.Ap0; //momentum. unit: GeV/c
260    delta_angle = B * p1.Zp0 * BLength * 299792458 / (p * 1000000000);
261    p1.coordonnees[1][1] = p1.coordonnees[1][1] + delta_angle * ca;
262    p1.coordonnees[1][3] = p1.coordonnees[1][3] + delta_angle * sa;
263
264    p1.coordonnees[1][0] = p1.coordonnees[1][0] - scaleorbit * this->XC; //coordinates relative to reference particle/middle point between collimators
265    p1.coordonnees[1][2] = p1.coordonnees[1][2] - scaleorbit * this->YC;
266    xl = p1.coordonnees[1][0] * ca + p1.coordonnees[1][2] * sa; //ca is cosine of collimator's angle
267    xsl = p1.coordonnees[1][1] * ca + p1.coordonnees[1][3] * sa;
268
269    pdepthZ = abs(xl) - (this->hgap * (this->L - z) + this->hgap2 * z) / this->L; //depth at the point the kick is given
270    pdepthEnd = abs(xl + (this->L - z) * xsl) - this->hgap2;
271    if (pdepthEnd > 0) { //enters collimator
272
273        this->second.push_back(1);
274
275        //Particles impacting along the jaw (outside the gap at the end but inside in beginning)
276
277        if (xl < 0) {
278            alf = -this->phi - xsl;
279        } else {
280            alf = -this->phi + xsl;
281        }
282
283        //impact angle on collimator; the sign determines which jaw is hit and therefore if the jaw angle should be added or subtracted.
284
285        lcolleff = pdepthEnd / alf; //effective length of orbit inside collimator
286
287        if ((lcolleff > (this->L - z)) || (lcolleff < 0)) {
288            lcolleff = this->L - z;
289        }
290
291        sImp = -pdepthZ / alf; //distance from current position to impact
292
293
294        //Move particle to this point. Drift => angles don't change, x,y change as straight line
295        xint = p1.coordonnees[1][0] + p1.coordonnees[1][1] * sImp;
296        yint = p1.coordonnees[1][2] + p1.coordonnees[1][3] * sImp;
297        xsint = p1.coordonnees[1][1];
298        ysint = p1.coordonnees[1][3];
299
300        double p1xtemp, p1ytemp, p1x0temp, p1xs0temp, p1y0temp, p1ys0temp;
301
302        p1xtemp = p1.coordonnees[1][0];
303        p1ytemp = p1.coordonnees[1][2];
304        p1x0temp = p1.coordonnees[0][0];
305        p1xs0temp = p1.coordonnees[0][1];
306        p1y0temp = p1.coordonnees[0][2];
307        p1ys0temp = p1.coordonnees[0][3];
308
309        p1.coordonnees[0][0] = xint;
310        p1.coordonnees[0][1] = xsint;
311        p1.coordonnees[0][2] = yint;
312        p1.coordonnees[0][3] = ysint;
313
314        //Apply thin collimator at impact position
315
316        collipassInteraction(p1, Apr, Zpr, betgam, lcolleff);
317
318        if (p1.Ap0 == 0) {
319            return;
320        }
321
322        xint = p1.coordonnees[1][0];
323        xsint = p1.coordonnees[1][1];
324        yint = p1.coordonnees[1][2];
325        ysint = p1.coordonnees[1][3];
326        p1.coordonnees[0][4] = p1.coordonnees[1][4];
327
328        dpopeff = (p1.Ap0 * Zpr) / (p1.Zp0 * Apr) * (1 + p1.coordonnees[0][4]) - 1;
329
330        xint = xint + scaleorbit * this->XC;
331        yint = yint + scaleorbit * this->YC;
332        p1.coordonnees[1][0] = p1.coordonnees[1][0] + scaleorbit * this->XC;
333        p1.coordonnees[1][2] = p1.coordonnees[1][2] + scaleorbit * this->YC;
334        p1.coordonnees[0][0] = p1x0temp;
335        p1.coordonnees[0][2] = p1y0temp;
336        p1.coordonnees[0][1] = p1xs0temp;
337        p1.coordonnees[0][3] = p1ys0temp;
338
339        //Move particle to next element of the collimator region as defined in MADX.
340        //Drift => angles don't change, x,y change as straight line
341
342        p1.coordonnees[1][0] = xint + xsint * (delta_s - z);
343        p1.coordonnees[1][2] = yint + ysint * (delta_s - z);
344        p1.coordonnees[1][1] = xsint;
345        p1.coordonnees[1][3] = ysint;
346
347    }//end if(pdepthend > 0)
348    else {
349
350        this->second.push_back(0);
351        p1.coordonnees[1][0] = p1.coordonnees[1][0] + scaleorbit * this->XC;
352        p1.coordonnees[1][2] = p1.coordonnees[1][2] + scaleorbit * this->YC;
353        p1.coordonnees[1][0] = p1.coordonnees[1][0] + p1.coordonnees[1][1] * (delta_s - z);
354        p1.coordonnees[1][2] = p1.coordonnees[1][2] + p1.coordonnees[1][3] * (delta_s - z);
355        p1.coordonnees[1][4] = p1.coordonnees[0][4];
356
357        dpopeff = (p1.Ap0 * Zpr) / (p1.Zp0 * Apr) * (1 + p1.coordonnees[0][4]) - 1;
358    }
359
360};
Note: See TracBrowser for help on using the repository browser.