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();
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";
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE,...
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils.
virtual void Configure(const Registry &config)
const Algorithm * SubAlg(const RgKey ®istry_key) const
STDHEP-like event record entry that can fit a particle or a nucleus.
void SetPosition(const TLorentzVector &v4)
void SetMomentum(const TLorentzVector &p4)
TLorentzVector * GetP4(void) const
double Mass(void) const
Mass that corresponds to the PDG code.
TLorentzVector * GetX4(void) const
GENIE's GHEP MC event record.
const Target & Tgt(void) const
Summary information for an interaction.
const XclsTag & ExclTag(void) const
static Interaction * NOsc(int tgt, int annihilation_mode=-1)
const InitialState & InitState(void) const
void GenerateFermiMomentum(GHepRecord *event) const
TGenPhaseSpace fPhaseSpaceGenerator
~NNBarOscPrimaryVtxGenerator()
void GenerateDecayProducts(GHepRecord *event) const
NNBarOscMode_t fCurrDecayMode
NNBarOscPrimaryVtxGenerator()
void GenerateOscillatingNeutronPosition(GHepRecord *event) const
void AddInitialState(GHepRecord *event) const
const NuclearModelI * fNuclModel
void ProcessEventRecord(GHepRecord *event) const
void Configure(const Registry &config)
Pure abstract base class. Defines the NuclearModelI interface to be implemented by any physics model ...
static PDGLibrary * Instance(void)
TParticlePDG * Find(int pdgc, bool must_exist=true)
A singleton holding random number generator classes. All random number generation in GENIE should tak...
TRandom3 & RndHadro(void) const
rnd number generator used by hadronization models
static RandomGen * Instance()
Access instance.
void SetSeed(long int seed)
TRandom3 & RndFsi(void) const
rnd number generator used by intranuclear cascade monte carlos
TRandom3 & RndNum(void) const
rnd number generator used by MC integrators & other numerical methods
A registry. Provides the container for algorithm configuration parameters.
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
void SetHitNucPdg(int pdgc)
int DecayMode(void) const
An exception thrown by EventRecordVisitorI when the normal processing sequence has to be disrupted (f...
void SwitchOnFastForward(void)
void SetReason(string reason)
static const unsigned int kMaxUnweightDecayIterations
static const unsigned int kRjMaxIterations
int IonPdgCode(int A, int Z)
int IonPdgCodeToZ(int pdgc)
int IonPdgCodeToA(int pdgc)
GHepStatus_t DecayProductStatus(bool in_nucleus, int pdgc)
int AnnihilatingNucleonPdgCode(NNBarOscMode_t ndm)
PDGCodeList DecayProductList(NNBarOscMode_t ndm)
string AsString(NNBarOscMode_t ndm)
double Density(double r, int A, double ring=0.)
string P4AsString(const TLorentzVector *p)
THE MAIN GENIE PROJECT NAMESPACE
enum genie::ENNBarOscMode NNBarOscMode_t
enum genie::EGHepStatus GHepStatus_t