CMS 3D CMS Logo

LayerNavigator.cc
Go to the documentation of this file.
3 
4 #include <vector>
5 
7 
14 
59 
61  : geometry_(&geometry),
62  nextBarrelLayer_(nullptr),
63  previousBarrelLayer_(nullptr),
64  nextForwardLayer_(nullptr),
65  previousForwardLayer_(nullptr) {
66  ;
67 }
68 
70  const fastsim::SimplifiedGeometry*& layer) {
71  LogDebug(MESSAGECATEGORY) << " moveToNextLayer called";
72 
73  // if the layer is provided, the particle must be on it
74  if (layer) {
75  if (!particle.isOnLayer(layer->isForward(), layer->index())) {
76  throw cms::Exception("FastSimulation") << "If layer is provided, particle must be on layer."
77  << "\n Layer: " << *layer << "\n Particle: " << particle;
78  }
79  }
80 
81  // magnetic field at the current position of the particle
82  // considered constant between the layers
83  double magneticFieldZ =
84  layer ? layer->getMagneticFieldZ(particle.position()) : geometry_->getMagneticFieldZ(particle.position());
85  LogDebug(MESSAGECATEGORY) << " magnetic field z component:" << magneticFieldZ;
86 
87  // particle moves inwards?
88  bool particleMovesInwards =
89  particle.momentum().X() * particle.position().X() + particle.momentum().Y() * particle.position().Y() < 0;
90 
91  //
92  // update nextBarrelLayer and nextForwardLayer
93  //
94 
96  // first time method is called
98  if (!layer) {
99  LogDebug(MESSAGECATEGORY) << " called for first time";
100 
101  // find the narrowest barrel layers with
102  // layer.r > particle.r (the closest layer with layer.r < particle.r will then be considered, too)
103  // assume barrel layers are ordered with increasing r
104  for (const auto& layer : geometry_->barrelLayers()) {
105  if (particle.isOnLayer(false, layer->index()) ||
106  std::abs(layer->getRadius() - particle.position().Rho()) < 1e-2) {
107  if (particleMovesInwards) {
108  nextBarrelLayer_ = layer.get();
109  break;
110  } else {
111  continue;
112  }
113  }
114 
115  if (particle.position().Pt() < layer->getRadius()) {
116  nextBarrelLayer_ = layer.get();
117  break;
118  }
119 
120  previousBarrelLayer_ = layer.get();
121  }
122 
123  // find the forward layer with smallest z with
124  // layer.z > particle z (the closest layer with layer.z < particle.z will then be considered, too)
125  for (const auto& layer : geometry_->forwardLayers()) {
126  if (particle.isOnLayer(true, layer->index()) || std::abs(layer->getZ() - particle.position().Z()) < 1e-3) {
127  if (particle.momentum().Z() < 0) {
128  nextForwardLayer_ = layer.get();
129  break;
130  } else {
131  continue;
132  }
133  }
134 
135  if (particle.position().Z() < layer->getZ()) {
136  nextForwardLayer_ = layer.get();
137  break;
138  }
139 
140  previousForwardLayer_ = layer.get();
141  }
142  }
144  // last move worked, let's update
146  else {
147  LogDebug(MESSAGECATEGORY) << " ordinary call";
148 
149  // barrel layer was hit
150  if (layer == nextBarrelLayer_) {
151  if (!particleMovesInwards) {
152  previousBarrelLayer_ = nextBarrelLayer_;
153  nextBarrelLayer_ = geometry_->nextLayer(nextBarrelLayer_);
154  }
155  } else if (layer == previousBarrelLayer_) {
156  if (particleMovesInwards) {
157  nextBarrelLayer_ = previousBarrelLayer_;
158  previousBarrelLayer_ = geometry_->previousLayer(previousBarrelLayer_);
159  }
160  }
161  // forward layer was hit
162  else if (layer == nextForwardLayer_) {
163  if (particle.momentum().Z() > 0) {
164  previousForwardLayer_ = nextForwardLayer_;
165  nextForwardLayer_ = geometry_->nextLayer(nextForwardLayer_);
166  }
167  } else if (layer == previousForwardLayer_) {
168  if (particle.momentum().Z() < 0) {
169  nextForwardLayer_ = previousForwardLayer_;
170  previousForwardLayer_ = geometry_->previousLayer(previousForwardLayer_);
171  }
172  }
173 
174  // reset layer
175  layer = nullptr;
176  }
177 
179  // move particle to first hit with one of the enclosing layers
181 
182  LogDebug(MESSAGECATEGORY) << " particle between BarrelLayers: "
183  << (previousBarrelLayer_ ? previousBarrelLayer_->index() : -1) << "/"
184  << (nextBarrelLayer_ ? nextBarrelLayer_->index() : -1)
185  << " (total: " << geometry_->barrelLayers().size() << ")"
186  << "\n particle between ForwardLayers: "
187  << (previousForwardLayer_ ? previousForwardLayer_->index() : -1) << "/"
188  << (nextForwardLayer_ ? nextForwardLayer_->index() : -1)
189  << " (total: " << geometry_->forwardLayers().size() << ")";
190 
191  // calculate and store some variables related to the particle's trajectory
192  std::unique_ptr<fastsim::Trajectory> trajectory = Trajectory::createTrajectory(particle, magneticFieldZ);
193 
194  // push back all possible candidates
195  std::vector<const fastsim::SimplifiedGeometry*> layers;
196  if (nextBarrelLayer_) {
197  layers.push_back(nextBarrelLayer_);
198  }
199  if (previousBarrelLayer_) {
200  layers.push_back(previousBarrelLayer_);
201  }
202 
203  if (particle.momentum().Z() > 0) {
204  if (nextForwardLayer_) {
205  layers.push_back(nextForwardLayer_);
206  }
207  } else {
208  if (previousForwardLayer_) {
209  layers.push_back(previousForwardLayer_);
210  }
211  }
212 
213  // calculate time until each possible intersection
214  // -> pick layer that is hit first
215  double deltaTimeC = -1;
216  for (auto _layer : layers) {
217  double tempDeltaTime =
218  trajectory->nextCrossingTimeC(*_layer, particle.isOnLayer(_layer->isForward(), _layer->index()));
219  LogDebug(MESSAGECATEGORY) << " particle crosses layer " << *_layer << " in time " << tempDeltaTime;
220  if (tempDeltaTime > 0 && (layer == nullptr || tempDeltaTime < deltaTimeC || deltaTimeC < 0)) {
221  layer = _layer;
222  deltaTimeC = tempDeltaTime;
223  }
224  }
225 
226  // if particle decays on the way to the next layer, stop propagation there and return
227  double properDeltaTimeC = deltaTimeC / particle.gamma();
228  if (!particle.isStable() && properDeltaTimeC > particle.remainingProperLifeTimeC()) {
229  // move particle in space, time and momentum until it decays
230  deltaTimeC = particle.remainingProperLifeTimeC() * particle.gamma();
231 
232  trajectory->move(deltaTimeC);
233  particle.position() = trajectory->getPosition();
234  particle.momentum() = trajectory->getMomentum();
235 
236  particle.setRemainingProperLifeTimeC(0.);
237 
238  // particle no longer is on a layer
239  particle.resetOnLayer();
240  LogDebug(MESSAGECATEGORY) << " particle about to decay. Will not be moved all the way to the next layer.";
241  return false;
242  }
243 
244  if (layer) {
245  // move particle in space, time and momentum so it is on the next layer
246  trajectory->move(deltaTimeC);
247  particle.position() = trajectory->getPosition();
248  particle.momentum() = trajectory->getMomentum();
249 
250  if (!particle.isStable())
251  particle.setRemainingProperLifeTimeC(particle.remainingProperLifeTimeC() - properDeltaTimeC);
252 
253  // link the particle to the layer
254  particle.setOnLayer(layer->isForward(), layer->index());
255  LogDebug(MESSAGECATEGORY) << " moved particle to layer: " << *layer;
256  } else {
257  // particle no longer is on a layer
258  particle.resetOnLayer();
259  }
260 
261  // return true / false if propagations succeeded /failed
262  LogDebug(MESSAGECATEGORY) << " success: " << bool(layer);
263  return layer;
264 }
bool isStable() const
Returns true if particle is considered stable.
Definition: Particle.h:171
Implementation of a generic detector layer (base class for forward/barrel layers).
LayerNavigator(const Geometry &geometry)
Constructor.
double gamma() const
Return Lorentz&#39; gamma factor.
Definition: Particle.h:180
const math::XYZTLorentzVector & position() const
Return position of the particle.
Definition: Particle.h:140
void setRemainingProperLifeTimeC(double remainingProperLifeTimeC)
Set the particle&#39;s remaining proper lifetime if not stable [in ct].
Definition: Particle.h:64
bool moveParticleToNextLayer(Particle &particle, const SimplifiedGeometry *&layer)
Move particle along its trajectory to the next intersection with any of the tracker layers...
double remainingProperLifeTimeC() const
Return the particle&#39;s remaining proper lifetime[in ct].
Definition: Particle.h:150
void resetOnLayer()
Reset layer this particle is currently on (i.e. particle is not on a layer anyomre) ...
Definition: Particle.h:78
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const math::XYZTLorentzVector & momentum() const
Return momentum of the particle.
Definition: Particle.h:143
Definition the tracker geometry (vectors of forward/barrel layers).
Definition: Geometry.h:30
void setOnLayer(bool isForward, int index)
Set layer this particle is currently on.
Definition: Particle.h:72
static std::unique_ptr< Trajectory > createTrajectory(const fastsim::Particle &particle, const double magneticFieldZ)
Calls constructor of derived classes.
Definition: Trajectory.cc:17
Definition of a generic FastSim Particle which can be propagated through the detector (formerly Parti...
Definition: Particle.h:16
bool isOnLayer(bool isForward, int index)
Check if particle is on layer.
Definition: Particle.h:168
static const std::string MESSAGECATEGORY
#define LogDebug(id)