19#include "BDSAuxiliaryNavigator.hh"
22#include "BDSUtilities.hh"
24#include "G4Navigator.hh"
26#include "G4StepPoint.hh"
27#include "G4StepStatus.hh"
28#include "G4ThreeVector.hh"
38BDSAuxiliaryNavigator::BDSAuxiliaryNavigator():
39 globalToLocal(G4AffineTransform()),
40 localToGlobal(G4AffineTransform()),
41 globalToLocalCL(G4AffineTransform()),
42 localToGlobalCL(G4AffineTransform()),
43 bridgeVolumeWasUsed(false),
44 volumeMargin(0.1*CLHEP::mm)
49BDSAuxiliaryNavigator::~BDSAuxiliaryNavigator()
61void BDSAuxiliaryNavigator::ResetNavigatorStates()
69 const G4ThreeVector* direction,
70 const G4bool pRelativeSearch,
71 const G4bool ignoreDirection,
72 G4bool useCurvilinear)
const
74 bridgeVolumeWasUsed =
false;
75 G4Navigator* nav =
Navigator(useCurvilinear);
76 auto selectedVol = nav->LocateGlobalPointAndSetup(point, direction,
77 pRelativeSearch, ignoreDirection);
80 G4cout <<
"Point lookup " << selectedVol->GetName() << G4endl;
87 G4cout <<
"Trying bridge world" << G4endl;
89 bridgeVolumeWasUsed =
true;
90 selectedVol =
auxNavigatorCLB->LocateGlobalPointAndSetup(point, direction,
91 pRelativeSearch, ignoreDirection);
96 G4cout <<
"Found " << selectedVol->GetName() << G4endl;
100 else if (selectedVol ==
worldPV)
103 {
return selectedVol;}
104 G4ThreeVector globalDirUnit = direction->unit();
105 G4ThreeVector newPosition = point +
volumeMargin*globalDirUnit;
106 selectedVol = nav->LocateGlobalPointAndSetup(newPosition, direction,
107 pRelativeSearch, ignoreDirection);
109 G4cout << __METHOD_NAME__ <<
"New selected volume is: " << selectedVol->GetName() << G4endl;
114 {
return selectedVol;}
118 G4bool useCurvilinear)
const
121 G4StepPoint* preStepPoint = step->GetPreStepPoint();
122 G4StepPoint* posStepPoint = step->GetPostStepPoint();
126 G4ThreeVector prePosition = preStepPoint->GetPosition();
127 G4ThreeVector postPosition = posStepPoint->GetPosition();
128 G4ThreeVector position = (postPosition + prePosition)/2.0;
129 G4ThreeVector globalDirUnit = (postPosition - prePosition).unit();
131 G4Navigator* nav =
Navigator(useCurvilinear);
132 G4VPhysicalVolume* selectedVol = nav->LocateGlobalPointAndSetup(position, &globalDirUnit);
133 bridgeVolumeWasUsed =
false;
135 G4cout << __METHOD_NAME__ << selectedVol->GetName() << G4endl;
141 G4cout <<
"Trying bridge world" << G4endl;
143 bridgeVolumeWasUsed =
true;
144 selectedVol =
auxNavigatorCLB->LocateGlobalPointAndSetup(position, &globalDirUnit);
149 G4cout <<
"Found " << selectedVol->GetName() << G4endl;
153 else if (selectedVol ==
worldPV)
155 G4ThreeVector newPosition = position +
volumeMargin*globalDirUnit;
156 selectedVol = nav->LocateGlobalPointAndSetup(position, &globalDirUnit);
158 G4cout << __METHOD_NAME__ <<
"New selected volume is: " << selectedVol->GetName() << G4endl;
163 {
return selectedVol;}
167 G4bool useCurvilinear)
const
172 G4cout << __METHOD_NAME__ << selectedVol->GetName() << G4endl;
175 useCurvilinear ? InitialiseTransform(
false,
true) : InitialiseTransform(
true,
false);
177 G4ThreeVector pre =
GlobalToLocal(useCurvilinear).TransformPoint(step->GetPreStepPoint()->GetPosition());
178 G4ThreeVector pos =
GlobalToLocal(useCurvilinear).TransformPoint(step->GetPostStepPoint()->GetPosition());
179 return BDSStep(pre, pos, selectedVol);
183 const G4ThreeVector& globalDirection,
184 const G4double stepLength,
185 const G4bool useCurvilinear,
186 const G4double marginLength)
const
188 G4ThreeVector point = globalPosition;
195 G4ThreeVector globalDirUnit = globalDirection.unit();
196 if (stepLength > 1*CLHEP::mm)
197 {point += globalDirUnit * marginLength;}
198 else if (stepLength > 0)
199 {point += globalDirUnit * (stepLength * 0.5);}
208 G4cout << __METHOD_NAME__ << selectedVol->GetName() << G4endl;
211 useCurvilinear ? InitialiseTransform(
false,
true) : InitialiseTransform(
true,
false);
212 const G4AffineTransform& aff =
GlobalToLocal(useCurvilinear);
213 G4ThreeVector localPos = aff.TransformPoint(globalPosition);
214 G4ThreeVector localDir = aff.TransformAxis(globalDirection);
215 return BDSStep(localPos, localDir, selectedVol);
219 const G4bool useCurvilinear)
const
221 G4ThreeVector globalPositionV(globalPosition[0], globalPosition[1], globalPosition[2]);
226 const G4bool useCurvilinear)
const
228 InitialiseTransform(globalPosition);
229 return GlobalToLocal(useCurvilinear).TransformPoint(globalPosition);
233 G4bool useCurvilinear)
const
235 return GlobalToLocal(useCurvilinear).TransformPoint(globalPosition);
239 const G4bool useCurvilinear)
const
241 return GlobalToLocal(useCurvilinear).TransformAxis(globalAxis);
245 const G4double globalAxis[3],
246 const G4bool useCurvilinear)
const
248 G4ThreeVector globalPositionV(globalPosition[0], globalPosition[1], globalPosition[2]);
249 G4ThreeVector globalAxisV(globalAxis[0], globalAxis[1], globalAxis[2]);
254 const G4ThreeVector& globalAxis,
255 const G4bool useCurvilinear)
const
257 InitialiseTransform(globalPosition);
258 return GlobalToLocal(useCurvilinear).TransformAxis(globalAxis);
262 const G4bool useCurvilinear)
const
263{
return LocalToGlobal(useCurvilinear).TransformAxis(localAxis);}
266 const G4bool useCurvilinear)
const
268 const G4AffineTransform& lToG =
LocalToGlobal(useCurvilinear);
269 G4ThreeVector globalB = lToG.TransformAxis(localAxis.first);
270 G4ThreeVector globalE = lToG.TransformAxis(localAxis.second);
271 return std::make_pair(globalB, globalE);
275 const G4bool useCurvilinear)
const
276{
return LocalToGlobal(useCurvilinear).TransformPoint(localPosition);}
279 const G4ThreeVector& localAxis,
280 const G4bool useCurvilinear)
const
282 InitialiseTransform(globalPosition);
283 return LocalToGlobal(useCurvilinear).TransformAxis(localAxis);
287 const G4ThreeVector& localDirection,
288 const G4bool useCurvilinear)
const
290 const G4AffineTransform& aff =
LocalToGlobal(useCurvilinear);
291 G4ThreeVector globalPos = aff.TransformPoint(localPosition);
292 G4ThreeVector globalDir = aff.TransformAxis(localDirection);
293 return BDSStep(globalPos, globalDir);
297 const G4ThreeVector& localPosition,
298 const G4bool useCurvilinear)
const
300 InitialiseTransform(globalPosition);
301 return LocalToGlobal(useCurvilinear).TransformPoint(localPosition);
305 const G4ThreeVector& unitMomentum,
307 const G4bool useCurvilinearWorld)
309 return ConvertToLocal(position, unitMomentum, h, useCurvilinearWorld);
313 const G4ThreeVector& unitField,
314 const G4double angle,
315 const G4ThreeVector& position,
316 const G4ThreeVector& unitMomentum,
318 const G4bool useCurvilinearWorld,
322 G4double radiusOfCurvature = fieldArcLength / angle;
323 G4double radiusAtChord = radiusOfCurvature * std::cos(angle*0.5);
328 {local = local.
rotateZ(-tilt);}
336 G4double localZ = localPos.z();
340 G4ThreeVector localUnitF = unitField;
358 G4ThreeVector localXZPos = G4ThreeVector(localPos.x(), 0, localPos.z());
359 G4ThreeVector arcCentre = G4ThreeVector(-1*radiusAtChord,0,0);
360 G4ThreeVector partVectToCentre = arcCentre - localXZPos;
361 G4double partToCentreDist = partVectToCentre.mag();
364 G4double theta = std::acos(partVectToCentre.dot(arcCentre) / (arcCentre.mag() * partToCentreDist));
371 G4double sign = (angle < 0)? -1:1;
373 G4double CLXOffset = sign*partToCentreDist - radiusOfCurvature;
374 G4double distAlongS = theta * sign * radiusOfCurvature;
377 G4double chargeSign = 0;
378 chargeSign = (FCof < 0)? -1: 1;
380 G4double rotationAngle = theta*chargeSign;
382 G4ThreeVector localMomCL = localMom.rotate(rotationAngle, localUnitF);
383 G4ThreeVector localPosCL = G4ThreeVector(CLXOffset, localPos.y(), distAlongS);
385 return BDSStep(localPosCL, localMomCL);
388BDSStep BDSAuxiliaryNavigator::CurvilinearToGlobal(
const G4ThreeVector& localPosition,
389 const G4ThreeVector& localMomentum,
390 const G4bool useCurvilinearWorld)
395BDSStep BDSAuxiliaryNavigator::CurvilinearToGlobal(
const G4double fieldArcLength,
396 const G4ThreeVector& unitField,
397 const G4double angle,
398 const G4ThreeVector& CLPositionIn,
399 const G4ThreeVector& CLMomentumIn,
400 const G4bool useCurvilinearWorld,
404 G4double radiusOfCurvature = fieldArcLength / angle;
405 G4double radiusAtChord = radiusOfCurvature * std::cos(angle*0.5);
408 G4ThreeVector CLPosition = CLPositionIn;
409 G4ThreeVector CLMomentum = CLMomentumIn;
416 CLPosition = CLPosition.rotateZ(tilt);
417 CLMomentum = CLMomentum.rotateZ(tilt);
422 G4double sign = (angle < 0)? 1:-1;
424 G4ThreeVector localUnitF = unitField;
425 G4ThreeVector arcCentre = G4ThreeVector(sign*radiusAtChord,0,0);
427 G4double theta = CLPosition.z() / radiusOfCurvature;
429 G4double partToCentreDist = CLPosition.x() + radiusOfCurvature;
430 G4double localZ = partToCentreDist * std::sin(theta);
431 G4double localX = (partToCentreDist * std::cos(theta)) - radiusAtChord;
434 G4double chargeSign = 0;
435 chargeSign = (FCof < 0)? -1: 1;
438 G4double rotationAngle = std::abs(theta)*chargeSign;
440 {rotationAngle *= -1;}
442 G4ThreeVector localPosition = G4ThreeVector(localX, CLPosition.y(), localZ);
443 G4ThreeVector localMomentum = G4ThreeVector(CLMomentum).rotate(rotationAngle, localUnitF);;
447 localPosition = localPosition.rotateZ(tilt);
448 localMomentum = localMomentum.rotateZ(tilt);
462 return curvilinear ? globalToLocalCL : globalToLocal;
467 return curvilinear ? localToGlobalCL : localToGlobal;
470void BDSAuxiliaryNavigator::InitialiseTransform(
const G4bool massWorld,
471 const G4bool curvilinearWorld)
const
475 globalToLocal =
auxNavigator->GetGlobalToLocalTransform();
476 localToGlobal =
auxNavigator->GetLocalToGlobalTransform();
478 if (curvilinearWorld)
480 if (bridgeVolumeWasUsed)
493void BDSAuxiliaryNavigator::InitialiseTransform(
const G4ThreeVector& globalPosition)
const
495 auxNavigator->LocateGlobalPointAndSetup(globalPosition);
497 globalToLocal =
auxNavigator->GetGlobalToLocalTransform();
498 localToGlobal =
auxNavigator->GetLocalToGlobalTransform();
503void BDSAuxiliaryNavigator::InitialiseTransform(
const G4ThreeVector &globalPosition,
504 const G4ThreeVector &globalMomentum,
505 const G4double stepLength)
507 G4ThreeVector endPoint = globalPosition + globalMomentum.unit()*stepLength;
508 G4ThreeVector midPoint = (endPoint + globalPosition) / 2;
509 InitialiseTransform(midPoint);
G4ThreeVector ConvertToGlobal(const G4ThreeVector &localPosition, const G4bool useCurvilinear=true) const
static G4VPhysicalVolume * curvilinearBridgeWorldPV
Cache of world PV to test if we're getting the wrong volume for the transform.
G4VPhysicalVolume * LocateGlobalPointAndSetup(const G4ThreeVector &point, const G4ThreeVector *direction=nullptr, const G4bool pRelativeSearch=true, const G4bool ignoreDirection=true, G4bool useCurvilinear=true) const
A wrapper for the underlying static navigator instance located within this class.
BDSStep GlobalToCurvilinear(const G4double fieldArcLength, const G4ThreeVector &unitField, const G4double angle, const G4ThreeVector &position, const G4ThreeVector &unitMomentum, const G4double h, const G4bool useCurvilinearWorld, const G4double FCof, const G4double tilt=0)
G4Navigator * Navigator(G4bool curvilinear) const
Utility function to select appropriate navigator.
static G4VPhysicalVolume * worldPV
Cache of world PV to test if we're getting the wrong volume for the transform.
G4ThreeVector ConvertAxisToLocal(const G4ThreeVector &globalAxis, const G4bool useCurvilinear=true) const
static G4int numberOfInstances
BDSStep ConvertToGlobalStep(const G4ThreeVector &localPosition, const G4ThreeVector &localDirection, const G4bool useCurvilinear=true) const
static G4Navigator * auxNavigator
G4ThreeVector ConvertToLocalNoSetup(const G4ThreeVector &globalPosition, const G4bool useCurvilinear=true) const
Similar to above function but does NOT initialise the transforms.
G4ThreeVector ConvertAxisToGlobal(const G4ThreeVector &localAxis, const G4bool useCurvilinear=true) const
static G4Navigator * auxNavigatorCLB
static G4Navigator * auxNavigatorCL
const G4AffineTransform & LocalToGlobal(G4bool curvilinear) const
Utility function to select appropriate transform.
static G4VPhysicalVolume * curvilinearWorldPV
Cache of world PV to test if we're getting the wrong volume for the transform.
BDSStep ConvertToLocal(G4Step const *const step, G4bool useCurvilinear=true) const
const G4AffineTransform & GlobalToLocal(G4bool curvilinear) const
Utility function to select appropriate transform.
A simple class to represent the positions of a step.
G4ThreeVector PostStepPoint() const
Accessor.
BDSStep rotateZ(const G4double &angle)
Mirror function to G4ThreeVector::rotateZ(). Returns copy that's rotated.
G4ThreeVector PreStepPoint() const
Accessor.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())