20#include "BDSException.hh"
21#include "BDSGlobalConstants.hh"
22#include "BDSParticleCoordsFullGlobal.hh"
23#include "BDSParticleDefinition.hh"
24#include "BDSPTCOneTurnMap.hh"
25#include "BDSTrajectoryPrimary.hh"
26#include "BDSUtilities.hh"
30#include "CLHEP/Units/SystemOfUnits.h"
40 initialPrimaryMomentum(0),
49 referenceMomentum = designParticle->
Momentum();
50 mass = designParticle->
Mass();
53 G4cout << __METHOD_NAME__ <<
"Using map table " << filePath << G4endl;
54 std::ifstream infile(filePath);
56 {
throw BDSException(__METHOD_NAME__,
"Failed to read maptable: \"" + maptableFile +
"\"");}
60 G4double coefficient = 0;
62 G4int dimensionality = 0;
72 while (std::getline(infile, line))
74 if (line.at(0) ==
'@' || line.at(0) ==
'*' || line.at(0) ==
'$')
76 std::istringstream stream(line);
78 stream >> name >> coefficient >> nVector >> dimensionality >> totalOrder >>
79 nx >> npx >> ny >> npy >> ndeltaP >> nt;
81 PTCMapTerm term{coefficient, nx, npx, ny, npy, ndeltaP};
86 {xTerms.push_back(term);
break;}
88 {pxTerms.push_back(term);
break;}
90 {yTerms.push_back(term);
break;}
92 {pyTerms.push_back(term);
break;}
94 {deltaPTerms.push_back(term);
break;}
97 throw BDSException(__METHOD_NAME__,
"Unrecognised PTC term index - maptable file is perhaps malformed.");
103 G4cout << __METHOD_NAME__ <<
"> Loaded Map:" << maptableFile << G4endl;
108 G4bool beamOffsetS0In)
111 initialPrimaryMomentum = std::sqrt(std::pow(coords.local.totalEnergy, 2) - std::pow(mass, 2));
113 xLastTurn = coords.local.x / CLHEP::m;
114 pxLastTurn = coords.global.xp * initialPrimaryMomentum / referenceMomentum;
115 yLastTurn = coords.local.y / CLHEP::m;
116 pyLastTurn = coords.global.yp * initialPrimaryMomentum / referenceMomentum;
117 deltaPLastTurn = (initialPrimaryMomentum - referenceMomentum) / referenceMomentum;
119 turnsScattered.clear();
124 beamOffsetS0 = beamOffsetS0In;
136 G4double pxOut = 0.0;
137 G4double pyOut = 0.0;
138 G4double pzOut = 0.0;
139 G4double deltaPOut = 0.0;
151 if (lastTurnNumber < turnsTaken)
154 G4cout << __METHOD_NAME__ <<
"Applying Map: " << G4endl;
155 G4cout <<
"Before map application: " << G4endl;
156 G4cout <<
"xLastTurn = " << xLastTurn << G4endl;
157 G4cout <<
"pxLastTurn = " << pxLastTurn << G4endl;
158 G4cout <<
"yLastTurn = " << yLastTurn << G4endl;
159 G4cout <<
"pyLastTurn = " << pyLastTurn << G4endl;
162 lastTurnNumber = turnsTaken;
163 xOut = Evaluate(xTerms,
164 xLastTurn, pxLastTurn,
165 yLastTurn, pyLastTurn,
167 pxOut = Evaluate(pxTerms,
168 xLastTurn, pxLastTurn,
169 yLastTurn, pyLastTurn,
171 yOut = Evaluate(yTerms,
172 xLastTurn, pxLastTurn,
173 yLastTurn, pyLastTurn,
175 pyOut = Evaluate(pyTerms,
176 xLastTurn, pxLastTurn,
177 yLastTurn, pyLastTurn,
179 deltaPOut = Evaluate(deltaPTerms,
180 xLastTurn, pxLastTurn,
181 yLastTurn, pyLastTurn,
188 deltaPLastTurn = deltaPOut;
190 G4cout <<
"After map application: " << G4endl;
191 G4cout <<
"xOut = " << xOut << G4endl;
192 G4cout <<
"pxOut = " << pxOut << G4endl;
193 G4cout <<
"yOut = " << yOut << G4endl;
194 G4cout <<
"pyOut = " << pyOut << G4endl;
203 deltaPOut = deltaPLastTurn;
205 G4cout << __METHOD_NAME__ <<
"Returning Cached Values:" << G4endl;
206 G4cout <<
"xOut = " << xOut << G4endl;
207 G4cout <<
"pxOut = " << pxOut << G4endl;
208 G4cout <<
"yOut = " << yOut << G4endl;
209 G4cout <<
"pyOut = " << pyOut << G4endl;
220 pxOut *= referenceMomentum;
221 pyOut *= referenceMomentum;
224 pzOut = std::sqrt(std::pow(initialPrimaryMomentum, 2)
236 G4cout << __METHOD_NAME__ <<
"Converting PTC to BDSIM " << G4endl;
237 G4cout <<
"xOut = " << xOut << G4endl;
238 G4cout <<
"pxOut = " << pxOut << G4endl;
239 G4cout <<
"yOut = " << yOut << G4endl;
240 G4cout <<
"pyOut = " << pyOut << G4endl;
241 G4cout <<
"initialPrimaryMomentum = " << initialPrimaryMomentum << G4endl;
242 G4cout <<
"referenceMomentum = " << referenceMomentum << G4endl;
243 G4cout <<
"pzOut = " << pz << G4endl;
247G4double BDSPTCOneTurnMap::Evaluate(std::vector<PTCMapTerm>& terms,
252 G4double deltaP)
const
255 for (
const auto& term : terms)
257 result += (term.coefficient
258 * std::pow(x, term.nx)
259 * std::pow(px, term.npx)
260 * std::pow(y, term.ny)
261 * std::pow(py, term.npy)
262 * std::pow(deltaP, term.ndeltaP));
276 G4bool offsetBeamS0AndOnFirstTurn = beamOffsetS0 && turnsTaken == 2;
286 turnsScattered.count(turnsTaken);
290 if (didScatterThisTurn)
291 {turnsScattered.insert(turnsTaken);}
294 G4double ratioOffReference = std::abs((momentum - referenceMomentum) / referenceMomentum);
295 G4double tolerance = 0.05;
296 G4bool tooFarOffMomentum = ratioOffReference > tolerance;
298 G4bool should = !offsetBeamS0AndOnFirstTurn && !didScatterThisTurn && !tooFarOffMomentum;
301 G4cout << __METHOD_NAME__
302 <<
"scatteredThisTurn = " << BDS::BoolToString(didScatterThisTurn)
304 G4cout << __METHOD_NAME__
305 <<
"beamOffsetS0 = " << BDS::BoolToString(beamOffsetS0) << G4endl;
306 G4cout << __METHOD_NAME__ <<
"turnsTaken = " << turnsTaken << G4endl;
307 G4cout << __METHOD_NAME__ <<
"Is on first turn with S0 != 0?"
308 << BDS::BoolToString(offsetBeamS0AndOnFirstTurn) << G4endl;
309 G4cout << __METHOD_NAME__
310 <<
"tooFarOffMomentum = " << BDS::BoolToString(tooFarOffMomentum)
312 G4cout << __METHOD_NAME__ <<
"ShouldApply = " << BDS::BoolToString(should)
321 G4ThreeVector localMomentum,
324 if (lastTurnNumber < turnsTaken)
331 xLastTurn = localPosition.x() / CLHEP::m;
332 yLastTurn = localPosition.y() / CLHEP::m;
333 pxLastTurn = localMomentum.x() / referenceMomentum;
334 pyLastTurn = localMomentum.y() / referenceMomentum;
335 G4double totalMomentum = localMomentum.mag();
336 deltaPLastTurn = (totalMomentum - referenceMomentum) / referenceMomentum;
338 lastTurnNumber = turnsTaken;
340 G4cout << __METHOD_NAME__
341 <<
"Updating map coords without use of map:" << G4endl;
342 G4cout <<
"xLastTurn = " << xLastTurn << G4endl;
343 G4cout <<
"yLastTurn = " << yLastTurn << G4endl;
344 G4cout <<
"pxLastTurn = " << pxLastTurn << G4endl;
345 G4cout <<
"pyLastTurn = " << pyLastTurn << G4endl;
349 G4cout << __METHOD_NAME__
350 <<
"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)