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