BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSDegrader.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 "BDSDebug.hh"
20#include "BDSDegrader.hh"
21#include "BDSException.hh"
22#include "BDSSDType.hh"
23
24#include "G4Box.hh"
25#include "G4ExtrudedSolid.hh"
26#include "G4LogicalVolume.hh"
27#include "G4PVPlacement.hh"
28#include "G4RotationMatrix.hh"
29#include "G4TwoVector.hh"
30#include "G4VisAttributes.hh"
31#include "G4VSolid.hh"
32
33#include "globals.hh" // geant4 globals / types
34#include <string>
35#include <vector>
36
37#include "CLHEP/Units/SystemOfUnits.h"
38
39BDSDegrader::BDSDegrader(const G4String& nameIn,
40 G4double lengthIn,
41 G4double horizontalWidthIn,
42 G4int numberWedgesIn,
43 G4double wedgeLengthIn,
44 G4double degraderHeightIn,
45 G4double degraderOffsetIn,
46 G4double baseWidthIn,
47 G4Material* degraderMaterialIn,
48 G4Material* vacuumMaterialIn,
49 G4Colour* colourIn):
50 BDSAcceleratorComponent(nameIn, lengthIn, 0, "degrader"),
51 horizontalWidth(horizontalWidthIn),
52 numberWedges(numberWedgesIn),
53 wedgeLength(wedgeLengthIn),
54 degraderHeight(degraderHeightIn),
55 degraderOffset(degraderOffsetIn),
56 baseWidth(baseWidthIn),
57 degraderMaterial(degraderMaterialIn),
58 vacuumMaterial(vacuumMaterialIn),
59 colour(colourIn)
60{;}
61
62BDSDegrader::~BDSDegrader()
63{;}
64
66{
67 // Input Checks
68 if (horizontalWidth <= 0)
69 {throw BDSException(__METHOD_NAME__,"option \"horizontalWidth\" is not defined or must be greater than 0 for element \"" + name + "\"");}
70
71 if (numberWedges < 1)
72 {throw BDSException(__METHOD_NAME__, "option \"numberWedges\" is not defined or must be greater than 0 for element \"" + name + "\"");}
73
74 if (wedgeLength <= 0)
75 {throw BDSException(__METHOD_NAME__, "option \"wedgeLength\" is not defined or must be greater than 0 for element \"" + name + "\"");}
76
77 if (degraderHeight <= 0)
78 {throw BDSException(__METHOD_NAME__, "option \"degraderHeight\" is not defined or must be greater than 0 for element \"" + name + "\"");}
79
80 if (degraderHeight > (0.5*horizontalWidth))
81 {throw BDSException(__METHOD_NAME__, "option \"degraderHeight\" must be less than 0.5 times \"horizontalWidth\" for element \"" + name + "\"");}
82
83 if ((degraderOffset + baseWidth) > 0.5*horizontalWidth)
84 {throw BDSException(__METHOD_NAME__, "option \"degraderOffset\" must be less than (0.5 times \"horizontalWidth\", minus aper1) for element \"" + name + "\"");}
85
86 // adjust wedge offset to account for added base width
87 degraderOffset += baseWidth;
88
89 // ensure the container is wide enough
90 G4double minimumWidth = wedgeLength;
91 G4double containerWidth = degraderOffset;
92 if (degraderOffset < minimumWidth)
93 {containerWidth = minimumWidth;}
94
95 containerSolid = new G4Box(name + "_container_solid",
96 containerWidth + lengthSafety,
97 degraderHeight*0.5,
98 chordLength*0.5);
99
100 containerLogicalVolume = new G4LogicalVolume(containerSolid,
101 vacuumMaterial,
102 name + "_container_lv");
103}
104
106{
108
109 // width of the wedge at its base
110 G4double wedgeWidth = chordLength/numberWedges - lengthSafety;
111
112 // additional width to make the additional base section triangular
113 // reduce by 10nm to remove annoying angstrom sized overlaps with fewer lengthSafety's
114 G4double addedBasewidth = baseWidth* wedgeWidth/(2.0*wedgeLength) - 10*lengthSafety;
115
116 std::vector<G4TwoVector> fullWedgeVertices; // vertex co-ordinates
117 std::vector<G4TwoVector> halfWedgeVertices; // vertex co-ordinates
118
119 // vertices of full wedge plus base
120 fullWedgeVertices.push_back(G4TwoVector(0.5*wedgeWidth + addedBasewidth, 0));
121 fullWedgeVertices.push_back(G4TwoVector(0, wedgeLength+baseWidth));
122 fullWedgeVertices.push_back(G4TwoVector(-0.5*wedgeWidth - addedBasewidth, 0));
123
124 // vertices of half wedge plus base
125 halfWedgeVertices.push_back(G4TwoVector(0, 0));
126 halfWedgeVertices.push_back(G4TwoVector(0.5*wedgeWidth + addedBasewidth, 0));
127 halfWedgeVertices.push_back(G4TwoVector(0, wedgeLength+baseWidth));
128
129 // full wedge Solid and logical Volume
130 G4ExtrudedSolid* fullWedge = new G4ExtrudedSolid(name + "_fullwedge_solid",
131 fullWedgeVertices,
132 degraderHeight*0.5 - lengthSafety,
133 G4TwoVector(),1, G4TwoVector(), 1);
134 RegisterSolid(fullWedge);
135 G4LogicalVolume* fullWedgeLV = new G4LogicalVolume(fullWedge, // solid
136 degraderMaterial, // material
137 name + "_fullwedge_lv"); // name
138 RegisterLogicalVolume(fullWedgeLV);
139
140 // half wedge Solid and logical Volume
141 G4ExtrudedSolid* halfWedge = new G4ExtrudedSolid(name + "_halfwedge_solid",
142 halfWedgeVertices,
143 degraderHeight*0.5 - lengthSafety,
144 G4TwoVector(),1, G4TwoVector(), 1);
145 RegisterSolid(halfWedge);
146 G4LogicalVolume* halfWedgeLV = new G4LogicalVolume(halfWedge, // solid
147 degraderMaterial, // material
148 name + "_halfwedge_lv"); // name
149 RegisterLogicalVolume(halfWedgeLV);
150
151 // Wedge color
152 G4VisAttributes* degraderVisAttr = new G4VisAttributes(colour);
153 fullWedgeLV->SetVisAttributes(degraderVisAttr);
154 halfWedgeLV->SetVisAttributes(degraderVisAttr);
155 RegisterVisAttributes(degraderVisAttr);
156
157 // Rotation of wedges. Left taken to be +VE x direction, right is -VE x direction.
158 G4RotationMatrix* rightRot = new G4RotationMatrix();
159 rightRot->rotateY(-CLHEP::halfpi);
160 rightRot->rotateX(-CLHEP::halfpi);
161 RegisterRotationMatrix(rightRot);
162
163 G4RotationMatrix* leftRot = new G4RotationMatrix();
164 leftRot->rotateY(CLHEP::halfpi);
165 leftRot->rotateX(-CLHEP::halfpi);
166 RegisterRotationMatrix(leftRot);
167
168 // seperate rotation for first half wedge in even number of wedges.
169 G4RotationMatrix* altRightRot = new G4RotationMatrix();
170 altRightRot->rotateY(CLHEP::halfpi);
171 altRightRot->rotateX(CLHEP::halfpi);
172 RegisterRotationMatrix(altRightRot);
173
174 // loop over number of wedges and place
175 for (G4int i = 0; i < (numberWedges + 1); i++)
176 {
177 G4String wedgeName = name + "_" + std::to_string(i)+"_pv";
178 if (IsEven(numberWedges))
179 {
180 if (i == 0)
181 {PlaceWedge(true, lengthSafety, wedgeName, halfWedgeLV, altRightRot);}
182 else if (i==numberWedges)
183 {PlaceWedge(true, arcLength-lengthSafety, wedgeName, halfWedgeLV, rightRot);}
184 else if(IsEven(i))
185 {PlaceWedge(true, i*wedgeWidth, wedgeName, fullWedgeLV, rightRot);}
186 else if (IsOdd(i))
187 {PlaceWedge(false, i*wedgeWidth, wedgeName, fullWedgeLV, leftRot);}
188 }
189 else if (IsOdd(numberWedges))
190 {
191 if (i == 0)
192 {PlaceWedge(false, lengthSafety, wedgeName, halfWedgeLV, leftRot);}
193 else if (i == numberWedges)
194 {PlaceWedge(true, arcLength-lengthSafety, wedgeName, halfWedgeLV, rightRot);}
195 else if (IsEven(i))
196 {PlaceWedge(false, i*wedgeWidth, wedgeName, fullWedgeLV, leftRot);}
197 else if (IsOdd(i))
198 {PlaceWedge(true, i*wedgeWidth, wedgeName, fullWedgeLV, rightRot);}
199 }
200 }
201
202 if (sensitiveOuter)
203 {
204 RegisterSensitiveVolume(fullWedgeLV, BDSSDType::energydep);
205 RegisterSensitiveVolume(halfWedgeLV, BDSSDType::energydep);
206 }
207}
208
209void BDSDegrader::PlaceWedge(G4bool placeRight,
210 G4double zOffset,
211 const G4String& placementName,
212 G4LogicalVolume* lv,
213 G4RotationMatrix* rotation)
214{
215 G4double xOffset = -degraderOffset; // default is right placement
216 if (!placeRight)
217 {xOffset = degraderOffset;}
218
219 G4VPhysicalVolume* wedgePV = new G4PVPlacement(rotation,
220 G4ThreeVector(xOffset, 0, -0.5*arcLength + zOffset),
221 lv,
222 placementName,
223 containerLogicalVolume,
224 false,
225 0,
227 RegisterPhysicalVolume(wedgePV);
228}
Abstract class that represents a component of an accelerator.
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 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 chordLength
Protected member variable that can be modified by derived classes.
void PlaceWedge(G4bool placeRight, G4double zOffset, const G4String &placementName, G4LogicalVolume *lv, G4RotationMatrix *rotation)
virtual void Build()
BDSDegrader()=delete
Private default constructor to force the use of the supplied one.
virtual void BuildContainerLogicalVolume()
General exception with possible name of object and message.
void RegisterRotationMatrix(G4RotationMatrix *rotationMatrix)
void RegisterLogicalVolume(G4LogicalVolume *logicalVolume)
void RegisterPhysicalVolume(G4VPhysicalVolume *physicalVolume)
void RegisterVisAttributes(G4VisAttributes *visAttribute)
void RegisterSolid(G4VSolid *solid)
void RegisterSensitiveVolume(G4LogicalVolume *sensitiveVolume, BDSSDType sensitivityType)