1 package org.lcsim.recon.tracking.trfzp;
2
3 import org.lcsim.recon.tracking.magfield.AbstractMagneticField;
4 import org.lcsim.recon.tracking.trfbase.*;
5
6 import static java.lang.Math.sqrt;
7 import static java.lang.Math.abs;
8 import static java.lang.Math.max;
9 import static java.lang.Math.pow;
10 import org.lcsim.recon.tracking.spacegeom.CartesianPoint;
11 import org.lcsim.recon.tracking.spacegeom.SpacePointTensor;
12 import org.lcsim.recon.tracking.spacegeom.SpacePointVector;
13 import org.lcsim.recon.tracking.trfutil.Assert;
14 import org.lcsim.recon.tracking.trfutil.TRFMath;
15
16
17
18
19
20
21
22 public class PropZZRK extends PropDirected
23 {
24
25 private AbstractMagneticField _bfield;
26
27 private static final int IX = SurfZPlane.IX;
28 private static final int IY = SurfZPlane.IY;
29 private static final int IDXDZ = SurfZPlane.IDXDZ;
30 private static final int IDYDZ = SurfZPlane.IDYDZ;
31 private static final int IQP = SurfZPlane.IQP;
32 private double _precision;
33 private double _derivprec;
34
35 public PropZZRK(AbstractMagneticField bfield, double precision, double derivprecision)
36 {
37 _bfield = bfield;
38 _precision = precision;
39 _derivprec = derivprecision;
40 assert (_precision > 0. && _precision <= 0.01);
41 assert (_derivprec > 0. && _derivprec <= 0.1);
42 }
43
44 public PropZZRK(AbstractMagneticField bfield)
45 {
46 _precision = 1.e-7;
47 _derivprec = 1.e-7;
48 _bfield = bfield;
49 }
50
51 @Override
52 public Propagator newPropagator()
53 {
54 throw new UnsupportedOperationException("Not supported yet.");
55 }
56
57
58
59 double[] motion(double[] par, double z, double crv, double sign_dz,
60 AbstractMagneticField bfield)
61 {
62
63 double[] result = new double[par.length];
64 boolean deriv = par.length > 5;
65
66
67
68 double x = par[0];
69 double y = par[1];
70 double xv = par[2];
71 double yv = par[3];
72 double s = par[4];
73
74
75
76 double dxdx0 = 0.;
77 double dxdy0 = 0.;
78 double dxdxv0 = 0.;
79 double dxdyv0 = 0.;
80 double dxdcrv = 0.;
81
82 double dydx0 = 0.;
83 double dydy0 = 0.;
84 double dydxv0 = 0.;
85 double dydyv0 = 0.;
86 double dydcrv = 0.;
87
88 double dxvdx0 = 0.;
89 double dxvdy0 = 0.;
90 double dxvdxv0 = 0.;
91 double dxvdyv0 = 0.;
92 double dxvdcrv = 0.;
93
94 double dyvdx0 = 0.;
95 double dyvdy0 = 0.;
96 double dyvdxv0 = 0.;
97 double dyvdyv0 = 0.;
98 double dyvdcrv = 0.;
99
100 if (deriv) {
101
102
103
104 dxdx0 = par[5];
105 dxdy0 = par[6];
106 dxdxv0 = par[7];
107 dxdyv0 = par[8];
108 dxdcrv = par[9];
109
110 dydx0 = par[10];
111 dydy0 = par[11];
112 dydxv0 = par[12];
113 dydyv0 = par[13];
114 dydcrv = par[14];
115
116 dxvdx0 = par[15];
117 dxvdy0 = par[16];
118 dxvdxv0 = par[17];
119 dxvdyv0 = par[18];
120 dxvdcrv = par[19];
121
122 dyvdx0 = par[20];
123 dyvdy0 = par[21];
124 dyvdxv0 = par[22];
125 dyvdyv0 = par[23];
126 dyvdcrv = par[24];
127 }
128 double dmax = 1.e30;
129 if (!(xv < dmax && xv > -dmax)) {
130 throw new RuntimeException("Floating point exception");
131 }
132 if (!(yv < dmax && yv > -dmax)) {
133 throw new RuntimeException("Floating point exception");
134 }
135 double dsdz2 = 1. + xv * xv + yv * yv;
136 double dsdz = sign_dz * sqrt(dsdz2);
137
138
139
140 double bx = 0.;
141 double by = 0.;
142 double bz = 0.;
143 double dbxdx = 0.;
144 double dbxdy = 0.;
145 double dbydx = 0.;
146 double dbydy = 0.;
147 double dbzdx = 0.;
148 double dbzdy = 0.;
149 SpacePointVector bf;
150 if (deriv) {
151 SpacePointTensor t = new SpacePointTensor();
152 bf = bfield.field(new CartesianPoint(x, y, z), t);
153 dbxdx = t.t_x_x();
154 dbxdy = t.t_x_y();
155 dbydx = t.t_y_x();
156 dbydy = t.t_y_y();
157 dbzdx = t.t_z_x();
158 dbzdy = t.t_z_y();
159 } else {
160 bf = bfield.field(new CartesianPoint(x, y, z));
161 }
162 bx = bf.v_x();
163 by = bf.v_y();
164 bz = bf.v_z();
165
166
167
168 result[0] = xv;
169
170
171
172 result[1] = yv;
173
174
175
176 double dxvdz_nocrv = TRFMath.BFAC * dsdz * (xv * yv * bx - (1. + xv * xv) * by + yv * bz);
177 result[2] = dxvdz_nocrv * crv;
178
179
180
181 double dyvdz_nocrv = TRFMath.BFAC * dsdz * ((1. + yv * yv) * bx - xv * yv * by - xv * bz);
182 result[3] = dyvdz_nocrv * crv;
183
184
185
186 result[4] = dsdz;
187
188 if (deriv) {
189
190
191
192 result[5] = dxvdx0;
193
194
195
196 result[6] = dxvdy0;
197
198
199
200 result[7] = dxvdxv0;
201
202
203
204 result[8] = dxvdyv0;
205
206
207
208 result[9] = dxvdcrv;
209
210
211
212 result[10] = dyvdx0;
213
214
215
216 result[11] = dyvdy0;
217
218
219
220 result[12] = dyvdxv0;
221
222
223
224 result[13] = dyvdyv0;
225
226
227
228 result[14] = dyvdcrv;
229
230
231
232 result[15] = result[2] * (xv * dxvdx0 + yv * dyvdx0) / dsdz2
233 + TRFMath.BFAC * crv * dsdz
234 * (dxvdx0 * yv * bx + xv * dyvdx0 * bx + xv * yv * (dbxdx * dxdx0 + dbxdy * dydx0)
235 - 2. * xv * dxvdx0 * by - (1. + xv * xv) * (dbydx * dxdx0 + dbydy * dydx0)
236 + dyvdx0 * bz + yv * (dbzdx * dxdx0 + dbzdy * dydx0));
237
238
239
240 result[16] = result[2] * (xv * dxvdy0 + yv * dyvdy0) / dsdz2
241 + TRFMath.BFAC * crv * dsdz
242 * (dxvdy0 * yv * bx + xv * dyvdy0 * bx + xv * yv * (dbxdx * dxdy0 + dbxdy * dydy0)
243 - 2. * xv * dxvdy0 * by - (1. + xv * xv) * (dbydx * dxdy0 + dbydy * dydy0)
244 + dyvdy0 * bz + yv * (dbzdx * dxdy0 + dbzdy * dydy0));
245
246
247
248 result[17] = result[2] * (xv * dxvdxv0 + yv * dyvdxv0) / dsdz2
249 + TRFMath.BFAC * crv * dsdz
250 * (dxvdxv0 * yv * bx + xv * dyvdxv0 * bx + xv * yv * (dbxdx * dxdxv0 + dbxdy * dydxv0)
251 - 2. * xv * dxvdxv0 * by - (1. + xv * xv) * (dbydx * dxdxv0 + dbydy * dydxv0)
252 + dyvdxv0 * bz + yv * (dbzdx * dxdxv0 + dbzdy * dydxv0));
253
254
255
256 result[18] = result[2] * (xv * dxvdyv0 + yv * dyvdyv0) / dsdz2
257 + TRFMath.BFAC * crv * dsdz
258 * (dxvdyv0 * yv * bx + xv * dyvdyv0 * bx + xv * yv * (dbxdx * dxdyv0 + dbxdy * dydyv0)
259 - 2. * xv * dxvdyv0 * by - (1. + xv * xv) * (dbydx * dxdyv0 + dbydy * dydyv0)
260 + dyvdyv0 * bz + yv * (dbzdx * dxdyv0 + dbzdy * dydyv0));
261
262
263
264 result[19] = dxvdz_nocrv * (1. + crv * (xv * dxvdcrv + yv * dyvdcrv) / dsdz2)
265 + TRFMath.BFAC * crv * dsdz
266 * (dxvdcrv * yv * bx + xv * dyvdcrv * bx + xv * yv * (dbxdx * dxdcrv + dbxdy * dydcrv)
267 - 2. * xv * dxvdcrv * by - (1. + xv * xv) * (dbydx * dxdcrv + dbydy * dydcrv)
268 + dyvdcrv * bz + yv * (dbzdx * dxdcrv + dbzdy * dydcrv));
269
270
271
272
273 result[20] = result[3] * (xv * dxvdx0 + yv * dyvdx0) / dsdz2
274 + TRFMath.BFAC * crv * dsdz
275 * (2. * yv * dyvdx0 * bx + (1. + yv * yv) * (dbxdx * dxdx0 + dbxdy * dydx0)
276 - dxvdx0 * yv * by - xv * dyvdx0 * by - xv * yv * (dbydx * dxdx0 + dbydy * dydx0)
277 - dxvdx0 * bz - xv * (dbzdx * dxdx0 + dbzdy * dydx0));
278
279
280
281 result[21] = result[3] * (xv * dxvdy0 + yv * dyvdy0) / dsdz2
282 + TRFMath.BFAC * crv * dsdz
283 * (2. * yv * dyvdy0 * bx + (1. + yv * yv) * (dbxdx * dxdy0 + dbxdy * dydy0)
284 - dxvdy0 * yv * by - xv * dyvdy0 * by - xv * yv * (dbydx * dxdy0 + dbydy * dydy0)
285 - dxvdy0 * bz - xv * (dbzdx * dxdy0 + dbzdy * dydy0));
286
287
288
289 result[22] = result[3] * (xv * dxvdxv0 + yv * dyvdxv0) / dsdz2
290 + TRFMath.BFAC * crv * dsdz
291 * (2. * yv * dyvdxv0 * bx + (1. + yv * yv) * (dbxdx * dxdxv0 + dbxdy * dydxv0)
292 - dxvdxv0 * yv * by - xv * dyvdxv0 * by - xv * yv * (dbydx * dxdxv0 + dbydy * dydxv0)
293 - dxvdxv0 * bz - xv * (dbzdx * dxdxv0 + dbzdy * dydxv0));
294
295
296
297 result[23] = result[3] * (xv * dxvdyv0 + yv * dyvdyv0) / dsdz2
298 + TRFMath.BFAC * crv * dsdz
299 * (2. * yv * dyvdyv0 * bx + (1. + yv * yv) * (dbxdx * dxdyv0 + dbxdy * dydyv0)
300 - dxvdyv0 * yv * by - xv * dyvdyv0 * by - xv * yv * (dbydx * dxdyv0 + dbydy * dydyv0)
301 - dxvdyv0 * bz - xv * (dbzdx * dxdyv0 + dbzdy * dydyv0));
302
303
304
305 result[24] = dyvdz_nocrv * (1. + crv * (xv * dxvdcrv + yv * dyvdcrv) / dsdz2)
306 + TRFMath.BFAC * crv * dsdz
307 * (2. * yv * dyvdcrv * bx + (1. + yv * yv) * (dbxdx * dxdcrv + dbxdy * dydcrv)
308 - dxvdcrv * yv * by - xv * dyvdcrv * by - xv * yv * (dbydx * dxdcrv + dbydy * dydcrv)
309 - dxvdcrv * bz - xv * (dbzdx * dxdcrv + dbzdy * dydcrv));
310 }
311 return result;
312 }
313
314
315
316 void rk4(double[] par, double[] z, double h, double crv, double sign_dz,
317 AbstractMagneticField bfield, double[] k1, boolean reuse)
318 {
319 int size = par.length;
320 double[] k2 = new double[size];
321 double[] k3 = new double[size];
322 double[] k4 = new double[size];
323 if (!reuse)
324
325
326
327 {
328 scale(motion(par, z[0], crv, sign_dz, bfield), h, k1);
329 }
330 scale(motion(add(par, 0.5, k1), z[0] + 0.5 * h, crv, sign_dz, bfield), h, k2);
331 scale(motion(add(par, 0.5, k2), z[0] + 0.5 * h, crv, sign_dz, bfield), h, k3);
332 scale(motion(add(par, 1.0, k3), z[0] + h, crv, sign_dz, bfield), h, k4);
333
334 sum(k1, k2, k3, k4, par);
335 z[0] += h;
336 double dmax = 1.e30;
337 for (int i = 0; i < par.length; ++i) {
338 double x = par[i];
339 if (!(x < dmax && x > -dmax)) {
340 throw new RuntimeException("Floating point exception");
341 }
342 }
343 }
344
345
346
347
348 double pardiff(double[] par1, double[] par2,
349 double derivscale)
350 {
351 int n = par1.length;
352 assert (par2.length == n);
353 double epsmax = 0.;
354 for (int i = 0; i < n; ++i) {
355 double p1 = par1[i];
356 double p2 = par2[i];
357 double eps = abs(p2 - p1) / max(max(abs(p1), abs(p2)), 10.);
358 if (i >= 5) {
359 eps *= derivscale;
360 }
361 if (eps > epsmax) {
362 epsmax = eps;
363 }
364 }
365 return epsmax;
366 }
367
368
369
370
371
372
373 double rkv(double[] par, double[] z, double h, double crv, double sign_dz,
374 AbstractMagneticField bfield, double precision,
375 double derivprec)
376 {
377
378 double derivscale = precision / derivprec;
379
380
381
382
383 double hmin = abs(h) / h;
384 if (abs(hmin) > abs(h)) {
385 hmin = h;
386 }
387 double hnext = h;
388 for (;;) {
389
390
391
392
393 double maxdiff = precision * sqrt(0.1 * abs(h));
394 double[] par1 = new double[par.length];
395 System.arraycopy(par,0,par1,0,par.length);
396 double[] par2 = new double[par.length];
397 System.arraycopy(par,0,par2,0,par.length);;
398
399
400
401
402 double[] z1 = new double[1];
403 z1[0] = z[0];
404 double[] k1 = new double[par.length];
405 rk4(par1, z1, h, crv, sign_dz, bfield, k1, false);
406
407
408
409 if (abs(hmin) <= 0.01) {
410 System.arraycopy(par1, 0, par, 0, par1.length);
411 z[0] = z1[0];
412 break;
413 }
414
415
416
417 double[] z2 = new double[1];
418 z2[0] = z[0];
419 double hh = 0.5 * h;
420
421 for (int i = 0; i < k1.length; ++i) {
422 k1[i] = 0.5 * k1[i];
423 }
424 rk4(par2, z2, hh, crv, sign_dz, bfield, k1, true);
425 rk4(par2, z2, hh, crv, sign_dz, bfield, k1, false);
426
427
428
429 double eps = pardiff(par1, par2, derivscale);
430 if (eps <= maxdiff || abs(h) <= abs(hmin)) {
431
432
433
434
435
436
437
438
439
440 if (eps != 0) {
441 hnext = 0.8 * h * pow(maxdiff / eps, 0.25);
442 if (abs(hnext) > 4. * abs(h)) {
443 hnext = 4. * h;
444 }
445 } else {
446 hnext = 4. * h;
447 }
448
449 subtract(par, par2, par1);
450 z[0] = z1[0];
451 break;
452 } else {
453
454
455
456
457 hnext = 0.8 * h * pow(maxdiff / eps, 0.25);
458 if (abs(hnext) < abs(hmin)) {
459 hnext = hmin;
460 }
461 h = hnext;
462 }
463 }
464
465
466
467 if (abs(hnext) < abs(hmin)) {
468 hnext = hmin;
469 }
470 return hnext;
471 }
472
473
474
475
476 void rka(double[] par, double[] z, double h, double crv, double sign_dz,
477 AbstractMagneticField bfield, double precision,
478 double derivprec)
479 {
480 assert (h != 0);
481 double htry = h;
482 double hnext;
483 double z2 = z[0] + h;
484 while (h > 0 && z[0] < z2 || h < 0 && z[0] > z2) {
485 double hmax = abs(z2 - z[0]);
486 if (abs(htry) > hmax) {
487 htry = z2 - z[0];
488 }
489 hnext = rkv(par, z, htry, crv, sign_dz, bfield, precision, derivprec);
490 assert (hnext * htry > 0);
491 assert (z[0] + hnext != z[0]);
492 htry = hnext;
493 }
494 }
495
496
497 private void scale(double[] a, double s, double[] b)
498 {
499 for (int i = 0; i < a.length; i++) {
500 b[i] = a[i] * s;
501 }
502 }
503
504 private double[] add(double[] a, double s, double[] b)
505 {
506 double[] f = new double[a.length];
507 for (int i = 0; i < a.length; i++) {
508 f[i] = a[i] + s * b[i];
509 }
510 return f;
511 }
512
513 private void sum(double[] k1, double[] k2, double[] k3, double[] k4, double[] p)
514 {
515 for (int i = 0; i < p.length; ++i) {
516 p[i] += (1. / 6.) * (k1[i] + 2. * k2[i] + 2. * k3[i] + k4[i]);
517 }
518 }
519
520 private void subtract(double[] par, double[] par2, double[] par1)
521 {
522 for (int i = 0; i < par.length; ++i) {
523 par[i] = (16. / 15.) * par2[i] - (1. / 15.) * par1[i];
524 }
525 }
526
527
528
529
530
531
532
533
534 public PropStat vecDirProp(VTrack trv, Surface srf, PropDir dir,
535 TrackDerivative deriv)
536 {
537
538
539 PropStat pstat = new PropStat();
540
541
542 Surface srf1 = trv.surface();
543
544
545 Assert.assertTrue(srf1.pureType().equals(SurfZPlane.staticType()));
546 if (!srf1.pureType().equals(SurfZPlane.staticType())) {
547 return pstat;
548 }
549
550 SurfZPlane sz1 = (SurfZPlane) srf1;
551
552
553 Assert.assertTrue(srf.pureType().equals(SurfZPlane.staticType()));
554 if (!srf.pureType().equals(SurfZPlane.staticType())) {
555 return pstat;
556 }
557 SurfZPlane sz2 = (SurfZPlane) srf;
558
559
560 PropDir rdir = dir;
561 boolean move = Propagator.reduceDirection(rdir);
562
563
564 boolean short_hop = false;
565
566
567
568 if (srf.pureEqual(srf1) && !move) {
569 if (deriv != null) {
570 deriv.setIdentity();
571 }
572 pstat.setSame();
573 return pstat;
574 }
575
576
577 int iz = SurfZPlane.ZPOS;
578 double z1 = sz1.parameter(iz);
579 double z2 = sz2.parameter(iz);
580
581
582 TrackVector vec = trv.vector();
583 double x1 = vec.get(IX);
584 double y1 = vec.get(IY);
585 double xv1 = vec.get(IDXDZ);
586 double yv1 = vec.get(IDYDZ);
587 double crv = vec.get(IQP);
588 double sign_dz = 0.;
589 if (trv.isForward()) {
590 sign_dz = 1.;
591 } else if (trv.isBackward()) {
592 sign_dz = -1.;
593 }
594 if (sign_dz == 0.) {
595 return pstat;
596 }
597
598
599
600
601
602 if (z2 == z1) {
603 if (move) {
604 System.out.println("PropZZRK: Invalid move");
605 return pstat;
606 }
607 } else if (z2 > z1) {
608 if (rdir == PropDir.FORWARD && trv.isBackward()
609 || rdir == PropDir.BACKWARD && trv.isForward()) {
610 System.out.println("PropZZRK: Wrong direction");
611 return pstat;
612 }
613 } else {
614 if (rdir == PropDir.FORWARD && trv.isForward()
615 || rdir == PropDir.BACKWARD && trv.isBackward()) {
616 System.out.println("PropZZRK: Wrong direction");
617 return pstat;
618 }
619 }
620
621
622
623
624 {
625
626
627
628 int size = 5;
629 if (deriv != null) {
630 size = 25;
631 }
632 double[] par = new double[size];
633 par[0] = x1;
634 par[1] = y1;
635 par[2] = xv1;
636 par[3] = yv1;
637 par[4] = 0.;
638 if (deriv != null) {
639 par[5] = 1.;
640 par[11] = 1.;
641 par[17] = 1.;
642 par[23] = 1.;
643 }
644
645
646
647 double[] z = new double[1];
648 z[0] = z1;
649 double h = z2 - z1;
650 if (abs(h) < 1.e-10) {
651 z[0] = z2;
652 } else {
653 rka(par, z, h, crv, sign_dz, _bfield, _precision, _derivprec);
654 }
655
656
657
658 double dmax = 1.e30;
659 double x2 = par[0];
660 double y2 = par[1];
661 double xv2 = par[2];
662 double yv2 = par[3];
663 double s = par[4];
664 vec.set(IX, x2);
665 vec.set(IY, y2);
666 vec.set(IDXDZ, xv2);
667 vec.set(IDYDZ, yv2);
668 vec.set(IQP, crv);
669 if (!(x2 < dmax && x2 > -dmax)) {
670 throw new RuntimeException("Floating point exception");
671 }
672 if (!(y2 < dmax && y2 > -dmax)) {
673 throw new RuntimeException("Floating point exception");
674 }
675 if (!(xv2 < dmax && xv2 > -dmax)) {
676 throw new RuntimeException("Floating point exception");
677 }
678 if (!(yv2 < dmax && yv2 > -dmax)) {
679 throw new RuntimeException("Floating point exception");
680 }
681 if (!(s < dmax && s > -dmax)) {
682 throw new RuntimeException("Floating point exception");
683 }
684 if (deriv != null) {
685
686
687
688
689 deriv.set(0, 0, par[5]);
690 deriv.set(0, 1, par[6]);
691 deriv.set(0, 2, par[7]);
692 deriv.set(0, 3, par[8]);
693 deriv.set(0, 4, par[9]);
694 deriv.set(1, 0, par[10]);
695 deriv.set(1, 1, par[11]);
696 deriv.set(1, 2, par[12]);
697 deriv.set(1, 3, par[13]);
698 deriv.set(1, 4, par[14]);
699 deriv.set(2, 0, par[15]);
700 deriv.set(2, 1, par[16]);
701 deriv.set(2, 2, par[17]);
702 deriv.set(2, 3, par[18]);
703 deriv.set(2, 4, par[19]);
704 deriv.set(3, 0, par[20]);
705 deriv.set(3, 1, par[21]);
706 deriv.set(3, 2, par[22]);
707 deriv.set(3, 3, par[23]);
708 deriv.set(3, 4, par[24]);
709 deriv.set(4, 0, 0.);
710 deriv.set(4, 1, 0.);
711 deriv.set(4, 2, 0.);
712 deriv.set(4, 3, 0.);
713 deriv.set(4, 4, 1.);
714 for (int i = 0; i < 4; ++i) {
715 for (int j = 0; j < 5; ++j) {
716 double x = deriv.get(i, j);
717 if (!(x < dmax && x > -dmax)) {
718 throw new RuntimeException("Floating point exception");
719 }
720 }
721 }
722 }
723
724
725 boolean forward = trv.isForward();
726 boolean backward = trv.isBackward();
727 assert (forward || backward);
728 assert (!(forward && backward));
729 trv.setSurface(srf.newPureSurface());
730 trv.setVector(vec);
731 if (forward) {
732 trv.setForward();
733 } else if (backward) {
734 trv.setBackward();
735 }
736
737
738 pstat.setPathDistance(s);
739 }
740 return pstat;
741 }
742
743 public String toString()
744 {
745 StringBuffer sb = new StringBuffer( "Z Plane RK propagation with magnetic field: \n");
746 sb.append(" "+_bfield+"\n");
747 sb.append(" precision = " + _precision);
748 sb.append(", derivprec = " + _derivprec+"\n");
749 return sb.toString();
750 }
751 }