g4system
Loading...
Searching...
No Matches
g4mirrors.cc
Go to the documentation of this file.
1// g4mirrors.cc : optical surface (mirror) construction.
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 std::string mirrorName = gvolume->getMirror();
111 if (gutilities::is_unset(mirrorName) || mirrorName == "no" || mirrorName == "none") { continue; }
112
113 // Nonexistent volumes are skipped quietly, consistent with the volume build phase.
114 if (!gvolume->getExistence()) { continue; }
115
116 const GMirror* gmirror = gsystem->getGMirror(mirrorName);
117 if (gmirror == nullptr) {
118 log->error(ERR_G4MIRRORNOTFOUND, "mirror <", mirrorName, "> referenced by volume <",
119 volumeName, "> is not defined in system <", systemName, ">");
120 }
121
122 G4OpticalSurface* surface = getOrCreateOpticalSurface(systemName, gmirror);
123
124 const G4Volume* g4volume = getG4Volume(gvolume->getG4Name());
125 if (g4volume == nullptr) {
126 log->error(ERR_G4VOLUMEBUILDFAILED, "volume <", gvolume->getG4Name(),
127 "> referencing mirror <", mirrorName, "> was not built");
128 }
129
130 if (gmirror->isSkinSurface()) {
131 // The skin surface covers the entire logical volume boundary.
132 new G4LogicalSkinSurface(gvolume->getG4Name(), g4volume->getLogical(), surface);
133 nSkinSurfaces++;
134 log->info(2, "G4World: skin surface <", systemName, GSYSTEM_DELIMITER, mirrorName,
135 "> attached to volume <", gvolume->getG4Name(), ">");
136 }
137 else {
138 // The border surface applies to photons crossing from this volume into the
139 // border volume, which must belong to the same system.
140 std::string borderG4Name = systemName + GSYSTEM_DELIMITER + gmirror->getBorder();
141 const G4Volume* borderG4Volume = getG4Volume(borderG4Name);
142 if (borderG4Volume == nullptr || borderG4Volume->getPhysical() == nullptr) {
143 log->error(ERR_G4MIRRORNOTFOUND, "border volume <", borderG4Name,
144 "> of mirror <", mirrorName, "> referenced by volume <",
145 volumeName, "> is not built");
146 }
147 std::string surfaceName = gvolume->getG4Name() + "_to_" + borderG4Name;
148 new G4LogicalBorderSurface(surfaceName, g4volume->getPhysical(),
149 borderG4Volume->getPhysical(), surface);
150 nBorderSurfaces++;
151 log->info(2, "G4World: border surface <", surfaceName, "> using mirror <",
152 systemName, GSYSTEM_DELIMITER, mirrorName, ">");
153 }
154 }
155 }
156
157 if (nSkinSurfaces + nBorderSurfaces > 0) {
158 log->info(1, "G4World: created ", g4opticalSurfacesMap.size(), " optical surfaces, attached to ",
159 nSkinSurfaces, " skin and ", nBorderSurfaces, " border logical surfaces");
160 }
161}
162
163
164G4OpticalSurface* G4World::getOrCreateOpticalSurface(const std::string& systemName, const GMirror* gmirror) {
165 std::string surfaceKey = systemName + GSYSTEM_DELIMITER + gmirror->getName();
166
167 auto cached = g4opticalSurfacesMap.find(surfaceKey);
168 if (cached != g4opticalSurfacesMap.end()) { return cached->second; }
169
170 auto* surface = new G4OpticalSurface(surfaceKey);
171
172 // Surface type / finish / model: unknown strings are hard errors.
173 auto typeIt = surfaceTypesMap().find(gmirror->getType());
174 if (typeIt == surfaceTypesMap().end()) {
175 log->error(ERR_G4SURFACECONFIGINVALID, "mirror <", gmirror->getName(),
176 ">: unknown surface type <", gmirror->getType(), ">");
177 }
178 surface->SetType(typeIt->second);
179
180 auto finishIt = surfaceFinishesMap().find(gmirror->getFinish());
181 if (finishIt == surfaceFinishesMap().end()) {
182 log->error(ERR_G4SURFACECONFIGINVALID, "mirror <", gmirror->getName(),
183 ">: unknown surface finish <", gmirror->getFinish(), ">");
184 }
185 surface->SetFinish(finishIt->second);
186
187 auto modelIt = surfaceModelsMap().find(gmirror->getModel());
188 if (modelIt == surfaceModelsMap().end()) {
189 log->error(ERR_G4SURFACECONFIGINVALID, "mirror <", gmirror->getName(),
190 ">: unknown surface model <", gmirror->getModel(), ">");
191 }
192 surface->SetModel(modelIt->second);
193
194 // sigmaAlpha only applies to the unified/glisur roughness description.
195 if (gmirror->hasSigmaAlpha()) { surface->SetSigmaAlpha(gmirror->getSigmaAlpha()); }
196
197 // Boundary properties table: reuse the matOptProps material table, or build one
198 // from the mirror's own property vectors (validated at GMirror construction).
199 if (gmirror->usesMaterialOpticalProperties()) {
200 std::string materialName = gmirror->getMatOptProps();
201 G4Material* material = nullptr;
202
203 auto matIt = g4materialsMap.find(materialName);
204 if (matIt != g4materialsMap.end()) { material = matIt->second; }
205 else { material = G4NistManager::Instance()->FindMaterial(materialName); }
206
207 if (material == nullptr) {
208 log->error(ERR_G4MATERIALNOTFOUND, "mirror <", gmirror->getName(),
209 ">: matOptProps material <", materialName, "> not found");
210 }
211 if (material->GetMaterialPropertiesTable() == nullptr) {
212 log->error(ERR_G4SURFACECONFIGINVALID, "mirror <", gmirror->getName(),
213 ">: matOptProps material <", materialName, "> has no material properties table");
214 }
215 surface->SetMaterialPropertiesTable(material->GetMaterialPropertiesTable());
216 }
217 else {
218 auto* mpt = new G4MaterialPropertiesTable();
219
220 auto photonEnergy = gmirror->getPhotonEnergy();
221 auto addProperty = [&](const char* propertyName, const std::vector<double>& values) {
222 if (values.empty()) { return; }
223 mpt->AddProperty(propertyName, photonEnergy, values);
224 };
225
226 addProperty("RINDEX", gmirror->getIndexOfRefraction());
227 addProperty("REFLECTIVITY", gmirror->getReflectivity());
228 addProperty("EFFICIENCY", gmirror->getEfficiency());
229 addProperty("SPECULARLOBECONSTANT", gmirror->getSpecularLobe());
230 addProperty("SPECULARSPIKECONSTANT", gmirror->getSpecularSpike());
231 addProperty("BACKSCATTERCONSTANT", gmirror->getBackscatter());
232 addProperty("TRANSMITTANCE", gmirror->getTransmittance());
233
234 surface->SetMaterialPropertiesTable(mpt);
235 }
236
237 g4opticalSurfacesMap[surfaceKey] = surface;
238 log->info(1, "G4World: created optical surface <", surfaceKey, "> type <", gmirror->getType(),
239 ">, finish <", gmirror->getFinish(), ">, model <", gmirror->getModel(), ">");
240
241 return surface;
242}
Convenience container holding a Geant4 solid, logical, and physical volume.
Definition g4volume.h:52
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:123
std::shared_ptr< GLogger > log
void info(int level, Args &&... args) const
void error(int exit_code, Args &&... args) const
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.
#define ERR_G4VOLUMEBUILDFAILED
A volume could not be fully built (solid/logical/physical).
#define ERR_G4MATERIALNOTFOUND
Material lookup failed and no fallback was available.
#define ERR_G4MIRRORNOTFOUND
A volume references a mirror that is not defined in its system.
#define ERR_G4SURFACECONFIGINVALID
Optical surface type/finish/model/properties are invalid.
High-level builder that turns a GEMC world description into Geant4 geometry.
#define GSYSTEM_DELIMITER
std::map< std::string, SystemPtr > SystemMap
bool is_unset(std::string_view s)