g4system
Loading...
Searching...
No Matches
g4mirrors.cc
Go to the documentation of this file.
1// g4mirrors.cc : optical surface (mirror) construction.
15
16// gemc
17#include "g4world.h"
18#include "gsystemConventions.h"
19#include "g4systemConventions.h"
20
21// geant4
22#include "G4OpticalSurface.hh"
23#include "G4LogicalSkinSurface.hh"
24#include "G4LogicalBorderSurface.hh"
25
26namespace {
27
28const std::unordered_map<std::string, G4SurfaceType>& surfaceTypesMap() {
29 static const std::unordered_map<std::string, G4SurfaceType> types = {
30 {"dielectric_metal", dielectric_metal},
31 {"dielectric_dielectric", dielectric_dielectric},
32 {"dielectric_LUT", dielectric_LUT},
33 {"dielectric_LUTDAVIS", dielectric_LUTDAVIS},
34 {"dielectric_dichroic", dielectric_dichroic},
35 {"firsov", firsov},
36 {"x_ray", x_ray}
37 };
38 return types;
39}
40
41const std::unordered_map<std::string, G4OpticalSurfaceFinish>& surfaceFinishesMap() {
42 static const std::unordered_map<std::string, G4OpticalSurfaceFinish> finishes = {
43 {"polished", polished},
44 {"polishedfrontpainted", polishedfrontpainted},
45 {"polishedbackpainted", polishedbackpainted},
46 {"ground", ground},
47 {"groundfrontpainted", groundfrontpainted},
48 {"groundbackpainted", groundbackpainted},
49 // LBNL LUT model finishes
50 {"polishedlumirrorair", polishedlumirrorair},
51 {"polishedlumirrorglue", polishedlumirrorglue},
52 {"polishedair", polishedair},
53 {"polishedteflonair", polishedteflonair},
54 {"polishedtioair", polishedtioair},
55 {"polishedtyvekair", polishedtyvekair},
56 {"polishedvm2000air", polishedvm2000air},
57 {"polishedvm2000glue", polishedvm2000glue},
58 {"etchedlumirrorair", etchedlumirrorair},
59 {"etchedlumirrorglue", etchedlumirrorglue},
60 {"etchedair", etchedair},
61 {"etchedteflonair", etchedteflonair},
62 {"etchedtioair", etchedtioair},
63 {"etchedtyvekair", etchedtyvekair},
64 {"etchedvm2000air", etchedvm2000air},
65 {"etchedvm2000glue", etchedvm2000glue},
66 {"groundlumirrorair", groundlumirrorair},
67 {"groundlumirrorglue", groundlumirrorglue},
68 {"groundair", groundair},
69 {"groundteflonair", groundteflonair},
70 {"groundtioair", groundtioair},
71 {"groundtyvekair", groundtyvekair},
72 {"groundvm2000air", groundvm2000air},
73 {"groundvm2000glue", groundvm2000glue},
74 // DAVIS model finishes
75 {"Rough_LUT", Rough_LUT},
76 {"RoughTeflon_LUT", RoughTeflon_LUT},
77 {"RoughESR_LUT", RoughESR_LUT},
78 {"RoughESRGrease_LUT", RoughESRGrease_LUT},
79 {"Polished_LUT", Polished_LUT},
80 {"PolishedTeflon_LUT", PolishedTeflon_LUT},
81 {"PolishedESR_LUT", PolishedESR_LUT},
82 {"PolishedESRGrease_LUT", PolishedESRGrease_LUT},
83 {"Detector_LUT", Detector_LUT}
84 };
85 return finishes;
86}
87
88const std::unordered_map<std::string, G4OpticalSurfaceModel>& surfaceModelsMap() {
89 static const std::unordered_map<std::string, G4OpticalSurfaceModel> models = {
90 {"glisur", glisur},
91 {"unified", unified},
92 {"LUT", LUT},
93 {"DAVIS", DAVIS},
94 {"dichroic", dichroic}
95 };
96 return models;
97}
98
99} // namespace
100
101
102void G4World::buildOpticalSurfaces(SystemMap* system_map) {
103 int nSkinSurfaces = 0;
104 int nBorderSurfaces = 0;
105
106 for (auto& [systemName, gsystem] : *system_map) {
107 for (auto& [volumeName, gvolumePtr] : gsystem->getGVolumesMap()) {
108 auto* gvolume = gvolumePtr.get();
109
110 const auto& mirror = gvolume->getMirror();
111 if (!mirror) { continue; }
112 const std::string& mirrorName = *mirror;
113
114 // Nonexistent volumes are skipped quietly, consistent with the volume build phase.
115 if (!gvolume->getExistence()) { continue; }
116
117 const GMirror* gmirror = gsystem->getGMirror(mirrorName);
118 if (gmirror == nullptr) {
119 log->error(
121 "mirror <%1> referenced by volume <%2> is not defined in system <%3>", mirrorName,
122 volumeName, systemName);
123 }
124
125 G4OpticalSurface* surface = getOrCreateOpticalSurface(systemName, gmirror);
126
127 const G4Volume* g4volume = getG4Volume(gvolume->getG4Name());
128 if (g4volume == nullptr) {
129 log->error(
130 g4system::ERR_G4VOLUMEBUILDFAILED, "volume <%1> referencing mirror <%2> was not built",
131 gvolume->getG4Name(), mirrorName);
132 }
133
134 if (gmirror->isSkinSurface()) {
135 // The skin surface covers the entire logical volume boundary.
136 new G4LogicalSkinSurface(gvolume->getG4Name(), g4volume->getLogical(), surface);
137 nSkinSurfaces++;
138 log->info(
139 2, "G4World: skin surface <%1%2%3> attached to volume <%4>", systemName,
140 gsystem::GSYSTEM_DELIMITER, mirrorName, gvolume->getG4Name());
141 }
142 else {
143 // The border surface applies to photons crossing from this volume into the
144 // border volume, which must belong to the same system.
145 std::string borderG4Name = systemName + gsystem::GSYSTEM_DELIMITER + gmirror->getBorder();
146 const G4Volume* borderG4Volume = getG4Volume(borderG4Name);
147 if (borderG4Volume == nullptr || borderG4Volume->getPhysical() == nullptr) {
148 log->error(
150 "border volume <%1> of mirror <%2> referenced by volume <%3> is not built",
151 borderG4Name, mirrorName, volumeName);
152 }
153 std::string surfaceName = gvolume->getG4Name() + "_to_" + borderG4Name;
154 new G4LogicalBorderSurface(surfaceName, g4volume->getPhysical(),
155 borderG4Volume->getPhysical(), surface);
156 nBorderSurfaces++;
157 log->info(
158 2, "G4World: border surface <%1> using mirror <%2%3%4>", surfaceName, systemName,
159 gsystem::GSYSTEM_DELIMITER, mirrorName);
160 }
161 }
162 }
163
164 if (nSkinSurfaces + nBorderSurfaces > 0) {
165 log->info(
166 1, "G4World: created %1 optical surfaces, attached to %2 skin and %3 border logical surfaces",
167 g4opticalSurfacesMap.size(), nSkinSurfaces, nBorderSurfaces);
168 }
169}
170
171
172G4OpticalSurface* G4World::getOrCreateOpticalSurface(const std::string& systemName, const GMirror* gmirror) {
173 std::string surfaceKey = systemName + gsystem::GSYSTEM_DELIMITER + gmirror->getName();
174
175 auto cached = g4opticalSurfacesMap.find(surfaceKey);
176 if (cached != g4opticalSurfacesMap.end()) { return cached->second; }
177
178 auto* surface = new G4OpticalSurface(surfaceKey);
179
180 // Surface type / finish / model: unknown strings are hard errors.
181 auto typeIt = surfaceTypesMap().find(gmirror->getType());
182 if (typeIt == surfaceTypesMap().end()) {
183 log->error(
184 g4system::ERR_G4SURFACECONFIGINVALID, "mirror <%1>: unknown surface type <%2>", gmirror->getName(),
185 gmirror->getType());
186 }
187 surface->SetType(typeIt->second);
188
189 auto finishIt = surfaceFinishesMap().find(gmirror->getFinish());
190 if (finishIt == surfaceFinishesMap().end()) {
191 log->error(
192 g4system::ERR_G4SURFACECONFIGINVALID, "mirror <%1>: unknown surface finish <%2>",
193 gmirror->getName(), gmirror->getFinish());
194 }
195 surface->SetFinish(finishIt->second);
196
197 auto modelIt = surfaceModelsMap().find(gmirror->getModel());
198 if (modelIt == surfaceModelsMap().end()) {
199 log->error(
200 g4system::ERR_G4SURFACECONFIGINVALID, "mirror <%1>: unknown surface model <%2>", gmirror->getName(),
201 gmirror->getModel());
202 }
203 surface->SetModel(modelIt->second);
204
205 // sigmaAlpha only applies to the unified/glisur roughness description.
206 if (gmirror->hasSigmaAlpha()) { surface->SetSigmaAlpha(gmirror->getSigmaAlpha()); }
207
208 // Boundary properties table: reuse the matOptProps material table, or build one
209 // from the mirror's own property vectors (validated at GMirror construction).
210 if (gmirror->usesMaterialOpticalProperties()) {
211 std::string materialName = gmirror->getMatOptProps();
212 G4Material* material = nullptr;
213
214 auto matIt = g4materialsMap.find(materialName);
215 if (matIt != g4materialsMap.end()) { material = matIt->second; }
216 else { material = G4NistManager::Instance()->FindMaterial(materialName); }
217
218 if (material == nullptr) {
219 log->error(
220 g4system::ERR_G4MATERIALNOTFOUND, "mirror <%1>: matOptProps material <%2> not found",
221 gmirror->getName(), materialName);
222 }
223 if (material->GetMaterialPropertiesTable() == nullptr) {
224 log->error(
226 "mirror <%1>: matOptProps material <%2> has no material properties table", gmirror->getName(),
227 materialName);
228 }
229 surface->SetMaterialPropertiesTable(material->GetMaterialPropertiesTable());
230 }
231 else {
232 auto* mpt = new G4MaterialPropertiesTable();
233
234 auto photonEnergy = gmirror->getPhotonEnergy();
235 auto addProperty = [&](const char* propertyName, const std::vector<double>& values) {
236 if (values.empty()) { return; }
237 mpt->AddProperty(propertyName, photonEnergy, values);
238 };
239
240 addProperty("RINDEX", gmirror->getIndexOfRefraction());
241 addProperty("REFLECTIVITY", gmirror->getReflectivity());
242 addProperty("EFFICIENCY", gmirror->getEfficiency());
243 addProperty("SPECULARLOBECONSTANT", gmirror->getSpecularLobe());
244 addProperty("SPECULARSPIKECONSTANT", gmirror->getSpecularSpike());
245 addProperty("BACKSCATTERCONSTANT", gmirror->getBackscatter());
246 addProperty("TRANSMITTANCE", gmirror->getTransmittance());
247
248 surface->SetMaterialPropertiesTable(mpt);
249 }
250
251 g4opticalSurfacesMap[surfaceKey] = surface;
252 log->info(
253 1, "G4World: created optical surface <%1> type <%2>, finish <%3>, model <%4>", surfaceKey,
254 gmirror->getType(), gmirror->getFinish(), gmirror->getModel());
255
256 return surface;
257}
G4VPhysicalVolume * getPhysical() const noexcept
Return the stored G4VPhysicalVolume pointer.
Definition g4volume.h:83
G4LogicalVolume * getLogical() const noexcept
Return the stored G4LogicalVolume pointer.
Definition g4volume.h:77
const G4Volume * getG4Volume(const std::string &volumeName) const
Return the G4Volume wrapper for a volume name.
Definition g4world.cc:130
std::shared_ptr< GLogger > log
std::vector< double > getReflectivity() const
std::vector< double > getSpecularSpike() const
std::vector< double > getEfficiency() const
bool hasSigmaAlpha() const
std::string getName() const
std::vector< double > getPhotonEnergy() const
std::string getMatOptProps() const
bool usesMaterialOpticalProperties() const
std::vector< double > getBackscatter() const
std::vector< double > getTransmittance() const
double getSigmaAlpha() const
std::string getType() const
std::vector< double > getSpecularLobe() const
std::string getFinish() const
std::string getBorder() const
std::string getModel() const
bool isSkinSurface() const
std::vector< double > getIndexOfRefraction() const
Conventions, labels, and error codes used by the g4system geometry/material layer.
High-level builder that turns a GEMC world description into Geant4 geometry.
std::map< std::string, SystemPtr > SystemMap
constexpr int ERR_G4SURFACECONFIGINVALID
Optical surface type/finish/model/properties are invalid.
constexpr int ERR_G4MATERIALNOTFOUND
Material lookup failed and no fallback was available.
constexpr int ERR_G4VOLUMEBUILDFAILED
A volume could not be fully built (solid/logical/physical).
constexpr int ERR_G4MIRRORNOTFOUND
A volume references a mirror that is not defined in its system.
constexpr char GSYSTEM_DELIMITER[]