BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSGeometryFactoryGDML.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2023.
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#ifdef USE_GDML
20#include "BDSAcceleratorModel.hh"
21#include "BDSColourFromMaterial.hh"
22#include "BDSColours.hh"
23#include "BDSDebug.hh"
24#include "BDSException.hh"
25#include "BDSGeometryExternal.hh"
26#include "BDSGeometryFactoryGDML.hh"
27#include "BDSGeometryInspector.hh"
28#include "BDSGDMLPreprocessor.hh" // also only available with USE_GDML
29#include "BDSGlobalConstants.hh"
30#include "BDSMaterials.hh"
31#include "BDSWarning.hh"
32
33#include "globals.hh"
34#include "G4Colour.hh"
35#include "G4GDMLParser.hh"
36#include "G4LogicalVolume.hh"
37#include "G4UserLimits.hh"
38#include "G4VisAttributes.hh"
39#include "G4VPhysicalVolume.hh"
40
41#include <fstream>
42#include <iostream>
43#include <iterator>
44#include <set>
45#include <sstream>
46#include <string>
47#include <utility>
48#include <vector>
49
50class G4VisAttributes;
51class G4VSolid;
52
53BDSGeometryFactoryGDML::BDSGeometryFactoryGDML()
54{;}
55
57 G4String fileName,
58 std::map<G4String, G4Colour*>* mapping,
59 G4bool autoColour,
60 G4double /*suggestedLength*/,
61 G4double /*suggestedHorizontalWidth*/,
62 std::vector<G4String>* namedVacuumVolumes,
63 G4bool makeSensitive,
64 BDSSDType sensitivityType,
65 BDSSDType vacuumSensitivityType,
66 G4UserLimits* userLimitsToAttachToAllLVs)
67{
68 CleanUp();
69
70 // Compensate for G4GDMLParser deficiency in loading more than one file with similar names
71 // in objects. Prepend all names with component name.
72 G4String processedFile;
73 G4bool preprocessGDML = BDSGlobalConstants::Instance()->PreprocessGDML();
74 G4bool preprocessGDMLSchema = BDSGlobalConstants::Instance()->PreprocessGDMLSchema();
75 if (preprocessGDML)
76 {processedFile = BDS::PreprocessGDML(fileName, componentName, preprocessGDMLSchema);} // use all in one method
77 else if (preprocessGDMLSchema) // generally don't process the file but process the schema to local copy only
78 {processedFile = BDS::PreprocessGDMLSchemaOnly(fileName);} // use schema only method
79 else // no processing
80 {processedFile = fileName;}
81 G4String preprocessNameToStrip = preprocessGDML ? componentName+"_" : "";
82
83 G4GDMLParser* parser = new G4GDMLParser();
84 parser->SetOverlapCheck(BDSGlobalConstants::Instance()->CheckOverlaps());
85 parser->Read(processedFile, /*validate=*/true);
86
87 G4VPhysicalVolume* containerPV = parser->GetWorldVolume();
88 G4LogicalVolume* containerLV = containerPV->GetLogicalVolume();
89 G4VSolid* containerSolid = containerLV->GetSolid();
90 G4ThreeVector gdmlWorldOrigin = G4ThreeVector();
91 if (containerPV->GetName() == "world_volume_lv_PV")
92 {
93 gdmlWorldOrigin = parser->GetPosition("PygdmlOrigin"); // TODO check if Pygdml geometry
94 gdmlWorldOrigin[2] = 0.0;
95 }
96
97 // record all pvs and lvs used in this loaded geometry
98 std::set<G4VPhysicalVolume*> pvsGDML;
99 std::set<G4LogicalVolume*> lvsGDML;
100 std::map<G4String, G4Material*> materialsGDML;
101 GetAllLogicalPhysicalAndMaterials(containerPV, pvsGDML, lvsGDML, materialsGDML);
104
105 // load possible colours in auxiliary tags
106 std::map<G4String, G4Colour*> gdmlColours;
107 G4int iColour = 0;
108 for (auto lv : lvsGDML)
109 {
110 auto auxInfo = parser->GetVolumeAuxiliaryInformation(lv);
111 for (const auto& af : auxInfo)
112 {
113 if (af.type == "colour")
114 {
115 std::stringstream ss(af.value);
116 std::vector<G4String> colVals((std::istream_iterator<G4String>(ss)), std::istream_iterator<G4String>());
117 if (colVals.size() != 4)
118 {BDS::Warning(__METHOD_NAME__, "invalid number of colour values for logical volume " + lv->GetName());}
119 G4String colourName = componentName + "_colour_"+std::to_string(iColour);
120 iColour++;
121 G4String colourString = colourName + ":";
122 for (const auto& c : colVals)
123 {colourString += " " + c;}
124 // false = don't normalise to 255 as already done so
125 G4Colour* colour = BDSColours::Instance()->GetColour(colourString, false);
126 gdmlColours[lv->GetName()] = colour;
127 }
128 }
129 }
130
131 G4cout << "Loaded GDML file \"" << processedFile << "\" containing:" << G4endl;
132 G4cout << pvsGDML.size() << " physical volumes, and " << lvsGDML.size() << " logical volumes" << G4endl;
133
134 // resolve loaded map with possible external map with minimal copying
135 std::map<G4String, G4Colour*>* mappingToUse = nullptr;
136 G4bool deleteMap = false;
137 if (!gdmlColours.empty())
138 {
139 if (mapping)
140 {// copy and extend the map
141 mappingToUse = new std::map<G4String, G4Colour*>(*mapping);
142 mappingToUse->insert(gdmlColours.begin(), gdmlColours.end());
143 deleteMap = true;
144 }
145 else
146 {mappingToUse = &gdmlColours;}
147 }
148 else
149 {mappingToUse = mapping;}
150
151 auto visesGDML = ApplyColourMapping(lvsGDML, mappingToUse, autoColour, preprocessNameToStrip);
152 if (deleteMap)
153 {delete mappingToUse;}
154
155 G4UserLimits* ul = userLimitsToAttachToAllLVs ? userLimitsToAttachToAllLVs : BDSGlobalConstants::Instance()->DefaultUserLimits();
156 ApplyUserLimits(lvsGDML, ul);
157
158 // make sure container is visible - Geant4 always makes the container invisible.
159 G4Colour* c = BDSColourFromMaterial::Instance()->GetColour(containerLV->GetMaterial(), preprocessNameToStrip);
160 G4VisAttributes* vis = new G4VisAttributes(*c);
161 vis->SetVisibility(true);
162 visesGDML.insert(vis);
163 containerLV->SetVisAttributes(vis);
164
165 std::pair<BDSExtent, BDSExtent> outerInner = BDS::DetermineExtents(containerSolid);
166
167 BDSGeometryExternal* result = new BDSGeometryExternal(containerSolid, containerLV,
168 outerInner.first, /*outer*/
169 outerInner.second, /*inner*/
170 gdmlWorldOrigin);
171 result->RegisterLogicalVolume(lvsGDML);
172 result->RegisterPhysicalVolume(pvsGDML);
173 result->RegisterVisAttributes(visesGDML);
174 result->RegisterVacuumVolumes(GetVolumes(lvsGDML, namedVacuumVolumes, preprocessGDML, componentName));
175
176 if (makeSensitive)
177 {
178 const auto &vacuumVolumes = result->VacuumVolumes();
179 ApplySensitivity(result,
180 result->GetAllLogicalVolumes(),
181 sensitivityType,
182 vacuumVolumes,
183 vacuumSensitivityType);
184 }
185
186 delete parser;
187 return result;
188}
189
190G4String BDSGeometryFactoryGDML::PreprocessedName(const G4String& objectName,
191 const G4String& acceleratorComponentName) const
192{return BDSGDMLPreprocessor::ProcessedNodeName(objectName, acceleratorComponentName);}
193
195 std::set<G4VPhysicalVolume*>& pvsIn,
196 std::set<G4LogicalVolume*>& lvsIn,
197 std::map<G4String, G4Material*>& materialsGDML)
198{
199 const auto& lv = volume->GetLogicalVolume();
200 lvsIn.insert(lv);
201 G4Material* mat = lv->GetMaterial();
202 materialsGDML[mat->GetName()] = mat;
203 for (G4int i = 0; i < (G4int)lv->GetNoDaughters(); i++)
204 {
205 const auto& pv = lv->GetDaughter(i);
206 pvsIn.insert(pv);
207 GetAllLogicalPhysicalAndMaterials(pv, pvsIn, lvsIn, materialsGDML); // recurse into daughter
208 }
209}
210
212 const G4String& outputFileName,
213 const G4String& key,
214 const G4String& replacement)
215{
216 // open input file in read mode
217 std::ifstream ifs(fileName);
218
219 // verify file open.
220 if (!ifs.is_open())
221 {throw BDSException(__METHOD_NAME__, "Cannot open file \"" + fileName + "\"");}
222
223 std::ofstream fout(outputFileName);
224#ifdef BDSDEBUG
225 G4cout << __METHOD_NAME__ << "Original file: " << fileName << G4endl;
226 G4cout << __METHOD_NAME__ << "Temporary file: " << outputFileName << G4endl;
227#endif
228
229 int lenOfKey = key.size();
230
231 // loop over and replace
232 std::string buffer;
233 while (std::getline(ifs, buffer))
234 {// if we find key, replace it
235 int f = buffer.find(key);
236 if (f != -1)
237 {
238 std::string outputString = std::string(buffer);
239 outputString.replace(f, lenOfKey, replacement);
240 fout << outputString << "\n"; // getline strips \n
241 }
242 else // copy line to temp file as is
243 {fout << buffer << "\n";}
244 }
245
246 // clean up
247 ifs.close();
248 fout.close();
249}
250
251#else
252// insert empty function to avoid no symbols warning
253void _SymbolToPreventWarningGeomFacGDML(){;}
254#endif
static BDSColourFromMaterial * Instance()
Singleton pattern.
G4Colour * GetColour(const G4Material *material, const G4String &prefixToStripFromName="")
Get colour from name.
static BDSColours * Instance()
singleton pattern
Definition: BDSColours.cc:33
G4Colour * GetColour(const G4String &type, G4bool normaliseTo255=true)
Get colour from name.
Definition: BDSColours.cc:204
General exception with possible name of object and message.
Definition: BDSException.hh:35
static G4String ProcessedNodeName(const G4String &nodeName, const G4String &prefix)
void RegisterLogicalVolume(G4LogicalVolume *logicalVolume)
virtual std::set< G4LogicalVolume * > GetAllLogicalVolumes() const
Access all logical volumes belonging to this component.
void RegisterPhysicalVolume(G4VPhysicalVolume *physicalVolume)
void RegisterVisAttributes(G4VisAttributes *visAttribute)
A loaded piece of externally provided geometry.
void RegisterVacuumVolumes(const std::set< G4LogicalVolume * > &vacuumVolumesIn)
Register a set of volumes to be identified as vacuum volumes for the BDSAcceleratorComponent.
const std::set< G4LogicalVolume * > & VacuumVolumes() const
Access the vacuum volumes.
virtual void ApplySensitivity(BDSGeometryExternal *result, const std::set< G4LogicalVolume * > &allLogicalVolumesIn, BDSSDType generalSensitivity, const std::set< G4LogicalVolume * > &vacuumLogicalVolumes, BDSSDType vacuumSensitivity)
Attach the relevant general and vacuum sensitivity to each volume.
std::set< G4LogicalVolume * > GetVolumes(const std::set< G4LogicalVolume * > &allLVs, std::vector< G4String > *volumeNames, G4bool preprocessGDML, const G4String &componentName) const
Get the volumes that match the name. Volume names are matched exactly and are case sensitive.
virtual void CleanUp()
Virtual clean up that derived classes can override that calls CleanUpBase().
virtual void ApplyUserLimits(const std::set< G4LogicalVolume * > &lvsIn, G4UserLimits *userLimits)
Attach a set of user limits to every logical volume supplied.
virtual std::set< G4VisAttributes * > ApplyColourMapping(std::set< G4LogicalVolume * > &lvs, std::map< G4String, G4Colour * > *mapping, G4bool autoColour, const G4String &preprocessPrefix="")
void GetAllLogicalPhysicalAndMaterials(const G4VPhysicalVolume *volume, std::set< G4VPhysicalVolume * > &pvs, std::set< G4LogicalVolume * > &lvs, std::map< G4String, G4Material * > &materialsGDML)
virtual BDSGeometryExternal * Build(G4String componentName, G4String fileName, 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, G4UserLimits *userLimitsToAttachToAllLVs=nullptr)
virtual G4String PreprocessedName(const G4String &objectName, const G4String &acceleratorComponentName) const
Use the GDML preprocessing scheme to prepare the preprocesseed volume names.
void ReplaceStringInFile(const G4String &filename, const G4String &outputFileName, const G4String &key, const G4String &replacement)
static BDSGlobalConstants * Instance()
Access method.
static BDSMaterials * Instance()
Singleton pattern access.
Definition: BDSMaterials.cc:39
void CacheMaterialsFromGDML(const std::map< G4String, G4Material * > &materialsGDML)
Introduce materials loaded from GDML into this instance.
void CheckForConflictingMaterialsAfterLoad(const G4String &geometryFileName, const G4String &componentName) const
Improve type-safety of native enum data type in C++.
std::pair< BDSExtent, BDSExtent > DetermineExtents(const G4VSolid *solid)