18#include "BDSAuxiliaryNavigator.hh"
21#include "BDSUtilities.hh"
23#include "G4Navigator.hh"
25#include "G4StepPoint.hh"
26#include "G4StepStatus.hh"
27#include "G4ThreeVector.hh"
37BDSAuxiliaryNavigator::BDSAuxiliaryNavigator():
38 globalToLocal(G4AffineTransform()),
39 localToGlobal(G4AffineTransform()),
40 globalToLocalCL(G4AffineTransform()),
41 localToGlobalCL(G4AffineTransform()),
42 bridgeVolumeWasUsed(false),
43 volumeMargin(0.1*CLHEP::mm)
48BDSAuxiliaryNavigator::~BDSAuxiliaryNavigator()
60void BDSAuxiliaryNavigator::ResetNavigatorStates()
68 const G4ThreeVector* direction,
69 const G4bool pRelativeSearch,
70 const G4bool ignoreDirection,
71 G4bool useCurvilinear)
const
73 bridgeVolumeWasUsed =
false;
74 G4Navigator* nav =
Navigator(useCurvilinear);
75 auto selectedVol = nav->LocateGlobalPointAndSetup(point, direction,
76 pRelativeSearch, ignoreDirection);
79 G4cout <<
"Point lookup " << selectedVol->GetName() << G4endl;
86 G4cout <<
"Trying bridge world" << G4endl;
88 bridgeVolumeWasUsed =
true;
89 selectedVol =
auxNavigatorCLB->LocateGlobalPointAndSetup(point, direction,
90 pRelativeSearch, ignoreDirection);
95 G4cout <<
"Found " << selectedVol->GetName() << G4endl;
99 else if (selectedVol ==
worldPV)
102 {
return selectedVol;}
103 G4ThreeVector globalDirUnit = direction->unit();
104 G4ThreeVector newPosition = point +
volumeMargin*globalDirUnit;
105 selectedVol = nav->LocateGlobalPointAndSetup(newPosition, direction,
106 pRelativeSearch, ignoreDirection);
108 G4cout << __METHOD_NAME__ <<
"New selected volume is: " << selectedVol->GetName() << G4endl;
113 {
return selectedVol;}
117 G4bool useCurvilinear)
const
120 G4StepPoint* preStepPoint = step->GetPreStepPoint();
121 G4StepPoint* posStepPoint = step->GetPostStepPoint();
125 G4ThreeVector prePosition = preStepPoint->GetPosition();
126 G4ThreeVector postPosition = posStepPoint->GetPosition();
127 G4ThreeVector position = (postPosition + prePosition)/2.0;
128 G4ThreeVector globalDirUnit = (postPosition - prePosition).unit();
130 G4Navigator* nav =
Navigator(useCurvilinear);
131 G4VPhysicalVolume* selectedVol = nav->LocateGlobalPointAndSetup(position, &globalDirUnit);
132 bridgeVolumeWasUsed =
false;
134 G4cout << __METHOD_NAME__ << selectedVol->GetName() << G4endl;
140 G4cout <<
"Trying bridge world" << G4endl;
142 bridgeVolumeWasUsed =
true;
143 selectedVol =
auxNavigatorCLB->LocateGlobalPointAndSetup(position, &globalDirUnit);
148 G4cout <<
"Found " << selectedVol->GetName() << G4endl;
152 else if (selectedVol ==
worldPV)
154 G4ThreeVector newPosition = position +
volumeMargin*globalDirUnit;
155 selectedVol = nav->LocateGlobalPointAndSetup(position, &globalDirUnit);
157 G4cout << __METHOD_NAME__ <<
"New selected volume is: " << selectedVol->GetName() << G4endl;
162 {
return selectedVol;}
166 G4bool useCurvilinear)
const
171 G4cout << __METHOD_NAME__ << selectedVol->GetName() << G4endl;
174 useCurvilinear ? InitialiseTransform(
false,
true) : InitialiseTransform(
true,
false);
176 G4ThreeVector pre =
GlobalToLocal(useCurvilinear).TransformPoint(step->GetPreStepPoint()->GetPosition());
177 G4ThreeVector pos =
GlobalToLocal(useCurvilinear).TransformPoint(step->GetPostStepPoint()->GetPosition());
178 return BDSStep(pre, pos, selectedVol);
182 const G4ThreeVector& globalDirection,
183 const G4double stepLength,
184 const G4bool useCurvilinear,
185 const G4double marginLength)
const
187 G4ThreeVector point = globalPosition;
194 G4ThreeVector globalDirUnit = globalDirection.unit();
195 if (stepLength > 1*CLHEP::mm)
196 {point += globalDirUnit * marginLength;}
197 else if (stepLength > 0)
198 {point += globalDirUnit * (stepLength * 0.5);}
207 G4cout << __METHOD_NAME__ << selectedVol->GetName() << G4endl;
210 useCurvilinear ? InitialiseTransform(
false,
true) : InitialiseTransform(
true,
false);
211 const G4AffineTransform& aff =
GlobalToLocal(useCurvilinear);
212 G4ThreeVector localPos = aff.TransformPoint(globalPosition);
213 G4ThreeVector localDir = aff.TransformAxis(globalDirection);
214 return BDSStep(localPos, localDir, selectedVol);
218 const G4bool useCurvilinear)
const
220 G4ThreeVector globalPositionV(globalPosition[0], globalPosition[1], globalPosition[2]);
225 const G4bool useCurvilinear)
const
227 InitialiseTransform(globalPosition);
228 return GlobalToLocal(useCurvilinear).TransformPoint(globalPosition);
232 G4bool useCurvilinear)
const
234 return GlobalToLocal(useCurvilinear).TransformPoint(globalPosition);
238 const G4bool useCurvilinear)
const
240 return GlobalToLocal(useCurvilinear).TransformAxis(globalAxis);
244 const G4double globalAxis[3],
245 const G4bool useCurvilinear)
const
247 G4ThreeVector globalPositionV(globalPosition[0], globalPosition[1], globalPosition[2]);
248 G4ThreeVector globalAxisV(globalAxis[0], globalAxis[1], globalAxis[2]);
253 const G4ThreeVector& globalAxis,
254 const G4bool useCurvilinear)
const
256 InitialiseTransform(globalPosition);
257 return GlobalToLocal(useCurvilinear).TransformAxis(globalAxis);
261 const G4bool useCurvilinear)
const
262{
return LocalToGlobal(useCurvilinear).TransformAxis(localAxis);}
265 const G4bool useCurvilinear)
const
267 const G4AffineTransform& lToG =
LocalToGlobal(useCurvilinear);
268 G4ThreeVector globalB = lToG.TransformAxis(localAxis.first);
269 G4ThreeVector globalE = lToG.TransformAxis(localAxis.second);
270 return std::make_pair(globalB, globalE);
274 const G4bool useCurvilinear)
const
275{
return LocalToGlobal(useCurvilinear).TransformPoint(localPosition);}
278 const G4ThreeVector& localAxis,
279 const G4bool useCurvilinear)
const
281 InitialiseTransform(globalPosition);
282 return LocalToGlobal(useCurvilinear).TransformAxis(localAxis);
286 const G4ThreeVector& localDirection,
287 const G4bool useCurvilinear)
const
289 const G4AffineTransform& aff =
LocalToGlobal(useCurvilinear);
290 G4ThreeVector globalPos = aff.TransformPoint(localPosition);
291 G4ThreeVector globalDir = aff.TransformAxis(localDirection);
292 return BDSStep(globalPos, globalDir);
296 const G4ThreeVector& localPosition,
297 const G4bool useCurvilinear)
const
299 InitialiseTransform(globalPosition);
300 return LocalToGlobal(useCurvilinear).TransformPoint(localPosition);
304 const G4ThreeVector& unitMomentum,
306 const G4bool useCurvilinearWorld)
308 return ConvertToLocal(position, unitMomentum, h, useCurvilinearWorld);
312 const G4ThreeVector& unitField,
313 const G4double angle,
314 const G4ThreeVector& position,
315 const G4ThreeVector& unitMomentum,
317 const G4bool useCurvilinearWorld,
321 G4double radiusOfCurvature = fieldArcLength / angle;
322 G4double radiusAtChord = radiusOfCurvature * std::cos(angle*0.5);
327 {local = local.
rotateZ(-tilt);}
335 G4double localZ = localPos.z();
339 G4ThreeVector localUnitF = unitField;
357 G4ThreeVector localXZPos = G4ThreeVector(localPos.x(), 0, localPos.z());
358 G4ThreeVector arcCentre = G4ThreeVector(-1*radiusAtChord,0,0);
359 G4ThreeVector partVectToCentre = arcCentre - localXZPos;
360 G4double partToCentreDist = partVectToCentre.mag();
363 G4double theta = std::acos(partVectToCentre.dot(arcCentre) / (arcCentre.mag() * partToCentreDist));
370 G4double sign = (angle < 0)? -1:1;
372 G4double CLXOffset = sign*partToCentreDist - radiusOfCurvature;
373 G4double distAlongS = theta * sign * radiusOfCurvature;
376 G4double chargeSign = 0;
377 chargeSign = (FCof < 0)? -1: 1;
379 G4double rotationAngle = theta*chargeSign;
381 G4ThreeVector localMomCL = localMom.rotate(rotationAngle, localUnitF);
382 G4ThreeVector localPosCL = G4ThreeVector(CLXOffset, localPos.y(), distAlongS);
384 return BDSStep(localPosCL, localMomCL);
387BDSStep BDSAuxiliaryNavigator::CurvilinearToGlobal(
const G4ThreeVector& localPosition,
388 const G4ThreeVector& localMomentum,
389 const G4bool useCurvilinearWorld)
394BDSStep BDSAuxiliaryNavigator::CurvilinearToGlobal(
const G4double fieldArcLength,
395 const G4ThreeVector& unitField,
396 const G4double angle,
397 const G4ThreeVector& CLPositionIn,
398 const G4ThreeVector& CLMomentumIn,
399 const G4bool useCurvilinearWorld,
403 G4double radiusOfCurvature = fieldArcLength / angle;
404 G4double radiusAtChord = radiusOfCurvature * std::cos(angle*0.5);
407 G4ThreeVector CLPosition = CLPositionIn;
408 G4ThreeVector CLMomentum = CLMomentumIn;
415 CLPosition = CLPosition.rotateZ(tilt);
416 CLMomentum = CLMomentum.rotateZ(tilt);
421 G4double sign = (angle < 0)? 1:-1;
423 G4ThreeVector localUnitF = unitField;
424 G4ThreeVector arcCentre = G4ThreeVector(sign*radiusAtChord,0,0);
426 G4double theta = CLPosition.z() / radiusOfCurvature;
428 G4double partToCentreDist = CLPosition.x() + radiusOfCurvature;
429 G4double localZ = partToCentreDist * std::sin(theta);
430 G4double localX = (partToCentreDist * std::cos(theta)) - radiusAtChord;
433 G4double chargeSign = 0;
434 chargeSign = (FCof < 0)? -1: 1;
437 G4double rotationAngle = std::abs(theta)*chargeSign;
439 {rotationAngle *= -1;}
441 G4ThreeVector localPosition = G4ThreeVector(localX, CLPosition.y(), localZ);
442 G4ThreeVector localMomentum = G4ThreeVector(CLMomentum).rotate(rotationAngle, localUnitF);;
446 localPosition = localPosition.rotateZ(tilt);
447 localMomentum = localMomentum.rotateZ(tilt);
461 return curvilinear ? globalToLocalCL : globalToLocal;
466 return curvilinear ? localToGlobalCL : localToGlobal;
469void BDSAuxiliaryNavigator::InitialiseTransform(
const G4bool massWorld,
470 const G4bool curvilinearWorld)
const
474 globalToLocal =
auxNavigator->GetGlobalToLocalTransform();
475 localToGlobal =
auxNavigator->GetLocalToGlobalTransform();
477 if (curvilinearWorld)
479 if (bridgeVolumeWasUsed)
492void BDSAuxiliaryNavigator::InitialiseTransform(
const G4ThreeVector& globalPosition)
const
494 auxNavigator->LocateGlobalPointAndSetup(globalPosition);
496 globalToLocal =
auxNavigator->GetGlobalToLocalTransform();
497 localToGlobal =
auxNavigator->GetLocalToGlobalTransform();
502void BDSAuxiliaryNavigator::InitialiseTransform(
const G4ThreeVector &globalPosition,
503 const G4ThreeVector &globalMomentum,
504 const G4double stepLength)
506 G4ThreeVector endPoint = globalPosition + globalMomentum.unit()*stepLength;
507 G4ThreeVector midPoint = (endPoint + globalPosition) / 2;
508 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())