BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSAcceleratorComponent.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 "BDSBeamPipeInfo.hh"
21#include "BDSDebug.hh"
22#include "BDSException.hh"
23#include "BDSFieldBuilder.hh"
24#include "BDSFieldInfo.hh"
25#include "BDSGlobalConstants.hh"
26#include "BDSMaterials.hh"
27#include "BDSTunnelInfo.hh"
28#include "BDSUtilities.hh"
29
30#include "G4AssemblyVolume.hh"
31#include "G4LogicalVolume.hh"
32#include "G4Material.hh"
33#include "G4ThreeVector.hh"
34#include "G4UserLimits.hh"
35
36#include <algorithm>
37#include <cmath>
38#include <string>
39
40G4Material* BDSAcceleratorComponent::emptyMaterial = nullptr;
41G4Material* BDSAcceleratorComponent::worldMaterial = nullptr;
46G4VisAttributes* BDSAcceleratorComponent::containerVisAttr = nullptr;
48
50 G4double arcLengthIn,
51 G4double angleIn,
52 const G4String& typeIn,
53 BDSBeamPipeInfo* beamPipeInfoIn,
54 const G4ThreeVector& inputFaceNormalIn,
55 const G4ThreeVector& outputFaceNormalIn,
56 BDSFieldInfo* fieldInfoIn):
57 BDSGeometryComponent(nullptr,nullptr),
58 name(nameIn),
59 arcLength(arcLengthIn),
60 type(typeIn),
61 angle(angleIn),
62 beamPipeInfo(beamPipeInfoIn),
63 endPieceBefore(nullptr),
64 endPieceAfter(nullptr),
65 userLimits(nullptr),
66 fieldInfo(fieldInfoIn),
67 copyNumber(-1), // -1 initialisation since it will be incremented when placed
68 inputFaceNormal(inputFaceNormalIn),
69 outputFaceNormal(outputFaceNormalIn)
70{
71#ifdef BDSDEBUG
72 G4cout << __METHOD_NAME__ << "(" << name << ")" << G4endl;
73#endif
74 // initialise static members
75 if (!emptyMaterial)
76 {
77 const auto globals = BDSGlobalConstants::Instance(); // shortcut
78 emptyMaterial = BDSMaterials::Instance()->GetMaterial(globals->EmptyMaterial());
79 worldMaterial = BDSMaterials::Instance()->GetMaterial(globals->WorldMaterial());
80 lengthSafety = globals->LengthSafety();
81 lengthSafetyLarge = globals->LengthSafetyLarge();
82 checkOverlaps = globals->CheckOverlaps();
83 sensitiveOuter = globals->SensitiveOuter();
84 sensitiveVacuum = globals->StoreELossVacuum();
85 containerVisAttr = BDSGlobalConstants::Instance()->ContainerVisAttr();
86 }
87
88 // Prevent negative length components.
89 if (arcLength < 0)
90 {
91 G4String message = "Negative length for component named \"" + name + "\" with length " + std::to_string(arcLength);
92 throw BDSException(__METHOD_NAME__, message);
93 }
94
95 // calculate the chord length if the angle is finite
96 if (BDS::IsFinite(angleIn))
97 {chordLength = 2.0 * arcLengthIn * std::sin(0.5*angleIn) / angleIn;}
98 else
99 {chordLength = arcLengthIn;}
100#ifdef BDSDEBUG
101 G4cout << __METHOD_NAME__ << "angle: " << angleIn << G4endl;
102 G4cout << __METHOD_NAME__ << "arc length: " << arcLengthIn << G4endl;
103 G4cout << __METHOD_NAME__ << "chord length: " << chordLength << G4endl;
104#endif
105
106 initialised = false;
107}
108
109BDSAcceleratorComponent::~BDSAcceleratorComponent()
110{
111 delete beamPipeInfo;
112 // Don't delete usersLimits as could be globals one. If not it'll be registered
113 // with BDSGeometryComponent
114}
115
117{
118 if (initialised)
119 {return;} // protect against duplicated initialisation and memory leaks
120#ifdef BDSDEBUG
121 G4cout << __METHOD_NAME__ << G4endl;
122#endif
123 Build();
124
125 // field construction must be done after all the geometry is constructed if the
126 // field is to propagate to the daughter volumes correctly.
127 if (fieldInfo)
128 {
130 containerLogicalVolume,
131 true);
132 }
133 initialised = true; // record that this component has been initialised
134}
135
137{
138 BuildContainerLogicalVolume(); // pure virtual provided by derived class
141 if (containerLogicalVolume)
142 {containerLogicalVolume->SetVisAttributes(containerVisAttr);}
143}
144
146{
147 fieldInfo = fieldInfoIn;
148}
149
151{
152 if (!BDS::IsFinite(angle))
153 {return 0;}
154 G4double bendingRadius = arcLength / angle;
155 G4double sagitta = bendingRadius - std::sqrt(std::pow(bendingRadius,2) - std::pow(chordLength, 2));
156 return sagitta;
157}
158
160{
161 G4ThreeVector zeroAngle = G4ThreeVector(0,0,-1);
162 G4ThreeVector cross = inputFaceNormal.cross(zeroAngle);
163 G4double det = cross.mag2();
164 return BDS::IsFinite(det); // if finite, there is an angle and if not, no angle
165}
166
168{
169 G4ThreeVector zeroAngle = G4ThreeVector(0,0,1);
170 G4ThreeVector cross = outputFaceNormal.cross(zeroAngle);
171 G4double det = cross.mag2();
172 return BDS::IsFinite(det);
173}
174
176{
177 // user limits
178 auto defaultUL = BDSGlobalConstants::Instance()->DefaultUserLimits();
179 //copy the default and update with the length of the object rather than the default 1m
180 G4UserLimits* ul = BDS::CreateUserLimits(defaultUL, std::max(chordLength, arcLength));
181 if (ul != defaultUL) // if it's not the default register it
182 {RegisterUserLimits(ul);}
183 userLimits = ul; // assign to member
184}
185
187{
188 if (!userLimits)
189 {return;}
190 if (containerLogicalVolume || containerAssembly)
191 {
192 if (containerIsAssembly && containerAssembly)
193 {AttachUserLimitsToAssembly(containerAssembly, userLimits);}
194 else if (containerLogicalVolume)
195 {containerLogicalVolume->SetUserLimits(userLimits);}
196 }
197}
198
200{
201 // get full set minus ones marked to be excluded completely from biasing
202 std::set<G4LogicalVolume*> result = GetAllBiasingVolumes();
203
204 for (auto lv : acceleratorVacuumLV)
205 {result.erase(lv);}
206 return result;
207}
208
210{
211 if (fieldInfo)
212 {fieldInfo->SetUsePlacementWorldTransform(true);}
213}
BDSFieldInfo * fieldInfo
Recipe for field that could overlay this whole component.
G4UserLimits * userLimits
Cache of user limits.
G4bool AngledInputFace() const
Whether the face normal is angled at all w.r.t. the incoming / outgoing reference trajectory.
G4double Sagitta() const
Calculate the sagitta - ie the distance between the chord and the arc at the centre.
G4ThreeVector outputFaceNormal
Output face unit normal vector in outgoing reference coordinate frame.
G4ThreeVector inputFaceNormal
Input face unit normal vector in incoming reference coordinate frame.
const G4double arcLength
Const protected member variable that may not be changed by derived classes.
const G4String name
Const protected member variable that may not be changed by derived classes.
static G4Material * emptyMaterial
Useful variable often used in construction.
static G4bool sensitiveOuter
Useful variable often used in construction.
static G4double lengthSafety
Useful variable often used in construction.
static G4bool checkOverlaps
Useful variable often used in construction.
G4double angle
Protected member variable that can be modified by derived classes.
virtual std::set< G4LogicalVolume * > GetAcceleratorMaterialLogicalVolumes() const
Return a set of logical volumes excluding the ones in the 'vacuum' set.
static G4Material * worldMaterial
Useful variable often used in construction.
BDSAcceleratorComponent()=delete
virtual void BuildContainerLogicalVolume()=0
void SetField(BDSFieldInfo *fieldInfoIn)
Set the field definition for the whole component.
virtual void AttachUserLimits() const
Doesn't change member variables, but may change their contents.
G4double chordLength
Protected member variable that can be modified by derived classes.
G4bool AngledOutputFace() const
Whether the face normal is angled at all w.r.t. the incoming / outgoing reference trajectory.
std::set< G4LogicalVolume * > acceleratorVacuumLV
A set of logical volumes we classify as 'vacuum' for biasing purposes.
static G4VisAttributes * containerVisAttr
Useful variable often used in construction.
static G4bool sensitiveVacuum
Useful variable often used in construction.
BDSBeamPipeInfo * beamPipeInfo
Optional beam pipe recipe that is written out to the survey if it exists.
virtual void SetFieldUsePlacementWorldTransform()
Holder class for all information required to describe a beam pipe model.
General exception with possible name of object and message.
Definition: BDSException.hh:35
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
A generic geometry component for a bdsim model.
virtual std::set< G4LogicalVolume * > GetAllBiasingVolumes() const
Return all logical volumes that should be used for biasing minus any that are in the excluded set.
static void AttachUserLimitsToAssembly(G4AssemblyVolume *av, G4UserLimits *ul)
Utility function to apply user limits to an assembly volume as there's not interface.
void RegisterUserLimits(G4UserLimits *userLimit)
G4bool containerIsAssembly
True if the 'container' is really an assembly; false if an LV.
static BDSGlobalConstants * Instance()
Access method.
static BDSMaterials * Instance()
Singleton pattern access.
Definition: BDSMaterials.cc:38
G4Material * GetMaterial(G4String material) const
Get material by name.
G4UserLimits * CreateUserLimits(G4UserLimits *defaultUL, G4double length, G4double fraction=1.6)
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())