11 #define qBr2p 0.003 // conversion for converting q*B*r to GeV/c
13 #define MAX_SWIM_DIST 2000.0 // Maximum distance to swim a track in cm
20 this->bfield = bfield;
22 start_pos = pos =
DVector3(0.0,0.0,0.0);
23 start_mom = mom =
DVector3(0.0,0.0,1.0);
24 last_stepsize = stepsize = 0.5;
33 this->bfield = bfield;
37 last_stepsize = stepsize = 0.5;
57 this->last_stepsize = this->stepsize;
68 this->bfield = bfield;
78 this->stepsize = step;
79 this->last_stepsize = step;
106 bfield->GetField(pos.x(), pos.y(), pos.z(), Bx, By, Bz);
108 B.SetXYZ(Bx, By, Bz);
111 double Bmag = B.Mag();
113 xdir.SetXYZ(1.0,0.0,0.0);
114 ydir.SetXYZ(0.0,1.0,0.0);
115 zdir.SetXYZ(0.0,0.0,1.0);
122 double momMag = mom.Mag();
123 double one_over_BMagXmomMag = 1./(Bmag * momMag);
127 sin_theta = xdir.Mag()*one_over_BMagXmomMag;
128 if(xdir.Mag2()<1.0E-6)xdir = mom.Orthogonal();
129 if(xdir.Mag2()!=0.0)xdir.SetMag(1.0);
132 ydir = B.Cross(xdir);
133 if(ydir.Mag2()!=0.0)ydir.SetMag(1.0);
137 if(zdir.Mag2()!=0.0)zdir.SetMag(1.0);
143 cos_theta = B.Dot( mom )*one_over_BMagXmomMag;
147 Rp = momMag /(q*Bmag*
qBr2p);
161 if(stepsize==0.0)stepsize = this->stepsize;
164 double x=pos.x(),
y=pos.y(),z=pos.z();
165 double px=mom.x(),
py=mom.y(),pz=mom.z();
169 bfield->GetField(pos,B);
172 double k_q=0.002998*q;
173 double ds_over_p=stepsize/p;
174 double factor=k_q*(0.25*ds_over_p);
175 double Bx=B.x(),By=B.y(),Bz=B.z();
176 double Ax=factor*Bx,Ay=factor*By,Az=factor*Bz;
177 double Ax2=Ax*Ax,Ay2=Ay*Ay,Az2=Az*Az;
178 double AxAy=Ax*Ay,AxAz=Ax*Az,AyAz=Ay*Az;
179 double one_plus_Ax2=1.+Ax2;
180 double scale=ds_over_p/(one_plus_Ax2+Ay2+Az2);
183 double dx=scale*(px*one_plus_Ax2+
py*(AxAy+Az)+pz*(AxAz-Ay));
184 double dy=scale*(px*(AxAy-Az)+
py*(1.+Ay2)+pz*(AyAz+Ax));
185 double dz=scale*(px*(AxAz+Ay)+
py*(AyAz-Ax)+pz*(1.+Az2));
187 pos.SetXYZ(x+dx,
y+dy,z+dz);
188 mom.SetXYZ(px+k_q*(Bz*dy-By*dz),
py+k_q*(Bx*dz-Bz*dx),
189 pz+k_q*(By*dx-Bx*dy));
199 double VECT[7], VOUT[7+3];
204 VECT[3] = mom.x()/VECT[6];
205 VECT[4] = mom.y()/VECT[6];
206 VECT[5] = mom.z()/VECT[6];
207 if(stepsize==0.0)stepsize = this->stepsize;
208 double &STEP = stepsize;
212 grkuta_(&CHARGE, &STEP, VECT, VOUT, bfield);
214 pos.SetXYZ(VOUT[0], VOUT[1], VOUT[2]);
215 mom.SetXYZ(VOUT[3], VOUT[4], VOUT[5]);
222 B->SetXYZ(VOUT[7],VOUT[8],VOUT[9]);
224 if(newpos)*newpos = pos;
262 stepsize = 1.25*this->last_stepsize;
265 if(stepsize>this->stepsize)stepsize=this->stepsize;
269 if(B.Mag2()==0.0 || q==0.0){
271 pstep.SetMag(stepsize);
273 if(newpos)*newpos = pos;
284 DVector3 delta_z = zdir*stepsize*cos_theta;
287 double delta_phi = stepsize/Rp;
290 DVector3 delta_x = Ro*(1.0-cos(delta_phi))*xdir;
296 DVector3 mypos = pos + delta_x + delta_y + delta_z;
308 if(fabs(stepsize/Ro) > 1.0E-4){
310 bfield->GetField(mypos.x(), mypos.y(), mypos.z(), Bx, By, Bz);
313 double f = Bdiff.Mag()/B.Mag();
315 return Step(newpos, stepsize/2.0);
324 mom.Rotate(-delta_phi, B);
336 if(newpos)*newpos = pos;
339 last_stepsize = stepsize;
403 double b = norm.Dot(mymom)*norm.Dot(pos-origin);
404 bool momentum_and_charge_flipped =
false;
406 momentum_and_charge_flipped =
true;
412 SetStartingParams(q, &mypos, &mymom);
413 double k, start_k = norm.Dot(mypos-origin);
421 if(momentum_and_charge_flipped){
427 k = norm.Dot(mypos-origin);
428 }
while(k/start_k > 0.0);
438 double dz_dphi = Ro*mom.Dot(zdir)/mom.Dot(ydir);
444 bool use_straight_track_projection =
false;
445 if(isfinite(dz_dphi) && fabs(dz_dphi)<1.0E8){
448 double A = xdir.Dot(norm);
449 double B = ydir.Dot(norm);
450 double C = zdir.Dot(norm);
451 double D = pos_diff.Dot(norm);
453 double alpha = -A*Ro/2.0;
457 if(alpha!=0.0 && isfinite(alpha)){
459 double beta = B*Ro + C*dz_dphi;
464 double d =
sqrt(beta*beta - 4.0*alpha*D);
465 double phi1 = (-beta + d)/(2.0*alpha);
466 double phi2 = (-beta - d)/(2.0*alpha);
467 double phi = fabs(phi1)<fabs(phi2) ? phi1:phi2;
470 mypos += -Ro*phi*phi/2.0*xdir + Ro*phi*ydir + dz_dphi*phi*zdir;
473 mom.Rotate(phi, zdir);
477 double temp2=0.5*temp1*phi;
478 double temp3=dz_dphi*phi;
479 double delta=
sqrt(temp1*temp1+temp2*temp2+temp3*temp3);
481 s += (phi<0 ? -delta:+delta);
483 use_straight_track_projection =
true;
486 use_straight_track_projection =
true;
489 if(use_straight_track_projection){
491 double num = norm.Dot(origin - last_pos);
492 double den = norm.Dot( mypos - last_pos);
493 double alpha = num/den;
496 mypos = last_pos + alpha*delta;
497 s -= (1.0-
alpha)*delta.Mag();
501 if(pathlen)*pathlen = s ;
504 if(momentum_and_charge_flipped){
541 SetStartingParams(q, &mypos_loc, &mymom_loc);
548 double old_doca2=1001.0, doca2=1000.0;
549 while(doca2 < old_doca2){
557 if(mypos_loc.z()<0.0 || mypos_loc.z()>625. || mypos_loc.Perp()>65.0)
return 1;
561 last_pos = mypos_loc;
565 doca2=mypos_loc.Perp2();
571 double p = mom.Mag();
572 if(p < 0.001)
return true;
575 double p_hat_z=p_hat.Z();
579 double s=(p_hat_z*mypos_loc.Z()-p_hat.Dot(mypos_loc))/(1.-p_hat_z*p_hat_z);
647 SetStartingParams(q, &mypos, &mymom);
656 }
while(mypos.Perp() < R);
666 DVector2 x1(last_pos.X(), last_pos.Y());
669 double A = dx.Mod2();
670 double B = 2.0*(x1.X()*dx.X() + x1.Y()*dx.Y());
671 double C = x1.Mod2() - R*R;
673 double alpha1 = (-B +
sqrt(B*B-4.0*A*C))/(2.0*A);
674 double alpha2 = (-B -
sqrt(B*B-4.0*A*C))/(2.0*A);
675 double alpha = alpha1;
676 if(alpha1<0.0 || alpha1>1.0)alpha=alpha2;
677 if(!isfinite(alpha))
return true;
682 DVector3 pos1=last_pos+alpha1*delta;
683 DVector3 pos2=last_pos+alpha2*delta;
686 if ((pos1-mypos).Mag()<(pos2-mypos).Mag()){
691 s -= (1.0-alpha1)*delta.Mag();
698 s -= (1.0-alpha2)*delta.Mag();
702 if(pathlen)*pathlen=s;
bool SwimToPlane(DVector3 &pos, DVector3 &mom, const DVector3 &origin, const DVector3 &norm, double *pathlen=NULL)
bool DistToRadius(DVector3 &pos, double R)
bool SwimToRadius(DVector3 &pos, DVector3 &mom, double R, double *pathlen=NULL)
jerror_t SetStartingParams(double q, const DVector3 *x, const DVector3 *p)
void CalcDirs(double *Bvals=NULL)
DMagneticFieldStepper(const DMagneticFieldMap *map, double q=1.0)
bool SwimToPOCAtoBeamLine(double q, DVector3 &pos, DVector3 &mom)
double FastStep(double stepsize=0.0)
bool DistToPlane(DVector3 &pos, const DVector3 &origin, const DVector3 &norm)
int grkuta_(double *CHARGE, double *STEP, double *VECT, double *VOUT, const DMagneticFieldMap *bfield)
double Step(DVector3 *newpos=NULL, DVector3 *B=NULL, double stepsize=0.0)
jerror_t SetMagneticFieldMap(const DMagneticFieldMap *map)
jerror_t SetStepSize(double step)
void GetDirs(DVector3 &xdir, DVector3 &ydir, DVector3 &zdir)