BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSParticleDefinition.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2024.
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#include "BDSWarning.hh"
26
27#include "G4ParticleDefinition.hh"
28
29#include "CLHEP/Units/SystemOfUnits.h"
30
31#include <cmath>
32#include <iomanip>
33#include <limits>
34#include <ostream>
35#include <stdexcept>
36#include <string>
37
38BDSParticleDefinition::BDSParticleDefinition(G4ParticleDefinition* particleIn,
39 G4double totalEnergyIn,
40 G4double kineticEnergyIn,
41 G4double momentumIn,
42 G4double ffactIn,
43 BDSIonDefinition* ionDefinitionIn,
44 G4int ionPDGIDIn):
45 particle(particleIn),
46 ionDefinition(nullptr),
47 ionPDGID(ionPDGIDIn),
48 name(particleIn->GetParticleName()),
49 mass(particleIn->GetPDGMass()),
50 charge(0),
51 totalEnergy(0),
52 kineticEnergy(0),
53 momentum(0),
54 gamma(1.0),
55 beta(1.0),
56 brho(std::numeric_limits<double>::max()),// if zero charge infinite magnetic rigidity
57 ffact(ffactIn),
58 forwards(true)
59{
60 charge = particle->GetPDGCharge();
61 if (ionDefinition) // may be nullptr
62 {
63 ionDefinition = new BDSIonDefinition(*ionDefinitionIn);
64 if (ionDefinition->OverrideCharge()) // if override for ions
66 }
67 SetEnergies(totalEnergyIn, kineticEnergyIn, momentumIn);
68}
69
71 G4double massIn,
72 G4double chargeIn,
73 G4double totalEnergyIn,
74 G4double kineticEnergyIn,
75 G4double momentumIn,
76 G4double ffactIn,
77 BDSIonDefinition* ionDefinitionIn,
78 G4int ionPDGIDIn):
79 particle(nullptr),
80 ionDefinition(nullptr),
81 ionPDGID(ionPDGIDIn),
82 name(nameIn),
83 mass(massIn),
84 charge(chargeIn),
85 totalEnergy(0),
86 kineticEnergy(0),
87 momentum(0),
88 gamma(1.0),
89 beta(1.0),
90 brho(std::numeric_limits<double>::max()),// if zero charge infinite magnetic rigidity
91 ffact(ffactIn),
92 forwards(true)
93{
94 if (ionDefinitionIn)
95 {ionDefinition = new BDSIonDefinition(*ionDefinitionIn);}
96 SetEnergies(totalEnergyIn, kineticEnergyIn, momentumIn);
97}
98
99void BDSParticleDefinition::SetEnergies(G4double totalEnergyIn,
100 G4double kineticEnergyIn,
101 G4double momentumIn)
102{
103 if (BDS::IsFinite(totalEnergyIn))
104 {
105 if (totalEnergyIn <= mass)
106 {
107 throw BDSException(__METHOD_NAME__, "total energy (" + std::to_string(totalEnergyIn / CLHEP::GeV)
108 + " GeV) is less than or equal to the mass (" + std::to_string(mass / CLHEP::GeV)
109 + " GeV) of the particle \"" + name + "\"");
110 }
111 totalEnergy = totalEnergyIn;
114 }
115 else if (BDS::IsFinite(kineticEnergyIn))
116 {
117 if (kineticEnergyIn <= 0)
118 {
119 throw BDSException(__METHOD_NAME__, "kinetic energy (" + std::to_string(kineticEnergyIn/CLHEP::GeV)
120 + " GeV) must be > 0");
121 }
122 kineticEnergy = kineticEnergyIn;
123 totalEnergy = mass + kineticEnergyIn;
125 }
126 else if (BDS::IsFinite(momentumIn))
127 {
128 if (momentumIn <= 0)
129 {
130 throw BDSException(__METHOD_NAME__, "momentum (" + std::to_string(momentumIn/CLHEP::GeV)
131 + " GeV) must be > 0");
132 }
133 momentum = momentumIn;
134 totalEnergy = std::hypot(momentumIn, mass);
135 if (std::isnan(totalEnergy))
136 {throw BDSException(__METHOD_NAME__, "sqrt(-ve) encountered in calculating total energy");}
138 }
139 else
140 {throw BDSException(__METHOD_NAME__, "total energy, kinetic energy and momentum 0 - one must be non-zero.");}
143}
144
146 particle(other.particle),
147 ionPDGID(other.ionPDGID),
148 name(other.name),
149 mass(other.mass),
150 charge(other.charge),
151 totalEnergy(other.totalEnergy),
152 kineticEnergy(other.kineticEnergy),
153 momentum(other.momentum),
154 gamma(other.gamma),
155 beta(other.beta),
156 brho(other.brho),
157 ffact(other.ffact),
158 forwards(other.forwards)
159{
160 if (other.ionDefinition)
162 else
163 {ionDefinition = nullptr;}
164}
165
167 particle(other.particle),
168 ionPDGID(other.ionPDGID),
169 name(other.name),
170 mass(other.mass),
171 charge(other.charge),
172 totalEnergy(other.totalEnergy),
173 kineticEnergy(other.kineticEnergy),
174 momentum(other.momentum),
175 gamma(other.gamma),
176 beta(other.beta),
177 brho(other.brho),
178 ffact(other.ffact),
179 forwards(other.forwards)
180{
181 ionDefinition = other.ionDefinition;
182 other.ionDefinition = nullptr;
183}
184
186{
187 if (this != &other)
188 {
189 delete ionDefinition;
190 ionDefinition = other.ionDefinition;
191 other.ionDefinition = nullptr;
192
193 particle = other.particle;
194 ionPDGID = other.ionPDGID;
195 name = other.name;
196 mass = other.mass;
197 charge = other.charge;
198 totalEnergy = other.totalEnergy;
199 kineticEnergy = other.kineticEnergy;
200 momentum = other.momentum;
201 gamma = other.gamma;
202 beta = other.beta;
203 brho = other.brho;
204 ffact = other.ffact;
205 forwards = other.forwards;
206 }
207 return *this;
208}
209
210BDSParticleDefinition::~BDSParticleDefinition()
211{
212 delete ionDefinition;
213}
214
216{
217 if (particle)
218 {return particle->GetPDGEncoding();}
219 else if (ionDefinition)
220 {return ionPDGID;}
221 else
222 {return 0;}
223}
224
225std::ostream& operator<<(std::ostream& out, const BDSParticleDefinition& def)
226{
227 G4int pre = 12;
228 out << "Particle: \""<< def.name << "\"" << G4endl;
229 out << "Mass: " << std::setprecision(pre) << def.mass/CLHEP::GeV << " GeV" << G4endl;
230 out << "Charge: " << def.charge << " e" << G4endl;
231 out << "Total Energy: " << std::setprecision(pre) << def.totalEnergy/CLHEP::GeV << " GeV" << G4endl;
232 out << "Kinetic Energy: " << std::setprecision(pre) << def.kineticEnergy/CLHEP::GeV << " GeV" << G4endl;
233 out << "Momentum: " << std::setprecision(pre) << def.momentum/CLHEP::GeV << " GeV" << G4endl;
234 out << "Gamma: " << std::setprecision(pre) << def.gamma << G4endl;
235 out << "Beta: " << std::setprecision(pre) << def.beta << G4endl;
236 out << "FFact: " << std::setprecision(pre) << def.ffact << G4endl;
237 out << "Rigidity (Brho): " << std::setprecision(pre) << def.brho/(CLHEP::tesla*CLHEP::m) << " T*m" << G4endl;
238 return out;
239}
240
242{
243 try
244 {momentum = std::sqrt(std::pow(totalEnergy,2) - std::pow(mass,2));}
245 catch (const std::domain_error&) // sqrt(-ve)
246 {throw BDSException(__METHOD_NAME__, "Total energy insufficient to include mass or particle.");}
247}
248
249void BDSParticleDefinition::CalculateRigidity(const G4double& ffactIn)
250{
251 // magnetic rigidity (brho)
252 // formula: B(Tesla)*rho(m) = p(GeV)/(0.299792458 * charge(e))
253 // charge (in e units); rigidity (in T*m)
255 {
256 brho = ffactIn * momentum / CLHEP::GeV / BDS::cOverGeV / charge;
257 brho *= CLHEP::tesla*CLHEP::m; // rigidity (in Geant4 units)
258 }
259}
260
262{
264 beta = std::sqrt(1 - (1./std::pow(gamma,2)));
265}
266
268{
269 if (!BDS::IsFinite(dEk))
270 {return;}
271 G4double newEk = kineticEnergy + dEk;
272 if (newEk < 0)
273 {
275 newEk = std::abs(newEk);
276 BDS::Warning(__METHOD_NAME__, "particle change of direction");
277 }
278 SetEnergies(0,newEk,0);
279}
General exception with possible name of object and message.
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 mass
Particle mass.
BDSParticleDefinition & operator=(BDSParticleDefinition &&other) noexcept
Copy, move and assignment constructors specified as we have to copy the ionDefinition if it exists.
G4bool forwards
In case of change of direction.
void ApplyChangeInKineticEnergy(G4double dEk)
Utility function to update quantities by adding on dEK (can be negative).
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())
STL namespace.