BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSMultilayerScreen.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 "BDSColourWheel.hh"
19#include "BDSDebug.hh"
20#include "BDSException.hh"
21#include "BDSGlobalConstants.hh"
22#include "BDSMaterials.hh"
23#include "BDSMultilayerScreen.hh"
24#include "BDSSamplerRegistry.hh"
25#include "BDSScreenLayer.hh"
26
27#include "G4Box.hh"
28#include "G4VisAttributes.hh"
29#include "G4LogicalBorderSurface.hh"
30#include "G4LogicalVolume.hh"
31#include "G4OpticalSurface.hh"
32#include "G4PVPlacement.hh"
33#include "G4VSolid.hh"
34#include "G4Version.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
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#if G4VERSION_NUMBER > 1109
136 SMPT->AddConstProperty("REFLECTIVITY",0.8,true);
137#else
138 SMPT->AddConstProperty("REFLECTIVITY",0.8);
139#endif
140
141 /*
142 OpSurface->SetSigmaAlpha(0.7);
143 SMPT->AddConstProperty("SPECULARLOBECONSTANT",1.0);
144 SMPT->AddConstProperty("SPECULARSPIKECONSTANT",0.0);
145 SMPT->AddConstProperty("BACKSCATTERCONSTANT",0.0);
146 SMPT->AddConstProperty("EFFICIENCY",0.0);
147 // SMPT->AddConstProperty("RINDEX",1.5750);
148 */
149
150 OpSurface->SetMaterialPropertiesTable(SMPT);
151}
152
153void BDSMultilayerScreen::RoughSurface(G4int layer1, G4int layer2)
154{
155 G4OpticalSurface* OpSurface=new G4OpticalSurface("OpSurface");
156 OpSurface->SetType(dielectric_dielectric);
157 OpSurface->SetFinish(ground);
158 OpSurface->SetModel(unified);
159
160 // G4LogicalBorderSurface* LogSurface =
161 new G4LogicalBorderSurface("LogSurface",
162 ScreenLayer(layer1)->GetPhys(),
163 ScreenLayer(layer2)->GetPhys(),
164 OpSurface);
165
166 G4double sigma_alpha=0.7;
167 OpSurface->SetSigmaAlpha(sigma_alpha);
168 G4MaterialPropertiesTable* SMPT = new G4MaterialPropertiesTable();
169#if G4VERSION_NUMBER > 1109
170 SMPT->AddConstProperty("REFLECTIVITY",0.0, true);
171#else
172 SMPT->AddConstProperty("REFLECTIVITY",0.0);
173#endif
174 OpSurface->SetMaterialPropertiesTable(SMPT);
175}
176
178{
179 if (screenLayers.empty())
180 {throw BDSException(__METHOD_NAME__, "Screen \"" + name +"\" has no layers.");}
181
182 //Compute the total z thickness.
183 G4double temp = 0;
184 for (const auto& layer : screenLayers)
185 {temp += layer->GetSize().z();}
186 size.setZ(temp);
187
188 //Compute the z positions of all the layers.
189 //Position each layer after the previous one.
190 G4double pos = screenLayers[0]->GetSize().z()/2.0 -1.0*size.z()/2.0;
191 screenLayerZPos.push_back(pos);
192 for (unsigned int i=1; i<screenLayers.size(); i++)
193 {
194 pos += (screenLayers[i-1]->GetSize().z()+screenLayers[i]->GetSize().z())/2.0;
195 screenLayerZPos.push_back(pos);
196 }
197}
198
200{
201 // Make container marginally bigger to avoid overlaps
202 G4double lengthSafety = BDSGlobalConstants::Instance()->LengthSafety();
203
204 solid = new G4Box((name+"_solid").c_str(),
205 size.x()/2.0 + lengthSafety,
206 size.y()/2.0 + lengthSafety,
207 size.z()/2.0 + lengthSafety);
208 G4Material* mat = BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->VacuumMaterial());
209
210 log = new G4LogicalVolume(solid,
211 mat,
212 (name+"_log").c_str());
213
214 G4VisAttributes* visAtt = new G4VisAttributes(G4Colour(0.0,0.0,1.0,0.3));
215 visAtt->SetForceWireframe(true);
216 log->SetVisAttributes(visAtt);
217}
218
220{
221 G4ThreeVector pos(0,0,0);
222
223 for (unsigned int i=0; i<screenLayers.size(); i++)
224 {
225 pos.setZ(screenLayerZPos[i]);
226#ifdef BDSDEBUG
227 G4cout << __METHOD_NAME__ << ": placing screen layer with ID: "
228 << screenLayers[i]->GetSamplerID() << G4endl;
229#endif
230 //Create a new physical volume placement for each groove in the screen.
231 screenLayers[i]->SetPhys(new G4PVPlacement(nullptr,
232 pos,
233 screenLayers[i]->GetLog(),
234 screenLayers[i]->GetName(),
235 log,
236 false,
237 screenLayers[i]->GetSamplerID(),
238 true));
239 }
240}
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.
static BDSGlobalConstants * Instance()
Access method.
static BDSMaterials * Instance()
Singleton pattern access.
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.