40 using namespace genie;
99 TLorentzVector v4(0,0,0,0);
109 TLorentzVector p4i(0,0,0,Mi);
110 event->AddParticle(ipdg,stis,-1,-1,-1,-1, p4i, v4);
115 TLorentzVector p4neut(0,0,0,mneut);
116 event->AddParticle(neutpdg,stdc,0,-1,-1,-1, p4neut, v4);
121 TLorentzVector p4n(0,0,0,mn);
122 event->AddParticle(dpdg,stdc, 0,-1,-1,-1, p4n, v4);
131 TLorentzVector p4f(0,0,0,Mf);
132 event->AddParticle(rpdg,stfs,0,-1,-1,-1, p4f, v4);
139 int A = initial_nucleus->
A();
147 double dA = (double)A;
148 double R = R0 * TMath::Power(dA, 1./3.);
151 <<
"Generating vertex according to a realistic nuclear density profile";
157 for(
double r = 0;
r < rmax;
r+=dr) {
163 TLorentzVector vtx(0,0,0,0);
164 unsigned int iter = 0;
171 <<
"Couldn't generate a vertex position after " << iter <<
" iterations";
173 exception.
SetReason(
"Couldn't generate vertex");
178 double r = rmax * rnd->
RndFsi().Rndm();
179 double t = ymax * rnd->
RndFsi().Rndm();
183 <<
"y = " << y <<
" > ymax = " << ymax <<
" for r = " << r <<
", A = " <<
A;
185 bool accept = (t <
y);
188 double cosphi = TMath::Cos(phi);
189 double sinphi = TMath::Sin(phi);
190 double costheta = -1 + 2 * rnd->
RndFsi().Rndm();
191 double sintheta = TMath::Sqrt(1-costheta*costheta);
192 vtx.SetX(r*sintheta*cosphi);
193 vtx.SetY(r*sintheta*sinphi);
194 vtx.SetZ(r*costheta);
201 GHepParticle * oscillating_neutron =
event->Particle(1);
202 assert(oscillating_neutron);
206 GHepParticle * annihilation_nucleon =
event->Particle(2);
207 assert(annihilation_nucleon);
215 int A = initial_nucleus->
A();
220 GHepParticle * oscillating_neutron =
event->Particle(1);
221 GHepParticle * annihilation_nucleon =
event->Particle(2);
223 assert(oscillating_neutron);
224 assert(annihilation_nucleon);
225 assert(remnant_nucleus);
238 double mass = oscillating_neutron->
Mass();
239 double energy = sqrt(
pow(mass,2) + p3.Mag2()) - w;
241 TLorentzVector p4(p3, energy);
245 <<
"Generated neutron momentum: (" 246 << p3.Px() <<
", " << p3.Py() <<
", " << p3.Pz() <<
"), " 247 <<
"|p| = " << p3.Mag();
250 tgt.SetHitNucPdg(annihilation_nucleon->
Pdg());
256 mass = annihilation_nucleon->
Mass();
257 energy = sqrt(
pow(mass,2) + p3.Mag2()) - w;
259 p4 = TLorentzVector(p3, energy);
263 <<
"Generated nucleon momentum: (" 264 << p3.Px() <<
", " << p3.Py() <<
", " << p3.Pz() <<
"), " 265 <<
"|p| = " << p3.Mag();
268 p3 = -1 * (oscillating_neutron->
GetP4()->Vect() + annihilation_nucleon->
GetP4()->Vect());
270 mass = remnant_nucleus->
Mass();
271 energy = sqrt(
pow(mass,2) + p3.Mag2());
273 p4 = TLorentzVector(p3, energy);
280 LOG(
"NeutronOsc",
pINFO) <<
"Generating decay...";
283 LOG(
"NeutronOsc",
pINFO) <<
"Decay product IDs: " << pdgv;
284 assert ( pdgv.size() > 1);
286 LOG(
"NeutronOsc",
pINFO) <<
"Performing a phase space decay...";
292 double * mass =
new double[pdgv.size()];
294 for(pdg_iter = pdgv.begin(); pdg_iter != pdgv.end(); ++pdg_iter) {
295 int pdgc = *pdg_iter;
302 <<
"Decaying N = " << pdgv.size() <<
" particles / total mass = " << sum;
303 int initial_nucleus_id = 0;
304 int oscillating_neutron_id = 1;
305 int annihilation_nucleon_id = 2;
308 GHepParticle * initial_nucleus =
event->Particle(initial_nucleus_id);
309 assert(initial_nucleus);
310 GHepParticle * oscillating_neutron =
event->Particle(oscillating_neutron_id);
311 assert(oscillating_neutron);
312 GHepParticle * annihilation_nucleon =
event->Particle(annihilation_nucleon_id);
313 assert(annihilation_nucleon);
319 TLorentzVector * p4_1 = oscillating_neutron->
GetP4();
320 TLorentzVector * p4_2 = annihilation_nucleon->
GetP4();
321 TLorentzVector * p4d =
new TLorentzVector(*p4_1 + *p4_2);
322 TVector3
boost = p4d->BoostVector();
326 TLorentzVector * v4d = annihilation_nucleon->
GetX4();
341 <<
"Not enough energy to generate decay products! Selecting a new final state.";
345 int initial_nucleus_pdg = initial_nucleus->
Pdg();
348 if (nucleus_pdg.size() != 10) {
350 <<
"Expecting the nuclear PDG code to be a 10-digit integer, but it is " << nucleus_pdg <<
", which is " 351 << nucleus_pdg.size() <<
" digits long. Drop me an email at jezhewes@gmail.com ; exiting...";
355 int n_nucleons = std::stoi(nucleus_pdg.substr(6,3)) - 1;
356 int n_protons = std::stoi(nucleus_pdg.substr(3,3));
357 double proton_frac = ((double)n_protons) / ((double) n_nucleons);
358 double neutron_frac = 1 - proton_frac;
361 const int n_modes = 16;
362 double br [n_modes] = { 0.010, 0.080, 0.100, 0.220,
363 0.360, 0.160, 0.070, 0.020,
364 0.015, 0.065, 0.110, 0.280,
365 0.070, 0.240, 0.100, 0.100 };
367 for (
int i = 0;
i < n_modes;
i++) {
370 br[
i] *= proton_frac;
373 br[
i] *= neutron_frac;
379 double p = rnd->
RndNum().Rndm();
382 double threshold = 0;
383 for (
int j = 0; j < n_modes; j++) {
397 event->AttachSummary(interaction);
402 LOG(
"NeutronOsc",
pINFO) <<
"Decay product IDs: " << pdgv;
403 assert ( pdgv.size() > 1);
406 LOG(
"NeutronOsc",
pINFO) <<
"Performing a phase space decay...";
409 mass =
new double[pdgv.size()];
411 for(pdg_iter = pdgv.begin(); pdg_iter != pdgv.end(); ++pdg_iter) {
412 int pdgc = *pdg_iter;
419 <<
"Decaying N = " << pdgv.size() <<
" particles / total mass = " << sum;
428 <<
" *** Phase space decay is not permitted \n" 429 <<
" Total particle mass = " << sum <<
"\n" 437 exception.
SetReason(
"Decay not permitted kinematically");
445 for(
int i=0;
i<200;
i++) {
447 wmax = TMath::Max(wmax,w);
453 <<
"Max phase space gen. weight @ current hadronic system: " << wmax;
458 bool accept_decay=
false;
467 <<
"Couldn't generate an unweighted phase space decay after " 468 << itry <<
" attempts";
475 exception.
SetReason(
"Couldn't select decay after N attempts");
482 <<
"Decay weight = " << w <<
" > max decay weight = " << wmax;
484 double gw = wmax * rnd->
RndHadro().Rndm();
485 accept_decay = (gw<=
w);
488 <<
"Decay weight = " << w <<
" / R = " << gw
489 <<
" - accepted: " << accept_decay;
494 TLorentzVector v4(*v4d);
496 for(pdg_iter = pdgv.begin(); pdg_iter != pdgv.end(); ++pdg_iter) {
497 int pdgc = *pdg_iter;
502 event->AddParticle(pdgc, ist, oscillating_neutron_id,-1,-1,-1, *p4fin, v4);
531 RgKey nuclkey =
"NuclearModel";
void GenerateDecayProducts(GHepRecord *event) const
TLorentzVector * GetX4(void) const
TRandom3 & RndFsi(void) const
rnd number generator used by intranuclear cascade monte carlos
~NeutronOscPrimaryVtxGenerator()
#include "Numerical/GSFunc.h"
void Configure(const Registry &config)
Configure the algorithm.
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.)
enum genie::EGHepStatus GHepStatus_t
int IonPdgCodeToA(int pdgc)
string P4AsString(const TLorentzVector *p)
static const unsigned int kMaxUnweightDecayIterations
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...
virtual double RemovalEnergy(void) const
const NuclearModelI * fNuclModel
NeutronOscPrimaryVtxGenerator()
Summary information for an interaction.
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...
PDGCodeList DecayProductList(NeutronOscMode_t ndm)
TLorentzVector * GetP4(void) const
void ProcessEventRecord(GHepRecord *event) const
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
virtual void Configure(const Registry &config)
Configure the algorithm.
int DecayMode(void) const
TRandom3 & RndNum(void) const
rnd number generator used by MC integrators & other numerical methods
void GenerateFermiMomentum(GHepRecord *event) const
string AsString(NeutronOscMode_t ndm)
TGenPhaseSpace fPhaseSpaceGenerator
TRandom3 & RndHadro(void) const
rnd number generator used by hadronization models
void SwitchOnFastForward(void)
static PDGLibrary * Instance(void)
void SetReason(string reason)
GHepStatus_t DecayProductStatus(bool in_nucleus, int pdgc)
int AnnihilatingNucleonPdgCode(NeutronOscMode_t ndm)
virtual TVector3 Momentum3(void) const
A registry. Provides the container for algorithm configuration parameters.
void SetHitNucPdg(int pdgc)
const XclsTag & ExclTag(void) const
TParticlePDG * Find(int pdgc)
int IonPdgCode(int A, int Z)
void AddInitialState(GHepRecord *event) const
virtual bool GenerateNucleon(const Target &) const =0
const InitialState & InitState(void) const
int IonPdgCodeToZ(int pdgc)
const Target & Tgt(void) const
NeutronOscMode_t fCurrDecayMode
static const unsigned int kRjMaxIterations
enum genie::ENeutronOscMode NeutronOscMode_t
GENIE's GHEP MC event record.
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.
std::string to_string(ModuleType const mt)
cet::coded_exception< error, detail::translate > exception
void GenerateOscillatingNeutronPosition(GHepRecord *event) const
Event finding and building.
static Interaction * NOsc(int tgt, int annihilation_mode=-1)
void SetSeed(long int seed)
const Algorithm * SubAlg(const RgKey ®istry_key) const