14 #include <Math/AxisAngle.h>
15 #include "Math/Boost.h"
75 std::vector<std::unique_ptr<fastsim::Particle> >& secondaries,
80 unsigned index(
int thePid);
128 1.0, 2.0, 3.0, 4.0, 5.0, 7.0, 9.0, 12.0, 15.0, 20.0, 30.0, 50.0, 100.0, 200.0, 300.0, 500.0, 700.0, 1000.0};
133 const std::vector<int>
theHadronID = {211, -211, 130, 321, -321, 2212, -2212, 2112, -2112};
136 "piplus",
"piminus",
"K0L",
"Kplus",
"Kminus",
"p",
"pbar",
"n",
"nbar"};
139 0.13957, 0.13957, 0.497648, 0.493677, 0.493677, 0.93827, 0.93827, 0.939565, 0.939565};
141 const std::vector<double>
theHadronPMin = {0.7, 0.0, 1.0, 1.0, 0.0, 1.1, 0.0, 1.1, 0.0};
330 const std::vector<int>
protonsID = {2212, 3222, -101, -102, -103, -104};
332 const std::vector<int>
neutronsID = {2112, 3122, 3112, 3312, 3322, 3334, -3334};
334 const std::vector<int>
K0LsID = {130, 310};
382 for (
const auto&
id :
K0LsID)
400 TFile* aVFile =
nullptr;
402 std::vector<TBranch*> aVBranch(
theHadronEN.size());
403 std::vector<NUEvent*> aVNUEvents(
theHadronEN.size());
404 std::vector<unsigned> aVCurrentEntry(
theHadronEN.size());
405 std::vector<unsigned> aVCurrentInteraction(
theHadronEN.size());
406 std::vector<unsigned> aVNumberOfEntries(
theHadronEN.size());
407 std::vector<unsigned> aVNumberOfInteractions(
theHadronEN.size());
408 std::vector<std::string> aVFileName(
theHadronEN.size());
409 std::vector<double> aVHadronCM(
theHadronEN.size());
420 for (
unsigned iname = 0; iname <
theHadronNA.size(); ++iname) {
435 std::cout <<
"***WARNING*** You are reading nuclear-interaction information from the file " <<
inputFile
436 <<
" created in an earlier run." << std::endl;
443 edm::FileInPath myDataFile(
"FastSimulation/MaterialEffects/data/NuclearInteractions.root");
449 for (
unsigned iname = 0; iname <
theHadronNA.size(); ++iname) {
450 for (
unsigned iene = 0; iene <
theHadronEN.size(); ++iene) {
461 throw cms::Exception(
"FastSimulation/MaterialEffects") <<
"Tree with name " << treeName <<
" not found ";
465 <<
"Branch with name nuEvent not found in " <<
theFileNames[iname][iene];
473 unsigned NInteractions =
theNUEvents[iname][iene]->nInteractions();
484 theHadronCM[iname][iene] = (Reference + Proton).M();
503 for (
auto& vEvents : theNUEvents) {
504 for (
auto evtPtr : vEvents) {
512 myOutputFile.close();
517 std::vector<std::unique_ptr<fastsim::Particle> >& secondaries,
529 radLengths *=
layer.getNuclearInteractionThicknessFactor();
533 if (radLengths < 1E-10) {
538 if (!currentValuesWereSet) {
539 currentValuesWereSet =
true;
540 for (
unsigned iname = 0; iname < theHadronNA.size(); ++iname) {
541 for (
unsigned iene = 0; iene < theHadronEN.size(); ++iene) {
542 theCurrentEntry[iname][iene] = (unsigned)(theNumberOfEntries[iname][iene] * random.
flatShoot());
544 theTrees[iname][iene]->GetEntry(theCurrentEntry[iname][iene]);
545 unsigned NInteractions = theNUEvents[iname][iene]->nInteractions();
546 theNumberOfInteractions[iname][iene] = NInteractions;
548 theCurrentInteraction[iname][iene] = (unsigned)(theNumberOfInteractions[iname][iene] * random.
flatShoot());
559 if (pHadron < theHadronEnergy) {
564 std::map<int, int>::const_iterator thePit = theIDMap.find(
pdgId);
566 int thePid = (thePit != theIDMap.end() ? thePit->second :
pdgId);
569 unsigned fPid =
abs(thePid);
570 if (fPid != 211 && fPid != 130 && fPid != 321 && fPid != 2112 && fPid != 2212) {
575 unsigned thePidIndex =
index(thePid);
577 double theInelasticLength = radLengths * theLengthRatio[thePidIndex];
582 double theElasticLength = (0.8753 * ee + 0.15) * theInelasticLength;
585 double theTotalInteractionLength = theInelasticLength + theElasticLength;
591 if (aNuclInteraction > theTotalInteractionLength) {
597 if (elastic < theElasticLength / theTotalInteractionLength) {
608 ROOT::Math::AxisAngle rotation1(orthogonal(particle.
momentum().Vect()),
theta);
609 ROOT::Math::AxisAngle rotation2(particle.
momentum().Vect(), phi);
615 secondaries.emplace_back(
621 if (particle.
charge() != 0) {
622 secondaries.back()->setMotherDeltaR(particle.
momentum());
623 secondaries.back()->setMotherPdgId(
pdgId);
624 secondaries.back()->setMotherSimTrackIndex(particle.
simTrackIndex());
628 particle.
momentum().SetXYZT(0., 0., 0., 0.);
631 particle.
momentum().SetXYZT(rotated.X(), rotated.Y(), rotated.Z(), particle.
momentum().E());
636 const std::vector<double>& aHadronCM = theHadronCM[thePidIndex];
637 const std::vector<double>& aRatios = theRatiosMap[thePidIndex];
644 double pMin = theHadronPMin[thePidIndex];
649 double ecm = (Proton + Hadron).M();
655 double ecm1 = (Proton + Hadron0).M();
657 double ecm2 = aHadronCM[0];
659 double ratio2 = aRatios[0];
660 if (ecm > aHadronCM[0] && ecm < aHadronCM[aHadronCM.size() - 1]) {
661 for (
unsigned ene = 1; ene < aHadronCM.size() && ecm > aHadronCM[ene - 1]; ++ene) {
662 if (ecm < aHadronCM[ene]) {
665 ecm1 = aHadronCM[ene1];
666 ecm2 = aHadronCM[ene2];
667 ratio1 = aRatios[ene1];
668 ratio2 = aRatios[ene2];
671 }
else if (ecm > aHadronCM[aHadronCM.size() - 1]) {
672 ene1 = aHadronCM.size() - 1;
673 ene2 = aHadronCM.size() - 2;
674 ecm1 = aHadronCM[ene1];
675 ecm2 = aHadronCM[ene2];
676 ratio1 = aRatios[ene2];
677 ratio2 = aRatios[ene2];
681 double slope = (std::log10(ecm) - std::log10(ecm1)) / (std::log10(ecm2) - std::log10(ecm1));
682 double inelastic = ratio1 + (ratio2 - ratio1) *
slope;
683 double inelastic4 = pHadron < 4. ? aRatios[ien4] : 1.;
686 if (elastic > 1. - (inelastic * theInelasticLength) / theTotalInteractionLength) {
688 std::vector<unsigned>& aCurrentInteraction = theCurrentInteraction[thePidIndex];
689 std::vector<unsigned>& aNumberOfInteractions = theNumberOfInteractions[thePidIndex];
690 std::vector<NUEvent*>& aNUEvents = theNUEvents[thePidIndex];
696 if (random.
flatShoot() <
slope || aNumberOfInteractions[ene1] == 0) {
704 theBoost /= theBoost.e();
708 if (aCurrentInteraction[ene] == aNumberOfInteractions[ene]) {
709 std::vector<unsigned>& aCurrentEntry = theCurrentEntry[thePidIndex];
710 std::vector<unsigned>& aNumberOfEntries = theNumberOfEntries[thePidIndex];
711 std::vector<TTree*>& aTrees = theTrees[thePidIndex];
712 ++aCurrentEntry[ene];
714 aCurrentInteraction[ene] = 0;
715 if (aCurrentEntry[ene] == aNumberOfEntries[ene]) {
716 aCurrentEntry[ene] = 0;
719 unsigned myEntry = aCurrentEntry[ene];
720 aTrees[ene]->GetEntry(myEntry);
721 aNumberOfInteractions[ene] = aNUEvents[ene]->nInteractions();
727 unsigned firstTrack = anInteraction.
first;
728 unsigned lastTrack = anInteraction.
last;
731 XYZVector theAxis = theBoost.Vect().Unit();
733 ROOT::Math::AxisAngle axisRotation(theAxis, theAngle);
734 ROOT::Math::Boost axisBoost(theBoost.x(), theBoost.y(), theBoost.z());
739 double orthAngle = acos(theBoost.Vect().Unit().Z());
740 ROOT::Math::AxisAngle orthRotation(orthAxis, orthAngle);
743 for (
unsigned iTrack = firstTrack; iTrack <= lastTrack; ++iTrack) {
749 aParticle.
pz * aParticle.
pz + aParticle.
mass * aParticle.
mass / (ecm * ecm));
754 XYZVector rotated = orthRotation(daugtherMomentum.Vect());
756 rotated = axisRotation(rotated);
759 daugtherMomentum.SetXYZT(rotated.X(), rotated.Y(), rotated.Z(), daugtherMomentum.E());
762 daugtherMomentum = axisBoost(daugtherMomentum);
771 if (particle.
charge() != 0) {
772 secondaries.back()->setMotherDeltaR(particle.
momentum());
773 secondaries.back()->setMotherPdgId(
pdgId);
774 secondaries.back()->setMotherSimTrackIndex(particle.
simTrackIndex());
779 particle.
momentum().SetXYZT(0., 0., 0., 0.);
787 ++aCurrentInteraction[ene];
790 }
else if (pHadron < 4. && elastic > 1. - (inelastic4 * theInelasticLength) / theTotalInteractionLength) {
792 particle.
momentum().SetXYZT(0., 0., 0., 0.);
802 if (myOutputBuffer / 1000 * 1000 == myOutputBuffer) {
803 myOutputFile.close();
804 myOutputFile.open(
"NuclearInteractionOutputFile.txt");
807 unsigned size1 = theCurrentEntry.size() * theCurrentEntry.begin()->size();
808 std::vector<unsigned> theCurrentEntries;
809 theCurrentEntries.resize(size1);
810 size1 *=
sizeof(unsigned);
812 unsigned size2 = theCurrentInteraction.size() * theCurrentInteraction.begin()->size();
813 std::vector<unsigned> theCurrentInteractions;
814 theCurrentInteractions.resize(size2);
815 size2 *=
sizeof(unsigned);
818 std::vector<std::vector<unsigned> >::const_iterator aCurrentEntry = theCurrentEntry.begin();
819 std::vector<std::vector<unsigned> >::const_iterator lastCurrentEntry = theCurrentEntry.end();
820 unsigned allEntries = 0;
821 for (; aCurrentEntry != lastCurrentEntry; ++aCurrentEntry) {
822 unsigned size = aCurrentEntry->size();
823 for (
unsigned iene = 0; iene <
size; ++iene)
824 theCurrentEntries[allEntries++] = (*aCurrentEntry)[iene];
828 std::vector<std::vector<unsigned> >::const_iterator aCurrentInteraction = theCurrentInteraction.begin();
829 std::vector<std::vector<unsigned> >::const_iterator lastCurrentInteraction = theCurrentInteraction.end();
830 unsigned allInteractions = 0;
831 for (; aCurrentInteraction != lastCurrentInteraction; ++aCurrentInteraction) {
832 unsigned size = aCurrentInteraction->size();
833 for (
unsigned iene = 0; iene <
size; ++iene)
834 theCurrentInteractions[allInteractions++] = (*aCurrentInteraction)[iene];
837 myOutputFile.write((
const char*)(&theCurrentEntries.front()), size1);
838 myOutputFile.write((
const char*)(&theCurrentInteractions.front()), size2);
839 myOutputFile.flush();
843 std::ifstream myInputFile;
846 unsigned size1 = theCurrentEntry.size() * theCurrentEntry.begin()->size();
847 std::vector<unsigned> theCurrentEntries;
848 theCurrentEntries.resize(size1);
849 size1 *=
sizeof(unsigned);
851 unsigned size2 = theCurrentInteraction.size() * theCurrentInteraction.begin()->size();
852 std::vector<unsigned> theCurrentInteractions;
853 theCurrentInteractions.resize(size2);
854 size2 *=
sizeof(unsigned);
860 if (myInputFile.is_open()) {
868 myInputFile.seekg(
size - size1 - size2);
869 myInputFile.read((
char*)(&theCurrentEntries.front()), size1);
870 myInputFile.read((
char*)(&theCurrentInteractions.front()), size2);
874 std::vector<std::vector<unsigned> >::iterator aCurrentEntry = theCurrentEntry.begin();
875 std::vector<std::vector<unsigned> >::iterator lastCurrentEntry = theCurrentEntry.end();
876 unsigned allEntries = 0;
877 for (; aCurrentEntry != lastCurrentEntry; ++aCurrentEntry) {
878 unsigned size = aCurrentEntry->size();
879 for (
unsigned iene = 0; iene <
size; ++iene)
880 (*aCurrentEntry)[iene] = theCurrentEntries[allEntries++];
884 std::vector<std::vector<unsigned> >::iterator aCurrentInteraction = theCurrentInteraction.begin();
885 std::vector<std::vector<unsigned> >::iterator lastCurrentInteraction = theCurrentInteraction.end();
886 unsigned allInteractions = 0;
887 for (; aCurrentInteraction != lastCurrentInteraction; ++aCurrentInteraction) {
888 unsigned size = aCurrentInteraction->size();
889 for (
unsigned iene = 0; iene <
size; ++iene)
890 (*aCurrentInteraction)[iene] = theCurrentInteractions[allInteractions++];
901 unsigned myIndex = 0;
902 while (thePid != theHadronID[myIndex])
908 double x = fabs(aVector.X());
909 double y = fabs(aVector.Y());
910 double z = fabs(aVector.Z());
913 return x <
z ?
XYZVector(0., aVector.Z(), -aVector.Y()) :
XYZVector(aVector.Y(), -aVector.X(), 0.);
915 return y <
z ?
XYZVector(-aVector.Z(), 0., aVector.X()) :
XYZVector(aVector.Y(), -aVector.X(), 0.);