File indexing completed on 2024-04-06 12:31:45
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include "MagneticField/Engine/interface/MagneticField.h"
0018 #include "MagneticField/VolumeBasedEngine/interface/VolumeBasedMagneticField.h"
0019 #include "MagneticField/VolumeGeometry/interface/MagVolume.h"
0020 #include "MagneticField/Interpolation/interface/MFGrid.h"
0021
0022 #include "DataFormats/GeometrySurface/interface/Cylinder.h"
0023 #include "DataFormats/GeometrySurface/interface/Plane.h"
0024 #include "DataFormats/GeometrySurface/interface/Cone.h"
0025
0026 #include "TrackingTools/GeomPropagators/interface/PropagationExceptions.h"
0027
0028 #include "TrackingTools/AnalyticalJacobians/interface/JacobianCartesianToCurvilinear.h"
0029 #include "TrackingTools/AnalyticalJacobians/interface/JacobianCurvilinearToCartesian.h"
0030
0031 #include "TrackPropagation/SteppingHelixPropagator/interface/SteppingHelixPropagator.h"
0032
0033 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0034
0035 #include <sstream>
0036 #include <typeinfo>
0037
0038 void SteppingHelixPropagator::initStateArraySHPSpecific(StateArray& svBuf, bool flagsOnly) const {
0039 for (int i = 0; i <= MAX_POINTS; i++) {
0040 svBuf[i].isComplete = true;
0041 svBuf[i].isValid_ = true;
0042 svBuf[i].hasErrorPropagated_ = !noErrorPropagation_;
0043 if (!flagsOnly) {
0044 svBuf[i].p3 = Vector(0, 0, 0);
0045 svBuf[i].r3 = Point(0, 0, 0);
0046 svBuf[i].bf = Vector(0, 0, 0);
0047 svBuf[i].bfGradLoc = Vector(0, 0, 0);
0048 svBuf[i].covCurv = AlgebraicSymMatrix55();
0049 svBuf[i].matDCovCurv = AlgebraicSymMatrix55();
0050 }
0051 }
0052 }
0053
0054 SteppingHelixPropagator::~SteppingHelixPropagator() {}
0055
0056 SteppingHelixPropagator::SteppingHelixPropagator() : Propagator(anyDirection) { field_ = nullptr; }
0057
0058 SteppingHelixPropagator::SteppingHelixPropagator(const MagneticField* field, PropagationDirection dir)
0059 : Propagator(dir), unit55_(AlgebraicMatrixID()) {
0060 field_ = field;
0061 vbField_ = dynamic_cast<const VolumeBasedMagneticField*>(field_);
0062 debug_ = false;
0063 noMaterialMode_ = false;
0064 noErrorPropagation_ = false;
0065 applyRadX0Correction_ = true;
0066 useMagVolumes_ = true;
0067 useIsYokeFlag_ = true;
0068 useMatVolumes_ = true;
0069 useInTeslaFromMagField_ = false;
0070 returnTangentPlane_ = true;
0071 sendLogWarning_ = false;
0072 useTuningForL2Speed_ = false;
0073 defaultStep_ = 5.;
0074
0075 ecShiftPos_ = 0;
0076 ecShiftNeg_ = 0;
0077 }
0078
0079 std::pair<TrajectoryStateOnSurface, double> SteppingHelixPropagator::propagateWithPath(
0080 const FreeTrajectoryState& ftsStart, const Plane& pDest) const {
0081 StateArray svBuf;
0082 initStateArraySHPSpecific(svBuf, true);
0083 int nPoints = 0;
0084 setIState(SteppingHelixStateInfo(ftsStart), svBuf, nPoints);
0085
0086 StateInfo svCurrent;
0087 propagate(svBuf[0], pDest, svCurrent);
0088
0089 return TsosPP(svCurrent.getStateOnSurface(pDest), svCurrent.path());
0090 }
0091
0092 std::pair<TrajectoryStateOnSurface, double> SteppingHelixPropagator::propagateWithPath(
0093 const FreeTrajectoryState& ftsStart, const Cylinder& cDest) const {
0094 StateArray svBuf;
0095 initStateArraySHPSpecific(svBuf, true);
0096 int nPoints = 0;
0097 setIState(SteppingHelixStateInfo(ftsStart), svBuf, nPoints);
0098
0099 StateInfo svCurrent;
0100 propagate(svBuf[0], cDest, svCurrent);
0101
0102 return TsosPP(svCurrent.getStateOnSurface(cDest, returnTangentPlane_), svCurrent.path());
0103 }
0104
0105 std::pair<FreeTrajectoryState, double> SteppingHelixPropagator::propagateWithPath(const FreeTrajectoryState& ftsStart,
0106 const GlobalPoint& pDest) const {
0107 StateArray svBuf;
0108 initStateArraySHPSpecific(svBuf, true);
0109 int nPoints = 0;
0110 setIState(SteppingHelixStateInfo(ftsStart), svBuf, nPoints);
0111
0112 StateInfo svCurrent;
0113 propagate(svBuf[0], pDest, svCurrent);
0114
0115 FreeTrajectoryState ftsDest;
0116 svCurrent.getFreeState(ftsDest);
0117
0118 return FtsPP(ftsDest, svCurrent.path());
0119 }
0120
0121 std::pair<FreeTrajectoryState, double> SteppingHelixPropagator::propagateWithPath(const FreeTrajectoryState& ftsStart,
0122 const GlobalPoint& pDest1,
0123 const GlobalPoint& pDest2) const {
0124 if ((pDest1 - pDest2).mag() < 1e-10) {
0125 if (sendLogWarning_) {
0126 edm::LogWarning("SteppingHelixPropagator")
0127 << "Can't propagate: the points should be at a bigger distance" << std::endl;
0128 }
0129 return FtsPP();
0130 }
0131 StateArray svBuf;
0132 initStateArraySHPSpecific(svBuf, true);
0133 int nPoints = 0;
0134 setIState(SteppingHelixStateInfo(ftsStart), svBuf, nPoints);
0135
0136 StateInfo svCurrent;
0137 propagate(svBuf[0], pDest1, pDest2, svCurrent);
0138
0139 FreeTrajectoryState ftsDest;
0140 svCurrent.getFreeState(ftsDest);
0141
0142 return FtsPP(ftsDest, svCurrent.path());
0143 }
0144
0145 std::pair<FreeTrajectoryState, double> SteppingHelixPropagator::propagateWithPath(
0146 const FreeTrajectoryState& ftsStart, const reco::BeamSpot& beamSpot) const {
0147 GlobalPoint pDest1(beamSpot.x0(), beamSpot.y0(), beamSpot.z0());
0148 GlobalPoint pDest2(pDest1.x() + beamSpot.dxdz() * 1e3, pDest1.y() + beamSpot.dydz() * 1e3, pDest1.z() + 1e3);
0149 return propagateWithPath(ftsStart, pDest1, pDest2);
0150 }
0151
0152 void SteppingHelixPropagator::propagate(const SteppingHelixStateInfo& sStart,
0153 const Surface& sDest,
0154 SteppingHelixStateInfo& out) const {
0155 if (!sStart.isValid()) {
0156 if (sendLogWarning_) {
0157 edm::LogWarning("SteppingHelixPropagator") << "Can't propagate: invalid input state" << std::endl;
0158 }
0159 out = invalidState_;
0160 return;
0161 }
0162
0163 const Plane* pDest = dynamic_cast<const Plane*>(&sDest);
0164 if (pDest != nullptr) {
0165 propagate(sStart, *pDest, out);
0166 return;
0167 }
0168
0169 const Cylinder* cDest = dynamic_cast<const Cylinder*>(&sDest);
0170 if (cDest != nullptr) {
0171 propagate(sStart, *cDest, out);
0172 return;
0173 }
0174
0175 throw PropagationException("The surface is neither Cylinder nor Plane");
0176 }
0177
0178 void SteppingHelixPropagator::propagate(const SteppingHelixStateInfo& sStart,
0179 const Plane& pDest,
0180 SteppingHelixStateInfo& out) const {
0181 if (!sStart.isValid()) {
0182 if (sendLogWarning_) {
0183 edm::LogWarning("SteppingHelixPropagator") << "Can't propagate: invalid input state" << std::endl;
0184 }
0185 out = invalidState_;
0186 return;
0187 }
0188 StateArray svBuf;
0189 initStateArraySHPSpecific(svBuf, true);
0190 int nPoints = 0;
0191 setIState(sStart, svBuf, nPoints);
0192
0193 Point rPlane(pDest.position().x(), pDest.position().y(), pDest.position().z());
0194 Vector nPlane(pDest.rotation().zx(), pDest.rotation().zy(), pDest.rotation().zz());
0195 nPlane /= nPlane.mag();
0196
0197 double pars[6] = {rPlane.x(), rPlane.y(), rPlane.z(), nPlane.x(), nPlane.y(), nPlane.z()};
0198
0199 propagate(svBuf, nPoints, PLANE_DT, pars);
0200
0201
0202
0203 double lDir = 0;
0204 if (sStart.path() < svBuf[cIndex_(nPoints - 1)].path())
0205 lDir = 1.;
0206 if (sStart.path() > svBuf[cIndex_(nPoints - 1)].path())
0207 lDir = -1.;
0208 svBuf[cIndex_(nPoints - 1)].dir = lDir;
0209
0210 out = svBuf[cIndex_(nPoints - 1)];
0211 return;
0212 }
0213
0214 void SteppingHelixPropagator::propagate(const SteppingHelixStateInfo& sStart,
0215 const Cylinder& cDest,
0216 SteppingHelixStateInfo& out) const {
0217 if (!sStart.isValid()) {
0218 if (sendLogWarning_) {
0219 edm::LogWarning("SteppingHelixPropagator") << "Can't propagate: invalid input state" << std::endl;
0220 }
0221 out = invalidState_;
0222 return;
0223 }
0224 StateArray svBuf;
0225 initStateArraySHPSpecific(svBuf, true);
0226 int nPoints = 0;
0227 setIState(sStart, svBuf, nPoints);
0228
0229 double pars[6] = {0, 0, 0, 0, 0, 0};
0230 pars[RADIUS_P] = cDest.radius();
0231
0232 propagate(svBuf, nPoints, RADIUS_DT, pars);
0233
0234
0235
0236 double lDir = 0;
0237 if (sStart.path() < svBuf[cIndex_(nPoints - 1)].path())
0238 lDir = 1.;
0239 if (sStart.path() > svBuf[cIndex_(nPoints - 1)].path())
0240 lDir = -1.;
0241 svBuf[cIndex_(nPoints - 1)].dir = lDir;
0242 out = svBuf[cIndex_(nPoints - 1)];
0243 return;
0244 }
0245
0246 void SteppingHelixPropagator::propagate(const SteppingHelixStateInfo& sStart,
0247 const GlobalPoint& pDest,
0248 SteppingHelixStateInfo& out) const {
0249 if (!sStart.isValid()) {
0250 if (sendLogWarning_) {
0251 edm::LogWarning("SteppingHelixPropagator") << "Can't propagate: invalid input state" << std::endl;
0252 }
0253 out = invalidState_;
0254 return;
0255 }
0256 StateArray svBuf;
0257 initStateArraySHPSpecific(svBuf, true);
0258 int nPoints = 0;
0259 setIState(sStart, svBuf, nPoints);
0260
0261 double pars[6] = {pDest.x(), pDest.y(), pDest.z(), 0, 0, 0};
0262
0263 propagate(svBuf, nPoints, POINT_PCA_DT, pars);
0264
0265 out = svBuf[cIndex_(nPoints - 1)];
0266 return;
0267 }
0268
0269 void SteppingHelixPropagator::propagate(const SteppingHelixStateInfo& sStart,
0270 const GlobalPoint& pDest1,
0271 const GlobalPoint& pDest2,
0272 SteppingHelixStateInfo& out) const {
0273 if ((pDest1 - pDest2).mag() < 1e-10 || !sStart.isValid()) {
0274 if (sendLogWarning_) {
0275 if ((pDest1 - pDest2).mag() < 1e-10)
0276 edm::LogWarning("SteppingHelixPropagator") << "Can't propagate: points are too close" << std::endl;
0277 if (!sStart.isValid())
0278 edm::LogWarning("SteppingHelixPropagator") << "Can't propagate: invalid input state" << std::endl;
0279 }
0280 out = invalidState_;
0281 return;
0282 }
0283 StateArray svBuf;
0284 initStateArraySHPSpecific(svBuf, true);
0285 int nPoints = 0;
0286 setIState(sStart, svBuf, nPoints);
0287
0288 double pars[6] = {pDest1.x(), pDest1.y(), pDest1.z(), pDest2.x(), pDest2.y(), pDest2.z()};
0289
0290 propagate(svBuf, nPoints, LINE_PCA_DT, pars);
0291
0292 out = svBuf[cIndex_(nPoints - 1)];
0293 return;
0294 }
0295
0296 void SteppingHelixPropagator::setIState(const SteppingHelixStateInfo& sStart, StateArray& svBuf, int& nPoints) const {
0297 nPoints = 0;
0298 svBuf[cIndex_(nPoints)] = sStart;
0299 if (sStart.isComplete) {
0300 svBuf[cIndex_(nPoints)] = sStart;
0301 nPoints++;
0302 } else {
0303 loadState(svBuf[cIndex_(nPoints)], sStart.p3, sStart.r3, sStart.q, propagationDirection(), sStart.covCurv);
0304 nPoints++;
0305 }
0306 svBuf[cIndex_(0)].hasErrorPropagated_ = sStart.hasErrorPropagated_ & !noErrorPropagation_;
0307 }
0308
0309 SteppingHelixPropagator::Result SteppingHelixPropagator::propagate(StateArray& svBuf,
0310 int& nPoints,
0311 SteppingHelixPropagator::DestType type,
0312 const double pars[6],
0313 double epsilon) const {
0314 static const std::string metname = "SteppingHelixPropagator";
0315 StateInfo* svCurrent = &svBuf[cIndex_(nPoints - 1)];
0316
0317
0318 double tanDist = 0;
0319 double dist = 0;
0320 PropagationDirection refDirection = anyDirection;
0321 Result result = refToDest(type, (*svCurrent), pars, dist, tanDist, refDirection);
0322
0323 if (result != SteppingHelixStateInfo::OK || fabs(dist) > 1e6) {
0324 svCurrent->status_ = result;
0325 if (fabs(dist) > 1e6)
0326 svCurrent->status_ = SteppingHelixStateInfo::INACC;
0327 svCurrent->isValid_ = false;
0328 svCurrent->field = field_;
0329 if (sendLogWarning_) {
0330 edm::LogWarning(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0331 << " Failed after first refToDest check with status "
0332 << SteppingHelixStateInfo::ResultName[result] << std::endl;
0333 }
0334 return result;
0335 }
0336
0337 result = SteppingHelixStateInfo::UNDEFINED;
0338 bool makeNextStep = true;
0339 double dStep = defaultStep_;
0340 PropagationDirection dir, oldDir;
0341 dir = propagationDirection();
0342 oldDir = dir;
0343 int nOsc = 0;
0344
0345 double distMag = 1e12;
0346 double tanDistMag = 1e12;
0347
0348 double distMat = 1e12;
0349 double tanDistMat = 1e12;
0350
0351 double tanDistNextCheck = -0.1;
0352 double tanDistMagNextCheck = -0.1;
0353 double tanDistMatNextCheck = -0.1;
0354 double oldDStep = 0;
0355 PropagationDirection oldRefDirection = propagationDirection();
0356
0357 Result resultToMat = SteppingHelixStateInfo::UNDEFINED;
0358 Result resultToMag = SteppingHelixStateInfo::UNDEFINED;
0359
0360 bool isFirstStep = true;
0361 bool expectNewMagVolume = false;
0362
0363 int loopCount = 0;
0364 while (makeNextStep) {
0365 dStep = defaultStep_;
0366 svCurrent = &svBuf[cIndex_(nPoints - 1)];
0367 double curZ = svCurrent->r3.z();
0368 double curR = svCurrent->r3.perp();
0369 if (fabs(curZ) < 440 && curR < 260)
0370 dStep = defaultStep_ * 2;
0371
0372
0373
0374 if (useTuningForL2Speed_) {
0375 dStep = 100.;
0376 if (!useIsYokeFlag_ && fabs(curZ) < 667 && curR > 380 && curR < 850) {
0377 dStep = 5 * (1 + 0.2 * svCurrent->p3.mag());
0378 }
0379 }
0380
0381
0382
0383 tanDistNextCheck -= oldDStep;
0384 tanDistMagNextCheck -= oldDStep;
0385 tanDistMatNextCheck -= oldDStep;
0386
0387 if (tanDistNextCheck < 0) {
0388
0389 if (!isFirstStep)
0390 refToDest(type, (*svCurrent), pars, dist, tanDist, refDirection);
0391
0392 if (fabs(tanDist) > 4. * (fabs(dist)))
0393 tanDist *= tanDist == 0 ? 0 : fabs(dist / tanDist * 4.);
0394
0395 tanDistNextCheck = fabs(tanDist) * 0.5 - 0.5;
0396
0397 if (tanDistNextCheck > defaultStep_ * 20.)
0398 tanDistNextCheck = defaultStep_ * 20.;
0399 oldRefDirection = refDirection;
0400 } else {
0401 tanDist = tanDist > 0. ? tanDist - oldDStep : tanDist + oldDStep;
0402 refDirection = oldRefDirection;
0403 if (debug_)
0404 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0405 << "Skipped refToDest: guess tanDist = " << tanDist << " next check at " << tanDistNextCheck
0406 << std::endl;
0407 }
0408
0409 double fastSkipDist = fabs(dist) > fabs(tanDist) ? tanDist : dist;
0410
0411 if (propagationDirection() == anyDirection) {
0412 dir = refDirection;
0413 } else {
0414 dir = propagationDirection();
0415 if (fabs(tanDist) < 0.1 && refDirection != dir) {
0416
0417 dir = refDirection;
0418 if (debug_)
0419 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0420 << "NOTE: overstepped last time: switch direction (can do it if within 1 mm)" << std::endl;
0421 }
0422 }
0423
0424 if (useMagVolumes_ && !(fabs(dist) < fabs(epsilon))) {
0425 if (tanDistMagNextCheck < 0) {
0426 resultToMag = refToMagVolume(
0427 (*svCurrent), dir, distMag, tanDistMag, fabs(fastSkipDist), expectNewMagVolume, fabs(tanDist));
0428
0429 if (fabs(tanDistMag) > 4. * (fabs(distMag)))
0430 tanDistMag *= tanDistMag == 0 ? 0 : fabs(distMag / tanDistMag * 4.);
0431
0432 tanDistMagNextCheck = fabs(tanDistMag) * 0.5 - 0.5;
0433
0434 if (tanDistMagNextCheck > defaultStep_ * 20. || fabs(dist) < fabs(distMag) ||
0435 resultToMag == SteppingHelixStateInfo::INACC)
0436 tanDistMagNextCheck = defaultStep_ * 20 > fabs(fastSkipDist) ? fabs(fastSkipDist) : defaultStep_ * 20;
0437 if (resultToMag != SteppingHelixStateInfo::INACC && resultToMag != SteppingHelixStateInfo::OK)
0438 tanDistMagNextCheck = -1;
0439 } else {
0440
0441 tanDistMag = tanDistMag > 0. ? tanDistMag - oldDStep : tanDistMag + oldDStep;
0442 if (debug_)
0443 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0444 << "Skipped refToMag: guess tanDistMag = " << tanDistMag << " next check at "
0445 << tanDistMagNextCheck;
0446 }
0447 }
0448
0449 if (useMatVolumes_ && !(fabs(dist) < fabs(epsilon))) {
0450 if (tanDistMatNextCheck < 0) {
0451 resultToMat = refToMatVolume((*svCurrent), dir, distMat, tanDistMat, fabs(fastSkipDist));
0452
0453 if (fabs(tanDistMat) > 4. * (fabs(distMat)))
0454 tanDistMat *= tanDistMat == 0 ? 0 : fabs(distMat / tanDistMat * 4.);
0455
0456 tanDistMatNextCheck = fabs(tanDistMat) * 0.5 - 0.5;
0457
0458 if (tanDistMatNextCheck > defaultStep_ * 20. || fabs(dist) < fabs(distMat) ||
0459 resultToMat == SteppingHelixStateInfo::INACC)
0460 tanDistMatNextCheck = defaultStep_ * 20 > fabs(fastSkipDist) ? fabs(fastSkipDist) : defaultStep_ * 20;
0461 if (resultToMat != SteppingHelixStateInfo::INACC && resultToMat != SteppingHelixStateInfo::OK)
0462 tanDistMatNextCheck = -1;
0463 } else {
0464
0465 tanDistMat = tanDistMat > 0. ? tanDistMat - oldDStep : tanDistMat + oldDStep;
0466 if (debug_)
0467 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0468 << "Skipped refToMat: guess tanDistMat = " << tanDistMat << " next check at "
0469 << tanDistMatNextCheck;
0470 }
0471 }
0472
0473 double rDotP = svCurrent->r3.dot(svCurrent->p3);
0474 if ((fabs(curZ) > 1.5e3 || curR > 800.) &&
0475 ((dir == alongMomentum && rDotP > 0) || (dir == oppositeToMomentum && rDotP < 0))) {
0476 dStep = fabs(tanDist) - 1e-12;
0477 }
0478 double tanDistMin = fabs(tanDist);
0479 if (tanDistMin > fabs(tanDistMag) + 0.05 &&
0480 (resultToMag == SteppingHelixStateInfo::OK || resultToMag == SteppingHelixStateInfo::WRONG_VOLUME)) {
0481 tanDistMin = fabs(tanDistMag) + 0.05;
0482 expectNewMagVolume = true;
0483 } else
0484 expectNewMagVolume = false;
0485
0486 if (tanDistMin > fabs(tanDistMat) + 0.05 && resultToMat == SteppingHelixStateInfo::OK) {
0487 tanDistMin = fabs(tanDistMat) + 0.05;
0488 if (expectNewMagVolume)
0489 expectNewMagVolume = false;
0490 }
0491
0492 if (tanDistMin * fabs(svCurrent->dEdx) > 0.5 * svCurrent->p3.mag()) {
0493 tanDistMin = 0.5 * svCurrent->p3.mag() / fabs(svCurrent->dEdx);
0494 if (expectNewMagVolume)
0495 expectNewMagVolume = false;
0496 }
0497
0498 double tanDistMinLazy = fabs(tanDistMin);
0499 if ((type == POINT_PCA_DT || type == LINE_PCA_DT) && fabs(tanDist) < 2. * fabs(tanDistMin)) {
0500
0501 tanDistMinLazy = fabs(tanDistMin) * 0.5;
0502 }
0503
0504 if (fabs(tanDistMinLazy) < dStep) {
0505 dStep = fabs(tanDistMinLazy);
0506 }
0507
0508
0509 oldDStep = dStep;
0510
0511 if (dStep > 1e-10 && !(fabs(dist) < fabs(epsilon))) {
0512 StateInfo* svNext = &svBuf[cIndex_(nPoints)];
0513 makeAtomStep((*svCurrent), (*svNext), dStep, dir, HEL_AS_F);
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526 nPoints++;
0527 svCurrent = &svBuf[cIndex_(nPoints - 1)];
0528 if (oldDir != dir) {
0529 nOsc++;
0530 tanDistNextCheck = -1;
0531 tanDistMagNextCheck = -1;
0532 tanDistMatNextCheck = -1;
0533 }
0534 oldDir = dir;
0535 }
0536
0537 if (nOsc > 1 && fabs(dStep) > epsilon) {
0538 if (debug_)
0539 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Ooops" << std::endl;
0540 }
0541
0542 if (fabs(dist) < fabs(epsilon))
0543 result = SteppingHelixStateInfo::OK;
0544
0545 if ((type == POINT_PCA_DT || type == LINE_PCA_DT) && fabs(dStep) < fabs(epsilon)) {
0546
0547 double nextDist = 0;
0548 double nextTanDist = 0;
0549 PropagationDirection nextRefDirection = anyDirection;
0550 StateInfo* svNext = &svBuf[cIndex_(nPoints)];
0551 makeAtomStep((*svCurrent), (*svNext), 1., dir, HEL_AS_F);
0552 nPoints++;
0553 svCurrent = &svBuf[cIndex_(nPoints - 1)];
0554 refToDest(type, (*svCurrent), pars, nextDist, nextTanDist, nextRefDirection);
0555 if (fabs(nextDist) > fabs(dist)) {
0556 nPoints--;
0557 svCurrent = &svBuf[cIndex_(nPoints - 1)];
0558 result = SteppingHelixStateInfo::OK;
0559 if (debug_) {
0560 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0561 << "Found real local minimum in PCA" << std::endl;
0562 }
0563 } else {
0564
0565 dStep = defaultStep_;
0566 if (debug_) {
0567 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Found branch point in PCA"
0568 << std::endl;
0569 }
0570 }
0571 }
0572
0573 if (nPoints > MAX_STEPS * 1. / defaultStep_ || loopCount > MAX_STEPS * 100 || nOsc > 6)
0574 result = SteppingHelixStateInfo::FAULT;
0575
0576 if (svCurrent->p3.mag() < 0.1)
0577 result = SteppingHelixStateInfo::RANGEOUT;
0578
0579 curZ = svCurrent->r3.z();
0580 curR = svCurrent->r3.perp();
0581 if (curR > 20000 || fabs(curZ) > 20000)
0582 result = SteppingHelixStateInfo::INACC;
0583
0584 makeNextStep = result == SteppingHelixStateInfo::UNDEFINED;
0585 svCurrent->status_ = result;
0586 svCurrent->isValid_ = (result == SteppingHelixStateInfo::OK || makeNextStep);
0587 svCurrent->field = field_;
0588
0589 isFirstStep = false;
0590 loopCount++;
0591 }
0592
0593 if (sendLogWarning_ && result != SteppingHelixStateInfo::OK) {
0594 edm::LogWarning(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0595 << " Propagation failed with status " << SteppingHelixStateInfo::ResultName[result]
0596 << std::endl;
0597 if (result == SteppingHelixStateInfo::RANGEOUT)
0598 edm::LogWarning(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0599 << " Momentum at last point is too low (<0.1) p_last = " << svCurrent->p3.mag()
0600 << std::endl;
0601 if (result == SteppingHelixStateInfo::INACC)
0602 edm::LogWarning(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0603 << " Went too far: the last point is at " << svCurrent->r3 << std::endl;
0604 if (result == SteppingHelixStateInfo::FAULT && nOsc > 6)
0605 edm::LogWarning(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0606 << " Infinite loop condidtion detected: going in cycles. Break after 6 cycles"
0607 << std::endl;
0608 if (result == SteppingHelixStateInfo::FAULT && nPoints > MAX_STEPS * 1. / defaultStep_)
0609 edm::LogWarning(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0610 << " Tired to go farther. Made too many steps: more than "
0611 << MAX_STEPS * 1. / defaultStep_ << std::endl;
0612 }
0613
0614 if (debug_) {
0615 switch (type) {
0616 case RADIUS_DT:
0617 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "going to radius "
0618 << pars[RADIUS_P] << std::endl;
0619 break;
0620 case Z_DT:
0621 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "going to z " << pars[Z_P]
0622 << std::endl;
0623 break;
0624 case PATHL_DT:
0625 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "going to pathL "
0626 << pars[PATHL_P] << std::endl;
0627 break;
0628 case PLANE_DT: {
0629 Point rPlane(pars[0], pars[1], pars[2]);
0630 Vector nPlane(pars[3], pars[4], pars[5]);
0631 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "going to plane r0:" << rPlane
0632 << " n:" << nPlane << std::endl;
0633 } break;
0634 case POINT_PCA_DT: {
0635 Point rDest(pars[0], pars[1], pars[2]);
0636 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "going to PCA to point "
0637 << rDest << std::endl;
0638 } break;
0639 case LINE_PCA_DT: {
0640 Point rDest1(pars[0], pars[1], pars[2]);
0641 Point rDest2(pars[3], pars[4], pars[5]);
0642 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "going to PCA to line "
0643 << rDest1 << " - " << rDest2 << std::endl;
0644 } break;
0645 default:
0646 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "going to NOT IMPLEMENTED"
0647 << std::endl;
0648 break;
0649 }
0650 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Made " << nPoints - 1
0651 << " steps and stopped at(cur step) " << svCurrent->r3 << " nOsc " << nOsc << std::endl;
0652 }
0653
0654 return result;
0655 }
0656
0657 void SteppingHelixPropagator::loadState(SteppingHelixPropagator::StateInfo& svCurrent,
0658 const SteppingHelixPropagator::Vector& p3,
0659 const SteppingHelixPropagator::Point& r3,
0660 int charge,
0661 PropagationDirection dir,
0662 const AlgebraicSymMatrix55& covCurv) const {
0663 static const std::string metname = "SteppingHelixPropagator";
0664
0665 svCurrent.q = charge;
0666 svCurrent.p3 = p3;
0667 svCurrent.r3 = r3;
0668 svCurrent.dir = dir == alongMomentum ? 1. : -1.;
0669
0670 svCurrent.path_ = 0;
0671 svCurrent.radPath_ = 0;
0672
0673 GlobalPoint gPointNorZ(svCurrent.r3.x(), svCurrent.r3.y(), svCurrent.r3.z());
0674
0675 float gpmag = gPointNorZ.mag2();
0676 float pmag2 = p3.mag2();
0677 if (gpmag > 1e20f) {
0678 LogTrace(metname) << "Initial point is too far";
0679 svCurrent.isValid_ = false;
0680 return;
0681 }
0682 if (pmag2 < 1e-18f) {
0683 LogTrace(metname) << "Initial momentum is too low";
0684 svCurrent.isValid_ = false;
0685 return;
0686 }
0687 if (!(gpmag == gpmag)) {
0688 LogTrace(metname) << "Initial point is a nan";
0689 edm::LogWarning("SteppingHelixPropagatorNAN") << "Initial point is a nan";
0690 svCurrent.isValid_ = false;
0691 return;
0692 }
0693 if (!(pmag2 == pmag2)) {
0694 LogTrace(metname) << "Initial momentum is a nan";
0695 edm::LogWarning("SteppingHelixPropagatorNAN") << "Initial momentum is a nan";
0696 svCurrent.isValid_ = false;
0697 return;
0698 }
0699
0700 GlobalVector bf(0, 0, 0);
0701
0702 if (useMagVolumes_) {
0703 if (vbField_) {
0704 svCurrent.magVol = vbField_->findVolume(gPointNorZ);
0705 if (useIsYokeFlag_) {
0706 double curRad = svCurrent.r3.perp();
0707 if (curRad > 380 && curRad < 850 && fabs(svCurrent.r3.z()) < 667) {
0708 svCurrent.isYokeVol = isYokeVolume(svCurrent.magVol);
0709 } else {
0710 svCurrent.isYokeVol = false;
0711 }
0712 }
0713 } else {
0714 edm::LogWarning(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0715 << "Failed to cast into VolumeBasedMagneticField: fall back to the default behavior"
0716 << std::endl;
0717 svCurrent.magVol = nullptr;
0718 }
0719 if (debug_) {
0720 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Got volume at "
0721 << svCurrent.magVol << std::endl;
0722 }
0723 }
0724
0725 if (useMagVolumes_ && svCurrent.magVol != nullptr && !useInTeslaFromMagField_) {
0726 bf = svCurrent.magVol->inTesla(gPointNorZ);
0727 if (debug_) {
0728 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Loaded bfield float: " << bf
0729 << " at global float " << gPointNorZ << " double " << svCurrent.r3 << std::endl;
0730 LocalPoint lPoint(svCurrent.magVol->toLocal(gPointNorZ));
0731 LocalVector lbf = svCurrent.magVol->fieldInTesla(lPoint);
0732 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "\t cf in local locF: " << lbf
0733 << " at " << lPoint << std::endl;
0734 }
0735 svCurrent.bf.set(bf.x(), bf.y(), bf.z());
0736 } else {
0737 GlobalPoint gPoint(r3.x(), r3.y(), r3.z());
0738 bf = field_->inTesla(gPoint);
0739 svCurrent.bf.set(bf.x(), bf.y(), bf.z());
0740 }
0741 if (svCurrent.bf.mag2() < 1e-32)
0742 svCurrent.bf.set(0., 0., 1e-16);
0743 if (debug_) {
0744 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0745 << "Loaded bfield double: " << svCurrent.bf << " from float: " << bf << " at float "
0746 << gPointNorZ << " double " << svCurrent.r3 << std::endl;
0747 }
0748
0749 double dEdXPrime = 0;
0750 double dEdx = 0;
0751 double radX0 = 0;
0752 MatBounds rzLims;
0753 dEdx = getDeDx(svCurrent, dEdXPrime, radX0, rzLims);
0754 svCurrent.dEdx = dEdx;
0755 svCurrent.dEdXPrime = dEdXPrime;
0756 svCurrent.radX0 = radX0;
0757 svCurrent.rzLims = rzLims;
0758
0759 svCurrent.covCurv = covCurv;
0760
0761 svCurrent.isComplete = true;
0762 svCurrent.isValid_ = true;
0763
0764 if (debug_) {
0765 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0766 << "Loaded at path: " << svCurrent.path() << " radPath: " << svCurrent.radPath() << " p3 "
0767 << " pt: " << svCurrent.p3.perp() << " phi: " << svCurrent.p3.phi()
0768 << " eta: " << svCurrent.p3.eta() << " " << svCurrent.p3 << " r3: " << svCurrent.r3
0769 << " bField: " << svCurrent.bf.mag() << std::endl;
0770 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0771 << "Input Covariance in Curvilinear RF " << covCurv << std::endl;
0772 }
0773 }
0774
0775 void SteppingHelixPropagator::getNextState(const SteppingHelixPropagator::StateInfo& svPrevious,
0776 SteppingHelixPropagator::StateInfo& svNext,
0777 double dP,
0778 const SteppingHelixPropagator::Vector& tau,
0779 const SteppingHelixPropagator::Vector& drVec,
0780 double dS,
0781 double dX0,
0782 const AlgebraicMatrix55& dCovCurvTransform) const {
0783 static const std::string metname = "SteppingHelixPropagator";
0784 svNext.q = svPrevious.q;
0785 svNext.dir = dS > 0.0 ? 1. : -1.;
0786 svNext.p3 = tau;
0787 svNext.p3 *= (svPrevious.p3.mag() - svNext.dir * fabs(dP));
0788
0789 svNext.r3 = svPrevious.r3;
0790 svNext.r3 += drVec;
0791
0792 svNext.path_ = svPrevious.path() + dS;
0793 svNext.radPath_ = svPrevious.radPath() + dX0;
0794
0795 GlobalPoint gPointNorZ(svNext.r3.x(), svNext.r3.y(), svNext.r3.z());
0796
0797 GlobalVector bf(0, 0, 0);
0798
0799 if (useMagVolumes_) {
0800 if (vbField_ != nullptr) {
0801 svNext.magVol = vbField_->findVolume(gPointNorZ);
0802 if (useIsYokeFlag_) {
0803 double curRad = svNext.r3.perp();
0804 if (curRad > 380 && curRad < 850 && fabs(svNext.r3.z()) < 667) {
0805 svNext.isYokeVol = isYokeVolume(svNext.magVol);
0806 } else {
0807 svNext.isYokeVol = false;
0808 }
0809 }
0810 } else {
0811 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
0812 << "Failed to cast into VolumeBasedMagneticField" << std::endl;
0813 svNext.magVol = nullptr;
0814 }
0815 if (debug_) {
0816 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Got volume at "
0817 << svNext.magVol << std::endl;
0818 }
0819 }
0820
0821 if (useMagVolumes_ && svNext.magVol != nullptr && !useInTeslaFromMagField_) {
0822 bf = svNext.magVol->inTesla(gPointNorZ);
0823 svNext.bf.set(bf.x(), bf.y(), bf.z());
0824 } else {
0825 GlobalPoint gPoint(svNext.r3.x(), svNext.r3.y(), svNext.r3.z());
0826 bf = field_->inTesla(gPoint);
0827 svNext.bf.set(bf.x(), bf.y(), bf.z());
0828 }
0829 if (svNext.bf.mag2() < 1e-32)
0830 svNext.bf.set(0., 0., 1e-16);
0831
0832 double dEdXPrime = 0;
0833 double dEdx = 0;
0834 double radX0 = 0;
0835 MatBounds rzLims;
0836 dEdx = getDeDx(svNext, dEdXPrime, radX0, rzLims);
0837 svNext.dEdx = dEdx;
0838 svNext.dEdXPrime = dEdXPrime;
0839 svNext.radX0 = radX0;
0840 svNext.rzLims = rzLims;
0841
0842
0843 svNext.hasErrorPropagated_ = svPrevious.hasErrorPropagated_;
0844 if (svPrevious.hasErrorPropagated_) {
0845 {
0846 AlgebraicMatrix55 tmp = dCovCurvTransform * svPrevious.covCurv;
0847 ROOT::Math::AssignSym::Evaluate(svNext.covCurv, tmp * ROOT::Math::Transpose(dCovCurvTransform));
0848
0849 svNext.covCurv += svPrevious.matDCovCurv;
0850 }
0851 } else {
0852
0853
0854 }
0855
0856 if (debug_) {
0857 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Now at path: " << svNext.path()
0858 << " radPath: " << svNext.radPath() << " p3 "
0859 << " pt: " << svNext.p3.perp() << " phi: " << svNext.p3.phi() << " eta: " << svNext.p3.eta()
0860 << " " << svNext.p3 << " r3: " << svNext.r3
0861 << " dPhi: " << acos(svNext.p3.unit().dot(svPrevious.p3.unit())) << " bField: " << svNext.bf.mag()
0862 << " dedx: " << svNext.dEdx << std::endl;
0863 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "New Covariance "
0864 << svNext.covCurv << std::endl;
0865 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Transf by dCovTransform "
0866 << dCovCurvTransform << std::endl;
0867 }
0868 }
0869
0870 void SteppingHelixPropagator::setRep(SteppingHelixPropagator::Basis& rep,
0871 const SteppingHelixPropagator::Vector& tau) const {
0872 Vector zRep(0., 0., 1.);
0873 rep.lX = tau;
0874 rep.lY = zRep.cross(tau);
0875 rep.lY *= 1. / tau.perp();
0876 rep.lZ = rep.lX.cross(rep.lY);
0877 }
0878
0879 bool SteppingHelixPropagator::makeAtomStep(SteppingHelixPropagator::StateInfo& svCurrent,
0880 SteppingHelixPropagator::StateInfo& svNext,
0881 double dS,
0882 PropagationDirection dir,
0883 SteppingHelixPropagator::Fancy fancy) const {
0884 static const std::string metname = "SteppingHelixPropagator";
0885 if (debug_) {
0886 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Make atom step "
0887 << svCurrent.path() << " with step " << dS << " in direction " << dir << std::endl;
0888 }
0889
0890 AlgebraicMatrix55 dCCurvTransform(unit55_);
0891
0892 double dP = 0;
0893 double curP = svCurrent.p3.mag();
0894 Vector tau = svCurrent.p3;
0895 tau *= 1. / curP;
0896 Vector tauNext(tau);
0897 Vector drVec(0, 0, 0);
0898
0899 dS = dir == alongMomentum ? fabs(dS) : -fabs(dS);
0900
0901 double radX0 = 1e24;
0902
0903 switch (fancy) {
0904 case HEL_AS_F:
0905 case HEL_ALL_F: {
0906 double p0 = curP;
0907 double p0Inv = 1. / p0;
0908 double b0 = svCurrent.bf.mag();
0909
0910
0911 double phi = (2.99792458e-3 * svCurrent.q * b0 * p0Inv) * dS / 2.;
0912 bool phiSmall = fabs(phi) < 1e-4;
0913
0914 double cosPhi = 0;
0915 double sinPhi = 0;
0916
0917 double oneLessCosPhi = 0;
0918 double oneLessCosPhiOPhi = 0;
0919 double phiLessSinPhiOPhi = 0;
0920
0921 if (phiSmall) {
0922 double phi2 = phi * phi;
0923 double phi3 = phi2 * phi;
0924 double phi4 = phi3 * phi;
0925 oneLessCosPhi = phi2 / 2. - phi4 / 24. + phi2 * phi4 / 720.;
0926 oneLessCosPhiOPhi = 0.5 * phi - phi3 / 24. + phi2 * phi3 / 720.;
0927 phiLessSinPhiOPhi = phi * phi / 6. - phi4 / 120. + phi4 * phi2 / 5040.;
0928 } else {
0929 cosPhi = cos(phi);
0930 sinPhi = sin(phi);
0931 oneLessCosPhi = 1. - cosPhi;
0932 oneLessCosPhiOPhi = oneLessCosPhi / phi;
0933 double sinPhiOPhi = sinPhi / phi;
0934 phiLessSinPhiOPhi = 1 - sinPhiOPhi;
0935 }
0936
0937 Vector bHat = svCurrent.bf;
0938 bHat *= 1. / b0;
0939
0940
0941 Vector btVec(bHat.cross(tau));
0942 double tauB = tau.dot(bHat);
0943 Vector bbtVec(bHat * tauB - tau);
0944
0945
0946 drVec = bbtVec * phiLessSinPhiOPhi;
0947 drVec -= btVec * oneLessCosPhiOPhi;
0948 drVec += tau;
0949 drVec *= dS / 2.;
0950
0951 double dEdx = svCurrent.dEdx;
0952 double dEdXPrime = svCurrent.dEdXPrime;
0953 radX0 = svCurrent.radX0;
0954 dP = dEdx * dS;
0955
0956
0957 drVec += svCurrent.r3;
0958 GlobalVector bfGV(0, 0, 0);
0959 Vector bf(0, 0, 0);
0960 if (useMagVolumes_ && svCurrent.magVol != nullptr && !useInTeslaFromMagField_) {
0961 bfGV = svCurrent.magVol->inTesla(GlobalPoint(drVec.x(), drVec.y(), drVec.z()));
0962 bf.set(bfGV.x(), bfGV.y(), bfGV.z());
0963 } else {
0964 bfGV = field_->inTesla(GlobalPoint(drVec.x(), drVec.y(), drVec.z()));
0965 bf.set(bfGV.x(), bfGV.y(), bfGV.z());
0966 }
0967 double b0Init = b0;
0968 b0 = bf.mag();
0969 if (b0 < 1e-16) {
0970 b0 = 1e-16;
0971 bf.set(0., 0., 1e-16);
0972 }
0973 if (debug_) {
0974 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Improved b " << b0
0975 << " at r3 " << drVec << std::endl;
0976 }
0977
0978 if (fabs((b0 - b0Init) * dS) > 1) {
0979
0980 if (debug_) {
0981 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Large bf*dS change "
0982 << fabs((b0 - svCurrent.bf.mag()) * dS) << " --> recalc dedx" << std::endl;
0983 }
0984 svNext.r3 = drVec;
0985 svNext.bf = bf;
0986 svNext.p3 = svCurrent.p3;
0987 svNext.isYokeVol = svCurrent.isYokeVol;
0988 svNext.magVol = svCurrent.magVol;
0989 MatBounds rzTmp;
0990 dEdx = getDeDx(svNext, dEdXPrime, radX0, rzTmp);
0991 dP = dEdx * dS;
0992 if (debug_) {
0993 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "New dEdX= " << dEdx
0994 << " dP= " << dP << " for p0 " << p0 << std::endl;
0995 }
0996 }
0997
0998 p0 += dP / 2.;
0999 if (p0 < 1e-2)
1000 p0 = 1e-2;
1001 p0Inv = 1. / p0;
1002
1003 phi = (2.99792458e-3 * svCurrent.q * b0 * p0Inv) * dS;
1004 phiSmall = fabs(phi) < 1e-4;
1005
1006 if (phiSmall) {
1007 double phi2 = phi * phi;
1008 double phi3 = phi2 * phi;
1009 double phi4 = phi3 * phi;
1010 sinPhi = phi - phi3 / 6. + phi4 * phi / 120.;
1011 cosPhi = 1. - phi2 / 2. + phi4 / 24.;
1012 oneLessCosPhi = phi2 / 2. - phi4 / 24. + phi2 * phi4 / 720.;
1013 oneLessCosPhiOPhi = 0.5 * phi - phi3 / 24. + phi2 * phi3 / 720.;
1014 phiLessSinPhiOPhi = phi * phi / 6. - phi4 / 120. + phi4 * phi2 / 5040.;
1015 } else {
1016 cosPhi = cos(phi);
1017 sinPhi = sin(phi);
1018 oneLessCosPhi = 1. - cosPhi;
1019 oneLessCosPhiOPhi = oneLessCosPhi / phi;
1020 double sinPhiOPhi = sinPhi / phi;
1021 phiLessSinPhiOPhi = 1. - sinPhiOPhi;
1022 }
1023
1024 bHat = bf;
1025 bHat *= 1. / b0;
1026
1027 btVec = bHat.cross(tau);
1028 tauB = tau.dot(bHat);
1029 bbtVec = bHat * tauB - tau;
1030
1031 tauNext = bbtVec * oneLessCosPhi;
1032 tauNext -= btVec * sinPhi;
1033 tauNext += tau;
1034 double tauNextPerpInv = 1. / tauNext.perp();
1035 drVec = bbtVec * phiLessSinPhiOPhi;
1036 drVec -= btVec * oneLessCosPhiOPhi;
1037 drVec += tau;
1038 drVec *= dS;
1039
1040 if (svCurrent.hasErrorPropagated_) {
1041 double theta02 = 0;
1042 double dX0 = fabs(dS) / radX0;
1043
1044 if (applyRadX0Correction_) {
1045
1046
1047
1048
1049 double x0 = fabs(svCurrent.radPath());
1050 double alphaX0 = 13.6e-3 * p0Inv;
1051 alphaX0 *= alphaX0;
1052 double betaX0 = 0.038;
1053 double logx0p1 = log(x0 + 1);
1054 theta02 = dX0 * alphaX0 * (1 + betaX0 * logx0p1) * (1 + betaX0 * logx0p1 + 2. * betaX0 * x0 / (x0 + 1));
1055 } else {
1056 theta02 = 196e-6 * p0Inv * p0Inv *
1057 dX0;
1058 }
1059
1060 double epsilonP0 = 1. + dP / (p0 - 0.5 * dP);
1061
1062
1063
1064 Vector tbtVec(bHat - tauB * tau);
1065
1066 {
1067
1068
1069
1070
1071
1072
1073 Point xStart = svCurrent.r3;
1074 const Vector& dx = drVec;
1075
1076
1077
1078
1079 double qbp = svCurrent.q * p0Inv;
1080
1081
1082
1083
1084 double t11 = tau.x();
1085 double t12 = tau.y();
1086 double t13 = tau.z();
1087 double t21 = tauNext.x();
1088 double t22 = tauNext.y();
1089 double t23 = tauNext.z();
1090 double cosl0 = tau.perp();
1091
1092 double cosecl1 = tauNextPerpInv;
1093
1094
1095
1096 const Vector& hn = bHat;
1097
1098
1099
1100 double q = -phi / dS;
1101
1102 double sint = -sinPhi;
1103 double cost = cosPhi;
1104 double hn1 = hn.x();
1105 double hn2 = hn.y();
1106 double hn3 = hn.z();
1107 double dx1 = dx.x();
1108 double dx2 = dx.y();
1109 double dx3 = dx.z();
1110
1111
1112 double gamma = hn1 * t21 + hn2 * t22 + hn3 * t23;
1113 double an1 = hn2 * t23 - hn3 * t22;
1114 double an2 = hn3 * t21 - hn1 * t23;
1115 double an3 = hn1 * t22 - hn2 * t21;
1116
1117 double auInv = cosl0;
1118 double au = auInv > 0 ? 1. / auInv : 1e24;
1119
1120 double u11 = -au * t12;
1121 double u12 = au * t11;
1122 double v11 = -t13 * u12;
1123 double v12 = t13 * u11;
1124 double v13 = auInv;
1125 auInv = sqrt(1. - t23 * t23);
1126 au = auInv > 0 ? 1. / auInv : 1e24;
1127
1128 double u21 = -au * t22;
1129 double u22 = au * t21;
1130 double v21 = -t23 * u22;
1131 double v22 = t23 * u21;
1132 double v23 = auInv;
1133
1134
1135
1136
1137
1138
1139 double anv = -(hn1 * u21 + hn2 * u22);
1140 double anu = (hn1 * v21 + hn2 * v22 + hn3 * v23);
1141 double omcost = oneLessCosPhi;
1142 double tmsint = -phi * phiLessSinPhiOPhi;
1143
1144 double hu1 = -hn3 * u12;
1145 double hu2 = hn3 * u11;
1146 double hu3 = hn1 * u12 - hn2 * u11;
1147
1148 double hv1 = hn2 * v13 - hn3 * v12;
1149 double hv2 = hn3 * v11 - hn1 * v13;
1150 double hv3 = hn1 * v12 - hn2 * v11;
1151
1152
1153 dCCurvTransform(0, 0) = 1. / (epsilonP0 * epsilonP0) * (1. + dS * dEdXPrime);
1154
1155
1156
1157 dCCurvTransform(1, 0) = phi * p0 / svCurrent.q * cosecl1 * (sinPhi * bbtVec.z() - cosPhi * btVec.z());
1158
1159
1160
1161 dCCurvTransform(1, 1) =
1162 cost * (v11 * v21 + v12 * v22 + v13 * v23) + sint * (hv1 * v21 + hv2 * v22 + hv3 * v23) +
1163 omcost * (hn1 * v11 + hn2 * v12 + hn3 * v13) * (hn1 * v21 + hn2 * v22 + hn3 * v23) +
1164 anv * (-sint * (v11 * t21 + v12 * t22 + v13 * t23) + omcost * (v11 * an1 + v12 * an2 + v13 * an3) -
1165 tmsint * gamma * (hn1 * v11 + hn2 * v12 + hn3 * v13));
1166
1167 dCCurvTransform(1, 2) = cost * (u11 * v21 + u12 * v22) + sint * (hu1 * v21 + hu2 * v22 + hu3 * v23) +
1168 omcost * (hn1 * u11 + hn2 * u12) * (hn1 * v21 + hn2 * v22 + hn3 * v23) +
1169 anv * (-sint * (u11 * t21 + u12 * t22) + omcost * (u11 * an1 + u12 * an2) -
1170 tmsint * gamma * (hn1 * u11 + hn2 * u12));
1171 dCCurvTransform(1, 2) *= cosl0;
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181 dCCurvTransform(2, 0) = -phi * p0 / svCurrent.q * cosecl1 * cosecl1 *
1182 (oneLessCosPhi * bHat.z() * btVec.mag2() + sinPhi * btVec.z() + cosPhi * tbtVec.z());
1183
1184
1185 dCCurvTransform(2, 1) =
1186 cost * (v11 * u21 + v12 * u22) + sint * (hv1 * u21 + hv2 * u22) +
1187 omcost * (hn1 * v11 + hn2 * v12 + hn3 * v13) * (hn1 * u21 + hn2 * u22) +
1188 anu * (-sint * (v11 * t21 + v12 * t22 + v13 * t23) + omcost * (v11 * an1 + v12 * an2 + v13 * an3) -
1189 tmsint * gamma * (hn1 * v11 + hn2 * v12 + hn3 * v13));
1190 dCCurvTransform(2, 1) *= cosecl1;
1191
1192 dCCurvTransform(2, 2) = cost * (u11 * u21 + u12 * u22) + sint * (hu1 * u21 + hu2 * u22) +
1193 omcost * (hn1 * u11 + hn2 * u12) * (hn1 * u21 + hn2 * u22) +
1194 anu * (-sint * (u11 * t21 + u12 * t22) + omcost * (u11 * an1 + u12 * an2) -
1195 tmsint * gamma * (hn1 * u11 + hn2 * u12));
1196 dCCurvTransform(2, 2) *= cosecl1 * cosl0;
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206 double pp = 1. / qbp;
1207
1208 dCCurvTransform(3, 0) = -pp * (u21 * dx1 + u22 * dx2);
1209 dCCurvTransform(4, 0) = -pp * (v21 * dx1 + v22 * dx2 + v23 * dx3);
1210
1211 dCCurvTransform(3, 1) = (sint * (v11 * u21 + v12 * u22) + omcost * (hv1 * u21 + hv2 * u22) +
1212 tmsint * (hn1 * u21 + hn2 * u22) * (hn1 * v11 + hn2 * v12 + hn3 * v13)) /
1213 q;
1214
1215 dCCurvTransform(3, 2) = (sint * (u11 * u21 + u12 * u22) + omcost * (hu1 * u21 + hu2 * u22) +
1216 tmsint * (hn1 * u21 + hn2 * u22) * (hn1 * u11 + hn2 * u12)) *
1217 cosl0 / q;
1218
1219 dCCurvTransform(3, 3) = (u11 * u21 + u12 * u22);
1220
1221 dCCurvTransform(3, 4) = (v11 * u21 + v12 * u22);
1222
1223
1224
1225 dCCurvTransform(4, 1) =
1226 (sint * (v11 * v21 + v12 * v22 + v13 * v23) + omcost * (hv1 * v21 + hv2 * v22 + hv3 * v23) +
1227 tmsint * (hn1 * v21 + hn2 * v22 + hn3 * v23) * (hn1 * v11 + hn2 * v12 + hn3 * v13)) /
1228 q;
1229
1230 dCCurvTransform(4, 2) = (sint * (u11 * v21 + u12 * v22) + omcost * (hu1 * v21 + hu2 * v22 + hu3 * v23) +
1231 tmsint * (hn1 * v21 + hn2 * v22 + hn3 * v23) * (hn1 * u11 + hn2 * u12)) *
1232 cosl0 / q;
1233
1234 dCCurvTransform(4, 3) = (u11 * v21 + u12 * v22);
1235
1236 dCCurvTransform(4, 4) = (v11 * v21 + v12 * v22 + v13 * v23);
1237
1238 }
1239
1240 if (debug_) {
1241 Basis rep;
1242 setRep(rep, tauNext);
1243 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "rep X: " << rep.lX << " "
1244 << rep.lX.mag() << "\t Y: " << rep.lY << " " << rep.lY.mag() << "\t Z: " << rep.lZ << " "
1245 << rep.lZ.mag();
1246 }
1247
1248
1249
1250
1251 double mulRR = theta02 * dS * dS / 3.;
1252 double mulRP = theta02 * fabs(dS) * p0 / 2.;
1253 double mulPP = theta02 * p0 * p0;
1254 double losPP = dP * dP * 1.6 / fabs(dS) * (1.0 + p0 * 1e-3);
1255
1256
1257
1258
1259
1260
1261 double sinThetaInv = tauNextPerpInv;
1262 double p0Mat =
1263 p0 + 0.5 * dP;
1264 double p0Mat2 = p0Mat * p0Mat;
1265
1266 svCurrent.matDCovCurv *= 0;
1267
1268 svCurrent.matDCovCurv(0, 0) = losPP / (p0Mat2 * p0Mat2);
1269
1270
1271
1272
1273
1274
1275 svCurrent.matDCovCurv(1, 1) = mulPP / p0Mat2;
1276
1277
1278 svCurrent.matDCovCurv(1, 4) = mulRP / p0Mat;
1279
1280
1281
1282 svCurrent.matDCovCurv(2, 2) = mulPP / p0Mat2 * (sinThetaInv * sinThetaInv);
1283 svCurrent.matDCovCurv(2, 3) = mulRP / p0Mat * sinThetaInv;
1284
1285
1286
1287
1288 svCurrent.matDCovCurv(3, 2) = mulRP / p0Mat * sinThetaInv;
1289
1290 svCurrent.matDCovCurv(3, 3) = mulRR;
1291
1292
1293
1294 svCurrent.matDCovCurv(4, 1) = mulRP / p0Mat;
1295
1296
1297 svCurrent.matDCovCurv(4, 4) = mulRR;
1298 }
1299 break;
1300 }
1301 default:
1302 break;
1303 }
1304
1305 double pMag = curP;
1306
1307 if (dir == oppositeToMomentum)
1308 dP = fabs(dP);
1309 else if (dP < 0) {
1310 dP = -dP > pMag ? -pMag + 1e-5 : dP;
1311 }
1312
1313 getNextState(svCurrent, svNext, dP, tauNext, drVec, dS, dS / radX0, dCCurvTransform);
1314 return true;
1315 }
1316
1317 double SteppingHelixPropagator::getDeDx(const SteppingHelixPropagator::StateInfo& sv,
1318 double& dEdXPrime,
1319 double& radX0,
1320 MatBounds& rzLims) const {
1321 radX0 = 1.e24;
1322 dEdXPrime = 0.;
1323 rzLims = MatBounds();
1324 if (noMaterialMode_)
1325 return 0;
1326
1327 double dEdx = 0.;
1328
1329 double lR = sv.r3.perp();
1330 double lZ = fabs(sv.r3.z());
1331
1332
1333
1334
1335 double dEdX_HCal = 0.95;
1336 double dEdX_ECal = 0.45;
1337 double dEdX_coil = 0.35;
1338 double dEdX_Fe = 1;
1339 double dEdX_MCh = 0.053;
1340 double dEdX_Trk = 0.0114;
1341 double dEdX_Air = 2E-4;
1342 double dEdX_Vac = 0.0;
1343
1344 double radX0_HCal = 1.44 / 0.8;
1345 double radX0_ECal = 0.89 / 0.7;
1346 double radX0_coil = 4.;
1347 double radX0_Fe = 1.76;
1348 double radX0_MCh = 1e3;
1349 double radX0_Trk = 320.;
1350 double radX0_Air = 3.e4;
1351 double radX0_Vac = 3.e9;
1352
1353
1354 if (!(lR < 380 && lZ < 785)) {
1355 if (lZ > 785)
1356 rzLims = MatBounds(0, 1e4, 785, 1e4);
1357 if (lZ < 785)
1358 rzLims = MatBounds(380, 1e4, 0, 785);
1359 }
1360
1361
1362
1363 double ecShift = sv.r3.z() > 0 ? fabs(ecShiftPos_) : fabs(ecShiftNeg_);
1364
1365
1366
1367 if (lR < 2.9) {
1368 dEdx = dEdX_Vac;
1369 radX0 = radX0_Vac;
1370 rzLims = MatBounds(0, 2.9, 0, 1E4);
1371 } else if (lR < 129) {
1372 if (lZ < 294) {
1373 rzLims = MatBounds(2.9, 129, 0, 294);
1374 dEdx = dEdX_Trk;
1375 radX0 = radX0_Trk;
1376
1377
1378
1379 double lEtaDet = fabs(sv.r3.eta());
1380 double scaleRadX = lEtaDet > 1.5 ? 0.7724 : 1. / cosh(0.5 * lEtaDet);
1381 scaleRadX *= scaleRadX;
1382 if (lEtaDet > 2 && lZ > 20)
1383 scaleRadX *= (lEtaDet - 1.);
1384 if (lEtaDet > 2.5 && lZ > 20)
1385 scaleRadX *= (lEtaDet - 1.);
1386 radX0 *= scaleRadX;
1387 }
1388
1389 else if (lZ < 294 + ecShift) {
1390
1391 rzLims = MatBounds(2.9, 129, 294, 294 + ecShift);
1392 dEdx = dEdX_Air;
1393 radX0 = radX0_Air;
1394 } else if (lZ < 372 + ecShift) {
1395 rzLims = MatBounds(2.9, 129, 294 + ecShift, 372 + ecShift);
1396 dEdx = dEdX_ECal;
1397 radX0 = radX0_ECal;
1398 }
1399 else if (lZ < 398 + ecShift) {
1400 rzLims =
1401 MatBounds(2.9, 129, 372 + ecShift, 398 + ecShift);
1402 dEdx = dEdX_HCal * 0.05;
1403 radX0 = radX0_Air;
1404 }
1405 else if (lZ < 555 + ecShift) {
1406 rzLims = MatBounds(2.9, 129, 398 + ecShift, 555 + ecShift);
1407 dEdx = dEdX_HCal * 0.96;
1408 radX0 = radX0_HCal / 0.96;
1409 }
1410 else {
1411
1412
1413
1414 if (lZ < 568 + ecShift)
1415 rzLims = MatBounds(2.9, 129, 555 + ecShift, 568 + ecShift);
1416 else if (lZ < 625 + ecShift) {
1417 if (lR < 85 + ecShift)
1418 rzLims = MatBounds(2.9, 85, 568 + ecShift, 625 + ecShift);
1419 else
1420 rzLims = MatBounds(85, 129, 568 + ecShift, 625 + ecShift);
1421 } else if (lZ < 785 + ecShift)
1422 rzLims = MatBounds(2.9, 129, 625 + ecShift, 785 + ecShift);
1423 else if (lZ < 1500 + ecShift)
1424 rzLims = MatBounds(2.9, 129, 785 + ecShift, 1500 + ecShift);
1425 else
1426 rzLims = MatBounds(2.9, 129, 1500 + ecShift, 1E4);
1427
1428
1429 if (!(lZ > 568 + ecShift && lZ < 625 + ecShift && lR > 85)
1430 && !(lZ > 785 + ecShift && lZ < 850 + ecShift && lR > 118)) {
1431 dEdx = dEdX_Fe;
1432 radX0 = radX0_Fe;
1433 } else {
1434 dEdx = dEdX_MCh;
1435 radX0 = radX0_MCh;
1436 }
1437 }
1438 } else if (lR < 287) {
1439 if (lZ < 372 + ecShift && lR < 177) {
1440 if (lZ < 304)
1441 rzLims = MatBounds(129, 177, 0, 304);
1442 else if (lZ < 343) {
1443 if (lR < 135)
1444 rzLims = MatBounds(129, 135, 304, 343);
1445 else if (lR < 172) {
1446 if (lZ < 311)
1447 rzLims = MatBounds(135, 172, 304, 311);
1448 else
1449 rzLims = MatBounds(135, 172, 311, 343);
1450 } else {
1451 if (lZ < 328)
1452 rzLims = MatBounds(172, 177, 304, 328);
1453 else
1454 rzLims = MatBounds(172, 177, 328, 343);
1455 }
1456 } else if (lZ < 343 + ecShift) {
1457 rzLims = MatBounds(129, 177, 343, 343 + ecShift);
1458 } else {
1459 if (lR < 156)
1460 rzLims = MatBounds(129, 156, 343 + ecShift, 372 + ecShift);
1461 else if ((lZ - 343 - ecShift) > (lR - 156) * 1.38)
1462 rzLims = MatBounds(156, 177, 127.72 + ecShift, 372 + ecShift, atan(1.38), 0);
1463 else
1464 rzLims = MatBounds(156, 177, 343 + ecShift, 127.72 + ecShift, 0, atan(1.38));
1465 }
1466
1467 if (!(lR > 135 && lZ < 343 + ecShift && lZ > 304) &&
1468 !(lR > 156 && lZ < 372 + ecShift && lZ > 343 + ecShift && ((lZ - 343. - ecShift) < (lR - 156.) * 1.38))) {
1469
1470 double cosThetaEquiv = 0.8 / sqrt(1. + lZ * lZ / lR / lR) + 0.2;
1471 if (lZ > 343)
1472 cosThetaEquiv = 1.;
1473 dEdx = dEdX_ECal * cosThetaEquiv;
1474 radX0 = radX0_ECal / cosThetaEquiv;
1475 }
1476 else {
1477 if ((lZ > 304 && lZ < 328 && lR < 177 && lR > 135) && !(lZ > 311 && lR < 172)) {
1478 dEdx = dEdX_Fe;
1479 radX0 = radX0_Fe;
1480 }
1481 else if (lZ > 343 && lZ < 343 + ecShift) {
1482 dEdx = dEdX_Air;
1483 radX0 = radX0_Air;
1484 } else {
1485 dEdx = dEdX_ECal * 0.2;
1486 radX0 = radX0_Air;
1487 }
1488 }
1489 } else if (lZ < 554 + ecShift) {
1490 if (lR < 177) {
1491 if (lZ > 372 + ecShift && lZ < 398 + ecShift)
1492 rzLims = MatBounds(129, 177, 372 + ecShift, 398 + ecShift);
1493 else if (lZ < 548 + ecShift)
1494 rzLims = MatBounds(129, 177, 398 + ecShift, 548 + ecShift);
1495 else
1496 rzLims = MatBounds(129, 177, 548 + ecShift, 554 + ecShift);
1497 } else if (lR < 193) {
1498 if ((lZ - 307) < (lR - 177.) * 1.739)
1499 rzLims = MatBounds(177, 193, 0, -0.803, 0, atan(1.739));
1500 else if (lZ < 389)
1501 rzLims = MatBounds(177, 193, -0.803, 389, atan(1.739), 0.);
1502 else if (lZ < 389 + ecShift)
1503 rzLims = MatBounds(177, 193, 389, 389 + ecShift);
1504 else if (lZ < 548 + ecShift)
1505 rzLims = MatBounds(177, 193, 389 + ecShift, 548 + ecShift);
1506 else
1507 rzLims = MatBounds(177, 193, 548 + ecShift, 554 + ecShift);
1508 } else if (lR < 264) {
1509 double anApex = 375.7278 - 193. / 1.327;
1510 if ((lZ - 375.7278) < (lR - 193.) / 1.327)
1511 rzLims = MatBounds(193, 264, 0, anApex, 0, atan(1. / 1.327));
1512 else if ((lZ - 392.7278) < (lR - 193.) / 1.327)
1513 rzLims = MatBounds(193, 264, anApex, anApex + 17., atan(1. / 1.327), atan(1. / 1.327));
1514 else if ((lZ - 392.7278 - ecShift) < (lR - 193.) / 1.327)
1515 rzLims = MatBounds(193,
1516 264,
1517 anApex + 17.,
1518 anApex + 17. + ecShift,
1519 atan(1. / 1.327),
1520 atan(1. / 1.327));
1521
1522 else if (lZ < 517 + ecShift)
1523 rzLims = MatBounds(193, 264, anApex + 17. + ecShift, 517 + ecShift, atan(1. / 1.327), 0);
1524 else if (lZ < 548 + ecShift) {
1525 if (lR < 246)
1526 rzLims = MatBounds(193, 246, 517 + ecShift, 548 + ecShift);
1527 else
1528 rzLims = MatBounds(246, 264, 517 + ecShift, 548 + ecShift);
1529 } else
1530 rzLims = MatBounds(193, 264, 548 + ecShift, 554 + ecShift);
1531 } else if (lR < 275) {
1532 if (lZ < 433)
1533 rzLims = MatBounds(264, 275, 0, 433);
1534 else if (lZ < 554)
1535 rzLims = MatBounds(264, 275, 433, 554);
1536 else
1537 rzLims = MatBounds(264, 275, 554, 554 + ecShift);
1538 } else {
1539 if (lZ < 402)
1540 rzLims = MatBounds(275, 287, 0, 402);
1541 else if (lZ < 554)
1542 rzLims = MatBounds(275, 287, 402, 554);
1543 else
1544 rzLims = MatBounds(275, 287, 554, 554 + ecShift);
1545 }
1546
1547 if ((lZ < 433 || lR < 264) && (lZ < 402 || lR < 275) &&
1548 (lZ < 517 + ecShift || lR < 246)
1549
1550 && lZ < 548 + ecShift && !(lZ < 389 + ecShift && lZ > 335 && lR < 193)
1551 && !(lZ > 307 && lZ < 335 && lR < 193 && ((lZ - 307) > (lR - 177.) * 1.739))
1552 && !(lR < 177 && lZ < 398 + ecShift)
1553 && !(lR < 264 && lR > 193 &&
1554 fabs(441.5 + 0.5 * ecShift - lZ + (lR - 269.) / 1.327) < (8.5 + ecShift * 0.5)))
1555 {
1556 dEdx = dEdX_HCal;
1557 radX0 = radX0_HCal;
1558 } else if ((lR < 193 && lZ > 389 && lZ < 389 + ecShift) ||
1559 (lR > 264 && lR < 287 && lZ > 554 && lZ < 554 + ecShift) ||
1560 (lR < 264 && lR > 193 &&
1561 fabs(441.5 + 8.5 + 0.5 * ecShift - lZ + (lR - 269.) / 1.327) < ecShift * 0.5)) {
1562 dEdx = dEdX_Air;
1563 radX0 = radX0_Air;
1564 } else {
1565 dEdx = dEdX_HCal * 0.05;
1566 radX0 = radX0_Air;
1567 }
1568 }
1569
1570 else if (lZ < 564 + ecShift) {
1571 if (lR < 251) {
1572 rzLims = MatBounds(129, 251, 554 + ecShift, 564 + ecShift);
1573 dEdx = dEdX_Fe;
1574 radX0 = radX0_Fe;
1575 }
1576 else {
1577 rzLims = MatBounds(251, 287, 554 + ecShift, 564 + ecShift);
1578 dEdx = dEdX_MCh;
1579 radX0 = radX0_MCh;
1580 }
1581 } else if (lZ < 625 + ecShift) {
1582 rzLims = MatBounds(129, 287, 564 + ecShift, 625 + ecShift);
1583 dEdx = dEdX_MCh;
1584 radX0 = radX0_MCh;
1585 } else if (lZ < 785 + ecShift) {
1586 if (lR < 275)
1587 rzLims = MatBounds(129, 275, 625 + ecShift, 785 + ecShift);
1588 else {
1589 if (lZ < 720 + ecShift)
1590 rzLims = MatBounds(275, 287, 625 + ecShift, 720 + ecShift);
1591 else
1592 rzLims = MatBounds(275, 287, 720 + ecShift, 785 + ecShift);
1593 }
1594 if (!(lR > 275 && lZ < 720 + ecShift)) {
1595 dEdx = dEdX_Fe;
1596 radX0 = radX0_Fe;
1597 }
1598 else {
1599 dEdx = dEdX_MCh;
1600 radX0 = radX0_MCh;
1601 }
1602 } else if (lZ < 850 + ecShift) {
1603 rzLims = MatBounds(129, 287, 785 + ecShift, 850 + ecShift);
1604 dEdx = dEdX_MCh;
1605 radX0 = radX0_MCh;
1606 } else if (lZ < 910 + ecShift) {
1607 rzLims = MatBounds(129, 287, 850 + ecShift, 910 + ecShift);
1608 dEdx = dEdX_Fe;
1609 radX0 = radX0_Fe;
1610 }
1611 else if (lZ < 975 + ecShift) {
1612 rzLims = MatBounds(129, 287, 910 + ecShift, 975 + ecShift);
1613 dEdx = dEdX_MCh;
1614 radX0 = radX0_MCh;
1615 } else if (lZ < 1000 + ecShift) {
1616 rzLims = MatBounds(129, 287, 975 + ecShift, 1000 + ecShift);
1617 dEdx = dEdX_Fe;
1618 radX0 = radX0_Fe;
1619 }
1620 else if (lZ < 1063 + ecShift) {
1621 rzLims = MatBounds(129, 287, 1000 + ecShift, 1063 + ecShift);
1622 dEdx = dEdX_MCh;
1623 radX0 = radX0_MCh;
1624 } else if (lZ < 1073 + ecShift) {
1625 rzLims = MatBounds(129, 287, 1063 + ecShift, 1073 + ecShift);
1626 dEdx = dEdX_Fe;
1627 radX0 = radX0_Fe;
1628 } else if (lZ < 1E4) {
1629 rzLims = MatBounds(129, 287, 1073 + ecShift, 1E4);
1630 dEdx = dEdX_Air;
1631 radX0 = radX0_Air;
1632 } else {
1633 dEdx = dEdX_Air;
1634 radX0 = radX0_Air;
1635 }
1636 } else if (lR < 380 && lZ < 667) {
1637 if (lZ < 630) {
1638 if (lR < 315)
1639 rzLims = MatBounds(287, 315, 0, 630);
1640 else if (lR < 341)
1641 rzLims = MatBounds(315, 341, 0, 630);
1642 else
1643 rzLims = MatBounds(341, 380, 0, 630);
1644 } else
1645 rzLims = MatBounds(287, 380, 630, 667);
1646
1647 if (lZ < 630) {
1648 dEdx = dEdX_coil;
1649 radX0 = radX0_coil;
1650 }
1651 else {
1652 dEdx = dEdX_Air;
1653 radX0 = radX0_Air;
1654 }
1655 } else {
1656 if (lZ < 667) {
1657 if (lR < 850) {
1658 bool isIron = false;
1659
1660 if (useIsYokeFlag_ && useMagVolumes_ && sv.magVol != nullptr) {
1661 isIron = sv.isYokeVol;
1662 } else {
1663 double bMag = sv.bf.mag();
1664 isIron = (bMag > 0.75 && !(lZ > 500 && lR < 500 && bMag < 1.15) && !(lZ < 450 && lR > 420 && bMag < 1.15));
1665 }
1666
1667 rzLims = MatBounds(380, 850, 0, 667);
1668 if (isIron) {
1669 dEdx = dEdX_Fe;
1670 radX0 = radX0_Fe;
1671 }
1672 else {
1673 dEdx = dEdX_MCh;
1674 radX0 = radX0_MCh;
1675 }
1676 } else {
1677 rzLims = MatBounds(850, 1E4, 0, 667);
1678 dEdx = dEdX_Air;
1679 radX0 = radX0_Air;
1680 }
1681 } else if (lR > 750) {
1682 rzLims = MatBounds(750, 1E4, 667, 1E4);
1683 dEdx = dEdX_Air;
1684 radX0 = radX0_Air;
1685 } else if (lZ < 667 + ecShift) {
1686 rzLims = MatBounds(287, 750, 667, 667 + ecShift);
1687 dEdx = dEdX_Air;
1688 radX0 = radX0_Air;
1689 }
1690
1691 else if (lZ < 724 + ecShift) {
1692 if (lR < 380)
1693 rzLims = MatBounds(287, 380, 667 + ecShift, 724 + ecShift);
1694 else
1695 rzLims = MatBounds(380, 750, 667 + ecShift, 724 + ecShift);
1696 dEdx = dEdX_MCh;
1697 radX0 = radX0_MCh;
1698 } else if (lZ < 785 + ecShift) {
1699 if (lR < 380)
1700 rzLims = MatBounds(287, 380, 724 + ecShift, 785 + ecShift);
1701 else
1702 rzLims = MatBounds(380, 750, 724 + ecShift, 785 + ecShift);
1703 dEdx = dEdX_Fe;
1704 radX0 = radX0_Fe;
1705 }
1706 else if (lZ < 850 + ecShift) {
1707 rzLims = MatBounds(287, 750, 785 + ecShift, 850 + ecShift);
1708 dEdx = dEdX_MCh;
1709 radX0 = radX0_MCh;
1710 } else if (lZ < 910 + ecShift) {
1711 rzLims = MatBounds(287, 750, 850 + ecShift, 910 + ecShift);
1712 dEdx = dEdX_Fe;
1713 radX0 = radX0_Fe;
1714 }
1715 else if (lZ < 975 + ecShift) {
1716 rzLims = MatBounds(287, 750, 910 + ecShift, 975 + ecShift);
1717 dEdx = dEdX_MCh;
1718 radX0 = radX0_MCh;
1719 } else if (lZ < 1000 + ecShift) {
1720 rzLims = MatBounds(287, 750, 975 + ecShift, 1000 + ecShift);
1721 dEdx = dEdX_Fe;
1722 radX0 = radX0_Fe;
1723 }
1724 else if (lZ < 1063 + ecShift) {
1725 if (lR < 360) {
1726 rzLims = MatBounds(287, 360, 1000 + ecShift, 1063 + ecShift);
1727 dEdx = dEdX_MCh;
1728 radX0 = radX0_MCh;
1729 }
1730
1731 else {
1732 rzLims = MatBounds(360, 750, 1000 + ecShift, 1063 + ecShift);
1733 dEdx = dEdX_Air;
1734 radX0 = radX0_Air;
1735 }
1736 } else if (lZ < 1073 + ecShift) {
1737 rzLims = MatBounds(287, 750, 1063 + ecShift, 1073 + ecShift);
1738
1739 dEdx = dEdX_Air;
1740 radX0 = radX0_Air;
1741 } else if (lZ < 1E4) {
1742 rzLims = MatBounds(287, 750, 1073 + ecShift, 1E4);
1743 dEdx = dEdX_Air;
1744 radX0 = radX0_Air;
1745 } else {
1746 dEdx = dEdX_Air;
1747 radX0 = radX0_Air;
1748 }
1749 }
1750
1751
1752
1753
1754 double p0 = sv.p3.mag();
1755 double logp0 = log(p0);
1756 double p0powN33 = 0;
1757 if (p0 > 3.) {
1758
1759 double xx = 1. / p0;
1760 xx = sqrt(sqrt(sqrt(sqrt(xx))));
1761 xx = xx * xx * xx * xx * xx;
1762 p0powN33 = xx;
1763 }
1764 double dEdX_mat = -(11.4 + 0.96 * fabs(logp0 + log(2.8)) + 0.033 * p0 * (1.0 - p0powN33)) * 1e-3;
1765
1766
1767 dEdXPrime = dEdx == 0 ? 0 : -dEdx * (0.96 / p0 + 0.033 - 0.022 * p0powN33) * 1e-3;
1768 dEdx *= dEdX_mat;
1769
1770 return dEdx;
1771 }
1772
1773 int SteppingHelixPropagator::cIndex_(int ind) const {
1774 int result = ind % MAX_POINTS;
1775 if (ind != 0 && result == 0) {
1776 result = MAX_POINTS;
1777 }
1778 return result;
1779 }
1780
1781 SteppingHelixPropagator::Result SteppingHelixPropagator::refToDest(SteppingHelixPropagator::DestType dest,
1782 const SteppingHelixPropagator::StateInfo& sv,
1783 const double pars[6],
1784 double& dist,
1785 double& tanDist,
1786 PropagationDirection& refDirection,
1787 double fastSkipDist) const {
1788 static const std::string metname = "SteppingHelixPropagator";
1789 Result result = SteppingHelixStateInfo::NOT_IMPLEMENTED;
1790
1791 switch (dest) {
1792 case RADIUS_DT: {
1793 double curR = sv.r3.perp();
1794 dist = pars[RADIUS_P] - curR;
1795 if (fabs(dist) > fastSkipDist) {
1796 result = SteppingHelixStateInfo::INACC;
1797 break;
1798 }
1799 double curP2 = sv.p3.mag2();
1800 double curPtPos2 = sv.p3.perp2();
1801 if (curPtPos2 < 1e-16)
1802 curPtPos2 = 1e-16;
1803
1804 double cosDPhiPR =
1805 (sv.r3.x() * sv.p3.x() + sv.r3.y() * sv.p3.y());
1806 refDirection = dist * cosDPhiPR > 0 ? alongMomentum : oppositeToMomentum;
1807 tanDist = dist * sqrt(curP2 / curPtPos2);
1808 result = SteppingHelixStateInfo::OK;
1809 } break;
1810 case Z_DT: {
1811 double curZ = sv.r3.z();
1812 dist = pars[Z_P] - curZ;
1813 if (fabs(dist) > fastSkipDist) {
1814 result = SteppingHelixStateInfo::INACC;
1815 break;
1816 }
1817 double curP = sv.p3.mag();
1818 refDirection = sv.p3.z() * dist > 0. ? alongMomentum : oppositeToMomentum;
1819 tanDist = dist / sv.p3.z() * curP;
1820 result = SteppingHelixStateInfo::OK;
1821 } break;
1822 case PLANE_DT: {
1823 Point rPlane(pars[0], pars[1], pars[2]);
1824 Vector nPlane(pars[3], pars[4], pars[5]);
1825
1826
1827
1828
1829 double dRDotN = (sv.r3.x() - rPlane.x()) * nPlane.x() + (sv.r3.y() - rPlane.y()) * nPlane.y() +
1830 (sv.r3.z() - rPlane.z()) * nPlane.z();
1831
1832 dist = fabs(dRDotN);
1833 if (dist > fastSkipDist) {
1834 result = SteppingHelixStateInfo::INACC;
1835 break;
1836 }
1837 double curP = sv.p3.mag();
1838 double p0 = curP;
1839 double p0Inv = 1. / p0;
1840 Vector tau(sv.p3);
1841 tau *= p0Inv;
1842 double tN = tau.dot(nPlane);
1843 refDirection = tN * dRDotN < 0. ? alongMomentum : oppositeToMomentum;
1844 double b0 = sv.bf.mag();
1845 if (fabs(tN) > 1e-24) {
1846 tanDist = -dRDotN / tN;
1847 } else {
1848 tN = 1e-24;
1849 if (fabs(dRDotN) > 1e-24)
1850 tanDist = 1e6;
1851 else
1852 tanDist = 1;
1853 }
1854 if (fabs(tanDist) > 1e4)
1855 tanDist = 1e4;
1856 if (b0 > 1.5e-6) {
1857 double b0Inv = 1. / b0;
1858 double tNInv = 1. / tN;
1859 Vector bHat(sv.bf);
1860 bHat *= b0Inv;
1861 double bHatN = bHat.dot(nPlane);
1862 double cosPB = bHat.dot(tau);
1863 double kVal = 2.99792458e-3 * sv.q * p0Inv * b0;
1864 double aVal = tanDist * kVal;
1865 Vector lVec = bHat.cross(tau);
1866 double bVal = lVec.dot(nPlane) * tNInv;
1867 if (fabs(aVal * bVal) < 0.3) {
1868 double cVal =
1869 1. - bHatN * cosPB * tNInv;
1870 double aacVal = cVal * aVal * aVal;
1871 if (fabs(aacVal) < 1) {
1872 double tanDCorr = bVal / 2. + (bVal * bVal / 2. + cVal / 6) * aVal;
1873 tanDCorr *= aVal;
1874
1875 if (debug_)
1876 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << tanDist << " vs "
1877 << tanDist * (1. + tanDCorr) << " corr " << tanDist * tanDCorr << std::endl;
1878 tanDist *= (1. + tanDCorr);
1879 } else {
1880 if (debug_)
1881 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "AACVal "
1882 << fabs(aacVal) << " = " << aVal << "**2 * " << cVal << " too large:: will not converge"
1883 << std::endl;
1884 }
1885 } else {
1886 if (debug_)
1887 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "ABVal "
1888 << fabs(aVal * bVal) << " = " << aVal << " * " << bVal << " too large:: will not converge"
1889 << std::endl;
1890 }
1891 }
1892 result = SteppingHelixStateInfo::OK;
1893 } break;
1894 case CONE_DT: {
1895 Point cVertex(pars[0], pars[1], pars[2]);
1896 if (cVertex.perp2() < 1e-10) {
1897
1898 Vector relV3 = sv.r3 - cVertex;
1899 double relV3mag = relV3.mag();
1900
1901 double theta(pars[3]);
1902
1903 double sinTheta = sin(theta);
1904 double cosTheta = cos(theta);
1905 double cosV3Theta = relV3.z() / relV3mag;
1906 if (cosV3Theta > 1)
1907 cosV3Theta = 1;
1908 if (cosV3Theta < -1)
1909 cosV3Theta = -1;
1910 double sinV3Theta = sqrt(1. - cosV3Theta * cosV3Theta);
1911
1912 double sinDTheta = sinTheta * cosV3Theta - cosTheta * sinV3Theta;
1913 double cosDTheta = cosTheta * cosV3Theta + sinTheta * sinV3Theta;
1914 bool isInside = sinTheta > sinV3Theta && cosTheta * cosV3Theta > 0;
1915 dist = isInside || cosDTheta > 0 ? relV3mag * sinDTheta : relV3mag;
1916 if (fabs(dist) > fastSkipDist) {
1917 result = SteppingHelixStateInfo::INACC;
1918 break;
1919 }
1920
1921 double relV3phi = relV3.phi();
1922 double normPhi = isInside ? Geom::pi() + relV3phi : relV3phi;
1923 double normTheta = theta > Geom::pi() / 2. ? (isInside ? 1.5 * Geom::pi() - theta : theta - Geom::pi() / 2.)
1924 : (isInside ? Geom::pi() / 2. - theta : theta + Geom::pi() / 2);
1925
1926 Vector norm;
1927 norm.setRThetaPhi(fabs(dist), normTheta, normPhi);
1928 double curP = sv.p3.mag();
1929 double cosp3theta = sv.p3.z() / curP;
1930 if (cosp3theta > 1)
1931 cosp3theta = 1;
1932 if (cosp3theta < -1)
1933 cosp3theta = -1;
1934 double sineConeP = sinTheta * cosp3theta - cosTheta * sqrt(1. - cosp3theta * cosp3theta);
1935
1936 double sinSolid = norm.dot(sv.p3) / (fabs(dist) * curP);
1937 tanDist = fabs(sinSolid) > fabs(sineConeP) ? dist / fabs(sinSolid) : dist / fabs(sineConeP);
1938
1939 refDirection = sinSolid > 0 ? oppositeToMomentum : alongMomentum;
1940 if (debug_) {
1941 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Cone pars: theta " << theta
1942 << " normTheta " << norm.theta() << " p3Theta " << sv.p3.theta() << " sinD: " << sineConeP
1943 << " sinSolid " << sinSolid;
1944 }
1945 if (debug_) {
1946 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
1947 << "refToDest:toCone the point is " << (isInside ? "in" : "out") << "side the cone"
1948 << std::endl;
1949 }
1950 }
1951 result = SteppingHelixStateInfo::OK;
1952 } break;
1953
1954
1955 case PATHL_DT: {
1956 double curS = fabs(sv.path());
1957 dist = pars[PATHL_P] - curS;
1958 if (fabs(dist) > fastSkipDist) {
1959 result = SteppingHelixStateInfo::INACC;
1960 break;
1961 }
1962 refDirection = pars[PATHL_P] > 0 ? alongMomentum : oppositeToMomentum;
1963 tanDist = dist;
1964 result = SteppingHelixStateInfo::OK;
1965 } break;
1966 case POINT_PCA_DT: {
1967 Point pDest(pars[0], pars[1], pars[2]);
1968 double curP = sv.p3.mag();
1969 dist = (sv.r3 - pDest).mag() + 1e-24;
1970 tanDist = (sv.r3.dot(sv.p3) - pDest.dot(sv.p3)) / curP;
1971
1972 double b0 = sv.bf.mag();
1973 if (b0 > 1.5e-6) {
1974 double p0 = curP;
1975 double kVal = 2.99792458e-3 * sv.q / p0 * b0;
1976 double aVal = fabs(dist * kVal);
1977 tanDist *= 1. / (1. + aVal);
1978 if (debug_)
1979 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "corrected by aVal " << aVal
1980 << " to " << tanDist;
1981 }
1982 refDirection = tanDist < 0 ? alongMomentum : oppositeToMomentum;
1983 result = SteppingHelixStateInfo::OK;
1984 } break;
1985 case LINE_PCA_DT: {
1986 Point rLine(pars[0], pars[1], pars[2]);
1987 Vector dLine(pars[3], pars[4], pars[5]);
1988 dLine = (dLine - rLine);
1989 dLine *= 1. / dLine.mag();
1990 if (debug_)
1991 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "dLine " << dLine;
1992
1993 Vector dR = sv.r3 - rLine;
1994 double curP = sv.p3.mag();
1995 Vector dRPerp = dR - dLine * (dR.dot(dLine));
1996 if (debug_)
1997 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "dRperp " << dRPerp;
1998
1999 dist = dRPerp.mag() + 1e-24;
2000 tanDist = dRPerp.dot(sv.p3) / curP;
2001
2002 double cosAlpha2 = dLine.dot(sv.p3) / curP;
2003 cosAlpha2 *= cosAlpha2;
2004 tanDist *= 1. / sqrt(fabs(1. - cosAlpha2) + 1e-96);
2005
2006
2007 double b0 = sv.bf.mag();
2008 if (b0 > 1.5e-6) {
2009 double p0 = curP;
2010 double kVal = 2.99792458e-3 * sv.q / p0 * b0;
2011 double aVal = fabs(dist * kVal);
2012 tanDist *= 1. / (1. + aVal);
2013 if (debug_)
2014 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "corrected by aVal " << aVal
2015 << " to " << tanDist;
2016 }
2017 refDirection = tanDist < 0 ? alongMomentum : oppositeToMomentum;
2018 result = SteppingHelixStateInfo::OK;
2019 } break;
2020 default: {
2021
2022 dist = 1e12;
2023 tanDist = 1e12;
2024 refDirection = anyDirection;
2025 result = SteppingHelixStateInfo::NOT_IMPLEMENTED;
2026 } break;
2027 }
2028
2029 double tanDistConstrained = tanDist;
2030 if (fabs(tanDist) > 4. * fabs(dist))
2031 tanDistConstrained *= tanDist == 0 ? 0 : fabs(dist / tanDist * 4.);
2032
2033 if (debug_) {
2034 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "refToDest input: dest" << dest
2035 << " pars[]: ";
2036 for (int i = 0; i < 6; i++) {
2037 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << ", " << i << " " << pars[i];
2038 }
2039 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << std::endl;
2040 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "refToDest output: "
2041 << "\t dist" << dist << "\t tanDist " << tanDist << "\t tanDistConstr " << tanDistConstrained
2042 << "\t refDirection " << refDirection << std::endl;
2043 }
2044 tanDist = tanDistConstrained;
2045
2046 return result;
2047 }
2048
2049 SteppingHelixPropagator::Result SteppingHelixPropagator::refToMagVolume(const SteppingHelixPropagator::StateInfo& sv,
2050 PropagationDirection dir,
2051 double& dist,
2052 double& tanDist,
2053 double fastSkipDist,
2054 bool expectNewMagVolume,
2055 double maxStep) const {
2056 static const std::string metname = "SteppingHelixPropagator";
2057 Result result = SteppingHelixStateInfo::NOT_IMPLEMENTED;
2058 const MagVolume* cVol = sv.magVol;
2059
2060 if (cVol == nullptr)
2061 return result;
2062 const std::vector<VolumeSide>& cVolFaces(cVol->faces());
2063
2064 double distToFace[6] = {0, 0, 0, 0, 0, 0};
2065 double tanDistToFace[6] = {0, 0, 0, 0, 0, 0};
2066 PropagationDirection refDirectionToFace[6] = {
2067 anyDirection, anyDirection, anyDirection, anyDirection, anyDirection, anyDirection};
2068 Result resultToFace[6] = {result, result, result, result, result, result};
2069 int iFDest = -1;
2070 int iDistMin = -1;
2071
2072 unsigned int iFDestSorted[6] = {0, 0, 0, 0, 0, 0};
2073 int nDestSorted = 0;
2074 unsigned int nearParallels = 0;
2075
2076 double curP = sv.p3.mag();
2077
2078 if (debug_) {
2079 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Trying volume "
2080 << " with " << cVolFaces.size() << " faces" << std::endl;
2081 }
2082
2083 unsigned int nFaces = cVolFaces.size();
2084 for (unsigned int iFace = 0; iFace < nFaces; ++iFace) {
2085 if (iFace > 5) {
2086 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Too many faces" << std::endl;
2087 }
2088 if (debug_) {
2089 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Start with face " << iFace
2090 << std::endl;
2091 }
2092
2093
2094
2095 const Surface* cPlane = nullptr;
2096 const Cylinder* cCyl = nullptr;
2097 const Cone* cCone = nullptr;
2098 auto& iSurface = cVolFaces[iFace].surface();
2099 if (typeid(iSurface) == typeid(const Plane&)) {
2100 cPlane = &cVolFaces[iFace].surface();
2101 } else if (typeid(iSurface) == typeid(const Cylinder&)) {
2102 cCyl = dynamic_cast<const Cylinder*>(&cVolFaces[iFace].surface());
2103 } else if (typeid(iSurface) == typeid(const Cone&)) {
2104 cCone = dynamic_cast<const Cone*>(&cVolFaces[iFace].surface());
2105 } else {
2106 edm::LogWarning(metname) << std::setprecision(17) << std::setw(20) << std::scientific
2107 << "Could not cast a volume side surface to a known type" << std::endl;
2108 }
2109
2110 if (debug_) {
2111 if (cPlane != nullptr)
2112 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "The face is a plane at "
2113 << cPlane << std::endl;
2114 if (cCyl != nullptr)
2115 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "The face is a cylinder at "
2116 << cCyl << std::endl;
2117 }
2118
2119 double pars[6] = {0, 0, 0, 0, 0, 0};
2120 DestType dType = UNDEFINED_DT;
2121 if (cPlane != nullptr) {
2122 Point rPlane(cPlane->position().x(), cPlane->position().y(), cPlane->position().z());
2123
2124 Vector nPlane(cPlane->rotation().zx(), cPlane->rotation().zy(), cPlane->rotation().zz());
2125 nPlane /= nPlane.mag();
2126
2127 pars[0] = rPlane.x();
2128 pars[1] = rPlane.y();
2129 pars[2] = rPlane.z();
2130 pars[3] = nPlane.x();
2131 pars[4] = nPlane.y();
2132 pars[5] = nPlane.z();
2133 dType = PLANE_DT;
2134 } else if (cCyl != nullptr) {
2135 if (debug_) {
2136 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Cylinder at "
2137 << cCyl->position() << " rorated by " << cCyl->rotation() << std::endl;
2138 }
2139 pars[RADIUS_P] = cCyl->radius();
2140 dType = RADIUS_DT;
2141 } else if (cCone != nullptr) {
2142 if (debug_) {
2143 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Cone at "
2144 << cCone->position() << " rorated by " << cCone->rotation() << " vertex at "
2145 << cCone->vertex() << " angle of " << cCone->openingAngle() << std::endl;
2146 }
2147 pars[0] = cCone->vertex().x();
2148 pars[1] = cCone->vertex().y();
2149 pars[2] = cCone->vertex().z();
2150 pars[3] = cCone->openingAngle();
2151 dType = CONE_DT;
2152 } else {
2153 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Unknown surface" << std::endl;
2154 resultToFace[iFace] = SteppingHelixStateInfo::UNDEFINED;
2155 continue;
2156 }
2157 resultToFace[iFace] =
2158 refToDest(dType, sv, pars, distToFace[iFace], tanDistToFace[iFace], refDirectionToFace[iFace], fastSkipDist);
2159
2160 if (resultToFace[iFace] != SteppingHelixStateInfo::OK) {
2161 if (resultToFace[iFace] == SteppingHelixStateInfo::INACC)
2162 result = SteppingHelixStateInfo::INACC;
2163 }
2164
2165
2166 if (resultToFace[iFace] == SteppingHelixStateInfo::OK) {
2167 double invDTFPosiF = 1. / (1e-32 + fabs(tanDistToFace[iFace]));
2168 double dSlope = fabs(distToFace[iFace]) * invDTFPosiF;
2169 double maxStepL = maxStep > 100 ? 100 : maxStep;
2170 if (maxStepL < 10)
2171 maxStepL = 10.;
2172 bool isNearParallel =
2173 fabs(tanDistToFace[iFace]) + 100. * curP * dSlope < maxStepL
2174
2175 && dSlope < 0.15;
2176 if (refDirectionToFace[iFace] == dir || isNearParallel) {
2177 if (isNearParallel)
2178 nearParallels++;
2179 iFDestSorted[nDestSorted] = iFace;
2180 nDestSorted++;
2181 }
2182 }
2183
2184
2185 if (refDirectionToFace[iFace] == dir) {
2186 if (iDistMin == -1)
2187 iDistMin = iFace;
2188 else if (fabs(distToFace[iFace]) < fabs(distToFace[iDistMin]))
2189 iDistMin = iFace;
2190 }
2191 if (debug_)
2192 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << cVol << " " << iFace << " "
2193 << tanDistToFace[iFace] << " " << distToFace[iFace] << " " << refDirectionToFace[iFace] << " "
2194 << dir << std::endl;
2195 }
2196
2197 for (int i = 0; i < nDestSorted; ++i) {
2198 int iMax = nDestSorted - i - 1;
2199 for (int j = 0; j < nDestSorted - i; ++j) {
2200 if (fabs(tanDistToFace[iFDestSorted[j]]) > fabs(tanDistToFace[iFDestSorted[iMax]])) {
2201 iMax = j;
2202 }
2203 }
2204 int iTmp = iFDestSorted[nDestSorted - i - 1];
2205 iFDestSorted[nDestSorted - i - 1] = iFDestSorted[iMax];
2206 iFDestSorted[iMax] = iTmp;
2207 }
2208
2209 if (debug_) {
2210 for (int i = 0; i < nDestSorted; ++i) {
2211 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << cVol << " " << i << " "
2212 << iFDestSorted[i] << " " << tanDistToFace[iFDestSorted[i]] << std::endl;
2213 }
2214 }
2215
2216
2217
2218
2219 for (int i = 0; i < nDestSorted; ++i) {
2220 iFDest = iFDestSorted[i];
2221
2222 double sign = dir == alongMomentum ? 1. : -1.;
2223 Point gPointEst(sv.r3);
2224 Vector lDelta(sv.p3);
2225 lDelta *= sign / curP * fabs(distToFace[iFDest]);
2226 gPointEst += lDelta;
2227 if (debug_) {
2228 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Linear est point " << gPointEst
2229 << " for iFace " << iFDest << std::endl;
2230 }
2231 GlobalPoint gPointEstNorZ(gPointEst.x(), gPointEst.y(), gPointEst.z());
2232 if (cVol->inside(gPointEstNorZ)) {
2233 if (debug_) {
2234 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
2235 << "The point is inside the volume" << std::endl;
2236 }
2237
2238 result = SteppingHelixStateInfo::OK;
2239 dist = distToFace[iFDest];
2240 tanDist = tanDistToFace[iFDest];
2241 if (debug_) {
2242 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
2243 << "Got a point near closest boundary -- face " << iFDest << std::endl;
2244 }
2245 break;
2246 }
2247 }
2248
2249 if (result != SteppingHelixStateInfo::OK && expectNewMagVolume) {
2250 double sign = dir == alongMomentum ? 1. : -1.;
2251
2252
2253 if (nDestSorted - nearParallels > 0)
2254 result = SteppingHelixStateInfo::WRONG_VOLUME;
2255 else {
2256
2257 Point gPointEst(sv.r3);
2258 double lDist = iDistMin == -1 ? fastSkipDist : fabs(distToFace[iDistMin]);
2259 if (lDist > fastSkipDist)
2260 lDist = fastSkipDist;
2261 Vector lDelta(sv.p3);
2262 lDelta *= sign / curP * lDist;
2263 gPointEst += lDelta;
2264 if (debug_) {
2265 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
2266 << "Linear est point to shortest dist " << gPointEst << " for iFace " << iDistMin
2267 << " at distance " << lDist * sign << std::endl;
2268 }
2269 GlobalPoint gPointEstNorZ(gPointEst.x(), gPointEst.y(), gPointEst.z());
2270 if (cVol->inside(gPointEstNorZ)) {
2271 if (debug_) {
2272 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
2273 << "The point is inside the volume" << std::endl;
2274 }
2275
2276 } else {
2277 result = SteppingHelixStateInfo::WRONG_VOLUME;
2278 }
2279 }
2280
2281 if (result == SteppingHelixStateInfo::WRONG_VOLUME) {
2282 dist = sign * 0.05;
2283 tanDist = dist * 1.01;
2284 if (debug_) {
2285 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
2286 << "Wrong volume located: return small dist, tandist" << std::endl;
2287 }
2288 }
2289 }
2290
2291 if (result == SteppingHelixStateInfo::INACC) {
2292 if (debug_)
2293 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "All faces are too far"
2294 << std::endl;
2295 } else if (result == SteppingHelixStateInfo::WRONG_VOLUME) {
2296 if (debug_)
2297 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Appear to be in a wrong volume"
2298 << std::endl;
2299 } else if (result != SteppingHelixStateInfo::OK) {
2300 if (debug_)
2301 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Something else went wrong"
2302 << std::endl;
2303 }
2304
2305 return result;
2306 }
2307
2308 SteppingHelixPropagator::Result SteppingHelixPropagator::refToMatVolume(const SteppingHelixPropagator::StateInfo& sv,
2309 PropagationDirection dir,
2310 double& dist,
2311 double& tanDist,
2312 double fastSkipDist) const {
2313 static const std::string metname = "SteppingHelixPropagator";
2314 Result result = SteppingHelixStateInfo::NOT_IMPLEMENTED;
2315
2316 double parLim[6] = {sv.rzLims.rMin, sv.rzLims.rMax, sv.rzLims.zMin, sv.rzLims.zMax, sv.rzLims.th1, sv.rzLims.th2};
2317
2318 double distToFace[4] = {0, 0, 0, 0};
2319 double tanDistToFace[4] = {0, 0, 0, 0};
2320 PropagationDirection refDirectionToFace[4] = {anyDirection, anyDirection, anyDirection, anyDirection};
2321 Result resultToFace[4] = {result, result, result, result};
2322 int iFDest = -1;
2323
2324 double curP = sv.p3.mag();
2325
2326 for (unsigned int iFace = 0; iFace < 4; iFace++) {
2327 if (debug_) {
2328 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Start with mat face " << iFace
2329 << std::endl;
2330 }
2331
2332 double pars[6] = {0, 0, 0, 0, 0, 0};
2333 DestType dType = UNDEFINED_DT;
2334 if (iFace > 1) {
2335 if (fabs(parLim[iFace + 2]) < 1e-6) {
2336 if (sv.r3.z() < 0) {
2337 pars[0] = 0;
2338 pars[1] = 0;
2339 pars[2] = -parLim[iFace];
2340 pars[3] = 0;
2341 pars[4] = 0;
2342 pars[5] = 1;
2343 } else {
2344 pars[0] = 0;
2345 pars[1] = 0;
2346 pars[2] = parLim[iFace];
2347 pars[3] = 0;
2348 pars[4] = 0;
2349 pars[5] = 1;
2350 }
2351 dType = PLANE_DT;
2352 } else {
2353 if (sv.r3.z() > 0) {
2354 pars[0] = 0;
2355 pars[1] = 0;
2356 pars[2] = parLim[iFace];
2357 pars[3] = Geom::pi() / 2. - parLim[iFace + 2];
2358 } else {
2359 pars[0] = 0;
2360 pars[1] = 0;
2361 pars[2] = -parLim[iFace];
2362 pars[3] = Geom::pi() / 2. + parLim[iFace + 2];
2363 }
2364 dType = CONE_DT;
2365 }
2366 } else {
2367 pars[RADIUS_P] = parLim[iFace];
2368 dType = RADIUS_DT;
2369 }
2370
2371 resultToFace[iFace] =
2372 refToDest(dType, sv, pars, distToFace[iFace], tanDistToFace[iFace], refDirectionToFace[iFace], fastSkipDist);
2373
2374 if (resultToFace[iFace] != SteppingHelixStateInfo::OK) {
2375 if (resultToFace[iFace] == SteppingHelixStateInfo::INACC)
2376 result = SteppingHelixStateInfo::INACC;
2377 continue;
2378 }
2379 if (refDirectionToFace[iFace] == dir || fabs(distToFace[iFace]) < 2e-2 * fabs(tanDistToFace[iFace])) {
2380 double sign = dir == alongMomentum ? 1. : -1.;
2381 Point gPointEst(sv.r3);
2382 Vector lDelta(sv.p3);
2383 lDelta *= sign * fabs(distToFace[iFace]) / curP;
2384 gPointEst += lDelta;
2385 if (debug_) {
2386 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific << "Linear est point "
2387 << gPointEst << std::endl;
2388 }
2389 double lZ = fabs(gPointEst.z());
2390 double lR = gPointEst.perp();
2391 double tan4 = parLim[4] == 0 ? 0 : tan(parLim[4]);
2392 double tan5 = parLim[5] == 0 ? 0 : tan(parLim[5]);
2393 if ((lZ - parLim[2]) > lR * tan4 && (lZ - parLim[3]) < lR * tan5 && lR > parLim[0] && lR < parLim[1]) {
2394 if (debug_) {
2395 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
2396 << "The point is inside the volume" << std::endl;
2397 }
2398
2399 if (iFDest == -1) {
2400 iFDest = iFace;
2401 } else {
2402 if (fabs(tanDistToFace[iFDest]) > fabs(tanDistToFace[iFace])) {
2403 iFDest = iFace;
2404 }
2405 }
2406 } else {
2407 if (debug_) {
2408 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
2409 << "The point is NOT inside the volume" << std::endl;
2410 }
2411 }
2412 }
2413 }
2414 if (iFDest != -1) {
2415 result = SteppingHelixStateInfo::OK;
2416 dist = distToFace[iFDest];
2417 tanDist = tanDistToFace[iFDest];
2418 if (debug_) {
2419 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
2420 << "Got a point near closest boundary -- face " << iFDest << std::endl;
2421 }
2422 } else {
2423 if (debug_) {
2424 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
2425 << "Failed to find a dest point inside the volume" << std::endl;
2426 }
2427 }
2428
2429 return result;
2430 }
2431
2432 bool SteppingHelixPropagator::isYokeVolume(const MagVolume* vol) const {
2433 static const std::string metname = "SteppingHelixPropagator";
2434 if (vol == nullptr)
2435 return false;
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457 bool result = vol->isIron();
2458 if (result) {
2459 if (debug_)
2460 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
2461 << "Volume is magnetic, located at " << vol->position() << std::endl;
2462 } else {
2463 if (debug_)
2464 LogTrace(metname) << std::setprecision(17) << std::setw(20) << std::scientific
2465 << "Volume is not magnetic, located at " << vol->position() << std::endl;
2466 }
2467
2468 return result;
2469 }