BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSLinkTrackerInterface.cc
1#include <vector>
2#include <string>
3#include <filesystem>
4
5#include "CLHEP/Units/SystemOfUnits.h"
6#include "CLHEP/Units/PhysicalConstants.h"
7
8#include "G4ParticleTable.hh"
9#include "G4IonTable.hh"
10
11#include "BDSLinkTrackerInterface.hh"
12#include "BDSLinkBunch.hh"
13#include "BDSIMLink.hh"
14#include "BDSParticleDefinition.hh"
15
16BDSLinkTrackerInterface* BDSLinkTrackerInterface::singleton = nullptr;
17
18BDSLinkTrackerInterface* BDSLinkTrackerInterface::GetInstance(std::string bdsimConfigFileIn,
19 int referenceParticlePDGIn,
20 double referenceKineticEnergyIn,
21 double relativeEnergyCutIn,
22 int seedIn,
23 int referenceIonChargeIn,
24 bool batchModeIn) {
25 // TODO does not work on all platforms
26 //if (!std::filesystem::exists(bdsimConfigFileIn)) {
27 // std::cout << "File does not exist.\n";
28 // return nullptr;
29 //}
30
31
32 if(singleton != nullptr) {
33 return singleton;
34 }
35 else {
36 singleton = new BDSLinkTrackerInterface(bdsimConfigFileIn,
37 referenceParticlePDGIn,
38 referenceKineticEnergyIn,
39 relativeEnergyCutIn,
40 seedIn,
41 referenceIonChargeIn,
42 batchModeIn);
43 return singleton;
44 }
45}
46
47BDSLinkTrackerInterface* BDSLinkTrackerInterface::GetInstance() {
48 if(singleton) {
49 return singleton;
50 }
51 else {
52 std::cout << "BDSLinkTrackerInterface not initialised" << std::endl;
53 return nullptr;
54 }
55}
56
57BDSLinkTrackerInterface::BDSLinkTrackerInterface(std::string bdsimConfigFileIn,
58 int referenceParticlePDGIn,
59 double referenceKineticEnergyIn,
60 double relativeEnergyCutIn,
61 int seedIn,
62 int referenceIonChargeIn,
63 bool batchModeIn) :
64 bdsimConfigFile(bdsimConfigFileIn),
65 referenceParticlePDG(referenceParticlePDGIn),
66 referenceKineticEnergy(referenceKineticEnergyIn),
67 relativeEnergyCut(relativeEnergyCutIn),
68 seed(seedIn),
69 referenceIonCharge(referenceIonChargeIn),
70 batchMode(batchModeIn)
71{
72 // keep local tables for ease
73 g4particle_table = G4ParticleTable::GetParticleTable();
74 g4ion_table = g4particle_table->GetIonTable();
75
76 // create link objects
77 linkBunch = new BDSLinkBunch();
78 linkBDSIM = new BDSIMLink(linkBunch);
79
80 std::vector<std::string> bdsim_args;
81 bdsim_args.push_back("bdsim");
82 bdsim_args.push_back("--file="+bdsimConfigFile);
83 bdsim_args.push_back("--seed="+std::to_string(seed));
84 bdsim_args.push_back("--output=None");
85
86 // append batch configuration
87 if(batchMode)
88 bdsim_args.push_back(std::string("--batch"));
89 else
90 bdsim_args.push_back(std::string("--vis_mac=vis.mac"));
91
92 // set minimum kinetic energy
93 if(relativeEnergyCut < 1e-6)
94 relativeEnergyCut = 1.0;
95 minimumKineticEnergy = relativeEnergyCut * referenceKineticEnergy;
96
97 // Create a vector of char* pointing to c_str()
98 std::vector<char*> c_args;
99 for (auto& arg : bdsim_args) {
100 c_args.push_back(const_cast<char*>(arg.c_str()));
101 }
102
103 // initialise link object
104 linkBDSIM->Initialise(c_args.size(),
105 c_args.data(),
106 true,
107 minimumKineticEnergy/CLHEP::GeV,
108 false);
109
110 referenceParticleDefinition = prepareBDSParticleDefition(referenceParticlePDG, 0, referenceKineticEnergy, static_cast<double>(referenceIonCharge));
111}
112
113BDSParticleDefinition* BDSLinkTrackerInterface::prepareBDSParticleDefition(int pdg,
114 double momentum,
115 double kineticEnergy,
116 int ionCharge) {
117 G4ParticleDefinition *particleDefGeant = nullptr;
118 BDSParticleDefinition *particleDefinition = nullptr;
119 BDSIonDefinition* ionDef = nullptr;
120
121 if (pdg < 1000000000) { // Not an ion
122 particleDefGeant = g4particle_table->FindParticle(pdg);
123 particleDefinition = new BDSParticleDefinition(particleDefGeant, 0,
124 kineticEnergy, momentum, 1, nullptr);
125 }
126 else { // Ions
127 particleDefGeant = g4ion_table->GetIon(pdg);
128
129 if (ionCharge == 0) {
130 ionCharge = particleDefGeant->GetAtomicNumber();
131 }
132
133 ionDef = new BDSIonDefinition(particleDefGeant->GetAtomicMass(),
134 particleDefGeant->GetAtomicNumber(),
135 ionCharge);
136
137 auto mass = g4ion_table->GetIonMass(ionDef->Z(), ionDef->A());
138 auto charge = ionDef->Charge();
139
140 auto bdsimPartName = "ion " + std::to_string(ionDef->A()) +
141 " " + std::to_string(ionDef->Z()) +
142 " " + std::to_string(charge);
143
144 particleDefinition = new BDSParticleDefinition(bdsimPartName, mass, charge, 0,
145 kineticEnergy, momentum, 1, ionDef, pdg);
146 }
147 return particleDefinition;
148}
149
150void BDSLinkTrackerInterface::AddParticle(double x, double y, double px, double py,
151 double ct, double deltap, double chi,
152 double chargeRatio, double /*s*/,
153 int trackid, int pdgid) {
154
155 auto q = chargeRatio * referenceParticleDefinition->Charge();
156 auto mass_ratio = chargeRatio / chi;
157 auto p = referenceParticleDefinition->Momentum() * (deltap + 1) * mass_ratio;
158
159 auto pdg = 0;
160 if(pdgid == 0)
161 pdg = referenceParticleDefinition->PDGID();
162 else
163 pdg = pdgid;
164
165 auto partDef = prepareBDSParticleDefition(pdg, p, 0, q);
166 auto t = - ct * CLHEP::m / (referenceParticleDefinition->Beta() * CLHEP::c_light);
167 auto oneplusdelta = (1 + deltap);
168 auto xp = px / oneplusdelta;
169 auto yp = py / oneplusdelta;
170 auto sqrtarg = 1 - std::pow(xp,2) - std::pow(yp,2);
171
172 auto zp = 0.0;
173
174 if (sqrtarg >=0)
175 { zp = std::sqrt(sqrtarg); }
176
177 auto coords = BDSParticleCoordsFull(x * CLHEP::m,
178 y * CLHEP::m,
179 0,
180 xp,
181 yp,
182 zp,
183 t,
184 0,
185 partDef->TotalEnergy(),
186 1);
187
188 linkBunch->AddParticle(partDef, coords, trackid, trackid);
189 return;
190}
191
192void BDSLinkTrackerInterface::AddParticle(double x, double y,
193 double px, double py, double pz,
194 double t, double /*s*/,
195 int trackid, int pdgid) {
196 auto pdg = 0;
197 auto q = 0.0;
198
199 if(pdgid == 0) {
200 pdg = referenceParticleDefinition->PDGID();
201 q = referenceParticleDefinition->Charge();
202 }
203 else {
204 pdg = pdgid;
205 q = G4ParticleTable::GetParticleTable()->FindParticle(pdg)->GetPDGCharge();
206 }
207
208 auto p = std::sqrt(std::pow(px,2) +
209 std::pow(py,2) +
210 std::pow(pz,2));
211 auto partDef = prepareBDSParticleDefition(pdg, p, 0, q);
212 auto xp = px / pz;
213 auto yp = py / pz;
214 auto zp = pz / p;
215
216 auto coords = BDSParticleCoordsFull(x,
217 y,
218 0,
219 xp,
220 yp,
221 zp,
222 t,
223 0,
224 partDef->TotalEnergy(),
225 1);
226
227 linkBunch->AddParticle(partDef, coords, trackid, trackid);
228 return;
229}
230
231void BDSLinkTrackerInterface::AddParticles(std::vector<double> x, std::vector<double> y,
232 std::vector<double> px, std::vector<double> py,
233 std::vector<double> ct, std::vector<double> deltap,
234 std::vector<double> chi, std::vector<double> chargeRatio,
235 std::vector<double> s, std::vector<int> trackid,
236 std::vector<int> pdgid) {
237 for(size_t i=0; i<x.size(); i++) {
238 AddParticle(x[i], y[i], px[i], py[i], ct[i], deltap[i],
239 chi[i], chargeRatio[i], s[i], trackid[i], pdgid[i]);
240 }
241}
Class to parse an ion particle definition.
G4int A() const
Accessor.
G4int Z() const
Accessor.
G4double Charge() const
Accessor.
A bunch distribution that holds a bunch from a Link.
void AddParticle(BDSParticleDefinition *particleDefinitionIn, const BDSParticleCoordsFull &coordsIn, int externalParticleID, int externalParentID)
Append particle to the bunch for tracking.
A set of particle coordinates including energy and weight.
Wrapper for particle definition.
G4double Momentum() const
Accessor.
G4double Charge() const
Accessor.
G4double Beta() const
Accessor.