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 - 2023.
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
68 SetEnergies(totalEnergyIn, kineticEnergyIn, momentumIn);
69}
70
72 G4double massIn,
73 G4double chargeIn,
74 G4double totalEnergyIn,
75 G4double kineticEnergyIn,
76 G4double momentumIn,
77 G4double ffactIn,
78 BDSIonDefinition* ionDefinitionIn,
79 G4int ionPDGIDIn):
80 particle(nullptr),
81 ionDefinition(nullptr),
82 ionPDGID(ionPDGIDIn),
83 name(nameIn),
84 mass(massIn),
85 charge(chargeIn),
86 totalEnergy(0),
87 kineticEnergy(0),
88 momentum(0),
89 gamma(1.0),
90 beta(1.0),
91 brho(std::numeric_limits<double>::max()),// if zero charge infinite magnetic rigidity
92 ffact(ffactIn),
93 forwards(true)
94{
95 if (ionDefinitionIn)
96 {ionDefinition = new BDSIonDefinition(*ionDefinitionIn);}
97 SetEnergies(totalEnergyIn, kineticEnergyIn, momentumIn);
98}
99
100void BDSParticleDefinition::SetEnergies(G4double totalEnergyIn,
101 G4double kineticEnergyIn,
102 G4double momentumIn)
103{
104 if (BDS::IsFinite(totalEnergyIn))
105 {
106 if (totalEnergyIn <= mass)
107 {
108 throw BDSException(__METHOD_NAME__, "total energy (" + std::to_string(totalEnergyIn / CLHEP::GeV)
109 + " GeV) is less than or equal to the mass (" + std::to_string(mass / CLHEP::GeV)
110 + " GeV) of the particle \"" + name + "\"");
111 }
112 totalEnergy = totalEnergyIn;
115 }
116 else if (BDS::IsFinite(kineticEnergyIn))
117 {
118 if (kineticEnergyIn <= 0)
119 {
120 throw BDSException(__METHOD_NAME__, "kinetic energy (" + std::to_string(kineticEnergyIn/CLHEP::GeV)
121 + " GeV) must be > 0");
122 }
123 kineticEnergy = kineticEnergyIn;
124 totalEnergy = mass + kineticEnergyIn;
126 }
127 else if (BDS::IsFinite(momentumIn))
128 {
129 if (momentumIn <= 0)
130 {
131 throw BDSException(__METHOD_NAME__, "momentum (" + std::to_string(momentumIn/CLHEP::GeV)
132 + " GeV) must be > 0");
133 }
134 momentum = momentumIn;
135 totalEnergy = std::hypot(momentumIn, mass);
136 if (std::isnan(totalEnergy))
137 {throw BDSException(__METHOD_NAME__, "sqrt(-ve) encountered in calculating total energy");}
139 }
140 else
141 {throw BDSException(__METHOD_NAME__, "total energy, kinetic energy and momentum 0 - one must be non-zero.");}
144}
145
147 particle(other.particle),
148 ionPDGID(other.ionPDGID),
149 name(other.name),
150 mass(other.mass),
151 charge(other.charge),
152 totalEnergy(other.totalEnergy),
153 kineticEnergy(other.kineticEnergy),
154 momentum(other.momentum),
155 gamma(other.gamma),
156 beta(other.beta),
157 brho(other.brho),
158 ffact(other.ffact),
159 forwards(other.forwards)
160{
161 if (other.ionDefinition)
163 else
164 {ionDefinition = nullptr;}
165}
166
168 particle(other.particle),
169 ionPDGID(other.ionPDGID),
170 name(other.name),
171 mass(other.mass),
172 charge(other.charge),
173 totalEnergy(other.totalEnergy),
174 kineticEnergy(other.kineticEnergy),
175 momentum(other.momentum),
176 gamma(other.gamma),
177 beta(other.beta),
178 brho(other.brho),
179 ffact(other.ffact),
180 forwards(other.forwards)
181{
182 ionDefinition = other.ionDefinition;
183 other.ionDefinition = nullptr;
184}
185
187{
188 if (this != &other)
189 {
190 delete ionDefinition;
191 ionDefinition = other.ionDefinition;
192 other.ionDefinition = nullptr;
193
194 particle = other.particle;
195 ionPDGID = other.ionPDGID;
196 name = other.name;
197 mass = other.mass;
198 charge = other.charge;
199 totalEnergy = other.totalEnergy;
200 kineticEnergy = other.kineticEnergy;
201 momentum = other.momentum;
202 gamma = other.gamma;
203 beta = other.beta;
204 brho = other.brho;
205 ffact = other.ffact;
206 forwards = other.forwards;
207 }
208 return *this;
209}
210
211BDSParticleDefinition::~BDSParticleDefinition()
212{
213 delete ionDefinition;
214}
215
217{
218 if (particle)
219 {return particle->GetPDGEncoding();}
220 else if (ionDefinition)
221 {return ionPDGID;}
222 else
223 {return 0;}
224}
225
226std::ostream& operator<<(std::ostream& out, const BDSParticleDefinition& def)
227{
228 G4int pre = 12;
229 out << "Particle: \""<< def.name << "\"" << G4endl;
230 out << "Mass: " << std::setprecision(pre) << def.mass/CLHEP::GeV << " GeV" << G4endl;
231 out << "Charge: " << def.charge << " e" << G4endl;
232 out << "Total Energy: " << std::setprecision(pre) << def.totalEnergy/CLHEP::GeV << " GeV" << G4endl;
233 out << "Kinetic Energy: " << std::setprecision(pre) << def.kineticEnergy/CLHEP::GeV << " GeV" << G4endl;
234 out << "Momentum: " << std::setprecision(pre) << def.momentum/CLHEP::GeV << " GeV" << G4endl;
235 out << "Gamma: " << std::setprecision(pre) << def.gamma << G4endl;
236 out << "Beta: " << std::setprecision(pre) << def.beta << G4endl;
237 out << "FFact: " << std::setprecision(pre) << def.ffact << G4endl;
238 out << "Rigidity (Brho): " << std::setprecision(pre) << def.brho/(CLHEP::tesla*CLHEP::m) << " T*m" << G4endl;
239 return out;
240}
241
243{
244 try
245 {momentum = std::sqrt(std::pow(totalEnergy,2) - std::pow(mass,2));}
246 catch (const std::domain_error&) // sqrt(-ve)
247 {throw BDSException(__METHOD_NAME__, "Total energy insufficient to include mass or particle.");}
248}
249
250void BDSParticleDefinition::CalculateRigidity(const G4double& ffactIn)
251{
252 // magnetic rigidity (brho)
253 // formula: B(Tesla)*rho(m) = p(GeV)/(0.299792458 * charge(e))
254 // charge (in e units); rigidity (in T*m)
256 {
257 brho = ffactIn * momentum / CLHEP::GeV / BDS::cOverGeV / charge;
258 brho *= CLHEP::tesla*CLHEP::m; // rigidity (in Geant4 units)
259 }
260}
261
263{
265
266 beta = std::sqrt(1 - (1./std::pow(gamma,2)) );
267}
268
270{
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.
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.
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())