1 package org.lcsim.recon.tracking.trfcyl;
2 import org.lcsim.recon.tracking.trfutil.TRFMath;
3 import org.lcsim.recon.tracking.trfutil.Assert;
4
5 import org.lcsim.recon.tracking.trfbase.TrackDerivative;
6 import org.lcsim.recon.tracking.trfbase.TrackVector;
7 import org.lcsim.recon.tracking.trfbase.Propagator;
8 import org.lcsim.recon.tracking.trfbase.PropDirected;
9 import org.lcsim.recon.tracking.trfbase.PropDir;
10 import org.lcsim.recon.tracking.trfbase.PropStat;
11 import org.lcsim.recon.tracking.trfbase.Surface;
12 import org.lcsim.recon.tracking.trfbase.VTrack;
13 import org.lcsim.recon.tracking.trfbase.ETrack;
14
15
16
17
18
19
20
21
22
23
24
25
26
27 public class PropCyl extends PropDirected
28 {
29
30 private static final int IPHI = SurfCylinder.IPHI;
31 private static final int IZ = SurfCylinder.IZ;
32 private static final int IALF = SurfCylinder.IALF;
33 private static final int ITLM = SurfCylinder.ITLM;
34 private static final int IQPT = SurfCylinder.IQPT;
35
36
37
38
39
40
41
42
43 private double _bfac;
44
45
46
47
48
49
50
51
52 public PropCyl(double bfield)
53 {
54 _bfac = TRFMath.BFAC*bfield;
55 }
56
57
58
59
60
61
62
63
64
65 public Propagator newPropagator()
66 {
67 return new PropCyl( bField() );
68 }
69
70
71
72
73
74
75
76
77 public String toString()
78 {
79 return "Cylinder propagation with constant "
80 + bField() + " Tesla field \n";
81 }
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 public PropStat vecDirProp(VTrack trv, Surface srf, PropDir dir)
97 {
98 TrackDerivative deriv = null;
99 return vecDirProp(trv, srf, dir, deriv);
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 public PropStat vecDirProp(VTrack trv, Surface srf, PropDir dir, TrackDerivative deriv)
117 {
118
119
120 PropStat pstat = new PropStat();
121
122
123 Surface srf1 = trv.surface();
124 TrackVector vec1 = trv.vector();
125
126
127
128 Assert.assertTrue( srf1.pureType().equals(SurfCylinder.staticType()) );
129 if ( !srf1.pureType( ).equals(SurfCylinder.staticType()) )
130 return pstat;
131 SurfCylinder scy1 = (SurfCylinder) srf1;
132
133 Assert.assertTrue( srf.pureType().equals(SurfCylinder.staticType()) );
134 if (! srf.pureType( ).equals(SurfCylinder.staticType()) )
135 return pstat;
136 SurfCylinder scy2 = ( SurfCylinder) srf;
137
138
139
140 PropDir rdir = dir;
141 boolean move = reduceDirection(rdir);
142 if(move) rdir = reduce(rdir);
143
144 if ( srf.pureEqual(srf1) && !move )
145 {
146
147 if ( deriv != null )
148 {
149
150 deriv.setIdentity();
151
152 }
153
154 pstat.setSame();
155 return pstat;
156 }
157
158
159 int irad = SurfCylinder.RADIUS;
160 double r1 = scy1.parameter(irad);
161 double r2 = scy2.parameter(irad);
162 TrackVector vec = trv.vector();
163 double phi1 = vec.get(SurfCylinder.IPHI);
164 double z1 = vec.get(SurfCylinder.IZ);
165 double alf1 = vec.get(SurfCylinder.IALF);
166 double tlam1 = vec.get(SurfCylinder.ITLM);
167 double qpt1 = vec.get(SurfCylinder.IQPT);
168
169
170 alf1 = TRFMath.fmod2( alf1, TRFMath.TWOPI );
171 Assert.assertTrue( Math.abs(alf1) <= Math.PI );
172 if ( trv.isForward() ) Assert.assertTrue( Math.abs(alf1) <= TRFMath.PI2 );
173 else Assert.assertTrue( Math.abs(alf1) > TRFMath.PI2 );
174
175
176 double clam1 = 1.0/Math.sqrt(1+tlam1*tlam1);
177
178
179 double dcrv1_dqpt1 = _bfac;
180 double crv1 = dcrv1_dqpt1*qpt1;
181 double dcrv1_dtlam1 = 0.0;
182
183
184
185
186 double tlam2 = tlam1;
187 double crv2 = crv1;
188 double qpt2 = qpt1;
189
190
191
192
193
194 double salf1 = Math.sin( alf1 );
195 double calf1 = Math.cos( alf1 );
196 double salf2 = r1/r2*salf1 + 0.5*crv1/r2*(r2*r2-r1*r1);
197
198 double diff = Math.abs( Math.abs(salf2) - 1.0 );
199 if ( diff < 1.e-10 ) salf2 = salf2>0 ? 1.0 : -1.0;
200
201 if ( Math.abs(salf2) > 1.0 ) return pstat;
202 double alf21 = Math.asin( salf2 );
203 double alf22 = alf21>0 ? Math.PI-alf21 : -Math.PI-alf21;
204 double calf21 = Math.cos( alf21 );
205 double calf22 = Math.cos( alf22 );
206 double phi20 = phi1 + Math.atan2( salf1-r1*crv1, calf1 );
207 double phi21 = phi20 - Math.atan2( salf2-r2*crv2, calf21 );
208 double phi22 = phi20 - Math.atan2( salf2-r2*crv2, calf22 );
209
210 STCalc sto1 = new STCalc(r1,phi1,alf1,crv1,r2,phi21,alf21);
211 STCalc sto2 = new STCalc(r1,phi1,alf1,crv1,r2,phi22,alf22);
212
213
214
215
216 double st1 = sto1.st();
217 double st2 = sto2.st();
218 double ast1 = Math.abs(st1);
219 double ast2 = Math.abs(st2);
220
221
222
223
224
225 if ( st1*st2 > 0.0 )
226 {
227 if ( ast1 > ast2 )
228 {
229 st1 = 0.0;
230 }
231 else
232 {
233 st2 = 0.0;
234 }
235 }
236
237 boolean use_first_solution;
238
239 if (rdir.equals(PropDir.NEAREST))
240 {
241 use_first_solution = st1!=0 && (st2==0.0 || ast1<ast2);
242 }
243 else if (rdir.equals(PropDir.FORWARD))
244 {
245 if ( st1 > 0.0 )
246 {
247 use_first_solution = true;
248 }
249 else if ( st2 > 0.0 )
250 {
251 use_first_solution = false;
252 }
253 else
254 {
255 return pstat;
256 }
257 }
258 else if (rdir.equals(PropDir.BACKWARD))
259 {
260 if ( st1 < 0.0 )
261 {
262 use_first_solution = true;
263 }
264 else if ( st2 < 0.0 )
265 {
266 use_first_solution = false;
267 }
268 else
269 {
270 return pstat;
271 }
272 }
273 else
274 {
275 throw new IllegalArgumentException("PropCyl._vec_propagate: Unknown direction.");
276 }
277
278 double phi2, alf2;
279 STCalc sto;
280 double calf2;
281 if ( use_first_solution )
282 {
283 sto = sto1;
284 phi2 = phi21;
285 alf2 = alf21;
286 calf2 = calf21;
287 }
288 else
289 {
290 sto = sto2;
291 phi2 = phi22;
292 alf2 = alf22;
293 calf2 = calf22;
294 }
295
296
297 double st = sto.st();
298
299 if ( st == 0.0 )
300 {
301 return pstat;
302 }
303
304
305 double z2 = z1 + tlam1*st;
306
307
308 Assert.assertTrue( Math.abs(alf2) <= Math.PI );
309
310
311 vec.set(SurfCylinder.IPHI, phi2);
312 vec.set(SurfCylinder.IZ, z2);
313 vec.set(SurfCylinder.IALF, alf2);
314 vec.set(SurfCylinder.ITLM, tlam2);
315 vec.set(SurfCylinder.IQPT, qpt2);
316
317
318 trv.setSurface( srf );
319 trv.setVector(vec);
320 if ( Math.abs(alf2) <= TRFMath.PI2 ) trv.setForward();
321 else trv.setBackward();
322
323
324
325 double s = st/clam1;
326 pstat.setPathDistance(s);
327
328
329 if ( deriv == null ) return pstat;
330
331
332
333
334 double da2da1 = r1*calf1/r2/calf2;
335 double da2dc1 = (r2*r2-r1*r1)*0.5/r2/calf2;
336
337
338 double rcsal1 = r1*crv1*salf1;
339 double rcsal2 = r2*crv2*salf2;
340 double den1 = 1.0 + r1*r1*crv1*crv1 - 2.0*rcsal1;
341 double den2 = 1.0 + r2*r2*crv2*crv2 - 2.0*rcsal2;
342 double dp2dp1 = 1.0;
343 double dp2da1 = (1.0-rcsal1)/den1 - (1.0-rcsal2)/den2*da2da1;
344 double dp2dc1 = -r1*calf1/den1 + r2*calf2/den2
345 - (1.0-rcsal2)/den2*da2dc1;
346
347
348 double dz2dz1 = 1.0;
349 double dz2dl1 = st;
350 double dz2da1 = tlam1*sto.d_st_dalf1(dp2da1, da2da1);
351 double dz2dc1 = tlam1*sto.d_st_dcrv1(dp2dc1, da2dc1);
352
353
354
355 deriv.set(IPHI, IPHI , dp2dp1);
356 deriv.set(IPHI, IALF , dp2da1);
357 deriv.set(IPHI, ITLM , dp2dc1*dcrv1_dtlam1);
358 deriv.set(IPHI, IQPT , dp2dc1*dcrv1_dqpt1);
359 deriv.set(IZ, IZ , dz2dz1);
360 deriv.set(IZ, IALF , dz2da1);
361 deriv.set(IZ, ITLM , dz2dl1 + dz2dc1*dcrv1_dtlam1);
362 deriv.set(IZ, IQPT , dz2dc1*dcrv1_dqpt1);
363 deriv.set(IALF, IALF , da2da1);
364 deriv.set(IALF, ITLM , da2dc1*dcrv1_dtlam1);
365 deriv.set(IALF, IQPT , da2dc1*dcrv1_dqpt1);
366 deriv.set(ITLM, ITLM , 1.0);
367 deriv.set(IQPT, IQPT , 1.0);
368 return pstat;
369 }
370
371
372
373
374
375
376
377
378
379
380 public double bField()
381 {
382 return _bfac/TRFMath.BFAC;
383 }
384
385
386
387
388
389
390
391
392
393 class STCalc
394 {
395
396 private boolean _big_crv;
397 private double _st;
398 private double _dst_dphi21;
399 private double _dst_dcrv1;
400 public double _crv1;
401
402
403 public STCalc()
404 {
405 }
406 public STCalc(double r1, double phi1, double alf1, double crv1,
407 double r2, double phi2, double alf2)
408 {
409 _crv1 = crv1;
410 Assert.assertTrue( r1 > 0.0 );
411 Assert.assertTrue( r2 > 0.0 );
412 double rmax = r1+r2;
413
414
415 double phi_dir_diff = TRFMath.fmod2(phi2+alf2-phi1-alf1,TRFMath.TWOPI);
416 Assert.assertTrue( Math.abs(phi_dir_diff) <= Math.PI );
417
418
419 _big_crv = rmax*Math.abs(crv1) > 0.001;
420
421
422
423 if ( _big_crv )
424 {
425 Assert.assertTrue( crv1 != 0.0 );
426 _st = phi_dir_diff/crv1;
427 }
428
429
430
431
432 else
433 {
434
435
436 double d = Math.sqrt( r1*r1 + r2*r2 - 2.0*r1*r2*Math.cos(phi2-phi1) );
437 double arg = 0.5*d*crv1;
438 double arg2 = arg*arg;
439 double st_minus_d = d*arg2*( 1.0/6.0 + 3.0/40.0*arg2 );
440 _st = d + st_minus_d;
441
442
443
444
445
446
447
448 double sign = 0.0;
449 if ( crv1!= 0. )
450 {
451 double xsign = Math.abs( (phi_dir_diff - _st*crv1) / (_st*crv1) );
452 if ( xsign < 0.5 ) sign = 1.0;
453 if ( xsign > 1.5 && xsign < 3.0 ) sign = -1.0;
454 }
455
456
457
458
459
460 if ( sign==0. )
461 {
462 sign = 1.0;
463 if ( Math.abs(alf2) > Math.abs(alf1) ) sign = -1.0;
464 if ( Math.abs(alf2) == Math.abs(alf1) )
465 {
466 if ( Math.abs(alf2) < TRFMath.PI2 )
467 {
468 if ( r2 < r1 ) sign = -1.0;
469 }
470 else
471 {
472 if ( r2 > r1 ) sign = -1.0;
473 }
474 }
475 }
476
477
478 Assert.assertTrue( Math.abs(sign) == 1.0 );
479 _st = sign*_st;
480
481
482 _dst_dcrv1 = sign*d*d*arg*( 1.0/6.0 + 3.0/20.0*arg2);
483 double root = (1.0 + 0.5*arg*arg + 3.0/8.0*arg*arg*arg*arg );
484 _dst_dphi21 = sign*(r1*r2*Math.sin(phi2-phi1))*root/d;
485
486 }
487
488 }
489
490 public double st()
491 { return _st;
492 }
493
494 public double d_st_dalf1(double dphi2_dalf1, double dalf2_dalf1 )
495 {
496 if ( _big_crv ) return ( dphi2_dalf1 + dalf2_dalf1 - 1.0 ) / _crv1;
497 else return _dst_dphi21 * dphi2_dalf1;
498 }
499
500 public double d_st_dcrv1(double dphi2_dcrv1, double dalf2_dcrv1 )
501 {
502 if ( _big_crv ) return ( dphi2_dcrv1 + dalf2_dcrv1 - _st ) / _crv1;
503 else return _dst_dcrv1 + _dst_dphi21*dphi2_dcrv1;
504 }
505
506 }
507
508
509
510
511 }