33 std::map<int, int>& idMap,
49 currentValuesWereSet(
false) {
54 TFile* aVFile =
nullptr;
55 std::vector<TTree*> aVTree(
thePionEN.size(),
static_cast<TTree*
>(
nullptr));
56 std::vector<TBranch*> aVBranch(
thePionEN.size(),
static_cast<TBranch*
>(
nullptr));
57 std::vector<NUEvent*> aVNUEvents(
thePionEN.size(),
static_cast<NUEvent*
>(
nullptr));
58 std::vector<unsigned> aVCurrentEntry(
thePionEN.size(),
static_cast<unsigned>(0));
59 std::vector<unsigned> aVCurrentInteraction(
thePionEN.size(),
static_cast<unsigned>(0));
60 std::vector<unsigned> aVNumberOfEntries(
thePionEN.size(),
static_cast<unsigned>(0));
61 std::vector<unsigned> aVNumberOfInteractions(
thePionEN.size(),
static_cast<unsigned>(0));
63 std::vector<double> aVPionCM(
thePionEN.size(),
static_cast<double>(0));
75 for (
unsigned iname = 0; iname <
thePionNA.size(); ++iname) {
90 std::cout <<
"***WARNING*** You are reading nuclear-interaction information from the file " <<
inputFile 91 <<
" created in an earlier run." << std::endl;
99 edm::FileInPath myDataFile(
"FastSimulation/MaterialEffects/data/NuclearInteractions.root");
105 for (
unsigned iname = 0; iname <
thePionNA.size(); ++iname) {
106 for (
unsigned iene = 0; iene <
thePionEN.size(); ++iene) {
110 filename <<
"NuclearInteractionsVal_" <<
thePionNA[iname] <<
"_E" << theEne <<
".root";
119 throw cms::Exception(
"FastSimulation/MaterialEffects") <<
"Tree with name " << treeName <<
" not found ";
125 <<
"Branch with name nuEvent not found in " <<
theFileNames[iname][iene];
135 unsigned NInteractions =
theNUEvents[iname][iene]->nInteractions();
144 thePionCM[iname][iene] = (Reference + Proton).M();
178 for (
auto evtPtr : vEvents) {
192 for (
unsigned iname = 0; iname <
thePionNA.size(); ++iname) {
193 for (
unsigned iene = 0; iene <
thePionEN.size(); ++iene) {
197 unsigned NInteractions =
theNUEvents[iname][iene]->nInteractions();
213 std::map<int, int>::const_iterator thePit =
theIDMap.find(
Particle.particle().pid());
215 int thePid = thePit !=
theIDMap.end() ? thePit->second :
Particle.particle().pid();
218 unsigned fPid =
abs(thePid);
219 if (fPid != 211 && fPid != 130 && fPid != 321 && fPid != 2112 && fPid != 2212) {
226 unsigned thePidIndex =
index(thePid);
232 double theElasticLength = (0.8753 * ee + 0.15)
235 * theInelasticLength;
238 double theTotalInteractionLength = theInelasticLength + theElasticLength;
242 if (aNuclInteraction < theTotalInteractionLength) {
245 if (elastic < theElasticLength / theTotalInteractionLength) {
253 double phi = 2. * 3.14159265358979323 * random->
flatShoot();
258 Particle.particle().rotate(rotation1);
259 Particle.particle().rotate(rotation2);
279 const std::vector<double>& aPionCM =
thePionCM[thePidIndex];
280 const std::vector<double>& aRatios =
theRatios[thePidIndex];
292 double ecm = (Proton + Hadron).M();
301 double ecm1 = (Proton + Hadron0).M();
305 double ecm2 = aPionCM[0];
307 double ratio2 = aRatios[0];
308 if (ecm > aPionCM[0] && ecm < aPionCM[aPionCM.size() - 1]) {
309 for (
unsigned ene = 1; ene < aPionCM.size() && ecm > aPionCM[ene - 1]; ++ene) {
310 if (ecm < aPionCM[ene]) {
313 ecm1 = aPionCM[ene1];
314 ecm2 = aPionCM[ene2];
315 ratio1 = aRatios[ene1];
316 ratio2 = aRatios[ene2];
319 }
else if (ecm > aPionCM[aPionCM.size() - 1]) {
320 ene1 = aPionCM.size() - 1;
321 ene2 = aPionCM.size() - 2;
322 ecm1 = aPionCM[ene1];
323 ecm2 = aPionCM[ene2];
324 ratio1 = aRatios[ene2];
325 ratio2 = aRatios[ene2];
329 double slope = (std::log10(ecm) - std::log10(ecm1)) / (std::log10(ecm2) - std::log10(ecm1));
330 double inelastic = ratio1 + (ratio2 - ratio1) *
slope;
331 double inelastic4 = pHadron < 4. ? aRatios[
ien4] : 1.;
338 if (elastic > 1. - (inelastic * theInelasticLength) / theTotalInteractionLength) {
342 std::vector<NUEvent*>& aNUEvents =
theNUEvents[thePidIndex];
351 if (random->
flatShoot() <
slope || aNumberOfInteractions[ene1] == 0)
366 theBoost /= theBoost.e();
377 if (aCurrentInteraction[ene] == aNumberOfInteractions[ene]) {
381 std::vector<TTree*>& aTrees =
theTrees[thePidIndex];
382 ++aCurrentEntry[ene];
385 aCurrentInteraction[ene] = 0;
386 if (aCurrentEntry[ene] == aNumberOfEntries[ene]) {
387 aCurrentEntry[ene] = 0;
390 unsigned myEntry = aCurrentEntry[ene];
393 aTrees[ene]->GetEntry(myEntry);
395 aNumberOfInteractions[ene] = aNUEvents[ene]->nInteractions();
402 unsigned firstTrack = anInteraction.
first;
403 unsigned lastTrack = anInteraction.
last;
412 XYZVector theAxis = theBoost.Vect().Unit();
413 double theAngle = random->
flatShoot() * 2. * 3.14159265358979323;
420 double orthAngle = acos(theBoost.Vect().Unit().Z());
427 for (
unsigned iTrack = firstTrack; iTrack <= lastTrack; ++iTrack) {
428 unsigned idaugh = iTrack - firstTrack;
441 aParticle.
pz * aParticle.
pz + aParticle.
mass * aParticle.
mass / (ecm * ecm));
448 aDaughter.
rotate(orthRotation);
451 aDaughter.
rotate(axisRotation);
454 aDaughter.
boost(axisBoost);
482 ++aCurrentInteraction[ene];
485 }
else if (pHadron < 4. && elastic > 1. - (inelastic4 * theInelasticLength) / theTotalInteractionLength) {
501 if (fabs(
Particle.charge()) > 1E-12) {
504 if (fabs(chargeDiff) < 1E-12) {
540 std::vector<unsigned> theCurrentEntries;
541 theCurrentEntries.resize(size1);
542 size1 *=
sizeof(unsigned);
545 std::vector<unsigned> theCurrentInteractions;
546 theCurrentInteractions.resize(size2);
547 size2 *=
sizeof(unsigned);
550 std::vector<std::vector<unsigned> >::const_iterator aCurrentEntry =
theCurrentEntry.begin();
551 std::vector<std::vector<unsigned> >::const_iterator lastCurrentEntry =
theCurrentEntry.end();
552 unsigned allEntries = 0;
553 for (; aCurrentEntry != lastCurrentEntry; ++aCurrentEntry) {
554 unsigned size = aCurrentEntry->size();
555 for (
unsigned iene = 0; iene <
size; ++iene)
556 theCurrentEntries[allEntries++] = (*aCurrentEntry)[iene];
560 std::vector<std::vector<unsigned> >::const_iterator aCurrentInteraction =
theCurrentInteraction.begin();
561 std::vector<std::vector<unsigned> >::const_iterator lastCurrentInteraction =
theCurrentInteraction.end();
562 unsigned allInteractions = 0;
563 for (; aCurrentInteraction != lastCurrentInteraction; ++aCurrentInteraction) {
564 unsigned size = aCurrentInteraction->size();
565 for (
unsigned iene = 0; iene <
size; ++iene)
566 theCurrentInteractions[allInteractions++] = (*aCurrentInteraction)[iene];
569 myOutputFile.write((
const char*)(&theCurrentEntries.front()), size1);
570 myOutputFile.write((
const char*)(&theCurrentInteractions.front()), size2);
575 std::ifstream myInputFile;
579 std::vector<unsigned> theCurrentEntries;
580 theCurrentEntries.resize(size1);
581 size1 *=
sizeof(unsigned);
584 std::vector<unsigned> theCurrentInteractions;
585 theCurrentInteractions.resize(size2);
586 size2 *=
sizeof(unsigned);
592 if (myInputFile.is_open()) {
600 myInputFile.seekg(
size - size1 - size2);
601 myInputFile.read((
char*)(&theCurrentEntries.front()), size1);
602 myInputFile.read((
char*)(&theCurrentInteractions.front()), size2);
606 std::vector<std::vector<unsigned> >::iterator aCurrentEntry =
theCurrentEntry.begin();
607 std::vector<std::vector<unsigned> >::iterator lastCurrentEntry =
theCurrentEntry.end();
608 unsigned allEntries = 0;
609 for (; aCurrentEntry != lastCurrentEntry; ++aCurrentEntry) {
610 unsigned size = aCurrentEntry->size();
611 for (
unsigned iene = 0; iene <
size; ++iene)
612 (*aCurrentEntry)[iene] = theCurrentEntries[allEntries++];
618 unsigned allInteractions = 0;
619 for (; aCurrentInteraction != lastCurrentInteraction; ++aCurrentInteraction) {
620 unsigned size = aCurrentInteraction->size();
621 for (
unsigned iene = 0; iene <
size; ++iene)
622 (*aCurrentInteraction)[iene] = theCurrentInteractions[allInteractions++];
632 unsigned myIndex = 0;
void boost(double bx, double by, double bz)
std::string fullPath() const
static const double slope[3]
Sin< T >::type sin(const T &t)
void compute(ParticlePropagator &Particle, RandomEngineAndDistribution const *) override
Generate a nuclear interaction according to the probability that it happens.
std::vector< double > thePionMA
std::string to_string(const V &value)
std::vector< std::vector< NUEvent * > > theNUEvents
std::vector< std::vector< std::string > > theFileNames
std::vector< int > thePionID
double charge() const
get the MEASURED charge
RawParticle makeParticle(HepPDT::ParticleDataTable const *, int id, const math::XYZTLorentzVector &p)
bool currentValuesWereSet
std::vector< std::vector< unsigned > > theNumberOfEntries
Abs< T >::type abs(const T &t)
XYZVector orthogonal(const XYZVector &) const
A vector orthogonal to another one (because it's not in XYZTLorentzVector)
void rotate(double rphi, const XYZVector &raxis)
bool read(std::string inputFile)
Read former nuclear interaction (from previous run)
std::vector< std::vector< unsigned > > theCurrentInteraction
unsigned index(int thePid)
Return a hashed index for a given pid.
std::vector< std::string > thePionNA
std::vector< std::vector< double > > thePionCM
~NuclearInteractionSimulator() override
Default Destructor.
XYZVector Vect() const
the momentum threevector
double distanceToPrimary(const RawParticle &Particle, const RawParticle &aDaughter) const
Compute distance between secondary and primary.
NuclearInteractionSimulator(std::vector< double > &hadronEnergies, std::vector< int > &hadronTypes, std::vector< std::string > &hadronNames, std::vector< double > &hadronMasses, std::vector< double > &hadronPMin, double pionEnergy, std::vector< double > &lengthRatio, std::vector< std::vector< double > > &ratios, std::map< int, int > &idMap, std::string inputFile, unsigned int distAlgo, double distCut)
Constructor.
std::vector< std::vector< TBranch * > > theBranches
std::vector< std::vector< unsigned > > theNumberOfInteractions
std::ofstream myOutputFile
std::vector< std::vector< unsigned > > theCurrentEntry
std::map< int, int > theIDMap
std::vector< double > theLengthRatio
std::vector< RawParticle > _theUpdatedState
ROOT::Math::AxisAngle Rotation
std::vector< double > thePionEN
std::vector< std::vector< double > > theRatios
lengthRatio
Default is 0.020 for algo 1;.
void save() override
Save current nuclear interaction (for later use)
double flatShoot(double xmin=0.0, double xmax=1.0) const
math::XYZVector XYZVector
int theClosestChargedDaughterId
Geom::Theta< T > theta() const
Power< A, B >::type pow(const A &a, const B &b)
std::vector< double > thePionPMin
math::XYZTLorentzVector XYZTLorentzVector
std::vector< std::vector< TTree * > > theTrees