File indexing completed on 2025-08-05 08:18:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include "MaterialEffects.h"
0021 #include "Exception.h"
0022 #include "IO.h"
0023
0024 #include <stdexcept>
0025 #include <string>
0026 #include <stdlib.h>
0027 #include <math.h>
0028 #include <assert.h>
0029
0030 #include <TDatabasePDG.h>
0031 #include "MonopoleConstants.h"
0032 #include <TMath.h>
0033
0034 #include <TH1D.h>
0035 #include <TFile.h>
0036
0037
0038 namespace genfit {
0039
0040 MaterialEffects* MaterialEffects::instance_ = nullptr;
0041
0042
0043 MaterialEffects::MaterialEffects():
0044 noEffects_(false),
0045 energyLossBetheBloch_(true), noiseBetheBloch_(true),
0046 noiseCoulomb_(true),
0047 energyLossBrems_(true), noiseBrems_(true),
0048 ignoreBoundariesBetweenEqualMaterials_(true),
0049 me_(0.510998910E-3),
0050 stepSize_(0),
0051 dEdx_(0),
0052 E_(0),
0053 matDensity_(0),
0054 matZ_(0),
0055 matA_(0),
0056 radiationLength_(0),
0057 mEE_(0),
0058 pdg_(0),
0059 charge_(0),
0060 mag_charge_(0),
0061 mass_(0),
0062 mscModelCode_(0),
0063 materialInterface_(nullptr),
0064 debugLvl_(0)
0065 {
0066 }
0067
0068 MaterialEffects::~MaterialEffects()
0069 {
0070 if (materialInterface_ != nullptr) delete materialInterface_;
0071 }
0072
0073 MaterialEffects* MaterialEffects::getInstance()
0074 {
0075 if (instance_ == nullptr) instance_ = new MaterialEffects();
0076 return instance_;
0077 }
0078
0079 void MaterialEffects::destruct()
0080 {
0081 if (instance_ != nullptr) {
0082 delete instance_;
0083 instance_ = nullptr;
0084 }
0085 }
0086
0087 void MaterialEffects::init(AbsMaterialInterface* matIfc)
0088 {
0089 if (materialInterface_ != nullptr) {
0090 std::string msg("MaterialEffects::initMaterialInterface(): Already initialized! ");
0091 std::runtime_error err(msg);
0092 }
0093 materialInterface_ = matIfc;
0094 }
0095
0096
0097
0098 void MaterialEffects::setMscModel(const std::string& modelName)
0099 {
0100 if (modelName == std::string("GEANE")) {
0101 mscModelCode_ = 0;
0102 } else if (modelName == std::string("Highland")) {
0103 mscModelCode_ = 1;
0104 } else {
0105 std::string errorMsg = std::string("There is no MSC model called \"") + modelName + "\". Maybe it is not implemented or you misspelled the model name";
0106 Exception exc(errorMsg, __LINE__, __FILE__);
0107 exc.setFatal();
0108 errorOut << exc.what();
0109 throw exc;
0110 }
0111 }
0112
0113
0114 double MaterialEffects::effects(const std::vector<RKStep>& steps,
0115 int materialsFXStart,
0116 int materialsFXStop,
0117 const double& mom,
0118 const int& pdg,
0119 M7x7* noise)
0120 {
0121
0122 if (debugLvl_ > 0) {
0123 debugOut << " MaterialEffects::effects \n";
0124 }
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134 if (noEffects_) return 0.;
0135
0136 if (materialInterface_ == nullptr) {
0137 std::string msg("MaterialEffects hasn't been initialized with a correct AbsMaterialInterface pointer!");
0138 std::runtime_error err(msg);
0139 throw err;
0140 }
0141
0142 bool doNoise(noise != nullptr);
0143
0144 pdg_ = pdg;
0145 getParticleParameters();
0146
0147 double momLoss = 0.;
0148
0149 for ( std::vector<RKStep>::const_iterator it = steps.begin() + materialsFXStart; it != steps.begin() + materialsFXStop; ++it) {
0150
0151 double realPath = it->matStep_.stepSize_;
0152 if (fabs(realPath) < 1.E-8) {
0153
0154 continue;
0155 }
0156
0157 if (debugLvl_ > 0) {
0158 debugOut << " calculate matFX ";
0159 if (doNoise)
0160 debugOut << "and noise";
0161 debugOut << " for ";
0162 debugOut << "stepSize = " << it->matStep_.stepSize_ << "\t";
0163 it->matStep_.material_.Print();
0164 }
0165
0166 double stepSign(1.);
0167 if (realPath < 0)
0168 stepSign = -1.;
0169 realPath = fabs(realPath);
0170 stepSize_ = realPath;
0171
0172
0173 const Material& currentMaterial = it->matStep_.material_;
0174 matDensity_ = currentMaterial.density;
0175 matZ_ = currentMaterial.Z;
0176 matA_ = currentMaterial.A;
0177 radiationLength_ = currentMaterial.radiationLength;
0178 mEE_ = currentMaterial.mEE;
0179
0180
0181 if (matZ_ > 1.E-3) {
0182
0183 momLoss += momentumLoss(stepSign, mom - momLoss, false);
0184
0185 if (doNoise){
0186
0187 double p(0), gammaSquare(0), gamma(0), betaSquare(0);
0188 this->getMomGammaBeta(E_, p, gammaSquare, gamma, betaSquare);
0189 double pSquare = p*p;
0190
0191 if (pdg_ == c_monopolePDGCode) {
0192 charge_ = mag_charge_ * mom / hypot(mom, mass_);
0193 }
0194
0195 if (energyLossBetheBloch_ && noiseBetheBloch_)
0196 this->noiseBetheBloch(*noise, p, betaSquare, gamma, gammaSquare);
0197
0198 if (noiseCoulomb_)
0199 this->noiseCoulomb(*noise, *((M1x3*) &it->state7_[3]), pSquare, betaSquare);
0200
0201 if (energyLossBrems_ && noiseBrems_)
0202 this->noiseBrems(*noise, pSquare, betaSquare);
0203 }
0204
0205 }
0206
0207 }
0208
0209 if (momLoss >= mom) {
0210 Exception exc("MaterialEffects::effects ==> momLoss >= momentum, aborting extrapolation!",__LINE__,__FILE__);
0211 exc.setFatal();
0212 throw exc;
0213 }
0214
0215 return momLoss;
0216 }
0217
0218
0219 void MaterialEffects::stepper(const RKTrackRep* rep,
0220 M1x7& state7,
0221 const double& mom,
0222 double& relMomLoss,
0223 const int& pdg,
0224 Material& currentMaterial,
0225 StepLimits& limits,
0226 bool varField)
0227 {
0228
0229 static const double maxRelMomLoss = .01;
0230 static const double Pmin = 4.E-3;
0231 static const double minStep = 1.E-4;
0232
0233
0234 if(mom < Pmin){
0235 std::ostringstream sstream;
0236 sstream << "MaterialEffects::stepper ==> momentum too low: " << mom*1000. << " MeV";
0237 Exception exc(sstream.str(),__LINE__,__FILE__);
0238 exc.setFatal();
0239 throw exc;
0240 }
0241
0242
0243 if (noEffects_)
0244 return;
0245
0246 if (materialInterface_ == nullptr) {
0247 std::string msg("MaterialEffects hasn't been initialized with a correct AbsMaterialInterface pointer!");
0248 std::runtime_error err(msg);
0249 throw err;
0250 }
0251
0252 if (relMomLoss > maxRelMomLoss) {
0253 limits.setLimit(stp_momLoss, 0);
0254 return;
0255 }
0256
0257
0258 double sMax = limits.getLowestLimitSignedVal();
0259
0260 if (fabs(sMax) < minStep)
0261 return;
0262
0263
0264
0265 pdg_ = pdg;
0266 getParticleParameters();
0267
0268
0269
0270 state7[0] += limits.getStepSign() * minStep * state7[3];
0271 state7[1] += limits.getStepSign() * minStep * state7[4];
0272 state7[2] += limits.getStepSign() * minStep * state7[5];
0273
0274 materialInterface_->initTrack(state7[0], state7[1], state7[2],
0275 limits.getStepSign() * state7[3], limits.getStepSign() * state7[4], limits.getStepSign() * state7[5]);
0276
0277
0278 currentMaterial = materialInterface_->getMaterialParameters();
0279 matDensity_ = currentMaterial.density;
0280 matZ_ = currentMaterial.Z;
0281 matA_ = currentMaterial.A;
0282 radiationLength_ = currentMaterial.radiationLength;
0283 mEE_ = currentMaterial.mEE;
0284
0285 if (debugLvl_ > 0) {
0286 debugOut << " currentMaterial "; currentMaterial.Print();
0287 }
0288
0289
0290 double relMomLossPer_cm(0);
0291 stepSize_ = 1.;
0292
0293 if (matZ_ > 1.E-3) {
0294 relMomLossPer_cm = this->momentumLoss(limits.getStepSign(), mom, true) / mom;
0295 }
0296
0297 double maxStepMomLoss = fabs((maxRelMomLoss - fabs(relMomLoss)) / relMomLossPer_cm);
0298 limits.setLimit(stp_momLoss, maxStepMomLoss);
0299
0300 if (debugLvl_ > 0) {
0301 debugOut << " momLoss exceeded after a step of " << maxStepMomLoss
0302 << "; relMomLoss up to now = " << relMomLoss << "\n";
0303 }
0304
0305
0306
0307 sMax = limits.getLowestLimitSignedVal();
0308
0309 stepSize_ = limits.getStepSign() * minStep;
0310 M1x3 SA;
0311 double boundaryStep(sMax);
0312
0313 for (unsigned int i=0; i<100; ++i) {
0314 if (debugLvl_ > 0) {
0315 debugOut << " find next boundary\n";
0316 }
0317 double step = materialInterface_->findNextBoundary(rep, state7, boundaryStep, varField);
0318
0319 if (debugLvl_ > 0) {
0320 if (step == 0) {
0321 debugOut << " materialInterface_ returned a step of 0 \n";
0322 }
0323 }
0324
0325 stepSize_ += step;
0326 boundaryStep -= step;
0327
0328 if (debugLvl_ > 0) {
0329 debugOut << " made a step of " << step << "\n";
0330 }
0331
0332 if (! ignoreBoundariesBetweenEqualMaterials_)
0333 break;
0334
0335 if (fabs(stepSize_) >= fabs(sMax))
0336 break;
0337
0338
0339 rep->RKPropagate(state7, nullptr, SA, step, varField);
0340
0341
0342 state7[0] += limits.getStepSign() * minStep * state7[3];
0343 state7[1] += limits.getStepSign() * minStep * state7[4];
0344 state7[2] += limits.getStepSign() * minStep * state7[5];
0345
0346 materialInterface_->initTrack(state7[0], state7[1], state7[2],
0347 limits.getStepSign() * state7[3], limits.getStepSign() * state7[4], limits.getStepSign() * state7[5]);
0348
0349 Material materialAfter = materialInterface_->getMaterialParameters();
0350
0351 if (debugLvl_ > 0) {
0352 debugOut << " material after step: "; materialAfter.Print();
0353 }
0354
0355 if (materialAfter != currentMaterial)
0356 break;
0357 }
0358
0359 limits.setLimit(stp_boundary, stepSize_);
0360
0361
0362 relMomLoss += relMomLossPer_cm * limits.getLowestLimitVal();
0363 }
0364
0365
0366 void MaterialEffects::getParticleParameters()
0367 {
0368 TParticlePDG* part = TDatabasePDG::Instance()->GetParticle(pdg_);
0369 charge_ = part->Charge() / 3.;
0370 mass_ = part->Mass();
0371 }
0372
0373
0374 void MaterialEffects::getMomGammaBeta(double Energy,
0375 double& mom, double& gammaSquare, double& gamma, double& betaSquare) const {
0376
0377 if (Energy <= mass_) {
0378 Exception exc("MaterialEffects::getMomGammaBeta - Energy <= mass",__LINE__,__FILE__);
0379 exc.setFatal();
0380 throw exc;
0381 }
0382 gamma = Energy/mass_;
0383 gammaSquare = gamma*gamma;
0384 betaSquare = 1.-1./gammaSquare;
0385 mom = Energy*sqrt(betaSquare);
0386 }
0387
0388
0389
0390
0391
0392 double MaterialEffects::momentumLoss(double stepSign, double mom, bool linear)
0393 {
0394 double E0 = hypot(mom, mass_);
0395 double step = stepSize_*stepSign;
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411 double dEdx1 = dEdx(E0);
0412
0413 if (linear) {
0414 dEdx_ = dEdx1;
0415 }
0416 else {
0417 double E1 = E0 - dEdx1*step/2.;
0418 double dEdx2 = dEdx(E1);
0419
0420 double E2 = E0 - dEdx2*step/2.;
0421 double dEdx3 = dEdx(E2);
0422
0423 double E3 = E0 - dEdx3*step;
0424 double dEdx4 = dEdx(E3);
0425
0426 dEdx_ = (dEdx1 + 2.*dEdx2 + 2.*dEdx3 + dEdx4)/6.;
0427 }
0428
0429 E_ = E0 - dEdx_*step*0.5;
0430
0431 double dE = step*dEdx_;
0432
0433 double momLoss(0);
0434
0435 if (E0 - dE <= mass_) {
0436
0437 return momLoss = mom;
0438 }
0439 else momLoss = mom - sqrt(pow(E0 - dE, 2) - mass_*mass_);
0440
0441 if (debugLvl_ > 0) {
0442 debugOut << " MaterialEffects::momentumLoss: mom = " << mom << "; E0 = " << E0
0443 << "; dEdx = " << dEdx_
0444 << "; dE = " << dE << "; mass = " << mass_ << "\n";
0445 }
0446
0447
0448
0449 return momLoss;
0450 }
0451
0452
0453 double MaterialEffects::dEdx(double Energy) {
0454
0455 double mom(0), gammaSquare(0), gamma(0), betaSquare(0);
0456 this->getMomGammaBeta(Energy, mom, gammaSquare, gamma, betaSquare);
0457 if (pdg_ == c_monopolePDGCode) {
0458 charge_ = mag_charge_ * sqrt(betaSquare);
0459 }
0460
0461 double result(0);
0462
0463 if (energyLossBetheBloch_)
0464 result += dEdxBetheBloch(betaSquare, gamma, gammaSquare);
0465
0466 if (energyLossBrems_)
0467 result += dEdxBrems(mom);
0468
0469 return result;
0470 }
0471
0472
0473 double MaterialEffects::dEdxBetheBloch(double betaSquare, double gamma, double gammaSquare) const
0474 {
0475 static const double betaGammaMin(0.05);
0476 if (betaSquare*gammaSquare < betaGammaMin*betaGammaMin) {
0477 Exception exc("MaterialEffects::dEdxBetheBloch ==> beta*gamma < 0.05, Bethe-Bloch implementation not valid anymore!",__LINE__,__FILE__);
0478 exc.setFatal();
0479 throw exc;
0480 }
0481
0482
0483 double result( 0.307075 * matZ_ / matA_ * matDensity_ / betaSquare * charge_ * charge_ );
0484 double massRatio( me_ / mass_ );
0485 double argument( gammaSquare * betaSquare * me_ * 1.E3 * 2. / ((1.E-6 * mEE_) *
0486 sqrt(1. + 2. * gamma * massRatio + massRatio * massRatio)) );
0487 result *= log(argument) - betaSquare;
0488 result *= 1.E-3;
0489 if (result < 0.) {
0490 result = 0;
0491 }
0492
0493 return result;
0494 }
0495
0496
0497 void MaterialEffects::noiseBetheBloch(M7x7& noise, double mom, double betaSquare, double gamma, double gammaSquare) const
0498 {
0499
0500
0501
0502 double sigma2E ( 0. );
0503 double zeta ( 153.4E3 * charge_ * charge_ / betaSquare * matZ_ / matA_ * matDensity_ * fabs(stepSize_) );
0504 double Emax ( 2.E9 * me_ * betaSquare * gammaSquare / (1. + 2.*gamma * me_ / mass_ + (me_ / mass_) * (me_ / mass_)) );
0505 double kappa ( zeta / Emax );
0506
0507 if (kappa > 0.01) {
0508 sigma2E += zeta * Emax * (1. - betaSquare / 2.);
0509 } else {
0510
0511 double I = 16. * pow(matZ_, 0.9);
0512 double f2 = 0.;
0513 if (matZ_ > 2.) f2 = 2. / matZ_;
0514 double f1 = 1. - f2;
0515 double e2 = 10.*matZ_ * matZ_;
0516 double e1 = pow((I / pow(e2, f2)), 1. / f1);
0517
0518 double mbbgg2 = 2.E9 * mass_ * betaSquare * gammaSquare;
0519 double Sigma1 = dEdx_ * 1.0E9 * f1 / e1 * (log(mbbgg2 / e1) - betaSquare) / (log(mbbgg2 / I) - betaSquare) * 0.6;
0520 double Sigma2 = dEdx_ * 1.0E9 * f2 / e2 * (log(mbbgg2 / e2) - betaSquare) / (log(mbbgg2 / I) - betaSquare) * 0.6;
0521 double Sigma3 = dEdx_ * 1.0E9 * Emax / (I * (Emax + I) * log((Emax + I) / I)) * 0.4;
0522
0523 double Nc = (Sigma1 + Sigma2 + Sigma3) * fabs(stepSize_);
0524
0525 if (Nc > 50.) {
0526 double sigmaalpha = 15.76;
0527
0528 double RLAMED = -0.422784 - betaSquare - log(zeta / Emax);
0529 double RLAMAX = 0.60715 + 1.1934 * RLAMED + (0.67794 + 0.052382 * RLAMED) * exp(0.94753 + 0.74442 * RLAMED);
0530
0531 if (RLAMAX <= 1010.) {
0532 sigmaalpha = 1.975560
0533 + 9.898841e-02 * RLAMAX
0534 - 2.828670e-04 * RLAMAX * RLAMAX
0535 + 5.345406e-07 * pow(RLAMAX, 3.)
0536 - 4.942035e-10 * pow(RLAMAX, 4.)
0537 + 1.729807e-13 * pow(RLAMAX, 5.);
0538 } else { sigmaalpha = 1.871887E+01 + 1.296254E-02 * RLAMAX; }
0539
0540 if (sigmaalpha > 54.6) sigmaalpha = 54.6;
0541 sigma2E += sigmaalpha * sigmaalpha * zeta * zeta;
0542 } else {
0543 static const double alpha = 0.996;
0544 double Ealpha = I / (1. - (alpha * Emax / (Emax + I)));
0545 double meanE32 = I * (Emax + I) / Emax * (Ealpha - I);
0546 sigma2E += fabs(stepSize_) * (Sigma1 * e1 * e1 + Sigma2 * e2 * e2 + Sigma3 * meanE32);
0547 }
0548 }
0549
0550 sigma2E *= 1.E-18;
0551
0552
0553 noise[6 * 7 + 6] += charge_*charge_/betaSquare / pow(mom, 4) * sigma2E;
0554 }
0555
0556
0557 void MaterialEffects::noiseCoulomb(M7x7& noise,
0558 const M1x3& direction, double momSquare, double betaSquare) const
0559 {
0560
0561
0562 double sigma2 = 0;
0563 assert(mscModelCode_ == 0 || mscModelCode_ == 1);
0564 const double step = fabs(stepSize_);
0565 const double step2 = step * step;
0566 if (mscModelCode_ == 0) {
0567 sigma2 = 225.E-6 * charge_ * charge_ / (betaSquare * momSquare) * step / radiationLength_ * matZ_ / (matZ_ + 1) * log(159.*pow(matZ_, -1. / 3.)) / log(287.*pow(matZ_, -0.5));
0568
0569 } else if (mscModelCode_ == 1) {
0570 double stepOverRadLength = step / radiationLength_;
0571 double logCor = (1 + 0.038 * log(stepOverRadLength));
0572 sigma2 = 0.0136 * 0.0136 * charge_ * charge_ / (betaSquare * momSquare) * stepOverRadLength * logCor * logCor;
0573 }
0574
0575 sigma2 = (sigma2 > 0.0 ? sigma2 : 0.0);
0576
0577
0578 M7x7 noiseAfter;
0579 std::fill(noiseAfter.begin(), noiseAfter.end(), 0);
0580
0581 const M1x3& a = direction;
0582
0583
0584 noiseAfter[0 * 7 + 0] = sigma2 * step2 / 3.0 * (1 - a[0]*a[0]);
0585 noiseAfter[1 * 7 + 0] = -sigma2 * step2 / 3.0 * a[0]*a[1];
0586 noiseAfter[2 * 7 + 0] = -sigma2 * step2 / 3.0 * a[0]*a[2];
0587 noiseAfter[3 * 7 + 0] = sigma2 * step * 0.5 * (1 - a[0]*a[0]);
0588 noiseAfter[4 * 7 + 0] = -sigma2 * step * 0.5 * a[0]*a[1];
0589 noiseAfter[5 * 7 + 0] = -sigma2 * step * 0.5 * a[0]*a[1];
0590 noiseAfter[0 * 7 + 1] = noiseAfter[1 * 7 + 0];
0591 noiseAfter[1 * 7 + 1] = sigma2 * step2 / 3.0 * (1 - a[1]*a[1]);
0592 noiseAfter[2 * 7 + 1] = -sigma2 * step2 / 3.0 * a[1]*a[2];
0593 noiseAfter[3 * 7 + 1] = noiseAfter[4 * 7 + 0];
0594 noiseAfter[4 * 7 + 1] = sigma2 * step * 0.5 * (1 - a[1] * a[1]);
0595 noiseAfter[5 * 7 + 1] = -sigma2 * step * 0.5 * a[1]*a[2];
0596 noiseAfter[0 * 7 + 2] = noiseAfter[2 * 7 + 0];
0597 noiseAfter[1 * 7 + 2] = noiseAfter[2 * 7 + 1];
0598 noiseAfter[2 * 7 + 2] = sigma2 * step2 / 3.0 * (1 - a[2]*a[2]);
0599 noiseAfter[3 * 7 + 2] = noiseAfter[5 * 7 + 0];
0600 noiseAfter[4 * 7 + 2] = noiseAfter[5 * 7 + 1];
0601 noiseAfter[5 * 7 + 2] = sigma2 * step * 0.5 * (1 - a[2]*a[2]);
0602 noiseAfter[0 * 7 + 3] = noiseAfter[3 * 7 + 0];
0603 noiseAfter[1 * 7 + 3] = noiseAfter[3 * 7 + 1];
0604 noiseAfter[2 * 7 + 3] = noiseAfter[3 * 7 + 2];
0605 noiseAfter[3 * 7 + 3] = sigma2 * (1 - a[0]*a[0]);
0606 noiseAfter[4 * 7 + 3] = -sigma2 * a[0]*a[1];
0607 noiseAfter[5 * 7 + 3] = -sigma2 * a[0]*a[2];
0608 noiseAfter[0 * 7 + 4] = noiseAfter[4 * 7 + 0];
0609 noiseAfter[1 * 7 + 4] = noiseAfter[4 * 7 + 1];
0610 noiseAfter[2 * 7 + 4] = noiseAfter[4 * 7 + 2];
0611 noiseAfter[3 * 7 + 4] = noiseAfter[4 * 7 + 3];
0612 noiseAfter[4 * 7 + 4] = sigma2 * (1 - a[1]*a[1]);
0613 noiseAfter[5 * 7 + 4] = -sigma2 * a[1]*a[2];
0614 noiseAfter[0 * 7 + 5] = noiseAfter[5 * 7 + 0];
0615 noiseAfter[1 * 7 + 5] = noiseAfter[5 * 7 + 1];
0616 noiseAfter[2 * 7 + 5] = noiseAfter[5 * 7 + 2];
0617 noiseAfter[3 * 7 + 5] = noiseAfter[5 * 7 + 3];
0618 noiseAfter[4 * 7 + 5] = noiseAfter[5 * 7 + 4];
0619 noiseAfter[5 * 7 + 5] = sigma2 * (1 - a[2]*a[2]);
0620
0621
0622 for (unsigned int i = 0; i < 7 * 7; ++i) {
0623 noise[i] += noiseAfter[i];
0624 }
0625 }
0626
0627
0628 double MaterialEffects::dEdxBrems(double mom) const
0629 {
0630
0631
0632
0633 if (abs(pdg_) != 11) return 0;
0634
0635 #if !defined(BETHE)
0636 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};
0637 static const double xi = 2.51, beta = 0.99, vl = 0.00004;
0638 #endif
0639 #if defined(BETHE)
0640 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};
0641 static const double xi = 2.10, beta = 1.00, vl = 0.001;
0642 #endif
0643
0644 double BCUT = 10000.;
0645
0646 static const double THIGH = 100., CHIGH = 50.;
0647 double dedxBrems = 0.;
0648
0649 if (BCUT > 0.) {
0650 double T, kc;
0651
0652 if (BCUT > mom) BCUT = mom;
0653
0654
0655
0656 if (mom > THIGH) {
0657 T = THIGH;
0658 if (BCUT >= THIGH)
0659 kc = CHIGH;
0660 else
0661 kc = BCUT;
0662 } else {
0663 T = mom;
0664 kc = BCUT;
0665 }
0666
0667 double E = T + me_;
0668 if (BCUT > T)
0669 kc = T;
0670
0671 double X = log(T / me_);
0672 double Y = log(kc / (E * vl));
0673
0674 double XX;
0675 int K;
0676 double S = 0., YY = 1.;
0677
0678 for (unsigned int I = 1; I <= 2; ++I) {
0679 XX = 1.;
0680 for (unsigned int J = 1; J <= 6; ++J) {
0681 K = 6 * I + J - 6;
0682 S += C[K] * XX * YY;
0683 XX *= X;
0684 }
0685 YY *= Y;
0686 }
0687
0688 for (unsigned int I = 3; I <= 6; ++I) {
0689 XX = 1.;
0690 for (unsigned int J = 1; J <= 6; ++J) {
0691 K = 6 * I + J - 6;
0692 if (Y > 0.)
0693 K += 24;
0694 S += C[K] * XX * YY;
0695 XX *= X;
0696 }
0697 YY *= Y;
0698 }
0699
0700 double SS = 0.;
0701 YY = 1.;
0702
0703 for (unsigned int I = 1; I <= 2; ++I) {
0704 XX = 1.;
0705 for (unsigned int J = 1; J <= 5; ++J) {
0706 K = 5 * I + J + 55;
0707 SS += C[K] * XX * YY;
0708 XX *= X;
0709 }
0710 YY *= Y;
0711 }
0712
0713 for (unsigned int I = 3; I <= 5; ++I) {
0714 XX = 1.;
0715 for (unsigned int J = 1; J <= 5; ++J) {
0716 K = 5 * I + J + 55;
0717 if (Y > 0.)
0718 K += 15;
0719 SS += C[K] * XX * YY;
0720 XX *= X;
0721 }
0722 YY *= Y;
0723 }
0724
0725 S += matZ_ * SS;
0726
0727 if (S > 0.) {
0728 double CORR = 1.;
0729 #if !defined(BETHE)
0730 CORR = 1. / (1. + 0.805485E-10 * matDensity_ * matZ_ * E * E / (matA_ * kc * kc));
0731 #endif
0732
0733
0734
0735
0736 double FAC = matZ_ * (matZ_ + xi) * E * E / (E + me_);
0737 if (beta == 1.)
0738 FAC *= kc * CORR / T;
0739 else
0740 FAC *= exp(beta * log(kc * CORR / T));
0741 if (FAC <= 0.)
0742 return 0.;
0743 dedxBrems = FAC * S;
0744
0745
0746 if (mom >= THIGH) {
0747 double RAT;
0748 if (BCUT < THIGH) {
0749 RAT = BCUT / mom;
0750 S = (1. - 0.5 * RAT + 2.*RAT * RAT / 9.);
0751 RAT = BCUT / T;
0752 S /= 1. - 0.5 * RAT + 2.*RAT * RAT / 9.;
0753 } else {
0754 RAT = BCUT / mom;
0755 S = BCUT * (1. - 0.5 * RAT + 2.*RAT * RAT / 9.);
0756 RAT = kc / T;
0757 S /= kc * (1. - 0.5 * RAT + 2.*RAT * RAT / 9.);
0758 }
0759 dedxBrems *= S;
0760 }
0761
0762 dedxBrems *= 0.60221367 * matDensity_ / matA_;
0763 }
0764 }
0765
0766 if (dedxBrems < 0.)
0767 dedxBrems = 0;
0768
0769 double factor = 1.;
0770
0771 if (pdg_ == -11) {
0772 static const double AA = 7522100., A1 = 0.415, A3 = 0.0021, A5 = 0.00054;
0773
0774 double ETA = 0.;
0775 if (matZ_ > 0.) {
0776 double X = log(AA * mom / (matZ_ * matZ_));
0777 if (X > -8.) {
0778 if (X >= +9.) ETA = 1.;
0779 else {
0780 double W = A1 * X + A3 * pow(X, 3.) + A5 * pow(X, 5.);
0781 ETA = 0.5 + atan(W) / M_PI;
0782 }
0783 }
0784 }
0785
0786 if (ETA < 0.0001)
0787 factor = 1.E-10;
0788 else if (ETA > 0.9999)
0789 factor = 1.;
0790 else {
0791 double E0 = BCUT / mom;
0792 if (E0 > 1.)
0793 E0 = 1.;
0794 if (E0 < 1.E-8)
0795 factor = 1.;
0796 else
0797 factor = ETA * (1. - pow(1. - E0, 1. / ETA)) / E0;
0798 }
0799 }
0800
0801 return factor * dedxBrems;
0802 }
0803
0804
0805 void MaterialEffects::noiseBrems(M7x7& noise, double momSquare, double betaSquare) const
0806 {
0807
0808
0809
0810
0811
0812 if (abs(pdg_) != 11) return;
0813
0814 double minusXOverLn2 = -1.442695 * fabs(stepSize_) / radiationLength_;
0815 double sigma2E = 1.44*(pow(3., minusXOverLn2) - pow(4., minusXOverLn2)) * momSquare;
0816 sigma2E = std::max(sigma2E, 0.0);
0817
0818
0819 noise[6 * 7 + 6] += charge_*charge_/betaSquare / pow(momSquare, 2) * sigma2E;
0820 }
0821
0822
0823 void MaterialEffects::setDebugLvl(unsigned int lvl) {
0824 debugLvl_ = lvl;
0825 if (materialInterface_ and debugLvl_ > 1)
0826 materialInterface_->setDebugLvl(debugLvl_-1);
0827 }
0828
0829
0830 void MaterialEffects::drawdEdx(int pdg) {
0831 pdg_ = pdg;
0832 this->getParticleParameters();
0833
0834 stepSize_ = 1;
0835
0836 materialInterface_->initTrack(0, 0, 0, 1, 1, 1);
0837 auto currentMaterial = materialInterface_->getMaterialParameters();
0838 matDensity_ = currentMaterial.density;
0839 matZ_ = currentMaterial.Z;
0840 matA_ = currentMaterial.A;
0841 radiationLength_ = currentMaterial.radiationLength;
0842 mEE_ = currentMaterial.mEE;
0843
0844 double minMom = 0.00001;
0845 double maxMom = 10000;
0846 int nSteps(10000);
0847 double logStepSize = (log10(maxMom) - log10(minMom)) / (nSteps-1);
0848
0849 TH1D hdEdxBethe("dEdxBethe", "dEdxBethe; log10(mom)", nSteps, log10(minMom), log10(maxMom));
0850 TH1D hdEdxBrems("dEdxBrems", "dEdxBrems; log10(mom)", nSteps, log10(minMom), log10(maxMom));
0851
0852 for (int i=0; i<nSteps; ++i) {
0853 double mom = pow(10., log10(minMom) + i*logStepSize);
0854 double E = hypot(mom, mass_);
0855 if (pdg_ == c_monopolePDGCode) {
0856 charge_ = mag_charge_ * mom / E;
0857 }
0858
0859 energyLossBrems_ = false;
0860 energyLossBetheBloch_ = true;
0861
0862 try {
0863 hdEdxBethe.Fill(log10(mom), dEdx(E));
0864 }
0865 catch (...) {
0866
0867 }
0868
0869
0870
0871
0872 energyLossBrems_ = true;
0873 energyLossBetheBloch_ = false;
0874 try {
0875 hdEdxBrems.Fill(log10(mom), dEdx(E));
0876 }
0877 catch (...) {
0878
0879 }
0880 }
0881
0882 energyLossBrems_ = true;
0883 energyLossBetheBloch_ = true;
0884
0885 std::string Result;
0886 std::stringstream convert;
0887 convert << pdg;
0888 Result = convert.str();
0889
0890 TFile outfile("dEdx_" + TString(Result) + ".root", "recreate");
0891 outfile.cd();
0892 hdEdxBethe.Write();
0893 hdEdxBrems.Write();
0894 outfile.Close();
0895 }
0896
0897 }
0898
0899