SND@LHC Software
Loading...
Searching...
No Matches
MaterialEffects.cc
Go to the documentation of this file.
1/* Copyright 2008-2014, Technische Universitaet Muenchen,
2 Authors: Christian Hoeppner & Sebastian Neubert
3
4 This file is part of GENFIT.
5
6 GENFIT is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 GENFIT is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with GENFIT. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include "MaterialEffects.h"
21#include "Exception.h"
22
23#include <iostream>
24#include <stdexcept>
25#include <string>
26#include <stdlib.h>
27#include <math.h>
28#include <assert.h>
29
30#include <TDatabasePDG.h>
31#include <TMath.h>
32
33
34//#define DEBUG
35
36namespace genfit {
37
38MaterialEffects* MaterialEffects::instance_ = nullptr;
39
40
42 noEffects_(false),
43 energyLossBetheBloch_(true), noiseBetheBloch_(true),
44 noiseCoulomb_(true),
45 energyLossBrems_(true), noiseBrems_(true),
46 ignoreBoundariesBetweenEqualMaterials_(true),
47 me_(0.510998910E-3),
48 stepSize_(0),
49 mom_(0),
50 beta_(0),
51 dEdx_(0),
52 gamma_(0),
53 gammaSquare_(0),
54 matDensity_(0),
55 matZ_(0),
56 matA_(0),
57 radiationLength_(0),
58 mEE_(0),
59 pdg_(0),
60 charge_(0),
61 mass_(0),
62 mscModelCode_(0),
63 materialInterface_(nullptr)
64{
65}
66
71
77
79{
80 if (instance_ != nullptr) {
81 delete instance_;
82 instance_ = nullptr;
83 }
84}
85
87{
88 if (materialInterface_ != nullptr) {
89 std::string msg("MaterialEffects::initMaterialInterface(): Already initialized! ");
90 std::runtime_error err(msg);
91 }
92 materialInterface_ = matIfc;
93}
94
95
96
97void MaterialEffects::setMscModel(const std::string& modelName)
98{
99 if (modelName == std::string("GEANE")) {
100 mscModelCode_ = 0;
101 } else if (modelName == std::string("Highland")) {
102 mscModelCode_ = 1;
103 } else {// throw exception
104 std::string errorMsg = std::string("There is no MSC model called \"") + modelName + "\". Maybe it is not implemented or you misspelled the model name";
105 Exception exc(errorMsg, __LINE__, __FILE__);
106 exc.setFatal();
107 std::cerr << exc.what();
108 throw exc;
109 }
110}
111
112
113double MaterialEffects::effects(const std::vector<RKStep>& steps,
114 int materialsFXStart,
115 int materialsFXStop,
116 const double& mom,
117 const int& pdg,
118 M7x7* noise)
119{
120
121#ifdef DEBUG
122 std::cout << " MaterialEffects::effects \n";
123#endif
124
125 /*std::cout << "noEffects_ " << noEffects_ << "\n";
126 std::cout << "energyLossBetheBloch_ " << energyLossBetheBloch_ << "\n";
127 std::cout << "noiseBetheBloch_ " << noiseBetheBloch_ << "\n";
128 std::cout << "noiseCoulomb_ " << noiseCoulomb_ << "\n";
129 std::cout << "energyLossBrems_ " << energyLossBrems_ << "\n";
130 std::cout << "noiseBrems_ " << noiseBrems_ << "\n";*/
131
132
133 if (noEffects_) return 0.;
134
135 if (materialInterface_ == nullptr) {
136 std::string msg("MaterialEffects hasn't been initialized with a correct AbsMaterialInterface pointer!");
137 std::runtime_error err(msg);
138 throw err;
139 }
140
141 bool doNoise(noise != nullptr);
142
143 pdg_ = pdg;
145
146 double momLoss = 0.;
147
148 for ( std::vector<RKStep>::const_iterator it = steps.begin() + materialsFXStart; it != steps.begin() + materialsFXStop; ++it) { // loop over steps
149
150 double realPath = it->matStep_.stepSize_;
151 if (fabs(realPath) < 1.E-8) {
152 // do material effects only if distance is not too small
153 continue;
154 }
155
156 #ifdef DEBUG
157 std::cout << " calculate matFX ";
158 if (doNoise)
159 std::cout << " and noise";
160 std::cout << " for ";
161 std::cout << "stepSize = " << it->stepSize_ << "\t";
162 it->materialProperties_.Print();
163 #endif
164
165 double stepSign(1.);
166 if (realPath < 0)
167 stepSign = -1.;
168 realPath = fabs(realPath);
169 stepSize_ = realPath;
170
171 it->matStep_.materialProperties_.getMaterialProperties(matDensity_, matZ_, matA_, radiationLength_, mEE_);
172
173 if (matZ_ > 1.E-3) { // don't calculate energy loss for vacuum
174
176 momLoss += stepSign * this->energyLossBetheBloch();
177 if (doNoise && energyLossBetheBloch_ && noiseBetheBloch_)
178 this->noiseBetheBloch(*noise);
179
180 if (doNoise && noiseCoulomb_)
181 this->noiseCoulomb(*noise, *((M1x3*) &it->state7_[3]) );
182
184 momLoss += stepSign * this->energyLossBrems();
185 if (doNoise && energyLossBrems_ && noiseBrems_)
186 this->noiseBrems(*noise);
187
188 }
189
190 } // end loop over steps
191
192 return momLoss;
193}
194
195
197 M1x7& state7,
198 const double& mom, // momentum
199 double& relMomLoss, // relative momloss for the step will be added
200 const int& pdg,
201 MaterialProperties& currentMaterial,
202 StepLimits& limits,
203 bool varField)
204{
205
206 static const double maxRelMomLoss = .005; // maximum relative momentum loss allowed
207 static const double minStep = 1.E-4; // 1 µm
208
209 // Trivial cases
210
211 if (noEffects_)
212 return;
213
214 if (materialInterface_ == nullptr) {
215 std::string msg("MaterialEffects hasn't been initialized with a correct AbsMaterialInterface pointer!");
216 std::runtime_error err(msg);
217 throw err;
218 }
219
220 if (relMomLoss > maxRelMomLoss) {
221 limits.setLimit(stp_momLoss, 0);
222 return;
223 }
224
225
226 double sMax = limits.getLowestLimitSignedVal(); // signed
227
228 if (fabs(sMax) < minStep)
229 return;
230
231
232
233 pdg_ = pdg;
235
236
237 // make minStep
238 state7[0] += limits.getStepSign() * minStep * state7[3];
239 state7[1] += limits.getStepSign() * minStep * state7[4];
240 state7[2] += limits.getStepSign() * minStep * state7[5];
241
242 materialInterface_->initTrack(state7[0], state7[1], state7[2],
243 limits.getStepSign() * state7[3], limits.getStepSign() * state7[4], limits.getStepSign() * state7[5]);
244
247
248
249 #ifdef DEBUG
250 std::cout << " currentMaterial "; currentMaterial.Print();
251 #endif
252
253 // limit due to momloss
254 double relMomLossPer_cm(0);
255 stepSize_ = 1; // set stepsize for momLoss calculation
256
257 if (matZ_ > 1.E-3) { // don't calculate energy loss for vacuum
258 if (energyLossBetheBloch_) relMomLossPer_cm += this->energyLossBetheBloch() / mom;
259 if (energyLossBrems_) relMomLossPer_cm += this->energyLossBrems() / mom;
260 }
261
262 double maxStepMomLoss = (maxRelMomLoss - relMomLoss) / relMomLossPer_cm;
263 limits.setLimit(stp_momLoss, maxStepMomLoss);
264
265 #ifdef DEBUG
266 std::cout << " momLoss exceeded after a step of " << maxStepMomLoss << "\n";
267 #endif
268
269
270 // now look for boundaries
271 sMax = limits.getLowestLimitSignedVal();
272
273 stepSize_ = limits.getStepSign() * minStep;
274 MaterialProperties materialAfter;
275 M1x3 SA;
276 double boundaryStep(sMax);
277
278 for (unsigned int i=0; i<100; ++i) {
279 #ifdef DEBUG
280 std::cout << " find next boundary\n";
281 #endif
282 double step = materialInterface_->findNextBoundary(rep, state7, boundaryStep, varField);
283 stepSize_ += step;
284 boundaryStep -= step;
285
286 #ifdef DEBUG
287 std::cout << " made a step of " << step << "\n";
288 #endif
289
291 break;
292
293 if (fabs(stepSize_) >= fabs(sMax))
294 break;
295
296 // propagate with found step to boundary
297 rep->RKPropagate(state7, NULL, SA, step, varField);
298
299 // make minStep to cross boundary
300 state7[0] += limits.getStepSign() * minStep * state7[3];
301 state7[1] += limits.getStepSign() * minStep * state7[4];
302 state7[2] += limits.getStepSign() * minStep * state7[5];
303
304 materialInterface_->initTrack(state7[0], state7[1], state7[2],
305 limits.getStepSign() * state7[3], limits.getStepSign() * state7[4], limits.getStepSign() * state7[5]);
306
308
309 #ifdef DEBUG
310 std::cout << " material after step "; materialAfter.Print();
311 #endif
312
313 if (materialAfter != currentMaterial)
314 break;
315 }
316
318
319
320 relMomLoss += relMomLossPer_cm * limits.getLowestLimitVal();
321}
322
323
325{
326 TParticlePDG* part = TDatabasePDG::Instance()->GetParticle(pdg_);
327 mom_ = mom;
328 charge_ = int(part->Charge() / 3.); // We only ever use the square
329 mass_ = part->Mass(); // GeV
330
331 beta_ = 1 / hypot(mass_ / mom, 1);
332 gammaSquare_ = 1 + mom*mom / mass_ / mass_;
333 gamma_ = hypot(mom / mass_, 1);
334}
335
336
337
338//---- Energy-loss and Noise calculations -----------------------------------------
339
341{
342
343 // calc dEdx_, also needed in noiseBetheBloch!
344 dEdx_ = 0.307075 * matZ_ / matA_ * matDensity_ / (beta_ * beta_) * charge_ * charge_;
345 double massRatio = me_ / mass_;
346 double argument = gammaSquare_ * beta_ * beta_ * me_ * 1.E3 * 2. / ((1.E-6 * mEE_) * sqrt(1 + 2 * gamma_ * massRatio + massRatio * massRatio));
347 dEdx_ *= log(argument) - beta_ * beta_; // Bethe-Bloch [MeV/cm]
348 dEdx_ *= 1.E-3; // in GeV/cm, hence 1.e-3
349 if (dEdx_ < 0.) dEdx_ = 0;
350
351 double dE = fabs(stepSize_) * dEdx_; //always positive
352 double momLoss = sqrt(mom_ * mom_ + 2.*sqrt(mom_ * mom_ + mass_ * mass_) * dE + dE * dE) - mom_; //always positive
353
354 //in vacuum it can numerically happen that momLoss becomes a small negative number.
355 if (momLoss < 0.) return 0.;
356 return momLoss;
357}
358
359
361{
362
363 // Code ported from GEANT 3
364
365 // ENERGY LOSS FLUCTUATIONS; calculate sigma^2(E);
366 double sigma2E = 0.;
367 double zeta = 153.4E3 * charge_ * charge_ / (beta_ * beta_) * matZ_ / matA_ * matDensity_ * fabs(stepSize_); // eV
368 double Emax = 2.E9 * me_ * beta_ * beta_ * gammaSquare_ / (1. + 2.*gamma_ * me_ / mass_ + (me_ / mass_) * (me_ / mass_)); // eV
369 double kappa = zeta / Emax;
370
371 if (kappa > 0.01) { // Vavilov-Gaussian regime
372 sigma2E += zeta * Emax * (1. - beta_ * beta_ / 2.); // eV^2
373 } else { // Urban/Landau approximation
374 // calculate number of collisions Nc
375 double I = 16. * pow(matZ_, 0.9); // eV
376 double f2 = 0.;
377 if (matZ_ > 2.) f2 = 2. / matZ_;
378 double f1 = 1. - f2;
379 double e2 = 10.*matZ_ * matZ_; // eV
380 double e1 = pow((I / pow(e2, f2)), 1. / f1); // eV
381
382 double mbbgg2 = 2.E9 * mass_ * beta_ * beta_ * gammaSquare_; // eV
383 double Sigma1 = dEdx_ * 1.0E9 * f1 / e1 * (log(mbbgg2 / e1) - beta_ * beta_) / (log(mbbgg2 / I) - beta_ * beta_) * 0.6; // 1/cm
384 double Sigma2 = dEdx_ * 1.0E9 * f2 / e2 * (log(mbbgg2 / e2) - beta_ * beta_) / (log(mbbgg2 / I) - beta_ * beta_) * 0.6; // 1/cm
385 double Sigma3 = dEdx_ * 1.0E9 * Emax / (I * (Emax + I) * log((Emax + I) / I)) * 0.4; // 1/cm
386
387 double Nc = (Sigma1 + Sigma2 + Sigma3) * fabs(stepSize_);
388
389 if (Nc > 50.) { // truncated Landau distribution
390 double sigmaalpha = 15.76;
391 // calculate sigmaalpha (see GEANT3 manual W5013)
392 double RLAMED = -0.422784 - beta_ * beta_ - log(zeta / Emax);
393 double RLAMAX = 0.60715 + 1.1934 * RLAMED + (0.67794 + 0.052382 * RLAMED) * exp(0.94753 + 0.74442 * RLAMED);
394 // from lambda max to sigmaalpha=sigma (empirical polynomial)
395 if (RLAMAX <= 1010.) {
396 sigmaalpha = 1.975560
397 + 9.898841e-02 * RLAMAX
398 - 2.828670e-04 * RLAMAX * RLAMAX
399 + 5.345406e-07 * pow(RLAMAX, 3.)
400 - 4.942035e-10 * pow(RLAMAX, 4.)
401 + 1.729807e-13 * pow(RLAMAX, 5.);
402 } else { sigmaalpha = 1.871887E+01 + 1.296254E-02 * RLAMAX; }
403 // alpha=54.6 corresponds to a 0.9996 maximum cut
404 if (sigmaalpha > 54.6) sigmaalpha = 54.6;
405 sigma2E += sigmaalpha * sigmaalpha * zeta * zeta; // eV^2
406 } else { // Urban model
407 static const double alpha = 0.996;
408 double Ealpha = I / (1. - (alpha * Emax / (Emax + I))); // eV
409 double meanE32 = I * (Emax + I) / Emax * (Ealpha - I); // eV^2
410 sigma2E += fabs(stepSize_) * (Sigma1 * e1 * e1 + Sigma2 * e2 * e2 + Sigma3 * meanE32); // eV^2
411 }
412 }
413
414 sigma2E *= 1.E-18; // eV -> GeV
415
416 // update noise matrix, using linear error propagation from E to q/p
417 noise[6 * 7 + 6] += charge_*charge_/beta_/beta_ / pow(mom_, 4) * sigma2E;
418}
419
420
422 const M1x3& direction) const
423{
424
425 // MULTIPLE SCATTERING; calculate sigma^2
426 double sigma2 = 0;
427 assert(mscModelCode_ == 0 || mscModelCode_ == 1);
428 const double step = fabs(stepSize_);
429 const double step2 = step * step;
430 if (mscModelCode_ == 0) {// PANDA report PV/01-07 eq(43); linear in step length
431 sigma2 = 225.E-6 * charge_ * charge_ / (beta_ * beta_ * mom_ * mom_) * step / radiationLength_ * matZ_ / (matZ_ + 1) * log(159.*pow(matZ_, -1. / 3.)) / log(287.*pow(matZ_, -0.5)); // sigma^2 = 225E-6*z^2/mom^2 * XX0/beta_^2 * Z/(Z+1) * ln(159*Z^(-1/3))/ln(287*Z^(-1/2)
432
433 } else if (mscModelCode_ == 1) { //Highland not linear in step length formula taken from PDG book 2011 edition
434 double stepOverRadLength = step / radiationLength_;
435 double logCor = (1 + 0.038 * log(stepOverRadLength));
436 sigma2 = 0.0136 * 0.0136 * charge_ * charge_ / (beta_ * beta_ * mom_ * mom_) * stepOverRadLength * logCor * logCor;
437 }
438 //assert(sigma2 >= 0.0);
439 sigma2 = (sigma2 > 0.0 ? sigma2 : 0.0);
440 //XXX std::cout << "MaterialEffects::noiseCoulomb the MSC variance is " << sigma2 << std::endl;
441
442 double noiseAfter[7 * 7]; // will hold the new MSC noise to cause by the current stepSize_ length
443 memset(noiseAfter, 0x00, 7 * 7 * sizeof(double));
444
445 const double *a = direction;
446 // This calculates the MSC angular spread in the 7D global
447 // coordinate system. See PDG 2010, Sec. 27.3 for formulae.
448 noiseAfter[0 * 7 + 0] = sigma2 * step2 / 3.0 * (1 - a[0]*a[0]);
449 noiseAfter[1 * 7 + 0] = -sigma2 * step2 / 3.0 * a[0]*a[1];
450 noiseAfter[2 * 7 + 0] = -sigma2 * step2 / 3.0 * a[0]*a[2];
451 noiseAfter[3 * 7 + 0] = sigma2 * step * 0.5 * (1 - a[0]*a[0]);
452 noiseAfter[4 * 7 + 0] = -sigma2 * step * 0.5 * a[0]*a[1];
453 noiseAfter[5 * 7 + 0] = -sigma2 * step * 0.5 * a[0]*a[1];
454 noiseAfter[0 * 7 + 1] = noiseAfter[1 * 7 + 0];
455 noiseAfter[1 * 7 + 1] = sigma2 * step2 / 3.0 * (1 - a[1]*a[1]);
456 noiseAfter[2 * 7 + 1] = -sigma2 * step2 / 3.0 * a[1]*a[2];
457 noiseAfter[3 * 7 + 1] = noiseAfter[4 * 7 + 0]; // Cov(x,a_y) = Cov(y,a_x)
458 noiseAfter[4 * 7 + 1] = sigma2 * step * 0.5 * (1 - a[1] * a[1]);
459 noiseAfter[5 * 7 + 1] = -sigma2 * step * 0.5 * a[1]*a[2];
460 noiseAfter[0 * 7 + 2] = noiseAfter[2 * 7 + 0];
461 noiseAfter[1 * 7 + 2] = noiseAfter[2 * 7 + 1];
462 noiseAfter[2 * 7 + 2] = sigma2 * step2 / 3.0 * (1 - a[2]*a[2]);
463 noiseAfter[3 * 7 + 2] = noiseAfter[5 * 7 + 0]; // Cov(z,a_x) = Cov(x,a_z)
464 noiseAfter[4 * 7 + 2] = noiseAfter[5 * 7 + 1]; // Cov(y,a_z) = Cov(z,a_y)
465 noiseAfter[5 * 7 + 2] = sigma2 * step * 0.5 * (1 - a[2]*a[2]);
466 noiseAfter[0 * 7 + 3] = noiseAfter[3 * 7 + 0];
467 noiseAfter[1 * 7 + 3] = noiseAfter[3 * 7 + 1];
468 noiseAfter[2 * 7 + 3] = noiseAfter[3 * 7 + 2];
469 noiseAfter[3 * 7 + 3] = sigma2 * (1 - a[0]*a[0]);
470 noiseAfter[4 * 7 + 3] = -sigma2 * a[0]*a[1];
471 noiseAfter[5 * 7 + 3] = -sigma2 * a[0]*a[2];
472 noiseAfter[0 * 7 + 4] = noiseAfter[4 * 7 + 0];
473 noiseAfter[1 * 7 + 4] = noiseAfter[4 * 7 + 1];
474 noiseAfter[2 * 7 + 4] = noiseAfter[4 * 7 + 2];
475 noiseAfter[3 * 7 + 4] = noiseAfter[4 * 7 + 3];
476 noiseAfter[4 * 7 + 4] = sigma2 * (1 - a[1]*a[1]);
477 noiseAfter[5 * 7 + 4] = -sigma2 * a[1]*a[2];
478 noiseAfter[0 * 7 + 5] = noiseAfter[5 * 7 + 0];
479 noiseAfter[1 * 7 + 5] = noiseAfter[5 * 7 + 1];
480 noiseAfter[2 * 7 + 5] = noiseAfter[5 * 7 + 2];
481 noiseAfter[3 * 7 + 5] = noiseAfter[5 * 7 + 3];
482 noiseAfter[4 * 7 + 5] = noiseAfter[5 * 7 + 4];
483 noiseAfter[5 * 7 + 5] = sigma2 * (1 - a[2]*a[2]);
484// std::cout << "new noise\n";
485// RKTools::printDim(noiseAfter, 7,7);
486 for (unsigned int i = 0; i < 7 * 7; ++i) {
487 noise[i] += noiseAfter[i];
488 }
489}
490
491
493{
494
495 // Code ported from GEANT 3
496
497 if (abs(pdg_) != 11) return 0; // only for electrons and positrons
498
499#if !defined(BETHE)
500 static const double C[101] = { 0.0, -0.960613E-01, 0.631029E-01, -0.142819E-01, 0.150437E-02, -0.733286E-04, 0.131404E-05, 0.859343E-01, -0.529023E-01, 0.131899E-01, -0.159201E-02, 0.926958E-04, -0.208439E-05, -0.684096E+01, 0.370364E+01, -0.786752E+00, 0.822670E-01, -0.424710E-02, 0.867980E-04, -0.200856E+01, 0.129573E+01, -0.306533E+00, 0.343682E-01, -0.185931E-02, 0.392432E-04, 0.127538E+01, -0.515705E+00, 0.820644E-01, -0.641997E-02, 0.245913E-03, -0.365789E-05, 0.115792E+00, -0.463143E-01, 0.725442E-02, -0.556266E-03, 0.208049E-04, -0.300895E-06, -0.271082E-01, 0.173949E-01, -0.452531E-02, 0.569405E-03, -0.344856E-04, 0.803964E-06, 0.419855E-02, -0.277188E-02, 0.737658E-03, -0.939463E-04, 0.569748E-05, -0.131737E-06, -0.318752E-03, 0.215144E-03, -0.579787E-04, 0.737972E-05, -0.441485E-06, 0.994726E-08, 0.938233E-05, -0.651642E-05, 0.177303E-05, -0.224680E-06, 0.132080E-07, -0.288593E-09, -0.245667E-03, 0.833406E-04, -0.129217E-04, 0.915099E-06, -0.247179E-07, 0.147696E-03, -0.498793E-04, 0.402375E-05, 0.989281E-07, -0.133378E-07, -0.737702E-02, 0.333057E-02, -0.553141E-03, 0.402464E-04, -0.107977E-05, -0.641533E-02, 0.290113E-02, -0.477641E-03, 0.342008E-04, -0.900582E-06, 0.574303E-05, 0.908521E-04, -0.256900E-04, 0.239921E-05, -0.741271E-07, -0.341260E-04, 0.971711E-05, -0.172031E-06, -0.119455E-06, 0.704166E-08, 0.341740E-05, -0.775867E-06, -0.653231E-07, 0.225605E-07, -0.114860E-08, -0.119391E-06, 0.194885E-07, 0.588959E-08, -0.127589E-08, 0.608247E-10};
501 static const double xi = 2.51, beta = 0.99, vl = 0.00004;
502#endif
503#if defined(BETHE) // no MIGDAL corrections
504 static const double C[101] = { 0.0, 0.834459E-02, 0.443979E-02, -0.101420E-02, 0.963240E-04, -0.409769E-05, 0.642589E-07, 0.464473E-02, -0.290378E-02, 0.547457E-03, -0.426949E-04, 0.137760E-05, -0.131050E-07, -0.547866E-02, 0.156218E-02, -0.167352E-03, 0.101026E-04, -0.427518E-06, 0.949555E-08, -0.406862E-02, 0.208317E-02, -0.374766E-03, 0.317610E-04, -0.130533E-05, 0.211051E-07, 0.158941E-02, -0.385362E-03, 0.315564E-04, -0.734968E-06, -0.230387E-07, 0.971174E-09, 0.467219E-03, -0.154047E-03, 0.202400E-04, -0.132438E-05, 0.431474E-07, -0.559750E-09, -0.220958E-02, 0.100698E-02, -0.596464E-04, -0.124653E-04, 0.142999E-05, -0.394378E-07, 0.477447E-03, -0.184952E-03, -0.152614E-04, 0.848418E-05, -0.736136E-06, 0.190192E-07, -0.552930E-04, 0.209858E-04, 0.290001E-05, -0.133254E-05, 0.116971E-06, -0.309716E-08, 0.212117E-05, -0.103884E-05, -0.110912E-06, 0.655143E-07, -0.613013E-08, 0.169207E-09, 0.301125E-04, -0.461920E-04, 0.871485E-05, -0.622331E-06, 0.151800E-07, -0.478023E-04, 0.247530E-04, -0.381763E-05, 0.232819E-06, -0.494487E-08, -0.336230E-04, 0.223822E-04, -0.384583E-05, 0.252867E-06, -0.572599E-08, 0.105335E-04, -0.567074E-06, -0.216564E-06, 0.237268E-07, -0.658131E-09, 0.282025E-05, -0.671965E-06, 0.565858E-07, -0.193843E-08, 0.211839E-10, 0.157544E-04, -0.304104E-05, -0.624410E-06, 0.120124E-06, -0.457445E-08, -0.188222E-05, -0.407118E-06, 0.375106E-06, -0.466881E-07, 0.158312E-08, 0.945037E-07, 0.564718E-07, -0.319231E-07, 0.371926E-08, -0.123111E-09};
505 static const double xi = 2.10, beta = 1.00, vl = 0.001;
506#endif
507
508 double BCUT = 10000.; // energy up to which soft bremsstrahlung energy loss is calculated
509
510 static const double THIGH = 100., CHIGH = 50.;
511 double dedxBrems = 0.;
512
513 if (BCUT > 0.) {
514 double T, kc;
515
516 if (BCUT >= mom_) BCUT = mom_; // confine BCUT to mom_
517
518 // T=mom_, confined to THIGH
519 // kc=BCUT, confined to CHIGH ??
520 if (mom_ >= THIGH) {
521 T = THIGH;
522 if (BCUT >= THIGH) kc = CHIGH;
523 else kc = BCUT;
524 } else {
525 T = mom_;
526 kc = BCUT;
527 }
528
529 double E = T + me_; // total electron energy
530 if (BCUT > T) kc = T;
531
532 double X = log(T / me_);
533 double Y = log(kc / (E * vl));
534
535 double XX;
536 int K;
537 double S = 0., YY = 1.;
538
539 for (unsigned int I = 1; I <= 2; ++I) {
540 XX = 1.;
541 for (unsigned int J = 1; J <= 6; ++J) {
542 K = 6 * I + J - 6;
543 S = S + C[K] * XX * YY;
544 XX = XX * X;
545 }
546 YY = YY * Y;
547 }
548
549 for (unsigned int I = 3; I <= 6; ++I) {
550 XX = 1.;
551 for (unsigned int J = 1; J <= 6; ++J) {
552 K = 6 * I + J - 6;
553 if (Y <= 0.) S = S + C[K] * XX * YY;
554 else S = S + C[K + 24] * XX * YY;
555 XX = XX * X;
556 }
557 YY = YY * Y;
558 }
559
560 double SS = 0.;
561 YY = 1.;
562
563 for (unsigned int I = 1; I <= 2; ++I) {
564 XX = 1.;
565 for (unsigned int J = 1; J <= 5; ++J) {
566 K = 5 * I + J + 55;
567 SS = SS + C[K] * XX * YY;
568 XX = XX * X;
569 }
570 YY = YY * Y;
571 }
572
573 for (unsigned int I = 3; I <= 5; ++I) {
574 XX = 1.;
575 for (unsigned int J = 1; J <= 5; ++J) {
576 K = 5 * I + J + 55;
577 if (Y <= 0.) SS = SS + C[K] * XX * YY;
578 else SS = SS + C[K + 15] * XX * YY;
579 XX = XX * X;
580 }
581 YY = YY * Y;
582 }
583
584 S = S + matZ_ * SS;
585
586 if (S > 0.) {
587 double CORR = 1.;
588#if !defined(BETHE)
589 CORR = 1. / (1. + 0.805485E-10 * matDensity_ * matZ_ * E * E / (matA_ * kc * kc)); // MIGDAL correction factor
590#endif
591
592 // We use exp(beta * log(...) here because pow(..., beta) is
593 // REALLY slow and we don't need ultimate numerical precision
594 // for this approximation.
595 double FAC = matZ_ * (matZ_ + xi) * E * E / (E + me_);
596 if (beta == 1.) { // That is the #ifdef BETHE case
597 FAC *= kc * CORR / T;
598 } else {
599 FAC *= exp(beta * log(kc * CORR / T));
600 }
601 if (FAC <= 0.) return 0.;
602 dedxBrems = FAC * S;
603
604
605 if (mom_ > THIGH) {
606 double RAT;
607 if (BCUT < THIGH) {
608 RAT = BCUT / mom_;
609 S = (1. - 0.5 * RAT + 2.*RAT * RAT / 9.);
610 RAT = BCUT / T;
611 S = S / (1. - 0.5 * RAT + 2.*RAT * RAT / 9.);
612 } else {
613 RAT = BCUT / mom_;
614 S = BCUT * (1. - 0.5 * RAT + 2.*RAT * RAT / 9.);
615 RAT = kc / T;
616 S = S / (kc * (1. - 0.5 * RAT + 2.*RAT * RAT / 9.));
617 }
618 dedxBrems = dedxBrems * S; // GeV barn
619 }
620
621 dedxBrems = 0.60221367 * matDensity_ * dedxBrems / matA_; // energy loss dE/dx [GeV/cm]
622 }
623 }
624
625 if (dedxBrems < 0.) dedxBrems = 0;
626
627 double factor = 1.; // positron correction factor
628
629 if (pdg_ == -11) {
630 static const double AA = 7522100., A1 = 0.415, A3 = 0.0021, A5 = 0.00054;
631
632 double ETA = 0.;
633 if (matZ_ > 0.) {
634 double X = log(AA * mom_ / (matZ_ * matZ_));
635 if (X > -8.) {
636 if (X >= +9.) ETA = 1.;
637 else {
638 double W = A1 * X + A3 * pow(X, 3.) + A5 * pow(X, 5.);
639 ETA = 0.5 + atan(W) / M_PI;
640 }
641 }
642 }
643
644 if (ETA < 0.0001) factor = 1.E-10;
645 else if (ETA > 0.9999) factor = 1.;
646 else {
647 double E0 = BCUT / mom_;
648 if (E0 > 1.) E0 = 1.;
649 if (E0 < 1.E-8) factor = 1.;
650 else factor = ETA * (1. - pow(1. - E0, 1. / ETA)) / E0;
651 }
652 }
653
654 double dE = fabs(stepSize_) * factor * dedxBrems; //always positive
655 double momLoss = sqrt(mom_ * mom_ + 2.*sqrt(mom_ * mom_ + mass_ * mass_) * dE + dE * dE) - mom_; //always positive
656
657 return momLoss;
658}
659
660
662{
663
664 // Code ported from GEANT 3 and simplified
665 // this formula assumes p >> m and therefore p^2 + m^2 = p^2
666 // the factor 1.44 is not in the original Behta Heitler model. It seems to be some empirical correction copied over from some other project
667
668 if (abs(pdg_) != 11) return; // only for electrons and positrons
669
670 double minusXOverLn2 = -1.442695 * fabs(stepSize_) / radiationLength_;
671 double sigma2 = 1.44*(pow(3., minusXOverLn2) - pow(4., minusXOverLn2)) / (mom_*mom_);
672 //XXX std::cout << "breams sigma: " << sigma2E << std::endl;
673 //assert(sigma2 >= 0.0);
674 sigma2 = (sigma2 > 0.0 ? sigma2 : 0.0);
675 noise[6 * 7 + 6] += charge_*charge_/beta_/beta_ / pow(mom_, 4) * sigma2;
676
677}
678
679} /* End of namespace genfit */
680
681
Abstract base class for geometry interfacing.
virtual void getMaterialParameters(double &density, double &Z, double &A, double &radiationLength, double &mEE)=0
Get material parameters in current material.
virtual double findNextBoundary(const RKTrackRep *rep, const M1x7 &state7, double sMax, bool varField=true)=0
Make a step until maxStep or the next boundary is reached.
virtual bool initTrack(double posX, double posY, double posZ, double dirX, double dirY, double dirZ)=0
Initialize the navigator at given position and with given direction. Return true if volume changed.
Exception class for error handling in GENFIT (provides storage for diagnostic information)
Definition Exception.h:48
void setFatal(bool b=true)
Set fatal flag.
Definition Exception.h:61
virtual const char * what() const
Standard error message handling for exceptions. use like "std::cerr << e.what();".
Definition Exception.cc:51
Stepper and energy loss/noise matrix calculation.
void setMscModel(const std::string &modelName)
Select the multiple scattering model that will be used during track fit.
static MaterialEffects * getInstance()
void noiseBrems(M7x7 &noise) const
calculation of energy loss straggeling
void noiseBetheBloch(M7x7 &noise) const
calculation of energy loss straggeling
double effects(const std::vector< genfit::RKStep > &steps, int materialsFXStart, int materialsFXStop, const double &mom, const int &pdg, M7x7 *noise=nullptr)
Calculates energy loss in the traveled path, optional calculation of noise matrix.
static MaterialEffects * instance_
void stepper(const RKTrackRep *rep, M1x7 &state7, const double &mom, double &relMomLoss, const int &pdg, MaterialProperties &currentMaterial, StepLimits &limits, bool varField=true)
Returns maximum length so that a specified momentum loss will not be exceeded.
void getParticleParameters(double mom)
sets charge_, mass_ and calculates beta_, gamma_, fgammasquare;
void init(AbsMaterialInterface *matIfc)
set the material interface here. Material interface classes must be derived from AbsMaterialInterface...
AbsMaterialInterface * materialInterface_
depending on this number a specific msc model is chosen in the noiseCoulomb function.
double energyLossBetheBloch()
Returns energy loss.
double energyLossBrems() const
Returns energy loss.
void noiseCoulomb(M7x7 &noise, const M1x3 &direction) const
calculation of multiple scattering
Material properties needed e.g. for material effects calculation.
void setMaterialProperties(const double &density, const double &Z, const double &A, const double &radiationLength, const double &mEE)
void Print(const Option_t *="") const
AbsTrackRep with 5D track parameterization in plane coordinates: (q/p, u', v', u, v)
Definition RKTrackRep.h:70
double RKPropagate(M1x7 &state7, M7x7 *jacobian, M1x3 &SA, double S, bool varField=true, bool calcOnlyLastRowOfJ=false) const
The actual Runge Kutta propagation.
Helper to store different limits on the stepsize for the RKTRackRep.
Definition StepLimits.h:54
void setLimit(StepLimitType type, double value)
absolute of value will be taken! If limit is already lower, it will be set to value anyway.
Definition StepLimits.h:89
double getLowestLimitSignedVal(double margin=1.E-3) const
Get the numerical value of the lowest limit, signed with stepSign_.
Definition StepLimits.h:80
char getStepSign() const
Definition StepLimits.h:84
double getLowestLimitVal(double margin=1.E-3) const
Get the unsigned numerical value of the lowest limit.
Definition StepLimits.cc:65
Matrix inversion tools.
Definition AbsBField.h:29
double M1x7[1 *7]
Definition RKTools.h:36
@ stp_boundary
Definition StepLimits.h:44
@ stp_momLoss
Definition StepLimits.h:39
double M1x3[1 *3]
Definition RKTools.h:33
double M7x7[7 *7]
Definition RKTools.h:39