diff --git a/DDG4/include/DDG4/Geant4GeometryInfo.h b/DDG4/include/DDG4/Geant4GeometryInfo.h index 31b6aa6e3..a2392170e 100644 --- a/DDG4/include/DDG4/Geant4GeometryInfo.h +++ b/DDG4/include/DDG4/Geant4GeometryInfo.h @@ -19,10 +19,13 @@ #include #include #include +#include + // C/C++ include files #include #include +#include // Forward declarations (TGeo) class TGeoElement; @@ -64,24 +67,19 @@ namespace dd4hep { * \ingroup DD4HEP_SIMULATION */ namespace Geant4GeometryMaps { - //typedef std::vector Geant4PlacementPath; - typedef std::map ElementMap; - typedef std::map IsotopeMap; - typedef std::map MaterialMap; - //typedef std::map LimitMap; - typedef std::map PlacementMap; - //typedef std::map RegionMap; - typedef std::map VolumeMap; - typedef std::map AssemblyMap; + typedef std::map ElementMap; + typedef std::map IsotopeMap; + typedef std::map MaterialMap; + typedef std::map PlacementMap; + typedef std::map VolumeMap; + typedef std::map AssemblyMap; - typedef std::vector VolumeChain; - typedef std::pair ImprintEntry; - typedef std::vector Imprints; - typedef std::map VolumeImprintMap; - typedef std::map SolidMap; - //typedef std::map VisMap; - //typedef std::map Geant4PathMap; - typedef std::map G4PlacementMap; + typedef std::vector PlacedVolumeChain; + typedef std::pair ImprintEntry; + typedef std::vector Imprints; + typedef std::map VolumeImprintMap; + typedef std::map SolidMap; + typedef std::map G4PlacementMap; } /// Concreate class holding the relation information between geant4 objects and dd4hep objects. @@ -92,22 +90,20 @@ namespace dd4hep { */ class Geant4GeometryInfo : public TNamed, public detail::GeoHandlerTypes::GeometryInfo { public: - struct Placement { - VolumeID volumeID; - int flags; - }; union PlacementFlags { - int value; - struct _flags { - unsigned parametrised:1; - unsigned replicated:1; - unsigned path_has_parametrised:1; - unsigned path_has_replicated:1; - } flags; - PlacementFlags() { this->value = 0; } - PlacementFlags(int v) { this->value = v; } + int value; + struct _flags { + unsigned parametrised:1; + unsigned replicated:1; + } flags; + PlacementFlags() { this->value = 0; } + PlacementFlags(int v) { this->value = v; } }; - typedef std::vector Geant4PlacementPath; + struct Placement { + VolumeID volumeID; + int flags; + }; + TGeoManager* manager = 0; Geant4GeometryMaps::IsotopeMap g4Isotopes; Geant4GeometryMaps::ElementMap g4Elements; @@ -126,35 +122,45 @@ namespace dd4hep { PropertyVector() = default; ~PropertyVector() = default; }; - std::map g4OpticalProperties; - std::map g4OpticalSurfaces; - std::map g4SkinSurfaces; - std::map g4BorderSurfaces; - std::map g4Regions; - std::map g4Vis; - std::map g4Limits; - std::map g4Paths; + std::map g4OpticalProperties; + std::map g4OpticalSurfaces; + std::map g4SkinSurfaces; + std::map g4BorderSurfaces; + std::map g4Regions; + std::map g4Vis; + std::map g4Limits; +#ifdef OLD_VOLMGR_TYPE + typedef std::vector Geant4PlacementPath; + std::map g4Paths; +#else + std::map g4Paths; +#endif std::map > sensitives; std::map > regions; std::map > limits; G4VPhysicalVolume* m_world; PrintLevel printLevel; + bool has_volmgr; bool valid; + + /// Assemble Geant4 volume path + static std::string placementPath(const Geant4TouchableHandler::Geant4PlacementPath& path, bool reverse=true) { + return Geant4TouchableHandler::placementPath(path, reverse); + } + private: friend class Geant4Mapping; /// Default constructor Geant4GeometryInfo(); /// Default destructor virtual ~Geant4GeometryInfo(); + public: /// The world placement G4VPhysicalVolume* world() const; /// Set the world volume void setWorld(const TGeoNode* node); - /// Assemble Geant4 volume path - static std::string placementPath(const Geant4PlacementPath& path, bool reverse=true); }; - } // End namespace sim } // End namespace dd4hep #endif // DDG4_GEANT4GEOMETRYINFO_H diff --git a/DDG4/include/DDG4/Geant4TouchableHandler.h b/DDG4/include/DDG4/Geant4TouchableHandler.h index 0be5a58c1..37b6e38e2 100644 --- a/DDG4/include/DDG4/Geant4TouchableHandler.h +++ b/DDG4/include/DDG4/Geant4TouchableHandler.h @@ -55,6 +55,9 @@ namespace dd4hep { /// Default constructor. Takes the step's pre-touchable Geant4TouchableHandler(const G4Step* step, bool use_post_step_point); + /// Assemble Geant4 volume path + static std::string placementPath(const Geant4PlacementPath& path, bool reverse=true); + /// Helper: Generate placement path from touchable object Geant4PlacementPath placementPath(bool exception=false) const; diff --git a/DDG4/include/DDG4/Geant4VolumeManager.h b/DDG4/include/DDG4/Geant4VolumeManager.h index 02027ad3e..e162be4a0 100644 --- a/DDG4/include/DDG4/Geant4VolumeManager.h +++ b/DDG4/include/DDG4/Geant4VolumeManager.h @@ -18,7 +18,9 @@ #include #include +// Geant4 include files #include + // Geant4 forward declarations class G4VPhysicalVolume; @@ -68,8 +70,6 @@ namespace dd4hep { /// Helper: Generate placement path from touchable object std::vector placementPath(const G4VTouchable* touchable, bool exception = true) const; - /// Access CELLID by placement path - //VolumeID volumeID(const std::vector& path) const; /// Access CELLID by Geant4 touchable object VolumeID volumeID(const G4VTouchable* touchable) const; /// Accessfully decoded volume fields by placement path @@ -79,7 +79,6 @@ namespace dd4hep { void volumeDescriptor(const G4VTouchable* touchable, std::pair > >& volume_desc) const; }; - } // End namespace sim } // End namespace dd4hep #endif // DDG4_GEANT4VOLUMEMANAGER_H diff --git a/DDG4/src/Geant4AssemblyVolume.cpp b/DDG4/src/Geant4AssemblyVolume.cpp index 4055636e7..95b1d784b 100644 --- a/DDG4/src/Geant4AssemblyVolume.cpp +++ b/DDG4/src/Geant4AssemblyVolume.cpp @@ -86,7 +86,7 @@ void Geant4AssemblyVolume::imprint(const Geant4Converter& cnv, path = detail::tools::placementPath(chain); printout(cnv.debugPlacements ? ALWAYS : DEBUG, "Geant4Converter", - "++ Assembly: %s", path.c_str()); + "++ Assembly: %s", path.c_str()); std::vector::iterator iter = par_ass->GetTripletsIterator(); for( unsigned int i = 0, n = par_ass->TotalTriplets(); i < n; i++, iter++ ) { Chain new_chain = chain; @@ -97,14 +97,14 @@ void Geant4AssemblyVolume::imprint(const Geant4Converter& cnv, new_chain.emplace_back(node); path = detail::tools::placementPath(new_chain); printout(cnv.debugPlacements ? ALWAYS : DEBUG, "Geant4Converter", - " Assembly: Entry: %s", path.c_str()); + " Assembly: Entry: %s", path.c_str()); G4Transform3D Ta( *(triplet.GetRotation()), triplet.GetTranslation() ); - if ( triplet.IsReflection() ) { + if( triplet.IsReflection() ) { Ta = Ta * G4ReflectZ3D(); } G4Transform3D Tfinal = transformation * Ta; - if ( triplet.GetVolume() ) { + if( triplet.GetVolume() ) { // Generate the unique name for the next PV instance // The name has format: // @@ -119,9 +119,9 @@ void Geant4AssemblyVolume::imprint(const Geant4Converter& cnv, pvName << "AV_" << m_assembly->GetAssemblyID() << '!' - << parent->GetName() - << '#' - << parent->GetNumber() + << parent->GetName() + << '#' + << parent->GetNumber() << '!' << node->GetName() << '#' @@ -140,24 +140,24 @@ void Geant4AssemblyVolume::imprint(const Geant4Converter& cnv, node->GetNumber(), surfCheck ); - info.g4VolumeImprints[vol].emplace_back(new_chain,pvPlaced.first); + info.g4VolumeImprints[vol].emplace_back(new_chain, pvPlaced.first); printout(cnv.debugPlacements ? ALWAYS : DEBUG, - "Geant4Converter", "++ Place %svolume %s in assembly.", - triplet.IsReflection() ? "REFLECTED " : "", path.c_str()); + "Geant4Converter", "++ Place %svolume %s in assembly.", + triplet.IsReflection() ? "REFLECTED " : "", path.c_str()); printout(cnv.debugPlacements ? ALWAYS : DEBUG, - "Geant4Converter", " Assembly:Parent: %s %s %p G4:%s", - parent->GetName(), node->GetName(), - (void*)node, pvName.str().c_str()); - if ( pvPlaced.second ) { + "Geant4Converter", " Assembly:Parent: %s %s %p G4:%s", + parent->GetName(), node->GetName(), + (void*)node, pvName.str().c_str()); + if( pvPlaced.second ) { G4Exception("Geant4AssemblyVolume::imprint(..)", "GeomVol0003", FatalException, "Fancy construct popping new mother from the stack!"); } } - else if ( triplet.GetAssembly() ) { + else if( triplet.GetAssembly() ) { // Place volumes in this assembly with composed transformation imprint(cnv, parent, std::move(new_chain), avol, pMotherLV, Tfinal, surfCheck ); } - else { + else { G4Exception("Geant4AssemblyVolume::imprint(..)", "GeomVol0003", FatalException, "Triplet has no volume and no assembly"); } diff --git a/DDG4/src/Geant4Converter.cpp b/DDG4/src/Geant4Converter.cpp index 56ea36de8..ce4de2fd4 100644 --- a/DDG4/src/Geant4Converter.cpp +++ b/DDG4/src/Geant4Converter.cpp @@ -745,7 +745,9 @@ void* Geant4Converter::handleVolume(const std::string& name, const TGeoVolume* v PrintLevel lvl = debugVolumes ? ALWAYS : outputLevel; Geant4GeometryMaps::VolumeMap::const_iterator volIt = info.g4Volumes.find(volume); if ( _v.testFlagBit(Volume::VETO_SIMU) ) { - printout(lvl, "Geant4Converter", "++ Volume %s not converted [Veto'ed for simulation]",volume->GetName()); + printout(lvl, "Geant4Converter", + "++ Volume %s not converted [Veto'ed for simulation]", + volume->GetName()); return nullptr; } else if (volIt == info.g4Volumes.end() ) { @@ -786,7 +788,7 @@ void* Geant4Converter::handleVolume(const std::string& name, const TGeoVolume* v G4LogicalVolume* g4vol = nullptr; if( _v.hasProperties() && !_v.getProperty(GEANT4_TAG_PLUGIN,"").empty() ) { - Detector* det = const_cast(&m_detDesc); + Detector* det = const_cast(&m_detDesc); std::string plugin = _v.getProperty(GEANT4_TAG_PLUGIN,""); g4vol = PluginService::Create(plugin, det, _v, g4solid, g4medium); if ( !g4vol ) { @@ -800,8 +802,9 @@ void* Geant4Converter::handleVolume(const std::string& name, const TGeoVolume* v /// Set smartless optimization unsigned char smart_less_value = _v.smartlessValue(); if( smart_less_value != Volume::NO_SMARTLESS_OPTIMIZATION ) { - printout(ALWAYS, "Geant4Converter", "++ Volume %s Set Smartless value to %d", - vnam, int(smart_less_value)); + printout(ALWAYS, "Geant4Converter", + "++ Volume %s Set Smartless value to %d", + vnam, int(smart_less_value)); g4vol->SetSmartless( smart_less_value ); } /// Assign limits if necessary @@ -809,8 +812,9 @@ void* Geant4Converter::handleVolume(const std::string& name, const TGeoVolume* v g4vol->SetUserLimits(g4limits); } if( g4region ) { - printout(plevel, "Geant4Converter", "++ Volume + Apply REGION settings: %-24s to volume %s.", - reg.name(), vnam); + printout(plevel, "Geant4Converter", + "++ Volume + Apply REGION settings: %-24s to volume %s.", + reg.name(), vnam); // Handle the region settings for the world volume seperately. // Geant4 does NOT WANT any regions assigned to the workd volume. // The world's region is created in the G4RunManagerKernel! diff --git a/DDG4/src/Geant4GeometryInfo.cpp b/DDG4/src/Geant4GeometryInfo.cpp index 666df2fa8..20fe5bb1c 100644 --- a/DDG4/src/Geant4GeometryInfo.cpp +++ b/DDG4/src/Geant4GeometryInfo.cpp @@ -21,21 +21,6 @@ using namespace dd4hep::sim; -std::string Geant4GeometryInfo::placementPath(const Geant4PlacementPath& path, bool reverse) { - std::string path_name; - if ( reverse ) { - for (Geant4PlacementPath::const_reverse_iterator pIt = path.rbegin(); pIt != path.rend(); ++pIt) { - path_name += "/"; path_name += (*pIt)->GetName(); - } - } - else { - for (Geant4PlacementPath::const_iterator pIt = path.begin(); pIt != path.end(); ++pIt) { - path_name += "/"; path_name += (*pIt)->GetName(); - } - } - return path_name; -} - /// Default constructor Geant4GeometryInfo::Geant4GeometryInfo() : TNamed("Geant4GeometryInfo", "Geant4GeometryInfo"), m_world(0), printLevel(DEBUG), valid(false) { diff --git a/DDG4/src/Geant4Mapping.cpp b/DDG4/src/Geant4Mapping.cpp index 490f8bd71..fc8abd32f 100644 --- a/DDG4/src/Geant4Mapping.cpp +++ b/DDG4/src/Geant4Mapping.cpp @@ -68,7 +68,7 @@ void Geant4Mapping::attach(Geant4GeometryInfo* data_ptr) { /// Access the volume manager Geant4VolumeManager Geant4Mapping::volumeManager() const { if ( m_dataPtr ) { - if ( m_dataPtr->g4Paths.empty() ) { + if ( m_dataPtr->has_volmgr ) { return Geant4VolumeManager(m_detDesc, m_dataPtr); } return Geant4VolumeManager(Handle < Geant4GeometryInfo > (m_dataPtr)); diff --git a/DDG4/src/Geant4TouchableHandler.cpp b/DDG4/src/Geant4TouchableHandler.cpp index c18367704..b6a48060b 100644 --- a/DDG4/src/Geant4TouchableHandler.cpp +++ b/DDG4/src/Geant4TouchableHandler.cpp @@ -54,8 +54,24 @@ Geant4TouchableHandler::Geant4PlacementPath Geant4TouchableHandler::placementPat return path_val; } +/// Assemble Geant4 volume path +std::string Geant4TouchableHandler::placementPath(const Geant4PlacementPath& path, bool reverse) { + std::string path_name; + if ( reverse ) { + for (Geant4PlacementPath::const_reverse_iterator pIt = path.rbegin(); pIt != path.rend(); ++pIt) { + path_name += "/"; path_name += (*pIt)->GetName(); + } + } + else { + for (Geant4PlacementPath::const_iterator pIt = path.begin(); pIt != path.end(); ++pIt) { + path_name += "/"; path_name += (*pIt)->GetName(); + } + } + return path_name; +} + /// Helper: Access the placement path of a Geant4 touchable object as a string std::string Geant4TouchableHandler::path() const { - return Geant4GeometryInfo::placementPath(this->placementPath()); + return Geant4TouchableHandler::placementPath(this->placementPath()); } diff --git a/DDG4/src/Geant4VolumeManager.cpp b/DDG4/src/Geant4VolumeManager.cpp index a24ee1e5e..a89949b46 100644 --- a/DDG4/src/Geant4VolumeManager.cpp +++ b/DDG4/src/Geant4VolumeManager.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include #include @@ -37,10 +39,16 @@ using VolIDDescriptor = std::pair Chain; - typedef std::map Registries; + // typedef std::map Registries; + typedef std::set Registries; /// Reference to the Detector instance const Detector& m_detDesc; @@ -51,16 +59,32 @@ namespace { /// Default constructor Populator(const Detector& description, Geant4GeometryInfo& g) - : m_detDesc(description), m_geo(g) { + : m_detDesc(description), m_geo(g) + { + } + + typedef std::pair Encoding; + /// Compute the encoding for a set of VolIDs within a readout descriptor + static Encoding encoding(const IDDescriptor iddesc, const PlacedVolume::VolIDs& ids) { + VolumeID volume_id = 0, mask = 0; + for( const auto& id : ids ) { + const BitFieldElement* f = iddesc.field(id.first); + VolumeID msk = f->mask(); + int off = f->offset(); + VolumeID val = id.second; // Necessary to extend volume IDs > 32 bit + volume_id |= ((f->value(val << off) << off)&msk); + mask |= msk; + } + return std::make_pair(volume_id, mask); } /// Populate the Volume manager - void populate(DetElement e) { + void populate(DetElement e) { const DetElement::Children& c = e.children(); - for (const auto& i : c) { + for( const auto& i : c ) { DetElement de = i.second; PlacedVolume pv = de.placement(); - if (pv.isValid()) { + if( pv.isValid() ) { Chain chain; SensitiveDetector sd; PlacedVolume::VolIDs ids; @@ -70,15 +94,17 @@ namespace { continue; } printout(WARNING, "Geant4VolumeManager", - "++ Detector element %s of type %s has no placement.", de.name(), de.type().c_str()); + "++ Detector element %s of type %s has no placement.", + de.name(), de.type().c_str()); } /// Needed to compute the cellID of parameterized volumes for( const auto& pv : m_geo.g4Placements ) { - if ( pv.second->IsParameterised() ) + if( pv.second->IsParameterised() ) m_geo.g4Parameterised[pv.second] = pv.first; - if ( pv.second->IsReplicated() ) + if( pv.second->IsReplicated() ) m_geo.g4Replicated[pv.second] = pv.first; } + m_entries.clear(); } /// Scan a single physical volume and look for sensitive elements below @@ -89,21 +115,21 @@ namespace { chain.emplace_back(node); ids.PlacedVolume::VolIDs::Base::insert(ids.end(), pv_ids.begin(), pv_ids.end()); - if (vol.isSensitive()) { + if( vol.isSensitive() ) { sd = vol.sensitiveDetector(); - if (sd.readout().isValid()) { + if( sd.readout().isValid() ) { add_entry(sd, node, ids, chain); } - else { + else { printout(WARNING, "Geant4VolumeManager", "populate: Strange constellation volume %s is sensitive, but has no readout! sd:%p", pv.volume().name(), sd.ptr()); } } - for (Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) { + for( Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau ) { TGeoNode* daughter = node->GetDaughter(idau); PlacedVolume placement(daughter); - if ( placement.data() ) { + if( placement.data() ) { scanPhysicalVolume(daughter, ids, sd, chain); } } @@ -111,26 +137,25 @@ namespace { } void add_entry(SensitiveDetector sd, const TGeoNode* n, const PlacedVolume::VolIDs& ids, const Chain& nodes) { - Chain control; - Volume vol; - const TGeoNode* node = nullptr; - Readout ro = sd.readout(); - IDDescriptor iddesc = ro.idSpec(); - VolumeID code = iddesc.encode(ids); - Geant4GeometryInfo::Geant4PlacementPath path; - Registries::const_iterator i = m_entries.find(code); + Chain control; + Volume vol; + Readout rdout = sd.readout(); + IDDescriptor iddesc = rdout.idSpec(); + VolumeID code = iddesc.encode(ids); PrintLevel print_level = m_geo.printLevel; PrintLevel print_action = print_level; PrintLevel print_chain = print_level; PrintLevel print_res = print_level; + Geant4TouchableHandler::Geant4PlacementPath path; + Registries::const_iterator i = m_entries.find(code); printout(print_action,"Geant4VolumeManager","+++ Add path:%s vid:%016X", - detail::tools::placementPath(nodes,false).c_str(),code); + detail::tools::placementPath(nodes, false).c_str(), code); if( i == m_entries.end() ) { path.reserve(nodes.size()); for( Chain::const_reverse_iterator k = nodes.rbegin(), kend=nodes.rend(); k != kend; ++k ) { - node = *(k); + const TGeoNode* node = *(k); auto g4pit = m_geo.g4Placements.find(node); if( g4pit != m_geo.g4Placements.end() ) { G4VPhysicalVolume* phys = g4pit->second; @@ -142,8 +167,8 @@ namespace { } } path.emplace_back(phys); - printout(print_chain, "Geant4VolumeManager", "+++ Chain: Node OK: %s [%s]", - node->GetName(), phys->GetName().c_str()); + printout(print_chain, "Geant4VolumeManager", + "+++ Chain: Node OK: %s [%s]", node->GetName(), phys->GetName().c_str()); continue; } control.insert(control.begin(),node); @@ -165,20 +190,17 @@ namespace { } if ( control.empty() ) { printout(print_res, "Geant4VolumeManager", "+++ Volume IDs:%s", - detail::tools::toString(ro.idSpec(),ids,code).c_str()); + detail::tools::toString(rdout.idSpec(),ids,code).c_str()); path.erase(path.begin()+path.size()-1); printout(print_res, "Geant4VolumeManager", "+++ Map %016X to Geant4 Path:%s", - (void*)code, Geant4GeometryInfo::placementPath(path).c_str()); - if ( m_geo.g4Paths.find(path) == m_geo.g4Paths.end() ) { + (void*)code, Geant4TouchableHandler::placementPath(path).c_str()); + auto hash = detail::hash64(&path[0], path.size()*sizeof(path[0])); + if ( m_geo.g4Paths.find(hash) == m_geo.g4Paths.end() ) { Geant4GeometryInfo::PlacementFlags opt; - for(const auto* phys : path) { - opt.flags.path_has_parametrised = phys->IsParameterised() ? 1 : 0; - opt.flags.path_has_replicated = phys->IsReplicated() ? 1 : 0; - } opt.flags.parametrised = path.front()->IsParameterised() ? 1 : 0; opt.flags.replicated = path.front()->IsReplicated() ? 1 : 0; - m_geo.g4Paths[path] = { code, opt.value }; - m_entries.emplace(code,path); + m_geo.g4Paths[hash] = { code, opt.value }; + m_entries.emplace(code); return; } /// This is a normal case for parametrized volumes and no error @@ -186,11 +208,11 @@ namespace { return; } printout(ERROR, "Geant4VolumeManager", "populate: Severe error: Duplicated Geant4 path!!!! %s %s", - " [THIS SHOULD NEVER HAPPEN]",Geant4GeometryInfo::placementPath(path).c_str()); + " [THIS SHOULD NEVER HAPPEN]", Geant4TouchableHandler::placementPath(path).c_str()); goto Err; } printout(INFO, "Geant4VolumeManager", "Control block has still %d entries:%s", - int(control.size()),detail::tools::placementPath(control,true).c_str()); + int(control.size()), detail::tools::placementPath(control,true).c_str()); goto Err; } else { @@ -204,12 +226,12 @@ namespace { Err: if ( i != m_entries.end() ) - printout(ERROR,"Geant4VolumeManager"," Known G4 path: %s",Geant4GeometryInfo::placementPath((*i).second).c_str()); + printout(ERROR,"Geant4VolumeManager"," Known G4 path: %s", Geant4TouchableHandler::placementPath(path).c_str()); if ( !path.empty() ) - printout(ERROR,"Geant4VolumeManager"," New G4 path: %s",Geant4GeometryInfo::placementPath(path).c_str()); + printout(ERROR,"Geant4VolumeManager"," New G4 path: %s", Geant4TouchableHandler::placementPath(path).c_str()); if ( !nodes.empty() ) - printout(ERROR,"Geant4VolumeManager"," TGeo path: %s",detail::tools::placementPath(nodes,false).c_str()); - printout(ERROR,"Geant4VolumeManager", " Offend.VolIDs: %s",detail::tools::toString(ro.idSpec(),ids,code).c_str()); + printout(ERROR,"Geant4VolumeManager"," TGeo path: %s", detail::tools::placementPath(nodes,false).c_str()); + printout(ERROR,"Geant4VolumeManager", " Offend.VolIDs: %s", detail::tools::toString(rdout.idSpec(),ids,code).c_str()); throw std::runtime_error("Failed to populate Geant4 volume manager!"); } }; @@ -218,9 +240,12 @@ namespace { /// Initializing constructor. The tree will automatically be built if possible Geant4VolumeManager::Geant4VolumeManager(const Detector& description, Geant4GeometryInfo* info) : Handle(info) { - if (info && info->valid && info->g4Paths.empty()) { - Populator p(description, *info); - p.populate(description.world()); + if( info && info->valid ) { + if( !info->has_volmgr ) { + Populator p(description, *info); + p.populate(description.world()); + info->has_volmgr = true; + } return; } except("Geant4VolumeManager", "Attempt populate from invalid Geant4 geometry info [Invalid-Info]"); @@ -228,56 +253,37 @@ Geant4VolumeManager::Geant4VolumeManager(const Detector& description, Geant4Geom /// Helper: Generate placement path from touchable object std::vector -Geant4VolumeManager::placementPath(const G4VTouchable* touchable, bool exception) const { +Geant4VolumeManager::placementPath(const G4VTouchable* touchable, bool exception) const { Geant4TouchableHandler handler(touchable); return handler.placementPath(exception); } /// Check the validity of the information before accessing it. -bool Geant4VolumeManager::checkValidity() const { - if (!isValid()) { +bool Geant4VolumeManager::checkValidity() const { + if( !isValid() ) { except("Geant4VolumeManager", "Attempt to use invalid Geant4 volume manager [Invalid-Handle]"); } - else if (!ptr()->valid) { + else if( !ptr()->valid ) { except("Geant4VolumeManager", "Attempt to use invalid Geant4 geometry info [Invalid-Info]"); } return true; } -#if 0 -/// Access CELLID by placement path -VolumeID Geant4VolumeManager::volumeID(const std::vector& path) const { - if (!path.empty() && checkValidity()) { - const auto& mapping = ptr()->g4Paths; - auto i = mapping.find(path); - if ( i != mapping.end() ) { - return (*i).second.first; - } - if (!path[0]) - return InvalidPath; - else if (!path[0]->GetLogicalVolume()->GetSensitiveDetector()) - return Insensitive; - } - printout(INFO, "Geant4VolumeManager","+++ Bad volume Geant4 Path: %s", - Geant4GeometryInfo::placementPath(path).c_str()); - return NonExisting; -} -#endif - /// Access CELLID by Geant4 touchable object -VolumeID Geant4VolumeManager::volumeID(const G4VTouchable* touchable) const { +VolumeID Geant4VolumeManager::volumeID(const G4VTouchable* touchable) const { Geant4TouchableHandler handler(touchable); std::vector path = handler.placementPath(); - if( !path.empty() && checkValidity() ) { - const auto& mapping = ptr()->g4Paths; - auto i = mapping.find(path); - if( i != mapping.end() ) { + + if( checkValidity() && !path.empty() ) { + auto hash = detail::hash64(&path[0], sizeof(path[0])*path.size()); + auto i = ptr()->g4Paths.find(hash); + if( i != ptr()->g4Paths.end() ) { const auto& e = (*i).second; + VolumeID volid = e.volumeID; /// No parametrization or replication. if( e.flags == 0 ) { - return e.volumeID; + return volid; } - VolumeID volid = e.volumeID; const auto& paramterised = ptr()->g4Parameterised; const auto& replicated = ptr()->g4Replicated; /// This is incredibly slow .... but what can I do ? Need a better idea. @@ -293,7 +299,8 @@ VolumeID Geant4VolumeManager::volumeID(const G4VTouchable* touchable) const { volid |= IDDescriptor::encode(field, copy_no); continue; } - except("Geant4VolumeManager","Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)"); + except("Geant4VolumeManager", + "Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)"); } else if( phys->IsReplicated() ) { int copy_no = touchable->GetCopyNumber(j); @@ -303,7 +310,8 @@ VolumeID Geant4VolumeManager::volumeID(const G4VTouchable* touchable) const { volid |= IDDescriptor::encode(field, copy_no); continue; } - except("Geant4VolumeManager","Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)"); + except("Geant4VolumeManager", + "Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)"); } } return volid; @@ -313,8 +321,8 @@ VolumeID Geant4VolumeManager::volumeID(const G4VTouchable* touchable) const { else if( !path[0]->GetLogicalVolume()->GetSensitiveDetector() ) return Insensitive; } - printout(INFO, "Geant4VolumeManager","+++ Bad volume Geant4 Path: %s", - Geant4GeometryInfo::placementPath(path).c_str()); + printout(INFO, "Geant4VolumeManager", "+++ Bad volume Geant4 Path: %s", + Geant4TouchableHandler::placementPath(path).c_str()); return NonExisting; } @@ -325,9 +333,9 @@ void Geant4VolumeManager::volumeDescriptor(const std::vectorg4Paths; - auto i = mapping.find(path); - if( i != mapping.end() ) { + auto hash = detail::hash64(&path[0], sizeof(path[0])*path.size()); + auto i = ptr()->g4Paths.find(hash); + if( i != ptr()->g4Paths.end() ) { VolumeID vid = (*i).second.volumeID; G4LogicalVolume* lvol = path[0]->GetLogicalVolume(); if( lvol->GetSensitiveDetector() ) { @@ -361,3 +369,4 @@ void Geant4VolumeManager::volumeDescriptor(const G4VTouchable* touchable, VolIDDescriptor& vol_desc) const { volumeDescriptor(placementPath(touchable), vol_desc); } +