File indexing completed on 2024-04-06 12:11:20
0001 #include "FastSimulation/Utilities/interface/RandomEngineAndDistribution.h"
0002 #include "FastSimulation/SimplifiedGeometryPropagator/interface/Particle.h"
0003 #include "FastSimulation/SimplifiedGeometryPropagator/interface/SimplifiedGeometry.h"
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0006
0007 #include <cmath>
0008 #include <memory>
0009
0010 #include <Math/RotationY.h>
0011 #include <Math/RotationZ.h>
0012
0013 #include "FastSimulation/SimplifiedGeometryPropagator/interface/InteractionModelFactory.h"
0014 #include "FastSimulation/SimplifiedGeometryPropagator/interface/InteractionModel.h"
0015 #include "FastSimulation/SimplifiedGeometryPropagator/interface/Constants.h"
0016 #include "DataFormats/Math/interface/LorentzVector.h"
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 namespace fastsim {
0028
0029
0030
0031
0032
0033 class Bremsstrahlung : public InteractionModel {
0034 public:
0035
0036 Bremsstrahlung(const std::string& name, const edm::ParameterSet& cfg);
0037
0038
0039 ~Bremsstrahlung() override { ; };
0040
0041
0042
0043
0044
0045
0046
0047
0048 void interact(Particle& particle,
0049 const SimplifiedGeometry& layer,
0050 std::vector<std::unique_ptr<Particle> >& secondaries,
0051 const RandomEngineAndDistribution& random) override;
0052
0053 private:
0054
0055
0056
0057
0058
0059
0060
0061 math::XYZTLorentzVector brem(Particle& particle, double xmin, const RandomEngineAndDistribution& random) const;
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 double gbteth(const double ener,
0072 const double partm,
0073 const double efrac,
0074 const RandomEngineAndDistribution& random) const;
0075
0076 double minPhotonEnergy_;
0077 double minPhotonEnergyFraction_;
0078 double Z_;
0079 };
0080 }
0081
0082 fastsim::Bremsstrahlung::Bremsstrahlung(const std::string& name, const edm::ParameterSet& cfg)
0083 : fastsim::InteractionModel(name) {
0084
0085 minPhotonEnergy_ = cfg.getParameter<double>("minPhotonEnergy");
0086 minPhotonEnergyFraction_ = cfg.getParameter<double>("minPhotonEnergyFraction");
0087
0088 Z_ = cfg.getParameter<double>("Z");
0089 }
0090
0091 void fastsim::Bremsstrahlung::interact(fastsim::Particle& particle,
0092 const SimplifiedGeometry& layer,
0093 std::vector<std::unique_ptr<fastsim::Particle> >& secondaries,
0094 const RandomEngineAndDistribution& random) {
0095
0096 if (std::abs(particle.pdgId()) != 11) {
0097 return;
0098 }
0099
0100 double radLengths = layer.getThickness(particle.position(), particle.momentum());
0101
0102
0103
0104 if (radLengths < 1E-10) {
0105 return;
0106 }
0107
0108
0109
0110
0111 if (radLengths > 4.) {
0112 particle.momentum().SetXYZT(0., 0., 0., 0.);
0113 return;
0114 }
0115
0116
0117 if (particle.momentum().E() - particle.momentum().mass() < minPhotonEnergy_) {
0118 return;
0119 }
0120
0121
0122 double xmin = std::max(minPhotonEnergy_ / particle.momentum().E(), minPhotonEnergyFraction_);
0123 if (xmin >= 1. || xmin <= 0.) {
0124 return;
0125 }
0126
0127
0128 double bremProba =
0129 radLengths * (4. / 3. * std::log(1. / xmin) - 4. / 3. * (1. - xmin) + 1. / 2. * (1. - xmin * xmin));
0130
0131
0132 unsigned int nPhotons = random.poissonShoot(bremProba);
0133 if (nPhotons == 0) {
0134 return;
0135 }
0136
0137
0138 double theta = particle.momentum().Theta();
0139 double phi = particle.momentum().Phi();
0140 double m2dontchange = particle.momentum().mass() * particle.momentum().mass();
0141
0142
0143 for (unsigned int i = 0; i < nPhotons; ++i) {
0144
0145 math::XYZTLorentzVector photonMom = brem(particle, xmin, random);
0146
0147
0148 if (particle.momentum().E() - particle.momentum().mass() < photonMom.E())
0149 break;
0150
0151
0152 photonMom = ROOT::Math::RotationZ(phi) * (ROOT::Math::RotationY(theta) * photonMom);
0153
0154
0155 secondaries.emplace_back(new fastsim::Particle(22, particle.position(), photonMom));
0156
0157
0158 particle.momentum() -= photonMom;
0159 particle.momentum().SetXYZT(particle.momentum().px(),
0160 particle.momentum().py(),
0161 particle.momentum().pz(),
0162 sqrt(pow(particle.momentum().P(), 2) + m2dontchange));
0163 }
0164 }
0165
0166 math::XYZTLorentzVector fastsim::Bremsstrahlung::brem(fastsim::Particle& particle,
0167 double xmin,
0168 const RandomEngineAndDistribution& random) const {
0169 double xp = 0;
0170 double weight = 0.;
0171
0172 do {
0173 xp = xmin * std::exp(-std::log(xmin) * random.flatShoot());
0174 weight = 1. - xp + 3. / 4. * xp * xp;
0175 } while (weight < random.flatShoot());
0176
0177
0178
0179
0180
0181 const double phi = random.flatShoot() * 2. * M_PI;
0182
0183 const double theta = gbteth(particle.momentum().E(), fastsim::Constants::eMass, xp, random) *
0184 fastsim::Constants::eMass / particle.momentum().E();
0185
0186
0187 double stheta = std::sin(theta);
0188 double ctheta = std::cos(theta);
0189 double sphi = std::sin(phi);
0190 double cphi = std::cos(phi);
0191
0192 return xp * particle.momentum().E() * math::XYZTLorentzVector(stheta * cphi, stheta * sphi, ctheta, 1.);
0193 }
0194
0195 double fastsim::Bremsstrahlung::gbteth(const double ener,
0196 const double partm,
0197 const double efrac,
0198 const RandomEngineAndDistribution& random) const {
0199
0200
0201
0202
0203 const double alfa = 0.625;
0204
0205 const double d = 0.13 * (0.8 + 1.3 / Z_) * (100.0 + (1.0 / ener)) * (1.0 + efrac);
0206 const double w1 = 9.0 / (9.0 + d);
0207 const double umax = ener * M_PI / partm;
0208 double u;
0209
0210 do {
0211 double beta = (random.flatShoot() <= w1) ? alfa : 3.0 * alfa;
0212 u = -std::log(random.flatShoot() * random.flatShoot()) / beta;
0213 } while (u >= umax);
0214
0215 return u;
0216 }
0217
0218 DEFINE_EDM_PLUGIN(fastsim::InteractionModelFactory, fastsim::Bremsstrahlung, "fastsim::Bremsstrahlung");