BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSTeleporter.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2022.
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 "BDSAcceleratorComponent.hh"
20#include "BDSBeamline.hh"
21#include "BDSBeamlineElement.hh"
22#include "BDSDebug.hh"
23#include "BDSException.hh"
24#include "BDSFieldBuilder.hh"
25#include "BDSFieldInfo.hh"
26#include "BDSGlobalConstants.hh"
27#include "BDSSamplerPlane.hh"
28#include "BDSTeleporter.hh"
29#include "BDSUtilities.hh"
30
31#include "globals.hh" //G4 global constants & types
32#include "G4Box.hh"
33#include "G4LogicalVolume.hh"
34#include "G4ThreeVector.hh"
35#include "G4Transform3D.hh"
36#include "G4UserLimits.hh"
37
38#include <cmath>
39#include <string>
40
41
42BDSTeleporter::BDSTeleporter(const G4double length,
43 const G4double horizontalWidthIn,
44 BDSFieldInfo* vacuumFieldInfoIn):
45 BDSAcceleratorComponent("teleporter", length, 0, "teleporter"),
46 horizontalWidth(horizontalWidthIn),
47 vacuumFieldInfo(vacuumFieldInfoIn)
48{;}
49
51{
52 // We don't use BDSAcceleratorComponent::Build() so we can control the user limits
53 // to limit the step length in the volume.
55 // set user limits for container & visual attributes
56 if(containerLogicalVolume)
57 {
58 // user limits
59 auto defaultUL = BDSGlobalConstants::Instance()->DefaultUserLimits();
60 //copy the default and update with the length of the object rather than the default 1m
61 G4UserLimits* ul = new G4UserLimits(*defaultUL);
62 ul->SetMaxAllowedStep(1.1*chordLength);
64
65 containerLogicalVolume->SetUserLimits(ul);
66 containerLogicalVolume->SetVisAttributes(BDSGlobalConstants::Instance()->ContainerVisAttr());
67 }
69 containerLogicalVolume,
70 true);
71}
72
74{
75 containerSolid = new G4Box(name+"_container_solid",
76 horizontalWidth * 0.5,
77 horizontalWidth * 0.5,
78 chordLength*0.5);
79 containerLogicalVolume = new G4LogicalVolume(containerSolid,
81 name + "_container_lv");
82
83 // register extents with BDSGeometryComponent base class
85}
86
87G4Transform3D BDS::CalculateTeleporterDelta(const BDSBeamline* beamline,
88 G4double& teleporterLength)
89{
90 if (beamline->empty())
91 {// can't do anything for an empty beam line
92 teleporterLength = 0;
93 return G4Transform3D();
94 }
95
96 // get position of last item in beamline
97 // and then calculate necessary offset teleporter should apply
98 // remember beam line could have finite offset and rotation to start with
99 auto firstElement = beamline->front();
100 auto lastElement = beamline->back();
101 G4ThreeVector lastItemPosition = lastElement->GetReferencePositionEnd();
102 G4ThreeVector firstItemPosition = firstElement->GetReferencePositionStart();
103 G4ThreeVector positionDelta = firstItemPosition - lastItemPosition;
104
105 // we must subtract off the required padding length from the teleporter
106 // delta 3-vector (note, along the axis of the beam line at the end)
107 const G4double sL = BDSSamplerPlane::ChordLength();
108 const G4double pL = beamline->PaddingLength();
109
110 // unit z direction at end of current beam line
111 G4ThreeVector lastItemUnitDir = G4ThreeVector(0,0,1).transform(*(lastElement->GetReferenceRotationEnd()));
112
113 // project the length of the position delta onto the beam line direction.
114 G4double rawLength = positionDelta.dot(lastItemUnitDir);
115
116 // minimum space for the circular mechanics are:
117 // 1x terminator with sampler chord length
118 // 1x teleporter with (minimum) 1x sampler chord length
119 // 3x padding length
120 G4double minimumRequiredSpace = 2*sL + 3*pL;
121
122 if (rawLength > 1*CLHEP::m)
123 {
124 std::string msg = "\nError - the calculated teleporter delta is above 1m!\nThe teleporter was only intended for small shifts";
125 throw BDSException(__METHOD_NAME__, msg);
126 }
127 else if (rawLength < minimumRequiredSpace)
128 {// should protect against -ve length teleporter
129 std::string msg = "\nInsufficient space between the first and last elements\n";
130 msg += "in the beam line to fit the terminator and teleporter - these will not be built.\n";
131 msg += "Minimum space for circular mechanics is ";
132 msg += std::to_string( minimumRequiredSpace/CLHEP::um) + " um";
133 throw BDSException(__METHOD_NAME__, msg);
134 }
135
136 // update input reference variable (ie 2nd output variable)
137 teleporterLength = rawLength - (sL + 3*pL);
138 positionDelta -= lastItemUnitDir * (sL + 3*pL); // subtraction only in local z
139
140 auto firstItemRotation = firstElement->GetReferenceRotationStart();
141 auto lastItemRotation = lastElement->GetReferenceRotationEnd();
142 auto rotation = (*firstItemRotation) * (*lastItemRotation);
143
144 G4Transform3D result = G4Transform3D(rotation, positionDelta);
145
146 G4cout << "Calculating Teleporter delta" << G4endl;
147 G4cout << "Last item end position: " << lastItemPosition << " mm" << G4endl;
148 G4cout << "First item start position: " << firstItemPosition << " mm" << G4endl;
149 G4cout << "Teleporter delta (pos): " << positionDelta << " mm" << G4endl;
150 G4cout << "Rotation: " << rotation << G4endl;
151 return result;
152}
153
154BDSTeleporter::~BDSTeleporter()
155{
156 delete vacuumFieldInfo;
157}
Abstract class that represents a component of an accelerator.
const G4String name
Const protected member variable that may not be changed by derived classes.
static G4Material * emptyMaterial
Useful variable often used in construction.
G4double chordLength
Protected member variable that can be modified by derived classes.
G4ThreeVector GetReferencePositionEnd() const
Accessor.
A vector of BDSBeamlineElement instances - a beamline.
Definition: BDSBeamline.hh:61
BDSBeamlineElement * front() const
Return a reference to the first element.
Definition: BDSBeamline.hh:209
BDSBeamlineElement * back() const
Return a reference to the last element.
Definition: BDSBeamline.hh:211
static G4double PaddingLength()
Access the padding length between each element added to the beamline.
Definition: BDSBeamline.hh:233
G4bool empty() const
Iterator mechanics.
Definition: BDSBeamline.hh:175
General exception with possible name of object and message.
Definition: BDSException.hh:35
Holder for +- extents in 3 dimensions.
Definition: BDSExtent.hh:39
void RegisterFieldForConstruction(const BDSFieldInfo *info, G4LogicalVolume *logicalVolume, const G4bool propagateToDaughters=false, const BDSMagnetStrength *magnetStrengthForScaling=nullptr, const G4String &scalingKey="none")
static BDSFieldBuilder * Instance()
Singleton pattern accessor.
All info required to build complete field of any type.
Definition: BDSFieldInfo.hh:65
void RegisterUserLimits(G4UserLimits *userLimit)
void SetExtent(const BDSExtent &extIn)
Set extent.
static BDSGlobalConstants * Instance()
Access method.
static G4double ChordLength()
Access the sampler plane length in other classes.
BDSTeleporter()=delete
Private default constructor to force the use of the supplied one.
BDSFieldInfo * vacuumFieldInfo
Recipe for teleporter 'field'.
G4double horizontalWidth
The full horizontal width of the teleporter.
virtual void Build()
Overridden method from BDSAcceleratorComponent that dictates the construction.
virtual void BuildContainerLogicalVolume()
G4Transform3D CalculateTeleporterDelta(const BDSBeamline *beamline, G4double &teleporterLength)