19#include "BDSException.hh"
20#include "BDSGlobalConstants.hh"
21#include "BDSParticleCoordsFullGlobal.hh"
22#include "BDSParticleDefinition.hh"
23#include "BDSPTCOneTurnMap.hh"
24#include "BDSTrajectoryPrimary.hh"
25#include "BDSUtilities.hh"
29#include "CLHEP/Units/SystemOfUnits.h"
39 initialPrimaryMomentum(0),
48 referenceMomentum = designParticle->
Momentum();
49 mass = designParticle->
Mass();
52 G4cout << __METHOD_NAME__ <<
"Using map table " << filePath << G4endl;
53 std::ifstream infile(filePath);
55 {
throw BDSException(__METHOD_NAME__,
"Failed to read maptable: \"" + maptableFile +
"\"");}
59 G4double coefficient = 0;
61 G4int dimensionality = 0;
71 while (std::getline(infile, line))
73 if (line.at(0) ==
'@' || line.at(0) ==
'*' || line.at(0) ==
'$')
75 std::istringstream stream(line);
77 stream >> name >> coefficient >> nVector >> dimensionality >> totalOrder >>
78 nx >> npx >> ny >> npy >> ndeltaP >> nt;
80 PTCMapTerm term{coefficient, nx, npx, ny, npy, ndeltaP};
85 {xTerms.push_back(term);
break;}
87 {pxTerms.push_back(term);
break;}
89 {yTerms.push_back(term);
break;}
91 {pyTerms.push_back(term);
break;}
93 {deltaPTerms.push_back(term);
break;}
96 throw BDSException(__METHOD_NAME__,
"Unrecognised PTC term index - maptable file is perhaps malformed.");
102 G4cout << __METHOD_NAME__ <<
"> Loaded Map:" << maptableFile << G4endl;
107 G4bool beamOffsetS0In)
110 initialPrimaryMomentum = std::sqrt(std::pow(coords.local.totalEnergy, 2) - std::pow(mass, 2));
112 xLastTurn = coords.local.x / CLHEP::m;
113 pxLastTurn = coords.global.xp * initialPrimaryMomentum / referenceMomentum;
114 yLastTurn = coords.local.y / CLHEP::m;
115 pyLastTurn = coords.global.yp * initialPrimaryMomentum / referenceMomentum;
116 deltaPLastTurn = (initialPrimaryMomentum - referenceMomentum) / referenceMomentum;
118 turnsScattered.clear();
123 beamOffsetS0 = beamOffsetS0In;
135 G4double pxOut = 0.0;
136 G4double pyOut = 0.0;
137 G4double pzOut = 0.0;
138 G4double deltaPOut = 0.0;
150 if (lastTurnNumber < turnsTaken)
153 G4cout << __METHOD_NAME__ <<
"Applying Map: " << G4endl;
154 G4cout <<
"Before map application: " << G4endl;
155 G4cout <<
"xLastTurn = " << xLastTurn << G4endl;
156 G4cout <<
"pxLastTurn = " << pxLastTurn << G4endl;
157 G4cout <<
"yLastTurn = " << yLastTurn << G4endl;
158 G4cout <<
"pyLastTurn = " << pyLastTurn << G4endl;
161 lastTurnNumber = turnsTaken;
162 xOut = Evaluate(xTerms,
163 xLastTurn, pxLastTurn,
164 yLastTurn, pyLastTurn,
166 pxOut = Evaluate(pxTerms,
167 xLastTurn, pxLastTurn,
168 yLastTurn, pyLastTurn,
170 yOut = Evaluate(yTerms,
171 xLastTurn, pxLastTurn,
172 yLastTurn, pyLastTurn,
174 pyOut = Evaluate(pyTerms,
175 xLastTurn, pxLastTurn,
176 yLastTurn, pyLastTurn,
178 deltaPOut = Evaluate(deltaPTerms,
179 xLastTurn, pxLastTurn,
180 yLastTurn, pyLastTurn,
187 deltaPLastTurn = deltaPOut;
189 G4cout <<
"After map application: " << G4endl;
190 G4cout <<
"xOut = " << xOut << G4endl;
191 G4cout <<
"pxOut = " << pxOut << G4endl;
192 G4cout <<
"yOut = " << yOut << G4endl;
193 G4cout <<
"pyOut = " << pyOut << G4endl;
202 deltaPOut = deltaPLastTurn;
204 G4cout << __METHOD_NAME__ <<
"Returning Cached Values:" << G4endl;
205 G4cout <<
"xOut = " << xOut << G4endl;
206 G4cout <<
"pxOut = " << pxOut << G4endl;
207 G4cout <<
"yOut = " << yOut << G4endl;
208 G4cout <<
"pyOut = " << pyOut << G4endl;
219 pxOut *= referenceMomentum;
220 pyOut *= referenceMomentum;
223 pzOut = std::sqrt(std::pow(initialPrimaryMomentum, 2)
235 G4cout << __METHOD_NAME__ <<
"Converting PTC to BDSIM " << G4endl;
236 G4cout <<
"xOut = " << xOut << G4endl;
237 G4cout <<
"pxOut = " << pxOut << G4endl;
238 G4cout <<
"yOut = " << yOut << G4endl;
239 G4cout <<
"pyOut = " << pyOut << G4endl;
240 G4cout <<
"initialPrimaryMomentum = " << initialPrimaryMomentum << G4endl;
241 G4cout <<
"referenceMomentum = " << referenceMomentum << G4endl;
242 G4cout <<
"pzOut = " << pz << G4endl;
246G4double BDSPTCOneTurnMap::Evaluate(std::vector<PTCMapTerm>& terms,
251 G4double deltaP)
const
254 for (
const auto& term : terms)
256 result += (term.coefficient
257 * std::pow(x, term.nx)
258 * std::pow(px, term.npx)
259 * std::pow(y, term.ny)
260 * std::pow(py, term.npy)
261 * std::pow(deltaP, term.ndeltaP));
275 G4bool offsetBeamS0AndOnFirstTurn = beamOffsetS0 && turnsTaken == 2;
285 turnsScattered.count(turnsTaken);
289 if (didScatterThisTurn)
290 {turnsScattered.insert(turnsTaken);}
293 G4double ratioOffReference = std::abs((momentum - referenceMomentum) / referenceMomentum);
294 G4double tolerance = 0.05;
295 G4bool tooFarOffMomentum = ratioOffReference > tolerance;
297 G4bool should = !offsetBeamS0AndOnFirstTurn && !didScatterThisTurn && !tooFarOffMomentum;
300 G4cout << __METHOD_NAME__
301 <<
"scatteredThisTurn = " << BDS::BoolToString(didScatterThisTurn)
303 G4cout << __METHOD_NAME__
304 <<
"beamOffsetS0 = " << BDS::BoolToString(beamOffsetS0) << G4endl;
305 G4cout << __METHOD_NAME__ <<
"turnsTaken = " << turnsTaken << G4endl;
306 G4cout << __METHOD_NAME__ <<
"Is on first turn with S0 != 0?"
307 << BDS::BoolToString(offsetBeamS0AndOnFirstTurn) << G4endl;
308 G4cout << __METHOD_NAME__
309 <<
"tooFarOffMomentum = " << BDS::BoolToString(tooFarOffMomentum)
311 G4cout << __METHOD_NAME__ <<
"ShouldApply = " << BDS::BoolToString(should)
320 G4ThreeVector localMomentum,
323 if (lastTurnNumber < turnsTaken)
330 xLastTurn = localPosition.x() / CLHEP::m;
331 yLastTurn = localPosition.y() / CLHEP::m;
332 pxLastTurn = localMomentum.x() / referenceMomentum;
333 pyLastTurn = localMomentum.y() / referenceMomentum;
334 G4double totalMomentum = localMomentum.mag();
335 deltaPLastTurn = (totalMomentum - referenceMomentum) / referenceMomentum;
337 lastTurnNumber = turnsTaken;
339 G4cout << __METHOD_NAME__
340 <<
"Updating map coords without use of map:" << G4endl;
341 G4cout <<
"xLastTurn = " << xLastTurn << G4endl;
342 G4cout <<
"yLastTurn = " << yLastTurn << G4endl;
343 G4cout <<
"pxLastTurn = " << pxLastTurn << G4endl;
344 G4cout <<
"pyLastTurn = " << pyLastTurn << G4endl;
348 G4cout << __METHOD_NAME__
349 <<
"Skipping further coordinate updates without use of map" << G4endl;
General exception with possible name of object and message.
static BDSGlobalConstants * Instance()
Access method.
G4bool ShouldApplyToPrimary(G4double momentum, G4int turnstaken)
Decides whether or not this should be applied. Can add more.
void GetThisTurn(G4double &x, G4double &px, G4double &y, G4double &py, G4double &pz, G4int turnstaken)
Return the coordinates for this turn.
BDSPTCOneTurnMap()=delete
Default constructor.
void UpdateCoordinates(G4ThreeVector localPosition, G4ThreeVector localMomentum, G4int turnstaken)
Update coordinates if the last turn is greater than the number of turns taken.
void SetInitialPrimaryCoordinates(const BDSParticleCoordsFullGlobal &coords, G4bool offsetS0)
Load initial coordinates where the beam started and convert to PTC coordinates.
A set of particle coordinates in both local and global.
Wrapper for particle definition.
G4double Mass() const
Accessor.
G4double Momentum() const
Accessor.
static G4bool hasScatteredThisTurn
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)