BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSParticleDefinition.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2022.
4
5This file is part of BDSIM.
6
7BDSIM is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published
9by the Free Software Foundation version 3 of the License.
10
11BDSIM is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "BDSDebug.hh"
20#include "BDSException.hh"
21#include "BDSIonDefinition.hh"
22#include "BDSParticleDefinition.hh"
23#include "BDSPhysicalConstants.hh"
24#include "BDSUtilities.hh"
25
26#include "G4ParticleDefinition.hh"
27
28#include "CLHEP/Units/SystemOfUnits.h"
29
30#include <cmath>
31#include <iomanip>
32#include <limits>
33#include <ostream>
34#include <stdexcept>
35#include <string>
36
37BDSParticleDefinition::BDSParticleDefinition(G4ParticleDefinition* particleIn,
38 G4double totalEnergyIn,
39 G4double kineticEnergyIn,
40 G4double momentumIn,
41 G4double ffactIn,
42 BDSIonDefinition* ionDefinitionIn,
43 G4int ionPDGIDIn):
44 particle(particleIn),
45 ionDefinition(nullptr),
46 ionPDGID(ionPDGIDIn),
47 name(particleIn->GetParticleName()),
48 mass(particleIn->GetPDGMass()),
49 charge(0),
50 totalEnergy(0),
51 kineticEnergy(0),
52 momentum(0),
53 gamma(1.0),
54 beta(1.0),
55 brho(std::numeric_limits<double>::max()),// if zero charge infinite magnetic rigidity
56 ffact(ffactIn)
57{
58 charge = particle->GetPDGCharge();
59 if (ionDefinition) // may be nullptr
60 {
61 ionDefinition = new BDSIonDefinition(*ionDefinitionIn);
62 if (ionDefinition->OverrideCharge()) // if override for ions
64 }
65
66 SetEnergies(totalEnergyIn, kineticEnergyIn, momentumIn);
67}
68
70 G4double massIn,
71 G4double chargeIn,
72 G4double totalEnergyIn,
73 G4double kineticEnergyIn,
74 G4double momentumIn,
75 G4double ffactIn,
76 BDSIonDefinition* ionDefinitionIn,
77 G4int ionPDGIDIn):
78 particle(nullptr),
79 ionDefinition(nullptr),
80 ionPDGID(ionPDGIDIn),
81 name(nameIn),
82 mass(massIn),
83 charge(chargeIn),
84 totalEnergy(0),
85 kineticEnergy(0),
86 momentum(0),
87 gamma(1.0),
88 beta(1.0),
89 brho(std::numeric_limits<double>::max()),// if zero charge infinite magnetic rigidity
90 ffact(ffactIn)
91{
92 if (ionDefinitionIn)
93 {ionDefinition = new BDSIonDefinition(*ionDefinitionIn);}
94 SetEnergies(totalEnergyIn, kineticEnergyIn, momentumIn);
95}
96
97void BDSParticleDefinition::SetEnergies(G4double totalEnergyIn,
98 G4double kineticEnergyIn,
99 G4double momentumIn)
100{
101 if (BDS::IsFinite(totalEnergyIn))
102 {
103 if (totalEnergyIn <= mass)
104 {
105 throw BDSException(__METHOD_NAME__, "total energy (" + std::to_string(totalEnergyIn / CLHEP::GeV)
106 + " GeV) is less than or equal to the mass (" + std::to_string(mass / CLHEP::GeV)
107 + " GeV) of the particle \"" + name + "\"");
108 }
109 totalEnergy = totalEnergyIn;
112 }
113 else if (BDS::IsFinite(kineticEnergyIn))
114 {
115 if (kineticEnergyIn <= 0)
116 {
117 throw BDSException(__METHOD_NAME__, "kinetic energy (" + std::to_string(kineticEnergyIn/CLHEP::GeV)
118 + " GeV) must be > 0");
119 }
120 kineticEnergy = kineticEnergyIn;
121 totalEnergy = mass + kineticEnergyIn;
123 }
124 else if (BDS::IsFinite(momentumIn))
125 {
126 if (momentumIn <= 0)
127 {
128 throw BDSException(__METHOD_NAME__, "momentum (" + std::to_string(momentumIn/CLHEP::GeV)
129 + " GeV) must be > 0");
130 }
131 momentum = momentumIn;
132 totalEnergy = std::hypot(momentumIn, mass);
133 if (std::isnan(totalEnergy))
134 {throw BDSException(__METHOD_NAME__, "sqrt(-ve) encountered in calculating total energy");}
136 }
137 else
138 {throw BDSException(__METHOD_NAME__, "total energy, kinetic energy and momentum 0 - one must be non-zero.");}
141}
142
144 particle(other.particle),
145 ionPDGID(other.ionPDGID),
146 name(other.name),
147 mass(other.mass),
148 charge(other.charge),
149 totalEnergy(other.totalEnergy),
150 kineticEnergy(other.kineticEnergy),
151 momentum(other.momentum),
152 gamma(other.gamma),
153 beta(other.beta),
154 brho(other.brho),
155 ffact(other.ffact)
156{
157 if (other.ionDefinition)
159 else
160 {ionDefinition = nullptr;}
161}
162
164 particle(other.particle),
165 ionPDGID(other.ionPDGID),
166 name(other.name),
167 mass(other.mass),
168 charge(other.charge),
169 totalEnergy(other.totalEnergy),
170 kineticEnergy(other.kineticEnergy),
171 momentum(other.momentum),
172 gamma(other.gamma),
173 beta(other.beta),
174 brho(other.brho),
175 ffact(other.ffact)
176{
177 ionDefinition = other.ionDefinition;
178 other.ionDefinition = nullptr;
179}
180
182{
183 if (this != &other)
184 {
185 delete ionDefinition;
186 ionDefinition = other.ionDefinition;
187 other.ionDefinition = nullptr;
188
189 particle = other.particle;
190 ionPDGID = other.ionPDGID;
191 name = other.name;
192 mass = other.mass;
193 charge = other.charge;
194 totalEnergy = other.totalEnergy;
195 kineticEnergy = other.kineticEnergy;
196 momentum = other.momentum;
197 gamma = other.gamma;
198 beta = other.beta;
199 brho = other.brho;
200 ffact = other.ffact;
201 }
202 return *this;
203}
204
205BDSParticleDefinition::~BDSParticleDefinition()
206{
207 delete ionDefinition;
208}
209
211{
212 if (particle)
213 {return particle->GetPDGEncoding();}
214 else if (ionDefinition)
215 {return ionPDGID;}
216 else
217 {return 0;}
218}
219
220std::ostream& operator<<(std::ostream& out, const BDSParticleDefinition& def)
221{
222 G4int pre = 12;
223 out << "Particle: \""<< def.name << "\"" << G4endl;
224 out << "Mass: " << std::setprecision(pre) << def.mass/CLHEP::GeV << " GeV" << G4endl;
225 out << "Charge: " << def.charge << " e" << G4endl;
226 out << "Total Energy: " << std::setprecision(pre) << def.totalEnergy/CLHEP::GeV << " GeV" << G4endl;
227 out << "Kinetic Energy: " << std::setprecision(pre) << def.kineticEnergy/CLHEP::GeV << " GeV" << G4endl;
228 out << "Momentum: " << std::setprecision(pre) << def.momentum/CLHEP::GeV << " GeV" << G4endl;
229 out << "Gamma: " << std::setprecision(pre) << def.gamma << G4endl;
230 out << "Beta: " << std::setprecision(pre) << def.beta << G4endl;
231 out << "Rigidity (Brho): " << std::setprecision(pre) << def.brho/(CLHEP::tesla*CLHEP::m) << " T*m" << G4endl;
232 return out;
233}
234
236{
237 try
238 {momentum = std::sqrt(std::pow(totalEnergy,2) - std::pow(mass,2));}
239 catch (const std::domain_error&) // sqrt(-ve)
240 {throw BDSException(__METHOD_NAME__, "Total energy insufficient to include mass or particle.");}
241}
242
243void BDSParticleDefinition::CalculateRigidity(const G4double& ffactIn)
244{
245 // magnetic rigidity (brho)
246 // formula: B(Tesla)*rho(m) = p(GeV)/(0.299792458 * charge(e))
247 // charge (in e units); rigidity (in T*m)
249 {
250 brho = ffactIn * momentum / CLHEP::GeV / BDS::cOverGeV / charge;
251 brho *= CLHEP::tesla*CLHEP::m; // rigidity (in Geant4 units)
252 }
253}
254
256{
258
259 beta = std::sqrt(1 - (1./std::pow(gamma,2)) );
260}
General exception with possible name of object and message.
Definition: BDSException.hh:35
Class to parse an ion particle definition.
G4bool OverrideCharge() const
Accessor.
G4double Charge() const
Accessor.
G4double charge
In units of eplus.
Wrapper for particle definition.
void CalculateRigidity(const G4double &ffactIn)
Calculate and set rigidity based on charge and momentum.
G4double beta
Relativistic beta.
G4double totalEnergy
Particle total energy.
void CalculateLorentzFactors()
Calculate and set lorentz factors.
G4double gamma
Relativistic gamma.
void SetEnergies(G4double totalEnergyIn, G4double kineticEnergyIn, G4double momentumIn)
G4double momentum
Particle momentum.
BDSIonDefinition * ionDefinition
Optional ion definition. Does own.
G4double charge
Particle charge.
BDSParticleDefinition()=delete
No default constructor.
G4double ffact
Flip factor.
G4double mass
Particle mass.
BDSParticleDefinition & operator=(BDSParticleDefinition &&other) noexcept
Copy, move and assignment constructors specified as we have to copy the ionDefinition if it exists.
G4String name
Particle name.
G4double brho
Particle rigidity.
G4int ionPDGID
Cache this for ions only.
G4ParticleDefinition * particle
Does not own.
void CalculateMomentum()
Calculate and set momentum based on totalEnergy and mass.
G4double kineticEnergy
Particle kinetic energy.
static const G4double cOverGeV
speed of light / 1 GeV, used for scaling in brho calculation
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())