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