BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSLinkOpaqueBox.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 "BDSApertureInfo.hh"
20#include "BDSApertureType.hh"
21#include "BDSBeamline.hh"
22#include "BDSColours.hh"
23#include "BDSDebug.hh"
24#include "BDSException.hh"
25#include "BDSExtent.hh"
26#include "BDSGlobalConstants.hh"
27#include "BDSLinkOpaqueBox.hh"
28#include "BDSMaterials.hh"
29#include "BDSSamplerCustom.hh"
30#include "BDSSamplerPlacementRecord.hh"
31#include "BDSSamplerPlane.hh"
32#include "BDSSamplerRegistry.hh"
33#include "BDSSDManager.hh"
34#include "BDSSDSamplerLink.hh"
35#include "BDSTiltOffset.hh"
36#include "BDSUtilities.hh"
37
38#include "G4Box.hh"
39#include "G4LogicalVolume.hh"
40#include "G4RotationMatrix.hh"
41#include "G4PVPlacement.hh"
42#include "G4SubtractionSolid.hh"
43#include "G4ThreeVector.hh"
44#include "G4Types.hh"
45#include "G4UserLimits.hh"
46#include "G4VisAttributes.hh"
47#include "G4TwoVector.hh"
48
49#include "CLHEP/Units/SystemOfUnits.h"
50
51#include <limits>
52
54 BDSTiltOffset* tiltOffsetIn,
55 G4double outputSamplerRadiusIn):
56 BDSGeometryComponent(nullptr, nullptr),
57 component(acceleratorComponentIn),
58 outputSamplerRadius(outputSamplerRadiusIn),
59 sampler(nullptr)
60{
61 if (tiltOffsetIn->HasFiniteTilt() && BDS::IsFinite(component->GetAngle()))
62 {throw BDSException(__METHOD_NAME__, "finite tilt with angled component unsupported.");}
63
64 G4double tilt = tiltOffsetIn->GetTilt();
65 G4double ox = tiltOffsetIn->GetXOffset();
66 G4double oy = tiltOffsetIn->GetYOffset();
67 BDSExtent extent = component->GetExtent();
68 extent = extent.TiltOffset(tiltOffsetIn);
69 const G4double gap = 10 * CLHEP::cm;
70 const G4double opaqueBoxThickness = 10 * CLHEP::mm;
71 G4String name = component->GetName();
72
73 G4double mx = extent.MaximumX();
74 G4double my = extent.MaximumY();
75 G4double mr = std::max({mx, my, outputSamplerRadius});
76 G4double mz = extent.MaximumZ();
77 G4Box* terminatorBoxOuter = new G4Box(name + "_terminator_box_outer_solid",
78 mr + gap + opaqueBoxThickness,
79 mr + gap + opaqueBoxThickness,
80 mz + gap + opaqueBoxThickness);
81 RegisterSolid(terminatorBoxOuter);
82 G4Box* terminatorBoxInner = new G4Box(name + "_terminator_box_inner_solid",
83 mr + gap,
84 mr + gap,
85 mz + gap);
86 RegisterSolid(terminatorBoxInner);
87 G4SubtractionSolid* opaqueBox = new G4SubtractionSolid(name + "_opaque_box_solid",
88 terminatorBoxOuter,
89 terminatorBoxInner);
90 RegisterSolid(opaqueBox);
91 G4LogicalVolume* opaqueBoxLV = new G4LogicalVolume(opaqueBox,
92 BDSMaterials::Instance()->GetMaterial("G4_Galactic"),
93 name + "_opaque_box_lv");
94 RegisterLogicalVolume(opaqueBoxLV);
95
96 G4UserLimits* termUL = new G4UserLimits();
97 termUL->SetUserMinEkine(std::numeric_limits<double>::max());
98 RegisterUserLimits(termUL);
99 opaqueBoxLV->SetUserLimits(termUL);
100
101 G4VisAttributes* obVis = new G4VisAttributes(*BDSColours::Instance()->GetColour("opaquebox"));
102 obVis->SetVisibility(true);
103 opaqueBoxLV->SetVisAttributes(obVis);
104 RegisterVisAttributes(obVis);
105
106 G4double ls = BDSGlobalConstants::Instance()->LengthSafetyLarge();
107 G4double margin = gap + opaqueBoxThickness + ls;
108 G4double xsize = mr + margin;
109 G4double ysize = mr + margin;
110 G4double zsize = mz + margin;
111 containerSolid = new G4Box(name + "_opaque_box_vacuum_solid",
112 xsize,
113 ysize,
114 zsize);
115
116 containerLogicalVolume = new G4LogicalVolume(containerSolid,
117 BDSMaterials::Instance()->GetMaterial("G4_Galactic"),
118 name + "_container_lv");
119 containerLogicalVolume->SetVisAttributes(BDSGlobalConstants::Instance()->ContainerVisAttr());
120
121 // auto boxPlacement =
122 new G4PVPlacement(nullptr,
123 G4ThreeVector(),
124 opaqueBoxLV,
125 name + "_opaque_box_pv",
126 containerLogicalVolume,
127 false,
128 1,
129 true);
130
131 G4ThreeVector of = G4ThreeVector(ox,oy,0);
132 G4RotationMatrix* rm = new G4RotationMatrix();
133 if (BDS::IsFinite(tilt))
134 {
135 rm->rotateZ(tilt);
136 }
137 G4Transform3D* placementTransform = new G4Transform3D(*rm, of);
138 delete rm;
139
140 new G4PVPlacement(*placementTransform,
141 component->GetContainerLogicalVolume(),
142 component->GetName() + "_pv",
143 containerLogicalVolume,
144 false,
145 1,
146 true);
147
148 outerExtent = BDSExtent(xsize, ysize, zsize);
149
150 G4RotationMatrix* rm2 = new G4RotationMatrix();
151 offsetToStart = G4ThreeVector(0.0, 0.0, -0.5*component->GetChordLength());
152 transformToStart = G4Transform3D(*rm2, offsetToStart);
153 delete rm2;
154}
155
156BDSLinkOpaqueBox::~BDSLinkOpaqueBox()
157{
158 delete sampler;
159}
160
162{
163 G4String samplerName = component->GetName() + "_out";
164 BDSApertureType apt = BDSApertureType::circular;
165 BDSApertureInfo ap = BDSApertureInfo(apt, outputSamplerRadius, 0, 0, 0);
166 sampler = new BDSSamplerCustom(samplerName, ap);
167 sampler->GetContainerLogicalVolume()->SetSensitiveDetector(BDSSDManager::Instance()->SamplerLink());
169 auto z2 = component->GetExtent();
170 G4ThreeVector position = G4ThreeVector(0,0,0.5*component->GetChordLength() + 2*BDSSamplerCustom::ChordLength());
171 G4RotationMatrix* rm = nullptr;
172 if (BDS::IsFinite(component->GetAngle()))
173 {
174 rm = new G4RotationMatrix();
175 rm->rotateY(0.5 * component->GetAngle()); // rotate to output face
177 position = G4ThreeVector(component->Sagitta(), 0, 0.5*component->GetChordLength());
178 G4ThreeVector gap = G4ThreeVector(0,0,2*BDSSamplerCustom::ChordLength());
179 position += gap.transform(*rm);
180 }
181 // if there's finite angle, we ensure (in constructor) there's no tilt
182 G4RotationMatrix* rml = rm ? new G4RotationMatrix(*rm) : new G4RotationMatrix();
183 BDSSamplerPlacementRecord info(samplerName, sampler, G4Transform3D(*rml, position));
184 delete rml;
185
186 G4int samplerID = BDSSamplerRegistry::Instance()->RegisterSampler(info);
187 new G4PVPlacement(rm,
188 position,
189 sampler->GetContainerLogicalVolume(),
190 samplerName + "_pv",
191 containerLogicalVolume,
192 false,
193 samplerID,
194 true);
195 return samplerID;
196}
Abstract class that represents a component of an accelerator.
G4double Sagitta() const
Calculate the sagitta - ie the distance between the chord and the arc at the centre.
virtual G4String GetName() const
The name of the component without modification.
virtual G4double GetChordLength() const
Holder class for all information required to describe an aperture.
static BDSColours * Instance()
singleton pattern
Definition BDSColours.cc:32
General exception with possible name of object and message.
Holder for +- extents in 3 dimensions.
Definition BDSExtent.hh:38
BDSExtent TiltOffset(const BDSTiltOffset *tiltOffset) const
Provide a new copy of this extent with both a tilt and an offset applied.
Definition BDSExtent.cc:104
A generic geometry component for a bdsim model.
G4LogicalVolume * GetContainerLogicalVolume() const
Accessor - see member for more info.
BDSExtent GetExtent() const
Accessor - see member for more info.
void RegisterRotationMatrix(G4RotationMatrix *rotationMatrix)
static BDSGlobalConstants * Instance()
Access method.
BDSLinkOpaqueBox()=delete
Default constructor.
G4int PlaceOutputSampler()
Place the output sampler.
static BDSMaterials * Instance()
Singleton pattern access.
Custom shaped sampler with fixed thickness.
static G4double ChordLength()
Access the sampler plane length in other classes.
Information about a registered sampler.
static BDSSamplerRegistry * Instance()
Accessor for registry.
G4int RegisterSampler(const G4String &name, BDSSampler *sampler, const G4Transform3D &transform=G4Transform3D(), G4double S=-1000, const BDSBeamlineElement *element=nullptr, BDSSamplerType type=BDSSamplerType::plane, G4double radius=0)
void MakeMaterialValidForUseInMassWorld()
Definition BDSSampler.cc:49
A holder for any placement offsets and rotations for a BDSAcceleratorComponent.
G4double GetYOffset() const
Accessor.
G4double GetXOffset() const
Accessor.
G4bool HasFiniteTilt() const
Inspector.
G4double GetTilt() const
Accessor.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())