BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSMultilayerScreen.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2022.
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 "BDSColourWheel.hh"
20#include "BDSDebug.hh"
21#include "BDSException.hh"
22#include "BDSGlobalConstants.hh"
23#include "BDSMaterials.hh"
24#include "BDSMultilayerScreen.hh"
25#include "BDSSamplerRegistry.hh"
26#include "BDSScreenLayer.hh"
27
28#include "G4Box.hh"
29#include "G4VisAttributes.hh"
30#include "G4LogicalBorderSurface.hh"
31#include "G4LogicalVolume.hh"
32#include "G4OpticalSurface.hh"
33#include "G4PVPlacement.hh"
34#include "G4VSolid.hh"
35
36BDSMultilayerScreen::BDSMultilayerScreen(const G4TwoVector& xysizeIn,
37 const G4String& nameIn):
38 xysize(xysizeIn),
39 name(nameIn),
40 log(nullptr),
41 phys(nullptr),
42 solid(nullptr),
43 colourWheel(new BDSColourWheel())
44{
45 size.setX(xysize.x());
46 size.setY(xysize.y());
47 size.setZ(0); // starts as 0, but expands as layers added
48}
49
50BDSMultilayerScreen::~BDSMultilayerScreen()
51{
52 delete colourWheel;
53 for (auto layer : screenLayers)
54 {delete layer;}
55}
56
58 G4String material,
59 G4String nameIn,
60 G4int isSampler,
61 G4double grooveWidth,
62 G4double grooveSpatialFrequency)
63{
64 G4String layerName;
65 if (isSampler)
66 {
67 G4int nThisSampler = BDSSamplerRegistry::Instance()->NumberOfExistingSamplers() + 1;
68 G4String tempString = "Sampler_" + std::to_string(nThisSampler);
69 layerName = tempString + "_" + nameIn;
70 }
71 else
72 {layerName = nameIn;}
73
74 G4ThreeVector layerSize(xysize.x(), xysize.y(), thickness);
75 BDSScreenLayer* screen = new BDSScreenLayer(layerSize, layerName, material,
76 grooveWidth,grooveSpatialFrequency);
77 AddScreenLayer(screen, isSampler);
78}
79
81{
83 layer->SetColour(colourWheel->Colour());
84 if (isSampler)
85 {layer->AssignSampler();}
86 screenLayers.push_back(layer);
87 screenLayerNames[layer->GetName()] = layer;
88}
89
91{
92 auto result = screenLayerNames.find(layerName);
93 if (result == screenLayerNames.end())
94 {throw BDSException(__METHOD_NAME__, "screen layer \"" + layerName + "\" not found");}
95 else
96 {return result->second;}
97}
98
100{
103 PlaceLayers();
104}
105
106void BDSMultilayerScreen::Place(G4RotationMatrix* rot,
107 const G4ThreeVector& pos,
108 G4LogicalVolume* motherVol)
109{
110 SetPhys(new G4PVPlacement(rot,
111 pos,
112 log,
113 "multilayerScreen",
114 motherVol,
115 false,
116 0,
117 true
118 ));
119}
120
121void BDSMultilayerScreen::ReflectiveSurface(G4int layer1, G4int layer2)
122{
123 G4OpticalSurface* OpSurface=new G4OpticalSurface("OpSurface");
124 // G4LogicalBorderSurface* LogSurface =
125 new G4LogicalBorderSurface("LogSurface",
126 ScreenLayer(layer1)->GetPhys(),
127 ScreenLayer(layer2)->GetPhys(),
128 OpSurface);
129 // G4LogicalSkinSurface* LogSurface = new G4LogicalSkinSurface("LogSurface",screenLayer(1)->GetLog(),OpSurface);
130 OpSurface->SetType(dielectric_metal);
131 OpSurface->SetModel(unified);
132 OpSurface->SetFinish(polished);
133
134 G4MaterialPropertiesTable* SMPT = new G4MaterialPropertiesTable();
135 SMPT->AddConstProperty("REFLECTIVITY",0.8);
136
137 /*
138 OpSurface->SetSigmaAlpha(0.7);
139 SMPT->AddConstProperty("SPECULARLOBECONSTANT",1.0);
140 SMPT->AddConstProperty("SPECULARSPIKECONSTANT",0.0);
141 SMPT->AddConstProperty("BACKSCATTERCONSTANT",0.0);
142 SMPT->AddConstProperty("EFFICIENCY",0.0);
143 // SMPT->AddConstProperty("RINDEX",1.5750);
144 */
145
146 OpSurface->SetMaterialPropertiesTable(SMPT);
147}
148
149void BDSMultilayerScreen::RoughSurface(G4int layer1, G4int layer2)
150{
151 G4OpticalSurface* OpSurface=new G4OpticalSurface("OpSurface");
152 OpSurface->SetType(dielectric_dielectric);
153 OpSurface->SetFinish(ground);
154 OpSurface->SetModel(unified);
155
156 // G4LogicalBorderSurface* LogSurface =
157 new G4LogicalBorderSurface("LogSurface",
158 ScreenLayer(layer1)->GetPhys(),
159 ScreenLayer(layer2)->GetPhys(),
160 OpSurface);
161
162 G4double sigma_alpha=0.7;
163 OpSurface->SetSigmaAlpha(sigma_alpha);
164 G4MaterialPropertiesTable* SMPT = new G4MaterialPropertiesTable();
165 SMPT->AddConstProperty("REFLECTIVITY",0.0);
166 OpSurface->SetMaterialPropertiesTable(SMPT);
167}
168
170{
171 if (screenLayers.empty())
172 {throw BDSException(__METHOD_NAME__, "Screen \"" + name +"\" has no layers.");}
173
174 //Compute the total z thickness.
175 G4double temp = 0;
176 for (const auto& layer : screenLayers)
177 {temp += layer->GetSize().z();}
178 size.setZ(temp);
179
180 //Compute the z positions of all the layers.
181 //Position each layer after the previous one.
182 G4double pos = screenLayers[0]->GetSize().z()/2.0 -1.0*size.z()/2.0;
183 screenLayerZPos.push_back(pos);
184 for (unsigned int i=1; i<screenLayers.size(); i++)
185 {
186 pos += (screenLayers[i-1]->GetSize().z()+screenLayers[i]->GetSize().z())/2.0;
187 screenLayerZPos.push_back(pos);
188 }
189}
190
192{
193 // Make container marginally bigger to avoid overlaps
194 G4double lengthSafety = BDSGlobalConstants::Instance()->LengthSafety();
195
196 solid = new G4Box((name+"_solid").c_str(),
197 size.x()/2.0 + lengthSafety,
198 size.y()/2.0 + lengthSafety,
199 size.z()/2.0 + lengthSafety);
200 G4Material* mat = BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->VacuumMaterial());
201
202 log = new G4LogicalVolume(solid,
203 mat,
204 (name+"_log").c_str());
205
206 G4VisAttributes* visAtt = new G4VisAttributes(G4Colour(0.0,0.0,1.0,0.3));
207 visAtt->SetForceWireframe(true);
208 log->SetVisAttributes(visAtt);
209}
210
212{
213 G4ThreeVector pos(0,0,0);
214
215 for (unsigned int i=0; i<screenLayers.size(); i++)
216 {
217 pos.setZ(screenLayerZPos[i]);
218#ifdef BDSDEBUG
219 G4cout << __METHOD_NAME__ << ": placing screen layer with ID: "
220 << screenLayers[i]->GetSamplerID() << G4endl;
221#endif
222 //Create a new physical volume placement for each groove in the screen.
223 screenLayers[i]->SetPhys(new G4PVPlacement(nullptr,
224 pos,
225 screenLayers[i]->GetLog(),
226 screenLayers[i]->GetName(),
227 log,
228 false,
229 screenLayers[i]->GetSamplerID(),
230 true));
231 }
232}
Three colours that are supplied sequentially.
void Spin()
Iterate colour choice from RGB.
G4Colour Colour()
Return current colour.
General exception with possible name of object and message.
Definition: BDSException.hh:35
static BDSGlobalConstants * Instance()
Access method.
static BDSMaterials * Instance()
Singleton pattern access.
Definition: BDSMaterials.cc:38
G4Material * GetMaterial(G4String material) const
Get material by name.
void AddScreenLayer(G4double thickness, G4String material, G4String name, G4int isSampler=0, G4double grooveWidth=0, G4double grooveSpatialFrequency=0)
Construct and add a screen layer.
std::vector< BDSScreenLayer * > screenLayers
Main storage of all layers.
void RoughSurface(G4int layer1, G4int layer2)
Construct a rough surface between two layers.
void SetPhys(G4PVPlacement *physIn)
Set a physical placement to member variable.
BDSMultilayerScreen()=delete
Private default constructor to force use of provided one.
G4ThreeVector size
Extent.
G4VSolid * solid
Geometrical objects:
void BuildMotherVolume()
Build a container volume.
std::map< G4String, BDSScreenLayer * > screenLayerNames
Map of names for looking up.
std::vector< G4double > screenLayerZPos
Cache of calculated z locations for layers.
virtual void Place(G4RotationMatrix *rot, const G4ThreeVector &pos, G4LogicalVolume *motherVol)
Place the member logical volume 'log' with a given transform in a given mother volume.
BDSScreenLayer * ScreenLayer(G4int layer)
Get a particular screen layer by index.
BDSColourWheel * colourWheel
void Build()
Construct container, compute dimensions then place layers.
G4LogicalVolume * log
Geometrical objects:
G4TwoVector xysize
X,Y size of multilayer screen.
void ReflectiveSurface(G4int layer1, G4int layer2)
Construct a reflective surface between two layers.
G4String name
Name of multilayer screen.
void PlaceLayers()
Place each layer in order in the container volume.
static BDSSamplerRegistry * Instance()
Accessor for registry.
G4int NumberOfExistingSamplers() const
Get number of registered samplers.
An individual screen layer for a multilayer screen.
void AssignSampler()
Make this plane a sampling plane.
G4String GetName() const
Accessor.