BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSParallelWorldImportance.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 "BDSDebug.hh"
20#include "BDSException.hh"
21#include "BDSGeometryExternal.hh"
22#include "BDSGeometryFactory.hh"
23#include "BDSGlobalConstants.hh"
24#include "BDSImportanceFileLoader.hh"
25#include "BDSParallelWorldImportance.hh"
26#include "BDSUtilities.hh"
27
28#include "globals.hh"
29#include "G4GeometryCell.hh"
30#include "G4IStore.hh"
31#include "G4LogicalVolume.hh"
32#include "G4PVPlacement.hh"
33#include "G4VisAttributes.hh"
34#include "G4VPhysicalVolume.hh"
35
36#ifdef USE_GZSTREAM
37#include "src-external/gzstream/gzstream.h"
38#endif
39
40#include <iomanip>
41#include <map>
42#include <string>
43#include <fstream>
44
45BDSParallelWorldImportance::BDSParallelWorldImportance(G4String name,
46 G4String importanceWorldGeometryFile,
47 G4String importanceValuesFile):
48 G4VUserParallelWorld("importanceWorld_" + name),
49 imWorldPV(nullptr),
50 imGeomFile(importanceWorldGeometryFile),
51 imVolMap(importanceValuesFile),
52 componentName("importanceWorld")
53{
54 userLimits = BDSGlobalConstants::Instance()->DefaultUserLimits();
55 visAttr = BDSGlobalConstants::Instance()->VisibleDebugVisAttr();
56 verbosity = BDSGlobalConstants::Instance()->VerboseImportanceSampling();
57#ifdef BDSDEBUG
58 verbosity = 10;
59#endif
60}
61
63{
64 // load the cell importance values
65 G4String importanceMapFile = BDS::GetFullPath(imVolMap);
66 if (importanceMapFile.rfind("gz") != std::string::npos)
67 {
68#ifdef USE_GZSTREAM
70 imVolumesAndValues = loader.Load(importanceMapFile);
71#else
72 throw BDSException(__METHOD_NAME__, "Compressed file loading - but BDSIM not compiled with ZLIB.");
73#endif
74 }
75 else
76 {
78 imVolumesAndValues = loader.Load(importanceMapFile);
79 }
80
81 // build world
82 BuildWorld();
83}
84
85BDSParallelWorldImportance::~BDSParallelWorldImportance()
86{;}
87
89{
90 // load the importance world geometry - we give a 'component' name that *may* be
91 // prepended to the loaded volume names to ensure it's unique - for example with
92 // GDML preprocessing turned on.
94 imGeomFile,
95 nullptr, // colour mapping
96 false, // autoColour
97 0, 0, // suggested dimensions
98 nullptr, // vacuum volumes
99 false); // sensitive
100
101 // clone mass world for parallel world PV
102 imWorldPV = GetWorld();
103
104 G4LogicalVolume* worldLV = imWorldPV->GetLogicalVolume();
105
106 // set parallel world vis attributes
107 G4VisAttributes* importanceWorldVis = new G4VisAttributes(*(visAttr));
108 importanceWorldVis->SetForceWireframe(true);//just wireframe so we can see inside it
109 worldLV->SetVisAttributes(importanceWorldVis);
110
111 // set limits
112 worldLV->SetUserLimits(userLimits);
113
114 G4LogicalVolume* container = geom->GetContainerLogicalVolume();
115
116 // Set motherLV for all daughters to be world LV, and add geometry cell
117 for (G4int i = 0; i < (G4int)container->GetNoDaughters(); i++)
118 {
119 G4VPhysicalVolume* daughter = container->GetDaughter(i);
120 daughter->SetMotherLogical(worldLV);
121
122 G4VPhysicalVolume* parallelPV = new G4PVPlacement(daughter->GetRotation(),
123 daughter->GetTranslation(),
124 daughter->GetLogicalVolume(),
125 daughter->GetName(),
126 worldLV,
127 false,
128 0);
129 // second arg (0) is replica number - assume no replication of cells
130 G4GeometryCell cell(*parallelPV, 0);
132 }
133}
134
136{
137 const G4VPhysicalVolume* p = imVolumeStore.GetPVolume(i);
138 if (p)
139 {return G4GeometryCell(*p,0);}
140 else
141 {
142 G4cout << __METHOD_NAME__ << " Couldn't get G4GeometryCell" << G4endl;
143 return G4GeometryCell(*imWorldPV,-2);
144 }
145}
146
148{
149 G4IStore* aIstore = G4IStore::GetInstance(imWorldPV->GetName());
150
151 // create a geometry cell for the world volume replicaNumber is 0!
152 G4GeometryCell gWorldVolumeCell(*imWorldPV, 0);
153
154 // set world volume importance to 1
155 aIstore->AddImportanceGeometryCell(1, gWorldVolumeCell);
156
157 // set importance values
158 for (const auto& cell : imVolumeStore)
159 {
160 G4String cellName = cell.GetPhysicalVolume().GetName();
161 G4double importanceValue = GetCellImportanceValue(cellName);
162
163 if (!aIstore->IsKnown(cell))
164 {aIstore->AddImportanceGeometryCell(importanceValue, cell.GetPhysicalVolume(), 0);}
165 else
166 {
167 G4String message = "Geometry cell \"" + cellName + "\" already exists and has been previously\n";
168 message += "added to the IStore.";
169 throw BDSException(__METHOD_NAME__, message);
170 }
171 }
172
173 // feedback - user controllable
174 if (verbosity > 0)
175 {
176 auto flagsCache(G4cout.flags());
177 G4cout << imVolumeStore;
178 for (const auto& cellAndImportance : imVolumesAndValues)
179 {G4cout << std::left << std::setw(25) << cellAndImportance.first << " " << cellAndImportance.second << G4endl;}
180 G4cout.flags(flagsCache);
181 }
182}
183
185{
186 // strip off the prepended componentName that we introduce in the geometry factory
187 // this is controlled by the member variable of this class above
188 G4String pureCellName = cellName;
189 if (BDS::StrContains(pureCellName, componentName))
190 {
191 // +1 for "_" that's added in the geometry factory
192 pureCellName = pureCellName.erase(0, componentName.size()+1);
193 }
194
195 // strip off possible stupid PREPEND default from pyg4ometry
196 const G4String prepend = "PREPEND";
197 if (BDS::StrContains(pureCellName, prepend))
198 {
199 std::size_t found = pureCellName.find(prepend); // should be found as contains() found it
200 pureCellName.erase(found, found + prepend.size());
201 }
202
203 // replace stupid double pv suffix from pyg4ometry perpetual bug
204 if (BDS::StrContains(pureCellName, "_pv_pv")) // would only be pv pv from pyg4ometry - can't tell otherwise
205 {
206 std::size_t found = pureCellName.find("_pv_pv");
207 pureCellName.erase(found+3, found+6);
208 }
209
210 auto result = imVolumesAndValues.find(pureCellName);
211 if (result != imVolumesAndValues.end())
212 {
213 G4double importanceValue = (*result).second;
214 // importance value must be finite and positive.
215 if (importanceValue < 0)
216 {
217 G4String message = "Importance value is negative for cell \"" + pureCellName + "\".";
218 throw BDSException(__METHOD_NAME__, message);
219 }
220 else if (!BDS::IsFinite(importanceValue))
221 {
222 G4String message = "Importance value is zero for cell \"" + pureCellName + "\".";
223 throw BDSException(__METHOD_NAME__, message);
224 }
225 return importanceValue;
226 }
227 else
228 {
229 // exit if trying to get the importance value for a PV that isnt provided by the user.
230 G4String message = "An importance value was not found for the cell \"" + pureCellName + "\" in \n";
231 message += "the importance world geometry.";
232 throw BDSException(__METHOD_NAME__, message);
233 }
234}
235
236void BDSParallelWorldImportance::ConstructSD()
237{
238 /*
239 G4SDManager* SDman = G4SDManager::GetSDMpointer();
240
241 // Sensitive Detector Name
242 G4String importanceSamplingSDname = "ImportanceSamplingSD";
243
244 // Create multifunctional detector for parallel world
245 G4MultiFunctionalDetector* MFDet = new G4MultiFunctionalDetector(importanceSamplingSDname);
246 SDman->AddNewDetector(MFDet); // Register SD to SDManager
247
248 // Neutron filter
249 G4SDParticleFilter* neutronFilter = new G4SDParticleFilter("neutronFilter", "neutron");
250 MFDet->SetFilter(neutronFilter);
251 */
252}
General exception with possible name of object and message.
Definition: BDSException.hh:35
G4LogicalVolume * GetContainerLogicalVolume() const
Accessor - see member for more info.
A loaded piece of externally provided geometry.
static BDSGeometryFactory * Instance()
Singleton accessor.
BDSGeometryExternal * BuildGeometry(G4String componentName, const G4String &formatAndFilePath, std::map< G4String, G4Colour * > *colourMapping=nullptr, G4bool autoColour=true, G4double suggestedLength=0, G4double suggestedHorizontalWidth=0, std::vector< G4String > *namedVacuumVolumes=nullptr, G4bool makeSensitive=true, BDSSDType sensitivityType=BDSSDType::energydep, G4bool stripOuterVolumeAndMakeAssembly=false, G4UserLimits *userLimitsToAttachToAllLVs=nullptr, G4bool dontReloadGeometry=false)
static BDSGlobalConstants * Instance()
Access method.
A loader for importance values used in importance sampling.
const G4VPhysicalVolume * GetPVolume(G4int index) const
Get stores physical volume from index.
void AddPVolume(const G4GeometryCell &cell)
Add geometry cell to the store.
const G4String componentName
String preprended to geometry with preprocessGDML.
BDSImportanceVolumeStore imVolumeStore
Store of geometry cells for importance volumes.
G4double GetCellImportanceValue(const G4String &cellName)
Get importance value of a given physical volume name.
void AddIStore()
Create IStore for all importance sampling geometry cells.
std::map< G4String, G4double > imVolumesAndValues
Container for all user placed physical volumes and corresponding importance values.
G4VPhysicalVolume * imWorldPV
Importance sampling world volume.
G4int verbosity
Cached global constants values.
G4GeometryCell GetGeometryCell(G4int i) const
Get geometry cell from store.
G4VisAttributes * visAttr
Cached global constants values.
G4UserLimits * userLimits
Cached global constants values.
G4bool StrContains(const G4String &str, const G4String &test)
Utility function to simplify lots of syntax changes for pedantic g4 changes.
Definition: BDSUtilities.cc:66
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())