BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSBeamlineElement.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2023.
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 "BDSBeamlineElement.hh"
20
21#include "BDSAcceleratorComponent.hh"
22#include "BDSBeamline.hh"
23#include "BDSExtentGlobal.hh"
24#include "BDSSamplerPlane.hh"
25#include "BDSSamplerType.hh"
26#include "BDSTiltOffset.hh"
27#include "BDSUtilities.hh"
28
29#include "G4AssemblyVolume.hh"
30#include "G4PVPlacement.hh"
31#include "G4RotationMatrix.hh"
32#include "G4String.hh"
33#include "G4ThreeVector.hh"
34#include "G4Types.hh"
35
36#include <algorithm>
37#include <ostream>
38#include <set>
39#include <string>
40
41BDSBeamlineElement::BDSBeamlineElement(BDSAcceleratorComponent* componentIn,
42 const G4ThreeVector& positionStartIn,
43 const G4ThreeVector& positionMiddleIn,
44 const G4ThreeVector& positionEndIn,
45 G4RotationMatrix* rotationStartIn,
46 G4RotationMatrix* rotationMiddleIn,
47 G4RotationMatrix* rotationEndIn,
48 const G4ThreeVector& referencePositionStartIn,
49 const G4ThreeVector& referencePositionMiddleIn,
50 const G4ThreeVector& referencePositionEndIn,
51 G4RotationMatrix* referenceRotationStartIn,
52 G4RotationMatrix* referenceRotationMiddleIn,
53 G4RotationMatrix* referenceRotationEndIn,
54 G4double sPositionStartIn,
55 G4double sPositionMiddleIn,
56 G4double sPositionEndIn,
57 BDSTiltOffset* tiltOffsetIn,
58 BDSSamplerInfo* samplerInfoIn,
59 G4int indexIn):
60 component(componentIn),
61 positionStart(positionStartIn), positionMiddle(positionMiddleIn), positionEnd(positionEndIn),
62 rotationStart(rotationStartIn), rotationMiddle(rotationMiddleIn), rotationEnd(rotationEndIn),
63 referencePositionStart(referencePositionStartIn),
64 referencePositionMiddle(referencePositionMiddleIn),
65 referencePositionEnd(referencePositionEndIn),
66 referenceRotationStart(referenceRotationStartIn),
67 referenceRotationMiddle(referenceRotationMiddleIn),
68 referenceRotationEnd(referenceRotationEndIn),
69 sPositionStart(sPositionStartIn), sPositionMiddle(sPositionMiddleIn), sPositionEnd(sPositionEndIn),
70 tiltOffset(tiltOffsetIn),
71 samplerInfo(samplerInfoIn),
72 samplerPlacementTransform(nullptr),
73 index(indexIn)
74{
75 componentIn->IncrementCopyNumber(); // increase copy number (starts at -1)
76 copyNumber = componentIn->GetCopyNumber();
78 placementName = componentIn->GetName() + "_" + std::to_string(copyNumber);
79
80 // create the placement transform from supplied rotation matrices and vector
83
84 // calculate sampler central position slightly away from end position of element.
85 auto samplerType = GetSamplerType();
86 if (samplerType == BDSSamplerType::plane)
87 {
88 G4ThreeVector dZLocal = G4ThreeVector(0,0,1);
89 // if we have a sampler, add on the thickness of the sampler to the padding
91 dZLocal.transform(*referenceRotationEnd);
92 G4ThreeVector samplerPosition = referencePositionEnd + dZLocal;
93 samplerPlacementTransform = new G4Transform3D(*referenceRotationEnd, samplerPosition);
94 }
95 else if (samplerType == BDSSamplerType::cylinder)
97}
98
99BDSBeamlineElement::~BDSBeamlineElement()
100{
101 delete rotationStart;
102 delete rotationMiddle;
103 delete rotationEnd;
107 delete placementTransform;
110 delete samplerInfo;
111}
112
113std::set<G4VPhysicalVolume*> BDSBeamlineElement::GetPVsFromAssembly(G4AssemblyVolume* av)
114{
115 // this is obtuse because of the lack of access in G4Assembly
116 std::vector<G4VPhysicalVolume*> allPlacementsFromThisAssembly;
117 auto it = av->GetVolumesIterator();
118 for (G4int i = 0; i < (G4int)av->TotalImprintedVolumes(); it++, i++)
119 {allPlacementsFromThisAssembly.push_back(*it);}
120 std::set<G4VPhysicalVolume*> result(allPlacementsFromThisAssembly.begin(), allPlacementsFromThisAssembly.end());
121 return result;
122}
123
124std::set<G4VPhysicalVolume*> BDSBeamlineElement::PlaceElement(const G4String& pvName,
125 G4VPhysicalVolume* motherPV,
126 G4bool useCLPlacementTransform,
127 G4int pvCopyNumber,
128 G4bool checkOverlaps) const
129{
130 G4Transform3D* pvTransform = GetPlacementTransform();
131 if (useCLPlacementTransform)
132 {pvTransform = GetPlacementTransformCL();}
133
134 std::set<G4VPhysicalVolume*> result;
136 {
137 G4AssemblyVolume* av = component->GetContainerAssemblyVolume();
138 auto existingPVSet = GetPVsFromAssembly(av);
139 av->MakeImprint(motherPV->GetLogicalVolume(),
140 *pvTransform,
141 pvCopyNumber,checkOverlaps);
142
143 // need to get pvs before and afterwards and o the difference
144 auto updatedPVSet = GetPVsFromAssembly(av);
145 std::set_difference(updatedPVSet.begin(), updatedPVSet.end(),
146 existingPVSet.begin(), existingPVSet.end(),
147 std::inserter(result, result.begin()));
148 }
149 else
150 {
151 G4LogicalVolume* lv = component->GetContainerLogicalVolume();
152 result.insert(new G4PVPlacement(*pvTransform, // placement transform
153 pvName, // placement name
154 lv, // volume to be placed
155 motherPV, // volume to place it in
156 false, // no boolean operation
157 pvCopyNumber, // copy number
158 checkOverlaps)); // overlap checking
159 }
160 return result;
161}
162
164{
167 return extG;
168}
169
171{
172 G4ThreeVector inputFNLocal = component->InputFaceNormal();
173 if (!tiltOffset) // no tilt so the same as local
174 {return inputFNLocal;}
175 else
176 {
177 G4ThreeVector inputFNGlobal = inputFNLocal.rotateZ(tiltOffset->GetTilt());
178 return inputFNGlobal;
179 }
180}
181
183{
184 G4ThreeVector outputFNLocal = component->OutputFaceNormal();
185 if (!tiltOffset) // no tilt so the same as local
186 {return outputFNLocal;}
187 else
188 {
189 G4ThreeVector outputFNGlobal = outputFNLocal.rotateZ(-tiltOffset->GetTilt());
190 return outputFNGlobal;
191 }
192}
193
194void BDSBeamlineElement::UpdateSamplerPlacementTransform(const G4Transform3D& tranfsormIn)
195{
197 samplerPlacementTransform = new G4Transform3D(tranfsormIn);
198}
199
200std::ostream& operator<< (std::ostream& out, BDSBeamlineElement const &e)
201{
202 out << "Beamline element: " << e.component->GetName() << G4endl;
203 out << "Start, middle & end position: "
204 << e.GetPositionStart() << " " << e.GetPositionMiddle() << " " << e.GetPositionEnd() << G4endl
205 << "Start, middle & end rotation: "
206 << *(e.GetRotationStart()) << " " << *(e.GetRotationMiddle()) << " " << *(e.GetRotationEnd()) << G4endl
207 << "Start, middle & end s position: "
208 << e.GetSPositionStart() << " " << e.GetSPositionMiddle() << " " << e.GetSPositionEnd() << G4endl;
209
210 return out;
211}
212
213G4bool BDSBeamlineElement::Overlaps(const BDSBeamlineElement* otherElement) const
214{
217 BDSExtentGlobal otherGlobal = BDSExtentGlobal(otherElement->GetAcceleratorComponent()->GetExtent(),
218 *(otherElement->GetPlacementTransform()));
219
220 return thisGlobal.Overlaps(otherGlobal);
221}
222
223
Abstract class that represents a component of an accelerator.
virtual G4String GetName() const
The name of the component without modification.
G4ThreeVector OutputFaceNormal() const
G4int GetCopyNumber() const
Get the number of times this component has been copied.
G4ThreeVector InputFaceNormal() const
void IncrementCopyNumber()
Increment (+1) the number of times this component has been copied.
A class that holds a fully constructed BDSAcceleratorComponent as well as any information relevant to...
G4ThreeVector OutputFaceNormal() const
Return face normal accounting for placement tilt of this component.
G4ThreeVector GetPositionMiddle() const
Accessor.
G4RotationMatrix * referenceRotationMiddle
BDSAcceleratorComponent * component
The accelerator component.
G4ThreeVector GetPositionEnd() const
Accessor.
BDSTiltOffset * tiltOffset
The tilt and offset this element was constructed with. Default is nullptr.
BDSSamplerType GetSamplerType() const
Accessor.
G4Transform3D * placementTransform
G4RotationMatrix * GetRotationEnd() const
Accessor.
std::set< G4VPhysicalVolume * > PlaceElement(const G4String &pvName, G4VPhysicalVolume *containerPV, G4bool useCLPlacementTransform, G4int copyNumber, G4bool checkOverlaps) const
G4ThreeVector GetPositionStart() const
Accessor.
void UpdateSamplerPlacementTransform(const G4Transform3D &tranfsormIn)
G4ThreeVector referencePositionEnd
G4ThreeVector InputFaceNormal() const
Return face normal accounting for placement tilt of this component.
G4Transform3D * samplerPlacementTransform
G4Transform3D * GetPlacementTransform() const
Accessor.
G4Transform3D * placementTransformCL
G4double GetSPositionEnd() const
Accessor.
G4RotationMatrix * GetRotationStart() const
Accessor.
BDSAcceleratorComponent * GetAcceleratorComponent() const
Accessor.
G4Transform3D * GetPlacementTransformCL() const
Accessor.
G4bool Overlaps(const BDSBeamlineElement *otherElement) const
Whether this beam line element will overlaps in 3D Cartesian coordinates with another.
G4ThreeVector positionMiddle
Global coordinates for the start, middle and end of this beamline element.
G4int copyNumber
identification number of AcceleratorComponent (0 for first volume of given type)
G4RotationMatrix * referenceRotationStart
G4RotationMatrix * rotationStart
Global rotation matrices for the start, middle and end of this beamline element.
G4RotationMatrix * rotationMiddle
Global rotation matrices for the start, middle and end of this beamline element.
G4double GetSPositionMiddle() const
Accessor.
G4RotationMatrix * rotationEnd
Global rotation matrices for the start, middle and end of this beamline element.
G4RotationMatrix * referenceRotationEnd
G4RotationMatrix * GetRotationMiddle() const
Accessor.
static std::set< G4VPhysicalVolume * > GetPVsFromAssembly(G4AssemblyVolume *av)
Utility method to account for the interface in G4AssemblyVolume.
G4ThreeVector referencePositionMiddle
BDSExtentGlobal GetExtentGlobal() const
Create a global extent object from the extent of the component.
G4double GetSPositionStart() const
Accessor.
static G4double PaddingLength()
Access the padding length between each element added to the beamline.
Definition: BDSBeamline.hh:236
Holder for +- extents in 3 dimensions with a rotation and translation.
Holder for +- extents in 3 dimensions.
Definition: BDSExtent.hh:39
G4LogicalVolume * GetContainerLogicalVolume() const
Accessor - see member for more info.
G4bool ContainerIsAssembly() const
Whether the container is an assembly. If not, it's a logical volume.
BDSExtent GetExtent() const
Accessor - see member for more info.
G4AssemblyVolume * GetContainerAssemblyVolume() const
Accessor - see member for more info.
All info required to build a sampler but not place it.
static G4double ChordLength()
Access the sampler plane length in other classes.
A holder for any placement offsets and rotations for a BDSAcceleratorComponent.
G4double GetTilt() const
Accessor.