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) 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 "BDSBeamlineElement.hh"
19
20#include "BDSAcceleratorComponent.hh"
21#include "BDSBeamline.hh"
22#include "BDSExtentGlobal.hh"
23#include "BDSSamplerPlane.hh"
24#include "BDSSamplerType.hh"
25#include "BDSTiltOffset.hh"
26#include "BDSUtilities.hh"
27
28#include "G4AssemblyVolume.hh"
29#include "G4PVPlacement.hh"
30#include "G4RotationMatrix.hh"
31#include "G4String.hh"
32#include "G4ThreeVector.hh"
33#include "G4Types.hh"
34
35#include <algorithm>
36#include <ostream>
37#include <set>
38#include <string>
39
40BDSBeamlineElement::BDSBeamlineElement(BDSAcceleratorComponent* componentIn,
41 const G4ThreeVector& positionStartIn,
42 const G4ThreeVector& positionMiddleIn,
43 const G4ThreeVector& positionEndIn,
44 G4RotationMatrix* rotationStartIn,
45 G4RotationMatrix* rotationMiddleIn,
46 G4RotationMatrix* rotationEndIn,
47 const G4ThreeVector& referencePositionStartIn,
48 const G4ThreeVector& referencePositionMiddleIn,
49 const G4ThreeVector& referencePositionEndIn,
50 G4RotationMatrix* referenceRotationStartIn,
51 G4RotationMatrix* referenceRotationMiddleIn,
52 G4RotationMatrix* referenceRotationEndIn,
53 G4double sPositionStartIn,
54 G4double sPositionMiddleIn,
55 G4double sPositionEndIn,
56 G4double synchronousTMiddleIn,
57 G4double startMomentumIn,
58 G4double startKineticEnergyIn,
59 BDSTiltOffset* tiltOffsetIn,
60 BDSSamplerInfo* samplerInfoIn,
61 G4int indexIn):
62 component(componentIn),
63 positionStart(positionStartIn), positionMiddle(positionMiddleIn), positionEnd(positionEndIn),
64 rotationStart(rotationStartIn), rotationMiddle(rotationMiddleIn), rotationEnd(rotationEndIn),
65 referencePositionStart(referencePositionStartIn),
66 referencePositionMiddle(referencePositionMiddleIn),
67 referencePositionEnd(referencePositionEndIn),
68 referenceRotationStart(referenceRotationStartIn),
69 referenceRotationMiddle(referenceRotationMiddleIn),
70 referenceRotationEnd(referenceRotationEndIn),
71 sPositionStart(sPositionStartIn), sPositionMiddle(sPositionMiddleIn), sPositionEnd(sPositionEndIn),
72 synchronousTMiddle(synchronousTMiddleIn),
73 startMomentum(startMomentumIn),
74 startKineticEnergy(startKineticEnergyIn),
75 tiltOffset(tiltOffsetIn),
76 samplerInfo(samplerInfoIn),
77 samplerPlacementTransform(nullptr),
78 index(indexIn)
79{
80 componentIn->IncrementCopyNumber(); // increase copy number (starts at -1)
81 copyNumber = componentIn->GetCopyNumber();
83 placementName = componentIn->GetName() + "_" + std::to_string(copyNumber);
84
85 // create the placement transform from supplied rotation matrices and vector
88
89 // calculate sampler central position slightly away from end position of element.
90 auto samplerType = GetSamplerType();
91 if (samplerType == BDSSamplerType::plane)
92 {
93 G4ThreeVector dZLocal = G4ThreeVector(0,0,1);
94 // if we have a sampler, add on the thickness of the sampler to the padding
96 dZLocal.transform(*referenceRotationEnd);
97 G4ThreeVector samplerPosition = referencePositionEnd + dZLocal;
98 samplerPlacementTransform = new G4Transform3D(*referenceRotationEnd, samplerPosition);
99 }
100 else if (samplerType == BDSSamplerType::cylinder)
102}
103
104BDSBeamlineElement::~BDSBeamlineElement()
105{
106 delete rotationStart;
107 delete rotationMiddle;
108 delete rotationEnd;
112 delete placementTransform;
115 delete samplerInfo;
116}
117
118std::set<G4VPhysicalVolume*> BDSBeamlineElement::GetPVsFromAssembly(G4AssemblyVolume* av)
119{
120 // this is obtuse because of the lack of access in G4Assembly
121 std::vector<G4VPhysicalVolume*> allPlacementsFromThisAssembly;
122 auto it = av->GetVolumesIterator();
123 for (G4int i = 0; i < (G4int)av->TotalImprintedVolumes(); it++, i++)
124 {allPlacementsFromThisAssembly.push_back(*it);}
125 std::set<G4VPhysicalVolume*> result(allPlacementsFromThisAssembly.begin(), allPlacementsFromThisAssembly.end());
126 return result;
127}
128
129std::set<G4VPhysicalVolume*> BDSBeamlineElement::PlaceElement(const G4String& pvName,
130 G4VPhysicalVolume* motherPV,
131 G4bool useCLPlacementTransform,
132 G4int pvCopyNumber,
133 G4bool checkOverlaps) const
134{
135 G4Transform3D* pvTransform = GetPlacementTransform();
136 if (useCLPlacementTransform)
137 {pvTransform = GetPlacementTransformCL();}
138
139 std::set<G4VPhysicalVolume*> result;
141 {
142 G4AssemblyVolume* av = component->GetContainerAssemblyVolume();
143 auto existingPVSet = GetPVsFromAssembly(av);
144 av->MakeImprint(motherPV->GetLogicalVolume(),
145 *pvTransform,
146 pvCopyNumber,checkOverlaps);
147
148 // need to get pvs before and afterwards and o the difference
149 auto updatedPVSet = GetPVsFromAssembly(av);
150 std::set_difference(updatedPVSet.begin(), updatedPVSet.end(),
151 existingPVSet.begin(), existingPVSet.end(),
152 std::inserter(result, result.begin()));
153 }
154 else
155 {
156 G4LogicalVolume* lv = component->GetContainerLogicalVolume();
157 result.insert(new G4PVPlacement(*pvTransform, // placement transform
158 pvName, // placement name
159 lv, // volume to be placed
160 motherPV, // volume to place it in
161 false, // no boolean operation
162 pvCopyNumber, // copy number
163 checkOverlaps)); // overlap checking
164 }
165 return result;
166}
167
174
176{
177 G4ThreeVector inputFNLocal = component->InputFaceNormal();
178 if (!tiltOffset) // no tilt so the same as local
179 {return inputFNLocal;}
180 else
181 {
182 G4ThreeVector inputFNGlobal = inputFNLocal.rotateZ(tiltOffset->GetTilt());
183 return inputFNGlobal;
184 }
185}
186
188{
189 G4ThreeVector outputFNLocal = component->OutputFaceNormal();
190 if (!tiltOffset) // no tilt so the same as local
191 {return outputFNLocal;}
192 else
193 {
194 G4ThreeVector outputFNGlobal = outputFNLocal.rotateZ(-tiltOffset->GetTilt());
195 return outputFNGlobal;
196 }
197}
198
199void BDSBeamlineElement::UpdateSamplerPlacementTransform(const G4Transform3D& tranfsormIn)
200{
202 samplerPlacementTransform = new G4Transform3D(tranfsormIn);
203}
204
205std::ostream& operator<< (std::ostream& out, BDSBeamlineElement const &e)
206{
207 out << "Beamline element: " << e.component->GetName() << G4endl;
208 out << "Start, middle & end position: "
209 << e.GetPositionStart() << " " << e.GetPositionMiddle() << " " << e.GetPositionEnd() << G4endl
210 << "Start, middle & end rotation: "
211 << *(e.GetRotationStart()) << " " << *(e.GetRotationMiddle()) << " " << *(e.GetRotationEnd()) << G4endl
212 << "Start, middle & end s position: "
213 << e.GetSPositionStart() << " " << e.GetSPositionMiddle() << " " << e.GetSPositionEnd() << G4endl;
214
215 return out;
216}
217
218G4bool BDSBeamlineElement::Overlaps(const BDSBeamlineElement* otherElement) const
219{
222 BDSExtentGlobal otherGlobal = BDSExtentGlobal(otherElement->GetAcceleratorComponent()->GetExtent(),
223 *(otherElement->GetPlacementTransform()));
224
225 return thisGlobal.Overlaps(otherGlobal);
226}
227
228
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.
Holder for +- extents in 3 dimensions with a rotation and translation.
Holder for +- extents in 3 dimensions.
Definition BDSExtent.hh:38
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.