12#include "G4ParticleTable.hh"
14#include "Randomize.hh"
27 const std::string& punit,
28 const std::string& arandomMomentumModel,
31 const std::string& arandomThetaModel,
34 const std::string& aunit,
41 const std::string& vunit,
42 const std::string& arandomVertexModel,
43 const std::shared_ptr<GLogger>& logger) :
45 multiplicity(amultiplicity),
60 delta_v(G4ThreeVector(
80 auto particleTable = G4ParticleTable::GetParticleTable();
84 auto particleDef = particleTable->FindParticle(name);
88 double mass = particleDef->GetPDGMass();
89 particleGun->SetParticleDefinition(particleDef);
92 for (
int i = 0; i < multiplicity; i++) {
93 particleGun->SetParticleEnergy(calculateKinEnergy(mass));
94 particleGun->SetParticleMomentumDirection(calculateBeamDirection());
95 particleGun->SetParticlePosition(calculateVertex());
96 particleGun->GeneratePrimaryVertex(anEvent);
101 "Particle <", name,
"> not found in G4ParticleTable* ", particleTable);
106 "G4ParticleTable not found - G4ParticleGun*: ", particleGun);
111double Gparticle::calculateMomentum() {
113 double pmev = randomizeNumberFromSigmaWithModel(p, delta_p, randomMomentumModel);
118double Gparticle::calculateKinEnergy(
double mass) {
119 double pmev = calculateMomentum();
121 return sqrt(pmev * pmev + mass * mass) - mass;
125G4ThreeVector Gparticle::calculateBeamDirection() {
127 double thetaRad = randomizeNumberFromSigmaWithModel(theta, delta_theta, randomThetaModel) / CLHEP::rad;
128 double phiRad = randomizeNumberFromSigmaWithModel(phi, delta_phi,
gutilities::uniform) / CLHEP::rad;
130 G4ThreeVector pdir = G4ThreeVector(
131 cos(phiRad) * sin(thetaRad),
132 sin(phiRad) * sin(thetaRad),
139G4ThreeVector Gparticle::calculateVertex() {
142 switch (randomVertexModel) {
161 double max_radius = delta_v.r();
168 radius = x * x + y * y + z * z;
170 while (radius > max_radius);
191double Gparticle::randomizeNumberFromSigmaWithModel(
double center,
double delta,
gutilities::randomModel model)
const {
195 return center + (2.0 * G4UniformRand() - 1.0) * delta;
199 return G4RandGauss::shoot(center, delta);
205 double lower = (center - delta) / CLHEP::rad;
206 double upper = (center + delta) / CLHEP::rad;
207 double center_rad = 0;
211 do { center_rad = acos(1 - 2 * G4UniformRand()); }
212 while (center_rad < lower || center_rad > upper);
216 center_rad = theta / CLHEP::rad;
219 return center_rad * CLHEP::rad;
236 constexpr int label_w = 15;
237 constexpr int value_w = 12;
240 auto show = [&](
const std::string& label,
const auto& value) {
241 os << left << setw(label_w) << label <<
' '
242 << right << setw(value_w) << value <<
'\n';
246 auto showf = [&](
const std::string& label,
double value,
int prec = 3) {
247 std::streamsize old_prec = os.precision();
248 auto old_flags = os.flags();
250 os << left << setw(label_w) << label <<
' '
251 << right << setw(value_w) << std::fixed
252 << std::setprecision(prec) << value <<
'\n';
254 os.precision(old_prec);
259 auto show_pm = [&](
const std::string& label,
260 double val,
double err,
262 std::streamsize old_prec = os.precision();
263 auto old_flags = os.flags();
265 os << left << setw(label_w) << label <<
' '
266 << right << setw(value_w) << std::fixed
267 << std::setprecision(prec) << val
268 <<
" ± " << std::setprecision(prec) << err <<
'\n';
270 os.precision(old_prec);
278 <<
" ┌─────────────────────────────────────────────────┐\n"
279 <<
" │ GParticle │\n"
280 <<
" └─────────────────────────────────────────────────┘\n";
285 os << left << setw(label_w) <<
" name:" << right << setw(value_w)
286 << gp.name <<
"(pid " << gp.pid <<
")\n";
288 show(
" multiplicity:", std::to_string(gp.multiplicity));
289 showf(
" mass [MeV]:", gp.get_mass());
293 gp.delta_p / CLHEP::MeV);
295 show(
" p model:", to_string(gp.randomMomentumModel));
297 show_pm(
" theta [deg]:",
298 gp.theta / CLHEP::deg,
299 gp.delta_theta / CLHEP::deg);
301 show(
" theta model:", to_string(gp.randomThetaModel));
303 show_pm(
" phi [deg]:",
305 gp.delta_phi / CLHEP::deg);
307 os << left << setw(label_w) <<
" vertex [cm]:" <<
' '
308 << gp.v <<
" ± " << gp.delta_v <<
'\n';
310 show(
" vertex model:", to_string(gp.randomVertexModel));
316int Gparticle::get_pdg_id() {
317 auto particleTable = G4ParticleTable::GetParticleTable();
320 auto particleDef = particleTable->FindParticle(name);
322 if (particleDef !=
nullptr) {
return particleDef->GetPDGEncoding(); }
325 "Particle <", name,
"> not found in G4ParticleTable* ", particleTable);
330 "G4ParticleTable not found - G4ParticleGun*: ", particleTable);
335double Gparticle::get_mass()
const {
336 auto particleTable = G4ParticleTable::GetParticleTable();
339 auto particleDef = particleTable->FindParticle(name);
342 double mass = particleDef->GetPDGMass();
void debug(debug_type type, Args &&... args) const
void info(int level, Args &&... args) const
void error(int exit_code, Args &&... args) const
Lightweight particle specification and primary vertex shooter.
void shootParticle(G4ParticleGun *particleGun, G4Event *anEvent)
Shoots this particle configuration into a Geant4 event.
Gparticle(const std::string &name, int multiplicity, double p, double delta_p, const std::string &punit, const std::string &randomMomentumModel, double theta, double delta_theta, const std::string &thetaModel, double phi, double delta_phi, const std::string &aunit, double avx, double avy, double avz, double adelta_vx, double adelta_vy, double adelta_vz, const std::string &vunit, const std::string &randomVertexModel, const std::shared_ptr< GLogger > &logger)
Constructs a particle configuration from user-facing parameters.
Conventions and error codes for the gparticle module.
#define ERR_GPARTICLETABLENOTFOUND
G4ParticleTable could not be obtained (unexpected runtime state).
#define ERR_GPARTICLENOTFOUND
Requested particle name was not found in the G4ParticleTable.
std::ostream & operator<<(std::ostream &os, const Gparticle &gp)
Definition of the Gparticle class used by the gparticle module.
Public API for defining and parsing gparticle-related options.
double getG4Number(const string &v, bool warnIfNotUnit=false)
randomModel stringToRandomModel(const std::string &str)