BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSAcceleratorComponent.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 "BDSAcceleratorComponent.hh"
19#include "BDSBeamPipeInfo.hh"
20#include "BDSDebug.hh"
21#include "BDSException.hh"
22#include "BDSFieldBuilder.hh"
23#include "BDSFieldInfo.hh"
24#include "BDSGlobalConstants.hh"
25#include "BDSMaterials.hh"
26#include "BDSTunnelInfo.hh"
27#include "BDSUtilities.hh"
28
29#include "G4AssemblyVolume.hh"
30#include "G4LogicalVolume.hh"
31#include "G4Material.hh"
32#include "G4ThreeVector.hh"
33#include "G4UserLimits.hh"
34
35#include <algorithm>
36#include <cmath>
37#include <string>
38
39G4Material* BDSAcceleratorComponent::emptyMaterial = nullptr;
40G4Material* BDSAcceleratorComponent::worldMaterial = nullptr;
45G4VisAttributes* BDSAcceleratorComponent::containerVisAttr = nullptr;
47
49 G4double arcLengthIn,
50 G4double angleIn,
51 const G4String& typeIn,
52 BDSBeamPipeInfo* beamPipeInfoIn,
53 const G4ThreeVector& inputFaceNormalIn,
54 const G4ThreeVector& outputFaceNormalIn,
55 BDSFieldInfo* fieldInfoIn):
56 BDSGeometryComponent(nullptr,nullptr),
57 name(nameIn),
58 arcLength(arcLengthIn),
59 type(typeIn),
60 angle(angleIn),
61 beamPipeInfo(beamPipeInfoIn),
62 endPieceBefore(nullptr),
63 endPieceAfter(nullptr),
64 userLimits(nullptr),
65 fieldInfo(fieldInfoIn),
66 copyNumber(-1), // -1 initialisation since it will be incremented when placed
67 inputFaceNormal(inputFaceNormalIn),
68 outputFaceNormal(outputFaceNormalIn)
69{
70 // initialise static members
71 if (!emptyMaterial)
72 {
73 const auto globals = BDSGlobalConstants::Instance(); // shortcut
74 emptyMaterial = BDSMaterials::Instance()->GetMaterial(globals->EmptyMaterial());
75 worldMaterial = BDSMaterials::Instance()->GetMaterial(globals->WorldMaterial());
76 lengthSafety = globals->LengthSafety();
77 lengthSafetyLarge = globals->LengthSafetyLarge();
78 checkOverlaps = globals->CheckOverlaps();
79 sensitiveOuter = globals->SensitiveOuter();
80 sensitiveVacuum = globals->StoreELossVacuum();
81 containerVisAttr = BDSGlobalConstants::Instance()->ContainerVisAttr();
82 }
83
84 // Prevent negative length components.
85 if (arcLength < 0)
86 {
87 G4String message = "Negative length for component named \"" + name + "\" with length " + std::to_string(arcLength);
88 throw BDSException(__METHOD_NAME__, message);
89 }
90
91 // calculate the chord length if the angle is finite
92 if (BDS::IsFinite(angleIn))
93 {chordLength = 2.0 * arcLengthIn * std::sin(0.5*angleIn) / angleIn;}
94 else
95 {chordLength = arcLengthIn;}
96#ifdef BDSDEBUG
97 G4cout << __METHOD_NAME__ << "angle: " << angleIn << G4endl;
98 G4cout << __METHOD_NAME__ << "arc length: " << arcLengthIn << G4endl;
99 G4cout << __METHOD_NAME__ << "chord length: " << chordLength << G4endl;
100#endif
101
102 initialised = false;
103}
104
105BDSAcceleratorComponent::~BDSAcceleratorComponent()
106{
107 delete beamPipeInfo;
108 // Don't delete usersLimits as could be globals one. If not it'll be registered
109 // with BDSGeometryComponent
110}
111
113{
114 if (initialised)
115 {return;} // protect against duplicated initialisation and memory leaks
116
117 Build();
118
119 // field construction must be done after all the geometry is constructed if the
120 // field is to propagate to the daughter volumes correctly.
121 if (fieldInfo)
122 {
124 containerLogicalVolume,
125 true);
126 }
127 initialised = true; // record that this component has been initialised
128}
129
131{
132 BuildContainerLogicalVolume(); // pure virtual provided by derived class
135 if (containerLogicalVolume)
136 {containerLogicalVolume->SetVisAttributes(containerVisAttr);}
137}
138
140{
141 fieldInfo = fieldInfoIn;
142}
143
145{
146 if (!BDS::IsFinite(angle))
147 {return 0;}
148 G4double bendingRadius = arcLength / angle;
149 G4double sagitta = bendingRadius - std::sqrt(std::pow(bendingRadius,2) - std::pow(chordLength, 2));
150 return sagitta;
151}
152
154{
155 G4ThreeVector zeroAngle = G4ThreeVector(0,0,-1);
156 G4ThreeVector cross = inputFaceNormal.cross(zeroAngle);
157 G4double det = cross.mag2();
158 return BDS::IsFinite(det); // if finite, there is an angle and if not, no angle
159}
160
162{
163 G4ThreeVector zeroAngle = G4ThreeVector(0,0,1);
164 G4ThreeVector cross = outputFaceNormal.cross(zeroAngle);
165 G4double det = cross.mag2();
166 return BDS::IsFinite(det);
167}
168
170{
171 // user limits
172 auto defaultUL = BDSGlobalConstants::Instance()->DefaultUserLimits();
173 //copy the default and update with the length of the object rather than the default 1m
174 G4UserLimits* ul = BDS::CreateUserLimits(defaultUL, std::max(chordLength, arcLength));
175 if (ul != defaultUL) // if it's not the default register it
176 {RegisterUserLimits(ul);}
177 userLimits = ul; // assign to member
178}
179
181{
182 if (!userLimits)
183 {return;}
184 if (containerLogicalVolume || containerAssembly)
185 {
186 if (containerIsAssembly && containerAssembly)
187 {AttachUserLimitsToAssembly(containerAssembly, userLimits);}
188 else if (containerLogicalVolume)
189 {containerLogicalVolume->SetUserLimits(userLimits);}
190 }
191}
192
194{
195 // get full set minus ones marked to be excluded completely from biasing
196 std::set<G4LogicalVolume*> result = GetAllBiasingVolumes();
197
198 for (auto lv : acceleratorVacuumLV)
199 {result.erase(lv);}
200 return result;
201}
202
204{
205 if (fieldInfo)
206 {fieldInfo->SetUsePlacementWorldTransform(true);}
207}
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.
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.
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.
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())