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) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "BDSDebug.hh"
19#include "BDSException.hh"
20#include "BDSIonDefinition.hh"
21#include "BDSParticleDefinition.hh"
22#include "BDSPhysicalConstants.hh"
23#include "BDSUtilities.hh"
24#include "BDSWarning.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 forwards(true)
58{
59 charge = particle->GetPDGCharge();
60 if (ionDefinition) // may be nullptr
61 {
62 ionDefinition = new BDSIonDefinition(*ionDefinitionIn);
63 if (ionDefinition->OverrideCharge()) // if override for ions
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 forwards(true)
92{
93 if (ionDefinitionIn)
94 {ionDefinition = new BDSIonDefinition(*ionDefinitionIn);}
95 SetEnergies(totalEnergyIn, kineticEnergyIn, momentumIn);
96}
97
98void BDSParticleDefinition::SetEnergies(G4double totalEnergyIn,
99 G4double kineticEnergyIn,
100 G4double momentumIn)
101{
102 if (BDS::IsFinite(totalEnergyIn))
103 {
104 if (totalEnergyIn <= mass)
105 {
106 throw BDSException(__METHOD_NAME__, "total energy (" + std::to_string(totalEnergyIn / CLHEP::GeV)
107 + " GeV) is less than or equal to the mass (" + std::to_string(mass / CLHEP::GeV)
108 + " GeV) of the particle \"" + name + "\"");
109 }
110 totalEnergy = totalEnergyIn;
113 }
114 else if (BDS::IsFinite(kineticEnergyIn))
115 {
116 if (kineticEnergyIn <= 0)
117 {
118 throw BDSException(__METHOD_NAME__, "kinetic energy (" + std::to_string(kineticEnergyIn/CLHEP::GeV)
119 + " GeV) must be > 0");
120 }
121 kineticEnergy = kineticEnergyIn;
122 totalEnergy = mass + kineticEnergyIn;
124 }
125 else if (BDS::IsFinite(momentumIn))
126 {
127 if (momentumIn <= 0)
128 {
129 throw BDSException(__METHOD_NAME__, "momentum (" + std::to_string(momentumIn/CLHEP::GeV)
130 + " GeV) must be > 0");
131 }
132 momentum = momentumIn;
133 totalEnergy = std::hypot(momentumIn, mass);
134 if (std::isnan(totalEnergy))
135 {throw BDSException(__METHOD_NAME__, "sqrt(-ve) encountered in calculating total energy");}
137 }
138 else
139 {throw BDSException(__METHOD_NAME__, "total energy, kinetic energy and momentum 0 - one must be non-zero.");}
142}
143
145 particle(other.particle),
146 ionPDGID(other.ionPDGID),
147 name(other.name),
148 mass(other.mass),
149 charge(other.charge),
150 totalEnergy(other.totalEnergy),
151 kineticEnergy(other.kineticEnergy),
152 momentum(other.momentum),
153 gamma(other.gamma),
154 beta(other.beta),
155 brho(other.brho),
156 ffact(other.ffact),
157 forwards(other.forwards)
158{
159 if (other.ionDefinition)
161 else
162 {ionDefinition = nullptr;}
163}
164
166 particle(other.particle),
167 ionPDGID(other.ionPDGID),
168 name(other.name),
169 mass(other.mass),
170 charge(other.charge),
171 totalEnergy(other.totalEnergy),
172 kineticEnergy(other.kineticEnergy),
173 momentum(other.momentum),
174 gamma(other.gamma),
175 beta(other.beta),
176 brho(other.brho),
177 ffact(other.ffact),
178 forwards(other.forwards)
179{
180 ionDefinition = other.ionDefinition;
181 other.ionDefinition = nullptr;
182}
183
185{
186 if (this != &other)
187 {
188 delete ionDefinition;
189 ionDefinition = other.ionDefinition;
190 other.ionDefinition = nullptr;
191
192 particle = other.particle;
193 ionPDGID = other.ionPDGID;
194 name = other.name;
195 mass = other.mass;
196 charge = other.charge;
197 totalEnergy = other.totalEnergy;
198 kineticEnergy = other.kineticEnergy;
199 momentum = other.momentum;
200 gamma = other.gamma;
201 beta = other.beta;
202 brho = other.brho;
203 ffact = other.ffact;
204 forwards = other.forwards;
205 }
206 return *this;
207}
208
209BDSParticleDefinition::~BDSParticleDefinition()
210{
211 delete ionDefinition;
212}
213
215{
216 if (particle)
217 {return particle->GetPDGEncoding();}
218 else if (ionDefinition)
219 {return ionPDGID;}
220 else
221 {return 0;}
222}
223
224std::ostream& operator<<(std::ostream& out, const BDSParticleDefinition& def)
225{
226 G4int pre = 12;
227 out << "Particle: \""<< def.name << "\"" << G4endl;
228 out << "Mass: " << std::setprecision(pre) << def.mass/CLHEP::GeV << " GeV" << G4endl;
229 out << "Charge: " << def.charge << " e" << G4endl;
230 out << "Total Energy: " << std::setprecision(pre) << def.totalEnergy/CLHEP::GeV << " GeV" << G4endl;
231 out << "Kinetic Energy: " << std::setprecision(pre) << def.kineticEnergy/CLHEP::GeV << " GeV" << G4endl;
232 out << "Momentum: " << std::setprecision(pre) << def.momentum/CLHEP::GeV << " GeV" << G4endl;
233 out << "Gamma: " << std::setprecision(pre) << def.gamma << G4endl;
234 out << "Beta: " << std::setprecision(pre) << def.beta << G4endl;
235 out << "FFact: " << std::setprecision(pre) << def.ffact << G4endl;
236 out << "Rigidity (Brho): " << std::setprecision(pre) << def.brho/(CLHEP::tesla*CLHEP::m) << " T*m" << G4endl;
237 return out;
238}
239
241{
242 try
243 {momentum = std::sqrt(std::pow(totalEnergy,2) - std::pow(mass,2));}
244 catch (const std::domain_error&) // sqrt(-ve)
245 {throw BDSException(__METHOD_NAME__, "Total energy insufficient to include mass or particle.");}
246}
247
248void BDSParticleDefinition::CalculateRigidity(const G4double& ffactIn)
249{
250 // magnetic rigidity (brho)
251 // formula: B(Tesla)*rho(m) = p(GeV)/(0.299792458 * charge(e))
252 // charge (in e units); rigidity (in T*m)
254 {
255 brho = ffactIn * momentum / CLHEP::GeV / BDS::cOverGeV / charge;
256 brho *= CLHEP::tesla*CLHEP::m; // rigidity (in Geant4 units)
257 }
258}
259
261{
263 beta = std::sqrt(1 - (1./std::pow(gamma,2)));
264}
265
267{
268 if (!BDS::IsFinite(dEk))
269 {return;}
270 G4double newEk = kineticEnergy + dEk;
271 if (newEk < 0)
272 {
274 newEk = std::abs(newEk);
275 BDS::Warning(__METHOD_NAME__, "particle change of direction");
276 }
277 SetEnergies(0,newEk,0);
278}
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.