1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 public class PropDCACyl extends PropDirected
35 {
36
37
38
39
40
41 public static final int IRSIGNED = SurfDCA.IRSIGNED;
42 public static final int IZ_DCA = SurfDCA.IZ;
43 public static final int IPHID = SurfDCA.IPHID;
44 public static final int ITLM_DCA = SurfDCA.ITLM;
45 public static final int IQPT_DCA = SurfDCA.IQPT;
46
47 public static final int IPHI = SurfCylinder.IPHI;
48 public static final int IZ_CYL = SurfCylinder.IZ;
49 public static final int IALF = SurfCylinder.IALF;
50 public static final int ITLM_CYL = SurfCylinder.ITLM;
51 public static final int IQPT_CYL = SurfCylinder.IQPT;
52
53
54
55
56
57
58 private double _bfac;
59
60
61
62
63
64
65
66
67
68
69
70
71 public static String typeName()
72 { return "PropDCACyl";
73 }
74
75
76
77
78
79
80
81 public static String staticType()
82 { return typeName();
83 }
84
85
86
87
88
89
90
91
92 public PropDCACyl(double bfield)
93 {
94 super(PropDir.FORWARD);
95 _bfac=bfield * TRFMath.BFAC;
96 }
97
98
99
100
101
102
103 public Propagator newPropagator()
104 {
105 return new PropDCACyl( bField() );
106 }
107
108
109
110
111
112
113
114 public String type()
115 { return staticType();
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131 public PropStat vecDirProp( VTrack trv, Surface srf,
132 PropDir dir, TrackDerivative deriv )
133 {
134 return dcaCylPropagate( _bfac, trv, srf, dir, deriv );
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148 public PropStat vecDirProp( VTrack trv, Surface srf,
149 PropDir dir )
150 {
151 TrackDerivative deriv =null;
152 return vecDirProp(trv, srf, dir, deriv);
153
154 }
155
156
157
158
159
160
161
162
163
164
165
166
167 public double bField()
168 {
169 return _bfac/TRFMath.BFAC;
170 }
171
172
173
174
175
176
177 public String toString()
178 {
179 return "DCA propagation to a Cylinder with constant "
180 + bField() + " Tesla field";
181 }
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196 public PropStat dcaCylPropagate( double _bfac,
197 VTrack trv,
198 Surface srf,
199 PropDir dir,
200 TrackDerivative deriv )
201 {
202
203
204 PropStat pstat = new PropStat();
205
206
207 Surface srf0 = trv.surface();
208 Assert.assertTrue( srf0.pureType().equals(SurfDCA.staticType() ));
209 if ( ! srf0.pureType( ).equals(SurfDCA.staticType()) )
210 return pstat;
211 SurfDCA srf_dca = ( SurfDCA ) srf0;
212
213
214
215 boolean tilted = srf_dca.dXdZ() != 0 || srf_dca.dYdZ() != 0;
216 Assert.assertTrue(!tilted);
217 if(tilted) return pstat;
218
219
220 Assert.assertTrue( srf.pureType().equals(SurfCylinder.staticType()) );
221 if ( !srf.pureType( ).equals(SurfCylinder.staticType()) )
222 return pstat;
223 SurfCylinder srf_cyl = ( SurfCylinder ) srf;
224
225
226
227 TrackVector vec_dca = trv.vector();
228 double r1p = Math.abs(vec_dca.get(IRSIGNED));
229 double z1 = vec_dca.get(IZ_DCA);
230 double phid1p= vec_dca.get(IPHID);
231 double tlam1 = vec_dca.get(ITLM_DCA);
232 double qpt1 = vec_dca.get(IQPT_DCA);
233
234 double xv = srf_dca.x();
235 double yv = srf_dca.y();
236
237
238 double sign_alf1p;
239 double sign_r1p=0.;
240
241 if ( !TRFMath.isZero( vec_dca.get(IRSIGNED) ) )
242 {
243 sign_alf1p = vec_dca.get(IRSIGNED)/Math.abs(vec_dca.get(IRSIGNED));
244 sign_r1p = sign_alf1p;
245 }
246 else
247 {
248 sign_alf1p = 0.0;
249 }
250
251 if( (!TRFMath.isZero(xv) || !TRFMath.isZero(yv)) && TRFMath.isZero(sign_alf1p) ) sign_alf1p=1;
252
253 double alf1p = sign_alf1p * TRFMath.PI2;
254 double phi1p = phid1p - alf1p;
255 phi1p = TRFMath.fmod2( phi1p, TRFMath.TWOPI );
256
257
258 double salf1p=0.;
259 salf1p = alf1p>0. ? 1.:( alf1p < 0. ? -1. : 0.) ;
260
261 double cosphi1p=Math.cos(phi1p);
262 double sinphi1p=Math.sin(phi1p);
263
264 double x1=r1p*cosphi1p+xv;
265 double y1=r1p*sinphi1p+yv;
266
267 double phi1 = Math.atan2(y1,x1);
268 double r1 = Math.sqrt(x1*x1+y1*y1);
269 double alf1 = alf1p + phi1p - phi1;
270 if( TRFMath.isZero(x1) && TRFMath.isZero(y1) )
271 {
272 phi1 = phid1p;
273 alf1 = 0.;
274 }
275 if( sign_r1p == 0 && !TRFMath.isZero(r1) )
276 sign_r1p=1;
277
278
279 double salf1 = Math.sin( alf1 );
280 double calf1 = Math.cos( alf1 );
281
282 if( TRFMath.isZero(alf1) )
283 {
284 salf1=0.;
285 calf1=1.;
286 }
287 if( TRFMath.isEqual(Math.abs(alf1),TRFMath.PI2) )
288 {
289 salf1= alf1 > 0 ? 1. : -1. ;
290 calf1=0.;
291 }
292
293 double crv1 = _bfac * qpt1;
294 double sign_crv = 1.;
295
296
297 double r2 = srf_cyl.parameter(SurfCylinder.RADIUS);
298
299
300 double tlam2 = tlam1;
301 double qpt2 = qpt1;
302 double crv2 = crv1;
303
304
305 double salf2 = r1/r2*salf1 + 0.5*crv1/r2*(r2*r2-r1*r1);
306
307
308 double diff = Math.abs( Math.abs(salf2) - 1.0 );
309 if ( diff < 1.e-10 ) salf2 = salf2>0 ? 1.0 : -1.0;
310
311 if ( Math.abs(salf2) > 1.0 ) return pstat;
312
313
314 double alf21 = Math.asin( salf2 );
315 double alf22 = alf21>0 ? Math.PI-alf21 : -Math.PI-alf21;
316 double calf21 = Math.cos( alf21 );
317 double calf22 = Math.cos( alf22 );
318
319
320
321
322
323 double cnst = Math.atan2(salf1-r1*crv1,calf1);
324 if( TRFMath.isEqual(Math.abs(alf1),TRFMath.PI2) )
325 {
326 cnst = salf1-r1*crv1 > 0 ? TRFMath.PI2 : -TRFMath.PI2;
327 cnst = (r1==0.) ? 0. : cnst;
328 }
329
330 double phi21 = phi1 + cnst - Math.atan2( salf2-r2*crv2, calf21 );
331 double phi22 = phi1 + cnst - Math.atan2( salf2-r2*crv2, calf22 );
332
333 if( TRFMath.isZero(crv1) )
334 {
335 phi21 = phi1 + cnst - alf21;
336 phi22 = phi1 + cnst - alf22;
337 }
338
339 if ( TRFMath.isZero(calf21) )
340 {
341 phi21 = phi1;
342 phi22 = phi1;
343 }
344
345
346 ST_DCACyl sto1 = new ST_DCACyl(r1,phi1,alf1,crv1,r2,phi21,alf21);
347 ST_DCACyl sto2 = new ST_DCACyl(r1,phi1,alf1,crv1,r2,phi22,alf22);
348
349
350
351
352 boolean use_first_solution;
353
354 if( dir.equals(PropDir.NEAREST))
355 use_first_solution = Math.abs(sto2.st()) > Math.abs(sto1.st());
356
357 else if( dir.equals(PropDir.FORWARD))
358 use_first_solution = sto1.st() > 0.0;
359
360 else if( dir.equals(PropDir.BACKWARD))
361 use_first_solution = sto1.st() < 0.0;
362
363 else
364 {
365 use_first_solution = false;
366 System.out.println( "PropCyl._vec_propagate: Unknown direction.");
367 System.exit(1);
368 }
369
370
371 double phi2, alf2;
372 ST_DCACyl sto = new ST_DCACyl();
373 double calf2;
374 if ( use_first_solution )
375 {
376 sto = sto1;
377 phi2 = phi21;
378 alf2 = alf21;
379 calf2 = calf21;
380 }
381 else
382 {
383 sto = sto2;
384 phi2 = phi22;
385 alf2 = alf22;
386 calf2 = calf22;
387 }
388
389
390 Assert.assertTrue( Math.abs(alf2) <= Math.PI );
391
392
393 double st = sto.st();
394 double s = st*Math.sqrt(1+tlam1*tlam1);
395
396
397 double z2 = z1 + st * tlam1;
398
399
400 TrackVector vec_cyl = new TrackVector();
401
402
403
404
405
406
407
408 vec_cyl.set(IPHI , phi2);
409 vec_cyl.set(IZ_CYL , z2);
410 vec_cyl.set(IALF , alf2);
411 vec_cyl.set(ITLM_CYL , tlam2);
412 vec_cyl.set(IQPT_CYL , qpt2);
413
414
415
416
417
418
419
420
421
422
423 trv.setSurface( srf_cyl.newPureSurface() );
424
425
426 trv.setVector(vec_cyl);
427
428
429 if ( Math.abs(alf2) <= TRFMath.PI2 ) trv.setForward();
430 else trv.setBackward();
431
432
433 pstat.setPathDistance(s);
434
435
436 if ( deriv == null ) return pstat;
437
438
439
440
441
442
443
444 double salf12 = sign_r1p*salf1;
445 if( sign_r1p == 0 && salf1 == 0. )
446 salf12 = 1;
447 double dalf2_dr1_sign = (salf12-crv1*r1*sign_r1p)/r2/calf2;
448 double dalf2_dr1 = (salf1-crv1*r1)/r2/calf2;
449 double dalf2_dalf1_or = 1/r2*calf1/calf2;
450 double dalf2_dalf1 = r1*dalf2_dalf1_or;
451 double dalf2_dcrv1 = (r2*r2-r1*r1)/(2.0*r2*calf2);
452
453
454
455
456
457
458
459
460
461
462
463
464
465 double dphi2_dphi1=1.;
466 double dphi2_dr1_sign = -crv1*calf1*sign_r1p/(1.-2.*r1*crv1*salf1+r1*r1*crv1*crv1)
467 - dalf2_dr1_sign*(1-salf2*crv2*r2)/(1.-2.*r2*crv2*salf2+r2*r2*crv2*crv2);
468
469 double dphi2_dr1 = -crv1*calf1/(1.-2.*r1*crv1*salf1+r1*r1*crv1*crv1)
470 - dalf2_dr1*(1-salf2*crv2*r2)/(1.-2.*r2*crv2*salf2+r2*r2*crv2*crv2);
471 double dphi2_dalf1_m1_or = (-salf1*crv1-r1*crv1*crv1+2.*crv1*salf1)/(1.-2.*r1*crv1*salf1+r1*r1*crv1*crv1)
472 - dalf2_dalf1_or*(1-salf2*crv2*r2)/(1.-2.*r2*crv2*salf2+r2*r2*crv2*crv2);
473 double dphi2_dalf1 = dphi2_dalf1_m1_or*r1 + 1;
474 double dphi2_dcrv1 = -r1*calf1/(1.-2.*r1*crv1*salf1+r1*r1*crv1*crv1)
475 -(dalf2_dcrv1*(1.-r2*crv2*salf2) - r2*calf2)/(1.-2.*r2*crv2*salf2+r2*r2*crv2*crv2);
476
477
478
479
480
481 double dst_dr1_sign = sto.d_st_dr1_sign(sign_r1p,dphi2_dr1_sign,dalf2_dr1_sign);
482 double dst_dr1 = sto.d_st_dr1(dphi2_dr1,dalf2_dr1);
483 double dst_dcrv1 = sto.d_st_dcrv1(dphi2_dcrv1, dalf2_dcrv1);
484 double dst_dalf1_or = sto.d_st_dalf1_or(r1,dphi2_dalf1_m1_or, dalf2_dalf1_or);
485
486
487
488
489
490 double dphi1_dphi1p_tr = r1p*Math.cos(phi1p-phi1);
491 double dphi1_dr1p_tr = sign_r1p*Math.sin(phi1p-phi1);
492
493 double dalf1_dphi1p_tr = r1 - dphi1_dphi1p_tr;
494 double dalf1_dr1p_tr = -dphi1_dr1p_tr;
495
496 double dr1_dr1p_sign = Math.cos(phi1p-phi1);
497 double dr1_dphi1p = r1p*Math.sin(phi1-phi1p);
498
499
500 double dphi2_dphi1p = dphi2_dr1*dr1_dphi1p +dphi2_dalf1 - dphi1_dphi1p_tr*dphi2_dalf1_m1_or;
501 double dphi2_dr1p = dphi2_dr1_sign*dr1_dr1p_sign - dphi2_dalf1_m1_or*dphi1_dr1p_tr;
502
503 double dalf2_dphi1p = dalf2_dr1*dr1_dphi1p + dalf2_dalf1_or*dalf1_dphi1p_tr;
504 double dalf2_dr1p = dalf2_dr1_sign*dr1_dr1p_sign + dalf2_dalf1_or*dalf1_dr1p_tr;
505
506 double dst_dphi1p = dst_dr1*dr1_dphi1p + dst_dalf1_or*dalf1_dphi1p_tr;
507 double dst_dr1p = dst_dr1_sign*dr1_dr1p_sign + dst_dalf1_or*dalf1_dr1p_tr;
508
509
510 deriv.set(IPHI, IRSIGNED, dphi2_dr1p);
511 deriv.set(IPHI, IZ_DCA, 0.0);
512 deriv.set(IPHI, IPHID, dphi2_dphi1p);
513 deriv.set(IPHI, ITLM_DCA, 0.0);
514 deriv.set(IPHI, IQPT_DCA, _bfac * dphi2_dcrv1);
515
516 deriv.set(IZ_CYL, IRSIGNED, tlam1 * dst_dr1p);
517 deriv.set(IZ_CYL, IZ_DCA, 1.0);
518 deriv.set(IZ_CYL, IPHID, tlam1 * dst_dphi1p);
519 deriv.set(IZ_CYL, ITLM_DCA, st);
520 deriv.set(IZ_CYL, IQPT_DCA, tlam1 * _bfac * dst_dcrv1);
521
522
523 deriv.set(IALF, IRSIGNED, dalf2_dr1p);
524 deriv.set(IALF, IZ_DCA, 0.0);
525 deriv.set(IALF, IPHID, dalf2_dphi1p);
526 deriv.set(IALF, ITLM_DCA, 0.0);
527 deriv.set(IALF, IQPT_DCA, _bfac * dalf2_dcrv1);
528
529 deriv.set(ITLM_CYL, IRSIGNED, 0.0);
530 deriv.set(ITLM_CYL, IZ_DCA, 0.0);
531 deriv.set(ITLM_CYL, IPHID, 0.0);
532 deriv.set(ITLM_CYL, ITLM_DCA, 1.0);
533 deriv.set(ITLM_CYL, IQPT_DCA, 0.0);
534
535 deriv.set(IQPT_CYL, IRSIGNED, 0.0);
536 deriv.set(IQPT_CYL, IZ_DCA, 0.0);
537 deriv.set(IQPT_CYL, IPHID, 0.0);
538 deriv.set(IQPT_CYL, ITLM_DCA, 0.0);
539 deriv.set(IQPT_CYL, IQPT_DCA, 1.0);
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557 return pstat;
558
559 }
560
561
562
563
564
565
566
567
568
569
570 class ST_DCACyl
571 {
572
573 private boolean _big_crv;
574 private double _st;
575
576 private double _dst_dr1;
577 private double _dst_dcrv1;
578 private double _dst_dphi2;
579 double _dst_dphi2_or;
580 private double _crv1;
581
582 public ST_DCACyl()
583 {
584 }
585 public ST_DCACyl(double r1, double phi1, double alf1, double crv1,
586 double r2, double phi2, double alf2)
587 {
588
589 _crv1 = crv1;
590 Assert.assertTrue( r1 >= 0.0 );
591 Assert.assertTrue( r2 >= 0.0 );
592 double rmax = r1+r2;
593
594
595 double phi_dir_diff = TRFMath.fmod2(phi2+alf2-phi1-alf1,TRFMath.TWOPI);
596 Assert.assertTrue( Math.abs(phi_dir_diff) <= Math.PI );
597
598
599 _big_crv = rmax*Math.abs(crv1) > 0.001;
600
601
602
603 if ( _big_crv )
604 {
605 Assert.assertTrue( crv1 != 0.0 );
606 _st = phi_dir_diff/crv1;
607 }
608
609
610
611
612 else
613 {
614
615
616 double d = Math.sqrt( r1*r1 + r2*r2 - 2.0*r1*r2*Math.cos(phi2-phi1) );
617 double arg = 0.5*d*crv1;
618 double arg2 = arg*arg;
619 double st_minus_d = d*arg2*( 1.0/6.0 + 3.0/40.0*arg2 );
620 _st = d + st_minus_d;
621
622
623
624
625
626
627
628 double sign = 0.0;
629 if ( crv1*_st != 0. )
630 {
631 double xsign = Math.abs( (phi_dir_diff - _st*crv1) / (_st*crv1) );
632 if ( xsign < 0.5 ) sign = 1.0;
633 if ( xsign > 1.5 && xsign < 3.0 ) sign = -1.0;
634 }
635
636
637
638
639
640 if ( sign == 0. )
641 {
642 sign = 1.0;
643 if ( Math.abs(alf2) > Math.abs(alf1) ) sign = -1.0;
644 if ( Math.abs(alf2) == Math.abs(alf1) )
645 {
646 if ( Math.abs(alf2) < TRFMath.PI2 )
647 {
648 if ( r2 < r1 ) sign = -1.0;
649 }
650 else
651 {
652 if ( r2 > r1 ) sign = -1.0;
653 }
654 }
655 }
656
657
658 Assert.assertTrue( Math.abs(sign) == 1.0 );
659 _st = sign*_st;
660
661
662
663
664
665
666
667
668
669 if ( TRFMath.isZero(d) )
670 {
671 _dst_dcrv1 = 0.0;
672 _dst_dphi2 = sign*r1;
673 _dst_dphi2_or = sign;
674 _dst_dr1 = 0.0;
675 }
676 else
677 {
678 _dst_dcrv1 = sign*d*d*arg*( 1.0/6.0 + 3.0/20.0*arg2);
679 double root = (1.0 + 0.5*arg*arg + 3.0/8.0*arg*arg*arg*arg );
680 _dst_dphi2_or = sign*(r2*Math.sin(phi2-phi1))*root/d;
681 _dst_dphi2 = _dst_dphi2_or*r1;
682 _dst_dr1 = sign*(r1-r2*Math.cos(phi2-phi1))*root/d;
683 }
684 }
685
686 }
687 public double st()
688 {
689 return _st;
690 }
691
692 public double d_st_dr1_sign(double sign_alf1,double dphi2_dr1_sign,double dalf2_dr1_sign)
693 {
694 if ( _big_crv ) return ( dphi2_dr1_sign + dalf2_dr1_sign ) / _crv1;
695 else return _dst_dphi2 * dphi2_dr1_sign + _dst_dr1*sign_alf1;
696 }
697
698 public double d_st_dr1( double d_phi2_dr1, double d_alf2_dr1 )
699 {
700 if ( _big_crv ) return ( d_phi2_dr1 + d_alf2_dr1 ) / _crv1;
701 else return _dst_dphi2 * d_phi2_dr1 + _dst_dr1;
702 }
703 public double d_st_dcrv1( double d_phi2_dcrv1, double d_alf2_dcrv1 )
704 {
705 if ( _big_crv ) return ( d_phi2_dcrv1 + d_alf2_dcrv1 - _st ) / _crv1;
706 else return _dst_dphi2 * d_phi2_dcrv1 + _dst_dcrv1;
707 }
708
709 public double d_st_dalf1_or(double r1,double dphi2_dalf1_m1_or, double dalf2_dalf1_or)
710 {
711 if ( _big_crv ) return ( dphi2_dalf1_m1_or + dalf2_dalf1_or) / _crv1;
712 else return _dst_dphi2_or * (dphi2_dalf1_m1_or*r1+1);
713 }
714
715 }
716
717 }
718
719