From 94f51fae8f56684e72b483d9624ee32d7d536285 Mon Sep 17 00:00:00 2001 From: Markus Frank <Markus.Frank@cern.ch> Date: Wed, 7 Mar 2018 12:19:51 +0100 Subject: [PATCH] Implement per particle limits in DDG4 --- DDCore/include/DD4hep/IOV.h | 15 ++-- DDCore/include/DD4hep/Objects.h | 6 ++ DDCore/src/IOV.cpp | 12 +-- DDG4/include/DDG4/Geant4UserLimits.h | 103 ++++++++++++++++++++++++++ DDG4/src/Geant4Converter.cpp | 9 ++- DDG4/src/Geant4UserLimits.cpp | 107 +++++++++++++++++++++++++++ 6 files changed, 238 insertions(+), 14 deletions(-) create mode 100644 DDG4/include/DDG4/Geant4UserLimits.h create mode 100644 DDG4/src/Geant4UserLimits.cpp diff --git a/DDCore/include/DD4hep/IOV.h b/DDCore/include/DD4hep/IOV.h index fbcbeca03..8cdf334a2 100644 --- a/DDCore/include/DD4hep/IOV.h +++ b/DDCore/include/DD4hep/IOV.h @@ -71,12 +71,17 @@ namespace dd4hep { typedef long Key_second_type; typedef std::pair<Key_first_type,Key_second_type> Key; - const IOVType* iovType; - Key keyData; - int optData; - /// IOV buffer type: Must be a bitmap! - unsigned int type; + enum { INVALID_KEY = 0 }; + /// Reference to IOV type + const IOVType* iovType = 0; + /// IOV key (if second==first, discrete, otherwise range) + Key keyData{INVALID_KEY,INVALID_KEY}; + /// Optional user data + int optData = 0; + /// IOV buffer type: Must be a bitmap! + unsigned int type = IOVType::UNKNOWN_IOV; + /// Initializing constructor explicit IOV(const IOVType* typ); /// Specialized copy constructor for range IOVs diff --git a/DDCore/include/DD4hep/Objects.h b/DDCore/include/DD4hep/Objects.h index d699a8753..5f207d2c7 100644 --- a/DDCore/include/DD4hep/Objects.h +++ b/DDCore/include/DD4hep/Objects.h @@ -362,11 +362,17 @@ namespace dd4hep { */ class Limit { public: + /// Particle the limit should be applied to std::string particles; + /// Limit name std::string name; + /// Units std::string unit; + /// Content std::string content; + /// Double value double value = 0.0; + public: /// Default constructor Limit() = default; /// Copy constructor diff --git a/DDCore/src/IOV.cpp b/DDCore/src/IOV.cpp index e5be1dd33..f52c1a9ec 100644 --- a/DDCore/src/IOV.cpp +++ b/DDCore/src/IOV.cpp @@ -41,22 +41,22 @@ std::string IOVType::str() const { } /// Initializing constructor -IOV::IOV(const IOVType* t) : iovType(t), keyData(0,0), optData(0) { - type = t ? t->type : int(IOVType::UNKNOWN_IOV); +IOV::IOV(const IOVType* t) : iovType(t) { + if ( t ) type = t->type; } /// Specialized copy constructor for discrete IOVs IOV::IOV(const IOVType* t, Key_first_type iov_value) - : iovType(t), keyData(iov_value,iov_value), optData(0) + : iovType(t), keyData(iov_value,iov_value) { - type = t ? t->type : int(IOVType::UNKNOWN_IOV); + if ( t ) type = t->type; } /// Copy constructor IOV::IOV(const IOVType* t, const Key& k) - : iovType(t), keyData(k), optData(0) + : iovType(t), keyData(k) { - type = t ? t->type : int(IOVType::UNKNOWN_IOV); + if ( t ) type = t->type; } /// Set discrete IOV value diff --git a/DDG4/include/DDG4/Geant4UserLimits.h b/DDG4/include/DDG4/Geant4UserLimits.h new file mode 100644 index 000000000..48dc389c6 --- /dev/null +++ b/DDG4/include/DDG4/Geant4UserLimits.h @@ -0,0 +1,103 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== +#ifndef DD4HEP_DDG4_GEANT4USERLIMITS_H +#define DD4HEP_DDG4_GEANT4USERLIMITS_H + +// Framework include files +#include "DD4hep/Objects.h" + +// Geant 4 include files +#include "G4UserLimits.hh" + +// Forward declarations +class G4ParticleDefinition; + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + + /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit + namespace sim { + + /// Helper to dump Geant4 volume hierarchy + /** + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class Geant4UserLimits : public G4UserLimits { + public: + /// Helper class to one limit type + /** + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + struct Handler { + public: + /// Default value (either from base class or value if Limit.particles='*') + double defaultValue = 0.0; + /// Handler particle ids for the limit (pdgID) + std::map<const G4ParticleDefinition*, double> particleLimits; + public: + /// Default constructor + Handler() = default; + /// Set the handler value(s) + void set(const std::string& particles, double val); + /// Access value according to track + double value(const G4Track& track) const; + }; + /// Handle to the limitset to be applied. + LimitSet limits; + /// Handler map for MaxStepLength limit + Handler maxStepLength; + /// Handler map for MaxTrackLength limit + Handler maxTrackLength; + /// Handler map for MaxTime limit + Handler maxTime; + /// Handler map for MinEKine limit + Handler minEKine; + /// Handler map for MinRange limit + Handler minRange; + + public: + /// Initializing Constructor + Geant4UserLimits(LimitSet ls); + /// Standard destructor + virtual ~Geant4UserLimits(); + /// Access the user tracklength for a G4 track object + virtual G4double GetMaxAllowedStep(const G4Track& track) + { return maxStepLength.value(track); } + /// Access the user tracklength for a G4 track object + virtual G4double GetUserMaxTrackLength(const G4Track& track) + { return maxTrackLength.value(track); } + /// Access the proper time cut for a G4 track object + virtual G4double GetUserMaxTime (const G4Track& track) + { return maxTime.value(track); } + /// Access the kinetic energy cut for a G4 track object + virtual G4double GetUserMinEkine(const G4Track& track) + { return minEKine.value(track); } + /// Access the range cut for a G4 track object + virtual G4double GetUserMinRange(const G4Track& track) + { return minRange.value(track); } + /// Setters may not be called! + virtual void SetMaxAllowedStep(G4double ustepMax); + virtual void SetUserMaxTrackLength(G4double utrakMax); + virtual void SetUserMaxTime(G4double utimeMax); + virtual void SetUserMinEkine(G4double uekinMin); + virtual void SetUserMinRange(G4double urangMin); + }; + } +} + +#endif // DD4HEP_DDG4_GEANT4USERLIMITS_H diff --git a/DDG4/src/Geant4Converter.cpp b/DDG4/src/Geant4Converter.cpp index 154db9353..6fe49ace5 100644 --- a/DDG4/src/Geant4Converter.cpp +++ b/DDG4/src/Geant4Converter.cpp @@ -22,6 +22,7 @@ #include "DDG4/Geant4Field.h" #include "DDG4/Geant4Converter.h" +#include "DDG4/Geant4UserLimits.h" #include "DDG4/Geant4SensitiveDetector.h" // ROOT includes @@ -856,11 +857,12 @@ void* Geant4Converter::handleRegion(Region region, const set<const TGeoVolume*>& void* Geant4Converter::handleLimitSet(LimitSet limitset, const set<const TGeoVolume*>& /* volumes */) const { G4UserLimits* g4 = data().g4Limits[limitset]; if (!g4) { + g4 = new Geant4UserLimits(limitset); + /* LimitSet ls = limitset; - g4 = new G4UserLimits(limitset->GetName()); + g4 = new G4UserLimits(limitset); const set<Limit>& limits = ls.limits(); - for (LimitSet::Object::const_iterator i = limits.begin(); i != limits.end(); ++i) { - const Limit& l = *i; + for (const auto& l : limits) { if (l.name == "step_length_max") g4->SetMaxAllowedStep(l.value*CLHEP::mm/units::mm); else if (l.name == "track_length_max") @@ -874,6 +876,7 @@ void* Geant4Converter::handleLimitSet(LimitSet limitset, const set<const TGeoVol else throw runtime_error("Unknown Geant4 user limit: " + l.toString()); } + */ data().g4Limits[limitset] = g4; } return g4; diff --git a/DDG4/src/Geant4UserLimits.cpp b/DDG4/src/Geant4UserLimits.cpp new file mode 100644 index 000000000..659dc7e56 --- /dev/null +++ b/DDG4/src/Geant4UserLimits.cpp @@ -0,0 +1,107 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "DDG4/Geant4UserLimits.h" +#include "DDG4/Geant4Particle.h" +#include "DD4hep/InstanceCount.h" +#include "DD4hep/DD4hepUnits.h" +#include "DD4hep/Primitives.h" + +// Geant 4 include files +#include "G4Track.hh" +#include "CLHEP/Units/SystemOfUnits.h" + +// C/C++ include files +#include <stdexcept> + +using namespace std; +using namespace dd4hep::sim; + +/// Access value according to track +double Geant4UserLimits::Handler::value(const G4Track& track) const { + if ( !particleLimits.empty() ) { + auto i = particleLimits.find(track.GetDefinition()); + if ( i != particleLimits.end() ) { + return (*i).second; + } + } + return defaultValue; +} + +/// Set the handler value(s) +void Geant4UserLimits::Handler::set(const string& particles, double val) { + if ( particles == "*" ) { + defaultValue = val; + return; + } + auto defs = Geant4ParticleHandle::g4DefinitionsRegEx(particles); + for(auto* d : defs) + particleLimits[d] = val; +} + +/// Initializing Constructor +Geant4UserLimits::Geant4UserLimits(LimitSet ls) + : G4UserLimits(ls.name()), limits(ls) +{ + const auto& lim = limits.limits(); + InstanceCount::increment(this); + /// Set defaults + maxStepLength.defaultValue = fMaxStep; + maxTrackLength.defaultValue = fMaxTrack; + maxTime.defaultValue = fMaxTime; + minEKine.defaultValue = fMinEkine; + minRange.defaultValue = fMinRange; + /// Overwrite with values if present: + for(const Limit& l : lim) { + if (l.name == "step_length_max") + maxStepLength.set(l.particles, l.value*CLHEP::mm/dd4hep::mm); + else if (l.name == "track_length_max") + maxTrackLength.set(l.particles, l.value*CLHEP::mm/dd4hep::mm); + else if (l.name == "time_max") + maxTime.set(l.particles, l.value*CLHEP::ns/dd4hep::ns); + else if (l.name == "ekin_min") + minEKine.set(l.particles, l.value*CLHEP::MeV/dd4hep::MeV); + else if (l.name == "range_min") + minRange.set(l.particles, l.value); + else + throw runtime_error("Unknown Geant4 user limit: " + l.toString()); + } +} + +/// Standard destructor +Geant4UserLimits::~Geant4UserLimits() { + InstanceCount::decrement(this); +} + +/// Setters may not be called! +void Geant4UserLimits::SetMaxAllowedStep(G4double /* ustepMax */) { + dd4hep::notImplemented(string(__PRETTY_FUNCTION__)+" May not be called!"); +} + +void Geant4UserLimits::SetUserMaxTrackLength(G4double /* utrakMax */) { + dd4hep::notImplemented(string(__PRETTY_FUNCTION__)+" May not be called!"); +} + +void Geant4UserLimits::SetUserMaxTime(G4double /* utimeMax */) { + dd4hep::notImplemented(string(__PRETTY_FUNCTION__)+" May not be called!"); +} + +void Geant4UserLimits::SetUserMinEkine(G4double /* uekinMin */) { + dd4hep::notImplemented(string(__PRETTY_FUNCTION__)+" May not be called!"); +} + +void Geant4UserLimits::SetUserMinRange(G4double /* urangMin */) { + dd4hep::notImplemented(string(__PRETTY_FUNCTION__)+" May not be called!"); +} + -- GitLab