BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSIntegratorTeleporter.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 "BDSGlobalConstants.hh"
21#include "BDSIntegratorTeleporter.hh"
22#include "BDSPTCOneTurnMap.hh"
23#include "BDSStep.hh"
24
25#include "globals.hh" // geant4 types / globals
26#include "G4ThreeVector.hh"
27#include "G4Transform3D.hh"
28
29BDSIntegratorTeleporter::BDSIntegratorTeleporter(G4Mag_EqRhs* eqOfMIn,
30 G4Transform3D transformIn,
31 G4double teleporterLengthIn,
32 BDSPTCOneTurnMap* oneTurnMapIn):
33 BDSIntegratorMag(eqOfMIn,6),
34 transform(transformIn),
35 dPos(transform.getTranslation()),
36 teleporterLength(teleporterLengthIn),
37 oneTurnMap(oneTurnMapIn)
38{
39 threeDMethod = BDSGlobalConstants::Instance()->TeleporterFullTransform();
40}
41
42BDSIntegratorTeleporter::~BDSIntegratorTeleporter()
43{
44 delete oneTurnMap;
45}
46
47void BDSIntegratorTeleporter::Stepper(const G4double yIn[],
48 const G4double /*dxdy*/[],
49 const G4double h,
50 G4double yOut[],
51 G4double yErr[])
52{
53 for(G4int i = 0; i < nVariables; i++)
54 {yErr[i] = 0;}
55 SetDistChord(0);
56
57 G4int turnsTaken = BDSGlobalConstants::Instance()->TurnsTaken();
58#ifdef BDSDEBUG
59 G4cout << __METHOD_NAME__ << "turnsTaken: " << turnsTaken << G4endl;
60#endif
61
62 G4double lengthFraction = h / teleporterLength;
63
64 // has to have completed at least 1 turn and be going forwards
65 // must test for this to avoid backwards going particles getting stuck
66 // also don't apply if for whatever reason the step length is less than half
67 // the teleporter length -> this ensures only applied once
68 if (turnsTaken > 0 && yIn[5] > 0 && lengthFraction > 0.51 && lengthFraction < 1.1)
69 {
70 G4ThreeVector globalPos = G4ThreeVector(yIn[0], yIn[1], yIn[2]);
71 G4ThreeVector globalMom = G4ThreeVector(yIn[3], yIn[4], yIn[5]);
72
73 G4ThreeVector globalPosAfter;
74 G4ThreeVector globalMomAfter;
75 G4bool shouldApplyOTMToPrimary = false;
76
77 if (oneTurnMap)
78 {shouldApplyOTMToPrimary = oneTurnMap->ShouldApplyToPrimary(globalMom.mag(), turnsTaken);}
79
80 if (oneTurnMap && currentTrackIsPrimary && shouldApplyOTMToPrimary)
81 {
82#ifdef BDSDEBUG
83 G4cout << __METHOD_NAME__ << "applying 1 turn map" << G4endl;
84#endif
85
86 // pass by reference, returning BDSIM coordinates:
87 G4double x, px, y, py, pz;
88 oneTurnMap->GetThisTurn(x, px, y, py, pz, turnsTaken);
89
90 // Get this for the sake of local.z, and also setting some
91 // internal state necessary for using ConvertToGlobalStep.
92 BDSStep localPosMom = ConvertToLocal(globalPos, globalMom, h, false, thinElementLength);
93 G4ThreeVector localPosition = localPosMom.PreStepPoint();
94 G4ThreeVector outLocalMomentum = G4ThreeVector(px, py, pz);
95 G4ThreeVector outLocalPosition = G4ThreeVector(x, y, localPosition.z());
96 BDSStep globalPosDir = ConvertToGlobalStep(outLocalPosition, outLocalMomentum, false);
97
98 // Set the output positions and momenta, including the threeDMethod from below...
99 globalPosAfter = globalPosDir.PreStepPoint() + dPos;
100 globalMomAfter = globalPosDir.PostStepPoint().transform(transform.getRotation());
101#ifdef BDSDEBUG
102 G4cout << __METHOD_NAME__ << "applied the map." << G4endl;
103 G4cout << "Applying teleporter offset: " << G4endl;
104#endif
105 }
106 else if (threeDMethod)
107 { // new method - full tranfsorm3D - works in 3d
108 // with beam line offset / rotation
109#ifdef BDSDEBUG
110 G4cout << __METHOD_NAME__ << "teleporter 3d method" << G4endl;
111#endif
112 globalPosAfter = globalPos + dPos;
113 globalMomAfter = globalMom.transform(transform.getRotation());
114 }
115 else
116 {// old method - only works with beam line pointing in global (0,0,1)
117 // global to local
118 BDSStep localPosMom = ConvertToLocal(globalPos, globalMom, h, false, thinElementLength);
119 G4ThreeVector localPosition = localPosMom.PreStepPoint();
120 G4ThreeVector localMomentum = localPosMom.PostStepPoint();
121 G4ThreeVector localPositionAfter;
122 G4ThreeVector localMomentumAfter;
123 G4ThreeVector posDelta = transform.getTranslation();
124 localPositionAfter[0] = localPosition.x() - posDelta.x();
125 localPositionAfter[1] = localPosition.y() - posDelta.y();
126 localPositionAfter[2] = localPosition.z() + h;
127
128 BDSStep globalPosDir = ConvertToGlobalStep(localPositionAfter, localMomentum, false);
129 globalPosAfter = globalPosDir.PreStepPoint();
130 globalMomAfter = globalPosDir.PostStepPoint();
131 }
132
133 // Whichever method gets used above, if the OTM is valid and the
134 // particle is a primary but not applicable according to
135 // ShouldApplyToPrimary, we should update the cached coordinates within
136 // the OTM regardless.
137 if (oneTurnMap && currentTrackIsPrimary && !shouldApplyOTMToPrimary)
138 {
139#ifdef BDSDEBUG
140 G4cout << "Updating coordinates in place of map application..." << G4endl;
141#endif
142 BDSStep localPosMom = ConvertToLocal(globalPosAfter, globalMomAfter, h,
143 false, thinElementLength);
144 G4ThreeVector localPosition = localPosMom.PreStepPoint();
145 G4ThreeVector localMomentum = localPosMom.PostStepPoint();
146 oneTurnMap->UpdateCoordinates(localPosition, localMomentum,
147 turnsTaken);
148 }
149
150 // Update the particle coordinates for whichever of the methods
151 // above was used.
152 for (G4int i = 0; i < 3; i++)
153 {
154 yOut[i] = globalPosAfter[i];
155 yOut[i+3] = globalMomAfter[i];
156 }
157 }
158 else
159 {
160 // move particle to other side without affecting anything
161 yOut[0] = yIn[0];
162 yOut[1] = yIn[1];
163 if (yIn[5] > 0) // going forwards
164 {yOut[2] = yIn[2] + h;}
165 else // going backwards
166 {yOut[2] = yIn[2] - h;}
167 yOut[3] = yIn[3];
168 yOut[4] = yIn[4];
169 yOut[5] = yIn[5];
170 }
171
172#ifdef BDSDEBUG
173 G4ThreeVector inA = G4ThreeVector(yIn[0], yIn[1], yIn[2]);
174 G4ThreeVector inB = G4ThreeVector(yIn[3], yIn[4], yIn[5]);
175 G4ThreeVector outA = G4ThreeVector(yOut[0], yOut[1], yOut[2]);
176 G4ThreeVector outB = G4ThreeVector(yOut[3], yOut[4], yOut[5]);
177 BDSStep localPosMomIn = ConvertToLocal(inA, inB, h, false, thinElementLength);
178 BDSStep localPosMomOut = ConvertToLocal(outA, outB, h, false, thinElementLength);
179 G4ThreeVector localPosIn = localPosMomIn.PreStepPoint();
180 G4ThreeVector localMomIn = localPosMomIn.PostStepPoint();
181 G4ThreeVector localPosOut = localPosMomOut.PreStepPoint();
182 G4ThreeVector localMomOut = localPosMomOut.PostStepPoint();
183 std::ios_base::fmtflags ff = G4cout.flags(); // save cout flags
184 G4cout.precision(10);
185 G4cout << __METHOD_NAME__ << G4endl;
186 G4cout << "h (step length) (metres) " << h / CLHEP::m << G4endl;
187 G4cout << "Global Input (x, y, z) " << inA / CLHEP::m << G4endl;
188 G4cout << "Global Input (px, py, pz) " << inB / CLHEP::m << G4endl;
189 G4cout << "Global Output (x, y, z) " << outA / CLHEP::m << G4endl;
190 G4cout << "Global Output (px, py, pz) " << outB / CLHEP::m << G4endl;
191 G4cout << "Local Input (x, y, z) " << localPosIn / CLHEP::m << G4endl;
192 G4cout << "Local Input (px, py, pz) " << localMomIn / CLHEP::m << G4endl;
193 G4cout << "Local Output (x, y, z) " << localPosOut / CLHEP::m << G4endl;
194 G4cout << "Local Output (px, py, pz) " << localMomOut / CLHEP::m << G4endl;
195 G4cout.flags(ff); // reset cout flags
196#endif
197}
BDSStep ConvertToGlobalStep(const G4ThreeVector &localPosition, const G4ThreeVector &localDirection, const G4bool useCurvilinear=true) const
BDSStep ConvertToLocal(G4Step const *const step, G4bool useCurvilinear=true) const
static BDSGlobalConstants * Instance()
Access method.
Common functionality to BDSIM integrators.
void SetDistChord(G4double distChordIn)
Setter for distChord to private member.
static G4double thinElementLength
static G4bool currentTrackIsPrimary
const G4int nVariables
Cache of the number of variables.
G4bool threeDMethod
Whether to use full 3D transform.
Class to load and use PTC 1 turn map.
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.
void UpdateCoordinates(G4ThreeVector localPosition, G4ThreeVector localMomentum, G4int turnstaken)
Update coordinates if the last turn is greater than the number of turns taken.
A simple class to represent the positions of a step.
Definition: BDSStep.hh:33
G4ThreeVector PostStepPoint() const
Accessor.
Definition: BDSStep.hh:43
G4ThreeVector PreStepPoint() const
Accessor.
Definition: BDSStep.hh:42