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");
104 for (
unsigned iname = 0; iname <
thePionNA.size(); ++iname) {
105 for (
unsigned iene = 0; iene <
thePionEN.size(); ++iene) {
109 filename <<
"NuclearInteractionsVal_" <<
thePionNA[iname] <<
"_E" << theEne <<
".root";
117 throw cms::Exception(
"FastSimulation/MaterialEffects") <<
"Tree with name " << treeName <<
" not found ";
123 <<
"Branch with name nuEvent not found in " <<
theFileNames[iname][iene];
133 unsigned NInteractions =
theNUEvents[iname][iene]->nInteractions();
142 thePionCM[iname][iene] = (Reference + Proton).M();
172 for (
auto evtPtr : vEvents) {
186 for (
unsigned iname = 0; iname <
thePionNA.size(); ++iname) {
187 for (
unsigned iene = 0; iene <
thePionEN.size(); ++iene) {
191 unsigned NInteractions =
theNUEvents[iname][iene]->nInteractions();
207 std::map<int, int>::const_iterator thePit =
theIDMap.find(
Particle.particle().pid());
209 int thePid = thePit !=
theIDMap.end() ? thePit->second :
Particle.particle().pid();
212 unsigned fPid =
abs(thePid);
213 if (fPid != 211 && fPid != 130 && fPid != 321 && fPid != 2112 && fPid != 2212) {
220 unsigned thePidIndex =
index(thePid);
226 double theElasticLength = (0.8753 * ee + 0.15)
229 * theInelasticLength;
232 double theTotalInteractionLength = theInelasticLength + theElasticLength;
236 if (aNuclInteraction < theTotalInteractionLength) {
239 if (elastic < theElasticLength / theTotalInteractionLength) {
247 double phi = 2. * 3.14159265358979323 * random->
flatShoot();
252 Particle.particle().rotate(rotation1);
253 Particle.particle().rotate(rotation2);
273 const std::vector<double>& aPionCM =
thePionCM[thePidIndex];
274 const std::vector<double>& aRatios =
theRatios[thePidIndex];
286 double ecm = (Proton + Hadron).M();
295 double ecm1 = (Proton + Hadron0).M();
299 double ecm2 = aPionCM[0];
301 double ratio2 = aRatios[0];
302 if (ecm > aPionCM[0] && ecm < aPionCM[aPionCM.size() - 1]) {
303 for (
unsigned ene = 1; ene < aPionCM.size() && ecm > aPionCM[ene - 1]; ++ene) {
304 if (ecm < aPionCM[ene]) {
307 ecm1 = aPionCM[ene1];
308 ecm2 = aPionCM[ene2];
309 ratio1 = aRatios[ene1];
310 ratio2 = aRatios[ene2];
313 }
else if (ecm > aPionCM[aPionCM.size() - 1]) {
314 ene1 = aPionCM.size() - 1;
315 ene2 = aPionCM.size() - 2;
316 ecm1 = aPionCM[ene1];
317 ecm2 = aPionCM[ene2];
318 ratio1 = aRatios[ene2];
319 ratio2 = aRatios[ene2];
323 double slope = (std::log10(ecm) - std::log10(ecm1)) / (std::log10(ecm2) - std::log10(ecm1));
324 double inelastic = ratio1 + (ratio2 - ratio1) *
slope;
325 double inelastic4 = pHadron < 4. ? aRatios[
ien4] : 1.;
332 if (elastic > 1. - (inelastic * theInelasticLength) / theTotalInteractionLength) {
336 std::vector<NUEvent*>& aNUEvents =
theNUEvents[thePidIndex];
345 if (random->
flatShoot() <
slope || aNumberOfInteractions[ene1] == 0)
360 theBoost /= theBoost.e();
371 if (aCurrentInteraction[ene] == aNumberOfInteractions[ene]) {
375 std::vector<TTree*>& aTrees =
theTrees[thePidIndex];
376 ++aCurrentEntry[ene];
379 aCurrentInteraction[ene] = 0;
380 if (aCurrentEntry[ene] == aNumberOfEntries[ene]) {
381 aCurrentEntry[ene] = 0;
384 unsigned myEntry = aCurrentEntry[ene];
387 aTrees[ene]->GetEntry(myEntry);
389 aNumberOfInteractions[ene] = aNUEvents[ene]->nInteractions();
396 unsigned firstTrack = anInteraction.
first;
397 unsigned lastTrack = anInteraction.
last;
406 XYZVector theAxis = theBoost.Vect().Unit();
407 double theAngle = random->
flatShoot() * 2. * 3.14159265358979323;
414 double orthAngle = acos(theBoost.Vect().Unit().Z());
421 for (
unsigned iTrack = firstTrack; iTrack <= lastTrack; ++iTrack) {
422 unsigned idaugh = iTrack - firstTrack;
435 aParticle.
pz * aParticle.
pz + aParticle.
mass * aParticle.
mass / (ecm * ecm));
442 aDaughter.
rotate(orthRotation);
445 aDaughter.
rotate(axisRotation);
448 aDaughter.
boost(axisBoost);
476 ++aCurrentInteraction[ene];
479 }
else if (pHadron < 4. && elastic > 1. - (inelastic4 * theInelasticLength) / theTotalInteractionLength) {
495 if (fabs(
Particle.charge()) > 1E-12) {
498 if (fabs(chargeDiff) < 1E-12) {
534 std::vector<unsigned> theCurrentEntries;
535 theCurrentEntries.resize(size1);
536 size1 *=
sizeof(unsigned);
539 std::vector<unsigned> theCurrentInteractions;
540 theCurrentInteractions.resize(size2);
541 size2 *=
sizeof(unsigned);
544 std::vector<std::vector<unsigned> >::const_iterator aCurrentEntry =
theCurrentEntry.begin();
545 std::vector<std::vector<unsigned> >::const_iterator lastCurrentEntry =
theCurrentEntry.end();
546 unsigned allEntries = 0;
547 for (; aCurrentEntry != lastCurrentEntry; ++aCurrentEntry) {
548 unsigned size = aCurrentEntry->size();
549 for (
unsigned iene = 0; iene <
size; ++iene)
550 theCurrentEntries[allEntries++] = (*aCurrentEntry)[iene];
554 std::vector<std::vector<unsigned> >::const_iterator aCurrentInteraction =
theCurrentInteraction.begin();
555 std::vector<std::vector<unsigned> >::const_iterator lastCurrentInteraction =
theCurrentInteraction.end();
556 unsigned allInteractions = 0;
557 for (; aCurrentInteraction != lastCurrentInteraction; ++aCurrentInteraction) {
558 unsigned size = aCurrentInteraction->size();
559 for (
unsigned iene = 0; iene <
size; ++iene)
560 theCurrentInteractions[allInteractions++] = (*aCurrentInteraction)[iene];
563 myOutputFile.write((
const char*)(&theCurrentEntries.front()), size1);
564 myOutputFile.write((
const char*)(&theCurrentInteractions.front()), size2);
569 std::ifstream myInputFile;
573 std::vector<unsigned> theCurrentEntries;
574 theCurrentEntries.resize(size1);
575 size1 *=
sizeof(unsigned);
578 std::vector<unsigned> theCurrentInteractions;
579 theCurrentInteractions.resize(size2);
580 size2 *=
sizeof(unsigned);
586 if (myInputFile.is_open()) {
594 myInputFile.seekg(
size - size1 - size2);
595 myInputFile.read((
char*)(&theCurrentEntries.front()), size1);
596 myInputFile.read((
char*)(&theCurrentInteractions.front()), size2);
600 std::vector<std::vector<unsigned> >::iterator aCurrentEntry =
theCurrentEntry.begin();
601 std::vector<std::vector<unsigned> >::iterator lastCurrentEntry =
theCurrentEntry.end();
602 unsigned allEntries = 0;
603 for (; aCurrentEntry != lastCurrentEntry; ++aCurrentEntry) {
604 unsigned size = aCurrentEntry->size();
605 for (
unsigned iene = 0; iene <
size; ++iene)
606 (*aCurrentEntry)[iene] = theCurrentEntries[allEntries++];
612 unsigned allInteractions = 0;
613 for (; aCurrentInteraction != lastCurrentInteraction; ++aCurrentInteraction) {
614 unsigned size = aCurrentInteraction->size();
615 for (
unsigned iene = 0; iene <
size; ++iene)
616 (*aCurrentInteraction)[iene] = theCurrentInteractions[allInteractions++];
626 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::vector< std::vector< NUEvent * > > theNUEvents
std::vector< std::vector< std::string > > theFileNames
std::vector< int > thePionID
double charge() const
get the MEASURED charge
static std::string to_string(const XMLCh *ch)
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