32 using namespace genie;
89 TLorentzVector v4(0,0,0,0);
99 TLorentzVector p4i(0,0,0,Mi);
100 event->AddParticle(ipdg,stis,-1,-1,-1,-1, p4i, v4);
105 TLorentzVector p4neut(0,0,0,mneut);
106 event->AddParticle(neutpdg,stdc,0,-1,-1,-1, p4neut, v4);
111 TLorentzVector p4n(0,0,0,mn);
112 event->AddParticle(dpdg,stdc, 0,-1,-1,-1, p4n, v4);
121 TLorentzVector p4f(0,0,0,Mf);
122 event->AddParticle(rpdg,stfs,0,-1,-1,-1, p4f, v4);
129 int A = initial_nucleus->
A();
137 double dA = (double)A;
138 double R = R0 * TMath::Power(dA, 1./3.);
141 <<
"Generating vertex according to a realistic nuclear density profile";
147 for(
double r = 0; r < rmax; r+=dr) {
153 TLorentzVector vtx(0,0,0,0);
154 unsigned int iter = 0;
161 <<
"Couldn't generate a vertex position after " << iter <<
" iterations";
163 exception.
SetReason(
"Couldn't generate vertex");
168 double r = rmax * rnd->
RndFsi().Rndm();
169 double t = ymax * rnd->
RndFsi().Rndm();
173 <<
"y = " << y <<
" > ymax = " << ymax <<
" for r = " << r <<
", A = " <<
A;
175 bool accept = (t < y);
178 double cosphi = TMath::Cos(phi);
179 double sinphi = TMath::Sin(phi);
180 double costheta = -1 + 2 * rnd->
RndFsi().Rndm();
181 double sintheta = TMath::Sqrt(1-costheta*costheta);
182 vtx.SetX(r*sintheta*cosphi);
183 vtx.SetY(r*sintheta*sinphi);
184 vtx.SetZ(r*costheta);
191 GHepParticle * oscillating_neutron =
event->Particle(1);
192 assert(oscillating_neutron);
196 GHepParticle * annihilation_nucleon =
event->Particle(2);
197 assert(annihilation_nucleon);
205 int A = initial_nucleus->
A();
210 GHepParticle * oscillating_neutron =
event->Particle(1);
211 GHepParticle * annihilation_nucleon =
event->Particle(2);
213 assert(oscillating_neutron);
214 assert(annihilation_nucleon);
215 assert(remnant_nucleus);
228 double mass = oscillating_neutron->
Mass();
229 double energy = sqrt(pow(mass,2) + p3.Mag2()) - w;
231 TLorentzVector p4(p3, energy);
235 <<
"Generated neutron momentum: ("
236 << p3.Px() <<
", " << p3.Py() <<
", " << p3.Pz() <<
"), "
237 <<
"|p| = " << p3.Mag();
240 tgt.SetHitNucPdg(annihilation_nucleon->
Pdg());
246 mass = annihilation_nucleon->
Mass();
247 energy = sqrt(pow(mass,2) + p3.Mag2()) - w;
249 p4 = TLorentzVector(p3, energy);
253 <<
"Generated nucleon momentum: ("
254 << p3.Px() <<
", " << p3.Py() <<
", " << p3.Pz() <<
"), "
255 <<
"|p| = " << p3.Mag();
258 p3 = -1 * (oscillating_neutron->
GetP4()->Vect() + annihilation_nucleon->
GetP4()->Vect());
260 mass = remnant_nucleus->
Mass();
261 energy = sqrt(pow(mass,2) + p3.Mag2());
263 p4 = TLorentzVector(p3, energy);
270 LOG(
"NNBarOsc",
pINFO) <<
"Generating decay...";
273 LOG(
"NNBarOsc",
pINFO) <<
"Decay product IDs: " << pdgv;
274 assert ( pdgv.size() > 1);
276 LOG(
"NNBarOsc",
pINFO) <<
"Performing a phase space decay...";
280 vector<int>::const_iterator pdg_iter;
282 double * mass =
new double[pdgv.size()];
284 for(pdg_iter = pdgv.begin(); pdg_iter != pdgv.end(); ++pdg_iter) {
285 int pdgc = *pdg_iter;
292 <<
"Decaying N = " << pdgv.size() <<
" particles / total mass = " << sum;
293 int initial_nucleus_id = 0;
294 int oscillating_neutron_id = 1;
295 int annihilation_nucleon_id = 2;
298 GHepParticle * initial_nucleus =
event->Particle(initial_nucleus_id);
299 assert(initial_nucleus);
300 GHepParticle * oscillating_neutron =
event->Particle(oscillating_neutron_id);
301 assert(oscillating_neutron);
302 GHepParticle * annihilation_nucleon =
event->Particle(annihilation_nucleon_id);
303 assert(annihilation_nucleon);
309 TLorentzVector * p4_1 = oscillating_neutron->
GetP4();
310 TLorentzVector * p4_2 = annihilation_nucleon->
GetP4();
311 TLorentzVector * p4d =
new TLorentzVector(*p4_1 + *p4_2);
312 TVector3 boost = p4d->BoostVector();
316 TLorentzVector * v4d = annihilation_nucleon->
GetX4();
331 <<
"Not enough energy to generate decay products! Selecting a new final state.";
335 int initial_nucleus_pdg = initial_nucleus->
Pdg();
337 std::string nucleus_pdg = std::to_string(static_cast<long long>(initial_nucleus_pdg));
338 if (nucleus_pdg.size() != 10) {
340 <<
"Expecting the nuclear PDG code to be a 10-digit integer, but it is " << nucleus_pdg <<
", which is "
341 << nucleus_pdg.size() <<
" digits long. Drop me an email at jezhewes@gmail.com ; exiting...";
345 int n_nucleons = std::stoi(nucleus_pdg.substr(6,3)) - 1;
346 int n_protons = std::stoi(nucleus_pdg.substr(3,3));
347 double proton_frac = ((double)n_protons) / ((double) n_nucleons);
348 double neutron_frac = 1 - proton_frac;
351 const int n_modes = 16;
352 double br [n_modes] = { 0.010, 0.080, 0.100, 0.220,
353 0.360, 0.160, 0.070, 0.020,
354 0.015, 0.065, 0.110, 0.280,
355 0.070, 0.240, 0.100, 0.100 };
357 for (
int i = 0; i < n_modes; i++) {
360 br[i] *= proton_frac;
363 br[i] *= neutron_frac;
369 double p = rnd->
RndNum().Rndm();
372 double threshold = 0;
373 for (
int j = 0; j < n_modes; j++) {
387 event->AttachSummary(interaction);
392 LOG(
"NNBarOsc",
pINFO) <<
"Decay product IDs: " << pdgv;
393 assert ( pdgv.size() > 1);
396 LOG(
"NNBarOsc",
pINFO) <<
"Performing a phase space decay...";
399 mass =
new double[pdgv.size()];
401 for(pdg_iter = pdgv.begin(); pdg_iter != pdgv.end(); ++pdg_iter) {
402 int pdgc = *pdg_iter;
409 <<
"Decaying N = " << pdgv.size() <<
" particles / total mass = " << sum;
418 <<
" *** Phase space decay is not permitted \n"
419 <<
" Total particle mass = " << sum <<
"\n"
427 exception.
SetReason(
"Decay not permitted kinematically");
435 for(
int i=0; i<200; i++) {
437 wmax = TMath::Max(wmax,w);
443 <<
"Max phase space gen. weight @ current hadronic system: " << wmax;
448 bool accept_decay=
false;
457 <<
"Couldn't generate an unweighted phase space decay after "
458 << itry <<
" attempts";
465 exception.
SetReason(
"Couldn't select decay after N attempts");
472 <<
"Decay weight = " << w <<
" > max decay weight = " << wmax;
474 double gw = wmax * rnd->
RndHadro().Rndm();
475 accept_decay = (gw<=w);
478 <<
"Decay weight = " << w <<
" / R = " << gw
479 <<
" - accepted: " << accept_decay;
484 TLorentzVector v4(*v4d);
486 for(pdg_iter = pdgv.begin(); pdg_iter != pdgv.end(); ++pdg_iter) {
487 int pdgc = *pdg_iter;
492 event->AddParticle(pdgc, ist, oscillating_neutron_id,-1,-1,-1, *p4fin, v4);
521 RgKey nuclkey =
"NuclearModel";
TLorentzVector * GetX4(void) const
TRandom3 & RndFsi(void) const
rnd number generator used by intranuclear cascade monte carlos
double RemovalEnergy(void) const
int AnnihilatingNucleonPdgCode(NNBarOscMode_t ndm)
NNBarOscMode_t fCurrDecayMode
static RandomGen * Instance()
Access instance.
Defines the EventRecordVisitorI interface. Concrete implementations of this interface use the 'Visito...
double Density(double r, int A, double ring=0.)
GHepStatus_t DecayProductStatus(bool in_nucleus, int pdgc)
NNBarOscPrimaryVtxGenerator()
int IonPdgCodeToA(int pdgc)
string P4AsString(const TLorentzVector *p)
static const unsigned int kMaxUnweightDecayIterations
~NNBarOscPrimaryVtxGenerator()
Pure abstract base class. Defines the NuclearModelI interface to be implemented by any physics model ...
void SetMomentum(const TLorentzVector &p4)
double Mass(void) const
Mass that corresponds to the PDG code.
A singleton holding random number generator classes. All random number generation in GENIE should tak...
const TVector3 & Momentum3(void) const
Summary information for an interaction.
const NuclearModelI * fNuclModel
void SetPosition(const TLorentzVector &v4)
An exception thrown by EventRecordVisitorI when the normal processing sequence has to be disrupted (f...
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
static constexpr double A
enum genie::ENNBarOscMode NNBarOscMode_t
TLorentzVector * GetP4(void) const
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
virtual void Configure(const Registry &config)
void AddInitialState(GHepRecord *event) const
int DecayMode(void) const
string AsString(NNBarOscMode_t ndm)
void Configure(const Registry &config)
TRandom3 & RndNum(void) const
rnd number generator used by MC integrators & other numerical methods
TRandom3 & RndHadro(void) const
rnd number generator used by hadronization models
PDGCodeList DecayProductList(NNBarOscMode_t ndm)
void SwitchOnFastForward(void)
static PDGLibrary * Instance(void)
void SetReason(string reason)
A registry. Provides the container for algorithm configuration parameters.
void SetHitNucPdg(int pdgc)
const XclsTag & ExclTag(void) const
void ProcessEventRecord(GHepRecord *event) const
int IonPdgCode(int A, int Z)
const InitialState & InitState(void) const
int IonPdgCodeToZ(int pdgc)
TParticlePDG * Find(int pdgc, bool must_exist=true)
void GenerateOscillatingNeutronPosition(GHepRecord *event) const
const Target & Tgt(void) const
static const unsigned int kRjMaxIterations
virtual bool GenerateNucleon(const Target &) const =0
GENIE's GHEP MC event record.
static constexpr double m
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
STDHEP-like event record entry that can fit a particle or a nucleus.
TGenPhaseSpace fPhaseSpaceGenerator
void GenerateFermiMomentum(GHepRecord *event) const
static Interaction * NOsc(int tgt, int annihilation_mode=-1)
enum genie::EGHepStatus GHepStatus_t
void GenerateDecayProducts(GHepRecord *event) const
void SetSeed(long int seed)
const Algorithm * SubAlg(const RgKey ®istry_key) const