1 /* 2 * PropXYCyl_Test.java 3 * 4 * Created on July 24, 2007, 10:50 PM 5 * 6 * $Id: PropXYCyl_Test.java,v 1.1.1.1 2010/04/08 20:38:00 jeremy Exp $ 7 */ 8 9 package org.lcsim.recon.tracking.trfcylplane; 10 11 import junit.framework.TestCase; 12 import org.lcsim.recon.tracking.spacegeom.SpacePath; 13 import org.lcsim.recon.tracking.spacegeom.SpacePoint; 14 import org.lcsim.recon.tracking.trfbase.ETrack; 15 import org.lcsim.recon.tracking.trfbase.PropDir; 16 import org.lcsim.recon.tracking.trfbase.PropStat; 17 import org.lcsim.recon.tracking.trfbase.Propagator; 18 import org.lcsim.recon.tracking.trfbase.Surface; 19 import org.lcsim.recon.tracking.trfbase.TrackDerivative; 20 import org.lcsim.recon.tracking.trfbase.TrackError; 21 import org.lcsim.recon.tracking.trfbase.TrackVector; 22 import org.lcsim.recon.tracking.trfbase.VTrack; 23 import org.lcsim.recon.tracking.trfcyl.SurfCylinder; 24 import org.lcsim.recon.tracking.trfutil.Assert; 25 import org.lcsim.recon.tracking.trfutil.TRFMath; 26 import org.lcsim.recon.tracking.trfxyp.SurfXYPlane; 27 28 /** 29 * 30 * @author Norman Graf 31 */ 32 public class PropXYCyl_Test extends TestCase 33 { 34 private boolean debug; 35 36 // Assign track parameter indices. 37 38 private static final int IV = SurfXYPlane.IV; 39 private static final int IZC = SurfXYPlane.IZ; 40 private static final int IDVDU = SurfXYPlane.IDVDU; 41 private static final int IDZDU = SurfXYPlane.IDZDU; 42 private static final int IQP_XY = SurfXYPlane.IQP; 43 44 private static final int IPHI = SurfCylinder.IPHI; 45 private static final int IZ = SurfCylinder.IZ; 46 private static final int IALF = SurfCylinder.IALF; 47 private static final int ITLM = SurfCylinder.ITLM; 48 private static final int IQPT = SurfCylinder.IQPT; 49 50 51 //************************************************************************ 52 53 // compare two tracks without errors 54 55 private double compare(VTrack trv1,VTrack trv2) 56 { 57 Surface srf = trv2.surface(); 58 59 Assert.assertTrue(trv1.surface().equals(srf)); 60 61 double diff = srf.vecDiff(trv2.vector(),trv1.vector()).amax(); 62 63 return diff; 64 } 65 66 //********************************************************************** 67 // compare two tracks with errors 68 69 private double[] compare(ETrack trv1,ETrack trv2 ) 70 { 71 double[] tmp = new double[2]; 72 Surface srf = trv2.surface(); 73 74 Assert.assertTrue(trv1.surface().equals(srf)); 75 76 tmp[0] = srf.vecDiff(trv2.vector(),trv1.vector()).amax(); 77 78 TrackError dfc = trv2.error().minus(trv1.error()); 79 tmp[1] = dfc.amax(); 80 81 82 return tmp; 83 } 84 85 /** Creates a new instance of PropXYCyl_Test */ 86 public void testPropXYCyl() 87 { 88 String ok_prefix = "PropXYCyl (I): "; 89 String error_prefix = "PropXYCyl test (E): "; 90 91 if(debug) System.out.println( ok_prefix 92 + "-------- Testing component PropXYCyl. --------" ); 93 94 if(debug) System.out.println( ok_prefix + "Test constructor." ); 95 double BFIELD = 2.0*TRFMath.BFAC; 96 PropXYCyl prop = new PropXYCyl(BFIELD/TRFMath.BFAC); 97 if(debug) System.out.println( prop ); 98 99 PropXYCyl_Test tst = new PropXYCyl_Test(); 100 101 //******************************************************************** 102 103 // Here we propagate some tracks both forward and backward and then 104 // the same track forward and backward but using method 105 // that we checked very thoroughly before. 106 107 if(debug) System.out.println( ok_prefix + "Check against correct propagation." ); 108 109 PropXYCyl propxycyl = new PropXYCyl(BFIELD/TRFMath.BFAC); 110 111 double u1[] ={10., 10., 10., 10., 10., 10. }; 112 double phi1[] ={5*Math.PI/6., 5*Math.PI/6., Math.PI/6., Math.PI/6., 5/3*Math.PI, 7/4*Math.PI }; 113 int sign_du[] ={ -1, 1, -1, 1, 1, -1 }; 114 double v[] ={ -2., 2., 5., 5., -2., -2. }; 115 double z[] ={ 3., 3., 3., 3., 3., 3. }; 116 double dvdu[] ={ 1.5, -2.3, 0., 0., -1.5, 0. }; 117 double dzdu[] ={-2.3, 1.5, -2.3, 1.5, 0., -1.5 }; 118 double qp[] ={ 0.01, -0.01, 0.01, -0.01, -0.01, 0.01 }; 119 120 double rcyl2[] ={ 20., 20., 20., 20., 20., 20. }; 121 double rcyl2b[] ={ 20., 20., 20., 20., 20., 20. }; 122 123 double maxdiff = 1.e-10; 124 double diff; 125 int ntrk = 6; 126 int i; 127 128 for ( i=0; i<ntrk; ++i ) 129 { 130 if(debug) System.out.println( "********** Propagate track " + i + ". **********" ); 131 132 PropStat pstat = new PropStat(); 133 134 SurfXYPlane sxyp1 = new SurfXYPlane(u1[i],phi1[i]); 135 SurfCylinder scy2 = new SurfCylinder(rcyl2[i]); 136 SurfCylinder scy2b = new SurfCylinder(rcyl2b[i]); 137 138 TrackVector vec1 = new TrackVector(); 139 140 vec1.set(SurfXYPlane.IV , v[i]); // v 141 vec1.set(SurfXYPlane.IZ , z[i]); // z 142 vec1.set(SurfXYPlane.IDVDU , dvdu[i]); // dv/du 143 vec1.set(SurfXYPlane.IDZDU , dzdu[i]); // dz/du 144 vec1.set(SurfXYPlane.IQP , qp[i]); // q/p 145 146 VTrack trv1 = new VTrack(sxyp1.newPureSurface(),vec1); 147 if (sign_du[i]==1) trv1.setForward(); 148 else trv1.setBackward(); 149 150 if(debug) System.out.println( "\n starting: " + trv1 ); 151 152 VTrack trv2f = new VTrack(trv1); 153 pstat = propxycyl.vecDirProp(trv2f,scy2,PropDir.FORWARD); 154 Assert.assertTrue( pstat.forward() ); 155 if(debug) System.out.println( "\n forward: " + trv2f ); 156 157 VTrack trv2f_my = new VTrack(trv1); 158 pstat = tst.vec_propxycyl(BFIELD,trv2f_my,scy2,PropDir.FORWARD); 159 Assert.assertTrue( pstat.forward() ); 160 if(debug) System.out.println( "\n forward my: " + trv2f_my ); 161 diff = tst.compare(trv2f_my,trv2f); 162 163 if(debug) System.out.println( "\n diff: " + diff ); 164 Assert.assertTrue( diff < maxdiff ); 165 166 167 VTrack trv2b = new VTrack(trv1); 168 pstat = propxycyl.vecDirProp(trv2b,scy2b,PropDir.BACKWARD); 169 Assert.assertTrue( pstat.backward() ); 170 if(debug) System.out.println( "\n backward: " + trv2b ); 171 172 VTrack trv2b_my = new VTrack(trv1); 173 pstat = tst.vec_propxycyl(BFIELD,trv2b_my,scy2b,PropDir.BACKWARD); 174 Assert.assertTrue( pstat.backward() ); 175 if(debug) System.out.println( "\n backward my: " + trv2b_my ); 176 diff = tst.compare(trv2b_my,trv2b); 177 178 if(debug) System.out.println( "\n diff: " + diff ); 179 Assert.assertTrue( diff < maxdiff ); 180 181 182 } 183 //******************************************************************** 184 185 // Repeat the above with errors. 186 if(debug) System.out.println( ok_prefix + "Check against correct propagation with errors." ); 187 188 double evv[] = { 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 }; 189 double evz[] = { 0.01, -0.01, 0.01, -0.01, 0.01, -0.01 }; 190 double ezz[] = { 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, }; 191 double evdv[] = { 0.004, -0.004, 0.004, -0.004, 0.004, -0.004 }; 192 double ezdv[] = { 0.004, -0.004, 0.004, -0.004, 0.004, -0.004 }; 193 double edvdv[] = { 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 }; 194 double evdz[] = { 0.004, -0.004, 0.004, -0.004, 0.004, -0.004 }; 195 double edvdz[] = { 0.004, -0.004, 0.004, -0.004, 0.004, -0.004 }; 196 double ezdz[] = { 0.04, -0.04, 0.04, -0.04, 0.04, -0.04 }; 197 double edzdz[] = { 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 }; 198 double evqp[] = { 0.004, -0.004, 0.004, -0.004, 0.004, -0.004 }; 199 double ezqp[] = { 0.004, -0.004, 0.004, -0.004, 0.004, -0.004 }; 200 double edvqp[] = { 0.004, -0.004, 0.004, -0.004, 0.004, -0.004 }; 201 double edzqp[] = { 0.004, -0.004, 0.004, -0.004, 0.004, -0.004 }; 202 double eqpqp[] = { 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 }; 203 204 maxdiff = 1.e-8; 205 double ediff; 206 ntrk = 6; 207 208 for ( i=0; i<ntrk; ++i ) 209 { 210 if(debug) System.out.println( "********** Propagate track " + i + ". **********" ); 211 212 PropStat pstat = new PropStat(); 213 214 SurfXYPlane sxyp1 = new SurfXYPlane(u1[i],phi1[i]); 215 SurfCylinder scy2 = new SurfCylinder(rcyl2[i]); 216 SurfCylinder scy2b = new SurfCylinder(rcyl2b[i]); 217 218 TrackVector vec1 = new TrackVector(); 219 220 vec1.set(SurfXYPlane.IV , v[i]); // v 221 vec1.set(SurfXYPlane.IZ , z[i]); // z 222 vec1.set(SurfXYPlane.IDVDU , dvdu[i]); // dv/du 223 vec1.set(SurfXYPlane.IDZDU , dzdu[i]); // dz/du 224 vec1.set(SurfXYPlane.IQP , qp[i]); // q/p 225 226 TrackError err1 = new TrackError(); 227 228 err1.set(SurfXYPlane.IV,SurfXYPlane.IV , evv[i]); 229 err1.set(SurfXYPlane.IV,SurfXYPlane.IZ , evz[i]); 230 err1.set(SurfXYPlane.IZ,SurfXYPlane.IZ , ezz[i]); 231 err1.set(SurfXYPlane.IV,SurfXYPlane.IDVDU , evdv[i]); 232 err1.set(SurfXYPlane.IZ,SurfXYPlane.IDVDU , ezdv[i]); 233 err1.set(SurfXYPlane.IDVDU,SurfXYPlane.IDVDU , edvdv[i]); 234 err1.set(SurfXYPlane.IV,SurfXYPlane.IDZDU , evdz[i]); 235 err1.set(SurfXYPlane.IZ,SurfXYPlane.IDZDU , ezdz[i]); 236 err1.set(SurfXYPlane.IDVDU,SurfXYPlane.IDZDU , edvdz[i]); 237 err1.set(SurfXYPlane.IDZDU,SurfXYPlane.IDZDU , edzdz[i]); 238 err1.set(SurfXYPlane.IV,SurfXYPlane.IQP , evqp[i]); 239 err1.set(SurfXYPlane.IZ,SurfXYPlane.IQP , ezqp[i]); 240 err1.set(SurfXYPlane.IDVDU,SurfXYPlane.IQP , edvqp[i]); 241 err1.set(SurfXYPlane.IDZDU,SurfXYPlane.IQP , edzqp[i]); 242 err1.set(SurfXYPlane.IQP,SurfXYPlane.IQP , eqpqp[i]); 243 244 ETrack trv1 = new ETrack(sxyp1.newPureSurface(),vec1,err1); 245 if (sign_du[i]==1)trv1.setForward(); 246 else trv1.setBackward(); 247 248 if(debug) System.out.println( "\n starting: " + trv1 ); 249 250 ETrack trv2f = new ETrack(trv1); 251 pstat = propxycyl.errDirProp(trv2f,scy2,PropDir.FORWARD); 252 Assert.assertTrue( pstat.forward() ); 253 if(debug) System.out.println( "\n forward: " + trv2f ); 254 255 ETrack trv2f_my = new ETrack(trv1); 256 TrackDerivative deriv = new TrackDerivative(); 257 pstat = tst.vec_propxycyl(BFIELD,trv2f_my,scy2,PropDir.FORWARD,deriv); 258 Assert.assertTrue( pstat.forward() ); 259 TrackError err = trv2f_my.error(); 260 trv2f_my.setError( err.Xform(deriv) ); 261 if(debug) System.out.println( "\n forward my: " + trv2f_my ); 262 double[] diffs = tst.compare(trv2f_my,trv2f); 263 264 if(debug) System.out.println( "\n diff: " + diffs[0] + ' ' + "ediff: "+ diffs[1] ); 265 Assert.assertTrue( diffs[0] < maxdiff ); 266 Assert.assertTrue( diffs[1] < maxdiff ); 267 268 ETrack trv2b = new ETrack(trv1); 269 pstat = propxycyl.errDirProp(trv2b,scy2b,PropDir.BACKWARD); 270 Assert.assertTrue( pstat.backward() ); 271 if(debug) System.out.println( "\n backward: " + trv2b ); 272 273 ETrack trv2b_my = new ETrack(trv1); 274 pstat = tst.vec_propxycyl(BFIELD,trv2b_my,scy2b,PropDir.BACKWARD,deriv); 275 Assert.assertTrue( pstat.backward() ); 276 err = trv2b_my.error(); 277 trv2b_my.setError( err.Xform(deriv) ); 278 if(debug) System.out.println( "\n backward my: " + trv2b_my ); 279 diffs = tst.compare(trv2b_my,trv2b); 280 281 if(debug) System.out.println( "\n diff: " + diffs[0] + ' ' + "ediff: "+ diffs[1] ); 282 Assert.assertTrue( diffs[0] < maxdiff ); 283 Assert.assertTrue( diffs[1] < maxdiff ); 284 } 285 286 //******************************************************************** 287 288 if(debug) System.out.println( ok_prefix + "Test Zero Field Propagation." ); 289 { 290 PropXYCyl prop0 = new PropXYCyl(0.0); 291 if(debug) System.out.println( prop0 ); 292 Assert.assertTrue( prop0.bField() == 0. ); 293 294 double u=10.,phi=0.1; 295 296 Surface srf = new SurfXYPlane(u,phi); 297 VTrack trv0 = new VTrack(srf); 298 TrackVector vec = new TrackVector(); 299 vec.set(SurfXYPlane.IV, 2.); 300 vec.set(SurfXYPlane.IZ, 10.); 301 vec.set(SurfXYPlane.IDVDU, 4.); 302 vec.set(SurfXYPlane.IDZDU, 2.); 303 trv0.setVector(vec); 304 trv0.setForward(); 305 Surface srf_to = new SurfCylinder(13.0); 306 307 VTrack trv = new VTrack(trv0); 308 VTrack trv_der = new VTrack(trv); 309 PropStat pstat = prop0.vecDirProp(trv,srf_to,PropDir.NEAREST); 310 Assert.assertTrue( pstat.success() ); 311 312 Assert.assertTrue( pstat.forward() ); 313 Assert.assertTrue(trv.surface().pureEqual(srf_to)); 314 315 check_zero_propagation(trv0,trv,pstat); 316 check_derivatives(prop0,trv_der,srf_to); 317 } 318 319 //******************************************************************** 320 321 if(debug) System.out.println( ok_prefix + "Test cloning." ); 322 Assert.assertTrue( prop.newPropagator() != null ); 323 324 //******************************************************************** 325 326 if(debug) System.out.println( ok_prefix + "Test the field." ); 327 Assert.assertTrue( prop.bField() == 2.0 ); 328 329 330 //******************************************************************** 331 332 if(debug) System.out.println( ok_prefix 333 + "------------- All tests passed. -------------" ); 334 335 //******************************************************************** 336 337 } 338 339 // Very well tested XY-Cyl propagator. Each new one can be tested against it 340 341 //********************************************************************** 342 // helpers 343 //********************************************************************** 344 345 346 //********************************************************************** 347 348 // The track parameters for a cylinder are: 349 // phi z alpha tan(lambda) curvature 350 // (NOT [. . . lambda .] as in TRF and earlier version of TRF++.) 351 // 352 // If pderiv is nonzero, return the derivative matrix there. 353 // On Cylinder: 354 // r (cm) is fixed 355 // 0 - phi 356 // 1 - z (cm) 357 // 2 - alp 358 // 3 - tlam 359 // 4 - q/pt pt is transverse momentum of a track, q is its charge 360 // On XYPlane: 361 // u (cm) is fixed 362 // 0 - v (cm) 363 // 1 - z (cm) 364 // 2 - dv/du 365 // 3 - dz/du 366 // 4 - q/p p is momentum of a track, q is its charge 367 368 PropStat 369 vec_propxycyl( double B, VTrack trv, Surface srf, 370 PropDir dir 371 ) 372 { 373 TrackDerivative deriv = null; 374 return vec_propxycyl(B, trv, srf, dir, deriv); 375 } 376 377 PropStat 378 vec_propxycyl( double B, VTrack trv, Surface srf, 379 PropDir dir, 380 TrackDerivative deriv ) 381 { 382 383 // construct return status 384 PropStat pstat = new PropStat(); 385 386 // fetch the originating surface and vector 387 Surface srf1 = trv.surface(); 388 //TrackVector vec1 = trv.vector(); 389 390 // Check origin is a XYPlane. 391 Assert.assertTrue( srf1.pureType().equals(SurfXYPlane.staticType()) ); 392 if ( !srf1.pureType( ).equals(SurfXYPlane.staticType()) ) 393 return pstat; 394 SurfXYPlane sxyp1 = ( SurfXYPlane ) srf1; 395 396 // Check destination is a cylinder. 397 Assert.assertTrue( srf.pureType().equals(SurfCylinder.staticType()) ); 398 if ( ! srf.pureType( ).equals(SurfCylinder.staticType()) ) 399 return pstat; 400 SurfCylinder scy2 = ( SurfCylinder) srf; 401 402 403 // Fetch the dist and phi of the plane and the starting track vector. 404 int iphi = SurfXYPlane.NORMPHI; 405 int idist = SurfXYPlane.DISTNORM; 406 double phi = sxyp1.parameter(iphi); 407 double r = sxyp1.parameter(idist); 408 409 TrackVector vec = trv.vector(); 410 double v = vec.get(IV); // v 411 double z = vec.get(IZC); // z 412 double b = vec.get(IDVDU); // dv/du 413 double a = vec.get(IDZDU); // dz/du 414 double e = vec.get(IQP_XY); // q/p 415 416 // Fetch the radii and the starting track vector. 417 int irad = SurfCylinder.RADIUS; 418 double r2 = scy2.parameter(irad); 419 420 int sign_du = 0; 421 if(trv.isForward()) sign_du = 1; 422 if(trv.isBackward()) sign_du = -1; 423 if(sign_du == 0) 424 { 425 if(debug) System.out.println("PropXYCyl._vec_propagate: Unknown direction of a track "); 426 System.exit(1); 427 } 428 429 // Calculate cylindrical coordinates 430 431 double cnst=sign_du>0?0.:Math.PI; 432 double atn=Math.atan(v/r); 433 Assert.assertTrue(r!=0.); 434 435 double phi1= TRFMath.fmod2(phi+atn,TRFMath.TWOPI); 436 double r1=Math.sqrt(r*r+v*v); 437 double z1=z; 438 double alp1= TRFMath.fmod2(Math.atan(b)-atn+cnst,TRFMath.TWOPI); 439 double tlm1= a*sign_du/Math.sqrt(1+b*b); 440 double qpt1=e*Math.sqrt((1+a*a+b*b)/(1+b*b)); 441 442 443 // Check alpha range. 444 alp1 = TRFMath.fmod2( alp1, TRFMath.TWOPI ); 445 Assert.assertTrue( Math.abs(alp1) <= Math.PI ); 446 if ( trv.isForward() ) Assert.assertTrue( Math.abs(alp1) <= TRFMath.PI2 ); 447 else Assert.assertTrue( Math.abs(alp1) > TRFMath.PI2 ); 448 449 // Calculate the cosine of lambda. 450 //double clam1 = 1.0/Math.sqrt(1+tlm1*tlm1); 451 452 // Calculate curvature: C = _bfac*(q/p)/cos(lambda) 453 // and its derivatives 454 // Assert.assertTrue( clam1 != 0.0 ); 455 // double dcrv1_dqp1 = B/clam1; 456 // double crv1 = dcrv1_dqp1*qp1; 457 // double dcrv1_dtlm1 = crv1*clam1*clam1*tlm1; 458 459 // Calculate the curvature = _bfac*(q/pt) 460 double dcrv1_dqpt1 = B; 461 double crv1 = dcrv1_dqpt1*qpt1; 462 //double dcrv1_dtlm1 = 0.0; 463 464 // Evaluate the new track vector. 465 // See dla log I-044 466 467 // lambda and curvature do not change 468 double tlm2 = tlm1; 469 double crv2 = crv1; 470 double qpt2 = qpt1; 471 472 // We can evaluate sin(alp2), leaving two possibilities for alp2 473 // 1st solution: alp21, phi21, phid21, tht21 474 // 2nd solution: alp22, phi22, phid22, tht22 475 // evaluate phi2 to choose 476 double salp1 = Math.sin( alp1 ); 477 double calp1 = Math.cos( alp1 ); 478 double salp2 = r1/r2*salp1 + 0.5*crv1/r2*(r2*r2-r1*r1); 479 // if salp2 > 1, track does not cross cylinder 480 if ( Math.abs(salp2) > 1.0 ) return pstat; 481 double alp21 = Math.asin( salp2 ); 482 double alp22 = alp21>0 ? Math.PI-alp21 : -Math.PI-alp21; 483 double calp21 = Math.cos( alp21 ); 484 double calp22 = Math.cos( alp22 ); 485 double phi20 = phi1 + Math.atan2( salp1-r1*crv1, calp1 ); 486 double phi21 = phi20 - Math.atan2( salp2-r2*crv2, calp21 ); // phi position 487 double phi22 = phi20 - Math.atan2( salp2-r2*crv2, calp22 ); 488 // Construct an sT object for each solution. 489 STCalcXY_CHECK sto1 = new STCalcXY_CHECK(r1,phi1,alp1,crv1,r2,phi21,alp21); 490 STCalcXY_CHECK sto2 = new STCalcXY_CHECK(r1,phi1,alp1,crv1,r2,phi22,alp22); 491 // Check the two solutions are nonzero and have opposite sign 492 // or at least one is nonzero. 493 494 // Choose the correct solution 495 boolean use_first_solution = false; 496 497 if (dir.equals(PropDir.NEAREST)) 498 { 499 use_first_solution = Math.abs(sto2.st()) > Math.abs(sto1.st()); 500 } 501 else if (dir.equals(PropDir.FORWARD)) 502 { 503 use_first_solution = sto1.st() > 0.0; 504 } 505 else if (dir.equals(PropDir.BACKWARD)) 506 { 507 use_first_solution = sto1.st() < 0.0; 508 } 509 else 510 { 511 if(debug) System.out.println("PropCyl._vec_propagate: Unknown direction." ); 512 System.exit(1); 513 } 514 515 // Assign phi2, alp2 and sto2 for the chosen solution. 516 double phi2, alp2; 517 STCalcXY_CHECK sto; 518 double calp2; 519 if ( use_first_solution ) 520 { 521 sto = sto1; 522 phi2 = phi21; 523 alp2 = alp21; 524 calp2 = calp21; 525 } 526 else 527 { 528 sto = sto2; 529 phi2 = phi22; 530 alp2 = alp22; 531 calp2 = calp22; 532 } 533 534 // fetch sT. 535 double st = sto.st(); 536 537 // use sT to evaluate z2 538 double z2 = z1 + tlm1*st; 539 540 // Check alpha range. 541 Assert.assertTrue( Math.abs(alp2) <= Math.PI ); 542 543 // put new values in vec 544 vec.set(IPHI , phi2); 545 vec.set(IZ , z2); 546 vec.set(IALF , alp2); 547 vec.set(ITLM , tlm2); 548 vec.set(IQPT , qpt2); 549 550 // Update trv 551 trv.setSurface(srf.newPureSurface()); 552 trv.setVector(vec); 553 if ( Math.abs(alp2) <= TRFMath.PI2 ) trv.setForward(); 554 else trv.setBackward(); 555 556 // Set the return status. 557 if(st > 0) pstat.setForward() ; 558 else pstat.setBackward(); 559 560 // exit now if user did not ask for error matrix. 561 if ( deriv == null) return pstat; 562 563 // Calculate derivatives. 564 // dphi1 565 566 double dphi1_dv= r/(r*r+v*v); 567 568 // dz1 569 570 double dz1_dz=1.; 571 572 // dalf1 573 574 double dalp1_db= 1./(1.+b*b); 575 double dalp1_dv= -r/(r*r+v*v); 576 577 // dr1 578 579 double dr1_dv= v/Math.sqrt(v*v+r*r); 580 581 // dtlm1 582 583 double dtlm1_da= sign_du/Math.sqrt(1+b*b); 584 double dtlm1_db= -a*sign_du*b/(1+b*b)/Math.sqrt(1+b*b); 585 586 // dcrv1 587 588 double dcrv1_de= Math.sqrt((1+a*a+b*b)/(1+b*b))*B; 589 double dcrv1_da= a*e/Math.sqrt((1+b*b)*(1+a*a+b*b))*B; 590 double dcrv1_db= -e*b*a*a/Math.sqrt(1+a*a+b*b)/Math.sqrt(1+b*b)/(1+b*b)*B; 591 592 // alpha_2 593 double da2da1 = r1*calp1/r2/calp2; 594 double da2dc1 = (r2*r2-r1*r1)*0.5/r2/calp2; 595 double da2dr1 = (salp1-crv2*r1)/r2/calp2; 596 597 // phi2 598 double rcsal1 = r1*crv1*salp1; 599 double rcsal2 = r2*crv2*salp2; 600 double den1 = 1.0 + r1*r1*crv1*crv1 - 2.0*rcsal1; 601 double den2 = 1.0 + r2*r2*crv2*crv2 - 2.0*rcsal2; 602 double dp2dp1 = 1.0; 603 double dp2da1 = (1.0-rcsal1)/den1 - (1.0-rcsal2)/den2*da2da1; 604 double dp2dc1 = -r1*calp1/den1 + r2*calp2/den2 605 - (1.0-rcsal2)/den2*da2dc1; 606 double dp2dr1= -crv1*calp1/den1-(1.0-rcsal2)*da2dr1/den2; 607 608 // z2 609 double dz2dz1 = 1.0; 610 double dz2dl1 = st; 611 double dz2da1 = tlm1*sto.d_st_dalp1(dp2da1, da2da1); 612 double dz2dc1 = tlm1*sto.d_st_dcrv1(dp2dc1, da2dc1); 613 double dz2dr1 = tlm1*sto.d_st_dr1( dp2dr1, da2dr1); 614 615 616 // final derivatives 617 618 // phi2 619 double dphi2_dv=dp2dp1*dphi1_dv+dp2da1*dalp1_dv+dp2dr1*dr1_dv; 620 double dphi2_db=dp2da1*dalp1_db+dp2dc1*dcrv1_db; 621 double dphi2_da=dp2dc1*dcrv1_da; 622 double dphi2_de=dp2dc1*dcrv1_de; 623 624 // alp2 625 double dalp2_dv= da2da1*dalp1_dv+da2dr1*dr1_dv; 626 double dalp2_db= da2da1*dalp1_db+da2dc1*dcrv1_db; 627 double dalp2_da= da2dc1*dcrv1_da; 628 double dalp2_de= da2dc1*dcrv1_de; 629 630 // crv2 631 double dcrv2_da=dcrv1_da; 632 double dcrv2_db=dcrv1_db; 633 double dcrv2_de=dcrv1_de; 634 635 // tlm2 636 double dtlm2_da= dtlm1_da; 637 double dtlm2_db= dtlm1_db; 638 639 // z2 640 double dz2_dz= dz2dz1*dz1_dz; 641 double dz2_dv= dz2dr1*dr1_dv+dz2da1*dalp1_dv; 642 double dz2_db= dz2da1*dalp1_db+dz2dl1*dtlm1_db+dz2dc1*dcrv1_db; 643 double dz2_da= dz2dl1*dtlm1_da+dz2dc1*dcrv1_da; 644 double dz2_de= dz2dc1*dcrv1_de; 645 646 647 // Build derivative matrix. 648 649 deriv.set(IPHI,IV , dphi2_dv); 650 deriv.set(IPHI,IDVDU , dphi2_db); 651 deriv.set(IPHI,IDZDU , dphi2_da); 652 deriv.set(IPHI,IQP_XY , dphi2_de); 653 deriv.set(IZ,IV , dz2_dv); 654 deriv.set(IZ,IZC , dz2_dz); 655 deriv.set(IZ,IDVDU , dz2_db); 656 deriv.set(IZ,IDZDU , dz2_da); 657 deriv.set(IZ,IQP_XY , dz2_de); 658 deriv.set(IALF,IV , dalp2_dv); 659 deriv.set(IALF,IDVDU , dalp2_db); 660 deriv.set(IALF,IDZDU , dalp2_da); 661 deriv.set(IALF,IQP_XY , dalp2_de); 662 deriv.set(ITLM,IDVDU , dtlm2_db); 663 deriv.set(ITLM,IDZDU , dtlm2_da); 664 deriv.set(IQPT,IDVDU , dcrv2_db/B); 665 deriv.set(IQPT,IDZDU , dcrv2_da/B); 666 deriv.set(IQPT,IQP_XY , dcrv2_de/B); 667 668 return pstat; 669 670 } 671 672 673 // Private class STCalcXY_CHECK. 674 // 675 // An STCalcXY_CHECK_ object calculates sT (the signed transverse path length) 676 // and its derivatives w.r.t. alf1 and crv1. It is constructed from 677 // the starting (r1, phi1, alf1, crv1) and final track parameters 678 // (r2, phi2, alf2) assuming these are consistent. Methods are 679 // provided to retrieve sT and the two derivatives. 680 681 class STCalcXY_CHECK 682 { 683 684 private boolean _big_crv; 685 private double _st; 686 private double _dst_dphi21; 687 private double _dst_dcrv1; 688 private double _dst_dr1; 689 private double _cnst1,_cnst2; 690 public double _crv1; 691 692 // constructor 693 public STCalcXY_CHECK() 694 { 695 } 696 public STCalcXY_CHECK(double r1, double phi1, double alf1, double crv1, 697 double r2, double phi2, double alf2) 698 { 699 700 _crv1 = crv1; 701 Assert.assertTrue( r1 > 0.0 ); 702 Assert.assertTrue( r2 > 0.0 ); 703 double rmax = r1+r2; 704 705 // Calculate the change in xy direction 706 double phi_dir_diff = TRFMath.fmod2(phi2+alf2-phi1-alf1,TRFMath.TWOPI); 707 Assert.assertTrue( Math.abs(phi_dir_diff) <= Math.PI ); 708 709 // Evaluate whether |C| is" big" 710 _big_crv = rmax*Math.abs(crv1) > 0.001; 711 712 // If the curvature is big we can use 713 // sT = (phi_dir2 - phi_dir1)/crv1 714 if ( _big_crv ) 715 { 716 Assert.assertTrue( crv1 != 0.0 ); 717 _st = phi_dir_diff/crv1; 718 } 719 720 // Otherwise, we calculate the straight-line distance 721 // between the points and use an approximate correction 722 // for the (small) curvature. 723 else 724 { 725 726 // evaluate the distance 727 double d = Math.sqrt( r1*r1 + r2*r2 - 2.0*r1*r2*Math.cos(phi2-phi1) ); 728 double arg = 0.5*d*crv1; 729 double arg2 = arg*arg; 730 double st_minus_d = d*arg2*( 1.0/6.0 + 3.0/40.0*arg2 ); 731 _st = d + st_minus_d; 732 733 // evaluate the sign 734 // We define a metric xsign = abs( (dphid-d*C)/(d*C) ). 735 // Because sT*C = dphid and d = abs(sT): 736 // xsign = 0 for sT > 0 737 // xsign = 2 for sT < 0 738 // Numerical roundoff will smear these predictions. 739 double xsign = Math.abs( (phi_dir_diff - _st*crv1) / (_st*crv1) ); 740 double sign = 0.0; 741 if ( crv1 != 0 ) 742 { 743 if ( xsign < 0.5 ) sign = 1.0; 744 if ( xsign > 1.5 && xsign < 3.0 ) sign = -1.0; 745 } 746 // If the above is indeterminate, assume zero curvature. 747 // In this case abs(alpha) decreases monotonically 748 // with sT. Track passing through origin has alpha = 0 on one 749 // side and alpha = +/-pi on the other. If both points are on 750 // the same side, we use dr/ds > 0 for |alpha|<pi/2. 751 if ( sign == 0. ) 752 { 753 sign = 1.0; 754 if ( Math.abs(alf2) > Math.abs(alf1) ) sign = -1.0; 755 if ( Math.abs(alf2) == Math.abs(alf1) ) 756 { 757 if ( Math.abs(alf2) < TRFMath.PI2 ) 758 { 759 if ( r2 < r1 ) sign = -1.0; 760 } 761 else 762 { 763 if ( r2 > r1 ) sign = -1.0; 764 } 765 } 766 } 767 768 // Correct _st using the above sign. 769 Assert.assertTrue( Math.abs(sign) == 1.0 ); 770 _st = sign*_st; 771 772 // save derivatives 773 _dst_dcrv1 = sign*d*d*arg*( 1.0/6.0 + 3.0/20.0*arg2); 774 double root = (1.0 + 0.5*arg*arg + 3.0/8.0*arg*arg*arg*arg ); 775 _dst_dphi21 = sign*(r1*r2*Math.sin(phi2-phi1))*root/d; 776 _dst_dr1= (1.+arg2/2.*(1+3./4.*arg2))/d*sign; 777 _cnst1=r1-r2*Math.cos(phi2-phi1); 778 _cnst2=r1*r2*Math.sin(phi2-phi1); 779 } 780 781 } 782 public double st() 783 { return _st; 784 } 785 public double d_st_dalp1(double d_phi2_dalf1, double d_alf2_dalf1 ) 786 { 787 if ( _big_crv ) return ( d_phi2_dalf1 + d_alf2_dalf1 - 1.0 ) / _crv1; 788 else return _dst_dphi21 * d_phi2_dalf1; 789 790 } 791 public double d_st_dcrv1(double d_phi2_dcrv1, double d_alf2_dcrv1 ) 792 { 793 if ( _big_crv ) return ( d_phi2_dcrv1 + d_alf2_dcrv1 - _st ) / _crv1; 794 else return _dst_dcrv1 + _dst_dphi21*d_phi2_dcrv1; 795 796 } 797 public double d_st_dr1( double d_phi2_dr1, double d_alf2_dr1 ) 798 { 799 if ( _big_crv ) return ( d_phi2_dr1 + d_alf2_dr1 ) / _crv1; 800 else return _dst_dr1*(_cnst1+_cnst2*d_phi2_dr1); 801 802 } 803 804 } 805 806 static void check_zero_propagation( VTrack trv0, VTrack trv, PropStat pstat) 807 { 808 809 SpacePoint sp = trv.spacePoint(); 810 SpacePoint sp0 = trv0.spacePoint(); 811 812 SpacePath sv = trv.spacePath(); 813 SpacePath sv0 = trv0.spacePath(); 814 815 // Assert.assertTrue( Math.abs(sv0.dx() - sv.dx())<1e-7 ); 816 // Assert.assertTrue( Math.abs(sv0.dy() - sv.dy())<1e-7 ); 817 // Assert.assertTrue( Math.abs(sv0.dz() - sv.dz())<1e-7 ); 818 819 double x0 = sp0.x(); 820 double y0 = sp0.y(); 821 double z0 = sp0.z(); 822 double x1 = sp.x(); 823 double y1 = sp.y(); 824 double z1 = sp.z(); 825 826 double dx = sv.dx(); 827 double dy = sv.dy(); 828 double dz = sv.dz(); 829 830 double prod = dx*(x1-x0)+dy*(y1-y0)+dz*(z1-z0); 831 double moda = Math.sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0) + (z1-z0)*(z1-z0)); 832 double modb = Math.sqrt(dx*dx+dy*dy+dz*dz); 833 double st = pstat.pathDistance(); 834 // Assert.assertTrue( Math.abs(prod-st) < 1.e-7 ); 835 // Assert.assertTrue( Math.abs(Math.abs(prod) - moda*modb) < 1.e-7 ); 836 } 837 838 static void check_derivatives( Propagator prop, VTrack trv0, Surface srf) 839 { 840 for(int i=0;i<4;++i) 841 for(int j=0;j<4;++j) 842 check_derivative(prop,trv0,srf,i,j); 843 } 844 845 static void check_derivative( Propagator prop, VTrack trv0, Surface srf,int i,int j) 846 { 847 848 double dx = 1.e-3; 849 VTrack trv = new VTrack(trv0); 850 TrackVector vec = trv.vector(); 851 boolean forward = trv0.isForward(); 852 853 VTrack trv_0 = new VTrack(trv0); 854 TrackDerivative der = new TrackDerivative(); 855 PropStat pstat = prop.vecProp(trv_0,srf,der); 856 Assert.assertTrue(pstat.success()); 857 858 TrackVector tmp=new TrackVector(vec); 859 tmp.set(j, tmp.get(j)+dx); 860 trv.setVector(tmp); 861 if(forward) trv.setForward(); 862 else trv.setBackward(); 863 864 VTrack trv_pl = new VTrack(trv); 865 pstat = prop.vecProp(trv_pl,srf); 866 Assert.assertTrue(pstat.success()); 867 868 TrackVector vecpl = trv_pl.vector(); 869 870 tmp= new TrackVector(vec); 871 tmp.set(j,tmp.get(j)-dx); 872 trv.setVector(tmp); 873 if(forward) trv.setForward(); 874 else trv.setBackward(); 875 876 VTrack trv_mn = new VTrack(trv); 877 pstat = prop.vecProp(trv_mn,srf); 878 Assert.assertTrue(pstat.success()); 879 880 TrackVector vecmn = trv_mn.vector(); 881 882 double dy = (vecpl.get(i)-vecmn.get(i))/2.; 883 884 double dydx = dy/dx; 885 886 double didj = der.get(i,j); 887 888 if( Math.abs(didj) > 1e-10 ) 889 Assert.assertTrue( Math.abs((dydx - didj)/didj) < 1e-4 ); 890 else 891 Assert.assertTrue( Math.abs(dydx) < 1e-4 ); 892 } 893 }