File indexing completed on 2024-12-01 23:40:41
0001 #include "SimG4Core/Application/interface/RunManagerMTWorker.h"
0002 #include "SimG4Core/Application/interface/RunManagerMT.h"
0003 #include "SimG4Core/Application/interface/SimRunInterface.h"
0004 #include "SimG4Core/Application/interface/RunAction.h"
0005 #include "SimG4Core/Application/interface/EventAction.h"
0006 #include "SimG4Core/Application/interface/StackingAction.h"
0007 #include "SimG4Core/Application/interface/TrackingAction.h"
0008 #include "SimG4Core/Application/interface/SteppingAction.h"
0009 #include "SimG4Core/Application/interface/Phase2SteppingAction.h"
0010 #include "SimG4Core/Application/interface/CMSSimEventManager.h"
0011 #include "SimG4Core/Application/interface/CustomUIsessionThreadPrefix.h"
0012 #include "SimG4Core/Application/interface/CustomUIsessionToFile.h"
0013 #include "SimG4Core/Application/interface/ExceptionHandler.h"
0014 #include "SimG4Core/Application/interface/CMSGDMLWriteStructure.h"
0015
0016 #include "SimG4Core/Geometry/interface/CustomUIsession.h"
0017
0018 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0019 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0020 #include "FWCore/Framework/interface/Event.h"
0021 #include "FWCore/Framework/interface/EventSetup.h"
0022 #include "FWCore/Framework/interface/ConsumesCollector.h"
0023 #include "FWCore/ServiceRegistry/interface/Service.h"
0024 #include "FWCore/Utilities/interface/Exception.h"
0025 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0026
0027 #include "SimG4Core/Notification/interface/SimActivityRegistry.h"
0028 #include "SimG4Core/Notification/interface/BeginOfJob.h"
0029 #include "SimG4Core/Notification/interface/CMSSteppingVerbose.h"
0030 #include "SimG4Core/Notification/interface/SimTrackManager.h"
0031 #include "SimG4Core/Watcher/interface/SimWatcherFactory.h"
0032
0033 #include "SimG4Core/Geometry/interface/DDDWorld.h"
0034 #include "SimG4Core/MagneticField/interface/FieldBuilder.h"
0035 #include "SimG4Core/MagneticField/interface/CMSFieldManager.h"
0036
0037 #include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h"
0038 #include "SimDataFormats/GeneratorProducts/interface/HepMC3Product.h"
0039 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
0040 #include "HepMC3/Print.h"
0041
0042 #include "SimG4Core/Physics/interface/PhysicsList.h"
0043
0044 #include "SimG4Core/SensitiveDetector/interface/AttachSD.h"
0045 #include "SimG4Core/SensitiveDetector/interface/SensitiveTkDetector.h"
0046 #include "SimG4Core/SensitiveDetector/interface/SensitiveCaloDetector.h"
0047 #include "SimG4Core/SensitiveDetector/interface/SensitiveDetectorMakerBase.h"
0048 #include "SimG4Core/SensitiveDetector/interface/sensitiveDetectorMakers.h"
0049
0050 #include "G4Timer.hh"
0051 #include "G4Event.hh"
0052 #include "G4Run.hh"
0053 #include <CLHEP/Units/SystemOfUnits.h>
0054 #include "G4Threading.hh"
0055 #include "G4UImanager.hh"
0056 #include "G4WorkerThread.hh"
0057 #include "G4WorkerRunManagerKernel.hh"
0058 #include "G4StateManager.hh"
0059 #include "G4TransportationManager.hh"
0060 #include "G4LossTableManager.hh"
0061 #include "G4PhysListUtil.hh"
0062 #include "G4Field.hh"
0063 #include "G4FieldManager.hh"
0064 #include "G4ScoringManager.hh"
0065 #include "G4UserSteppingAction.hh"
0066 #include "G4GDMLParser.hh"
0067 #include "G4Threading.hh"
0068
0069 #include <atomic>
0070 #include <memory>
0071 #include <thread>
0072 #include <sstream>
0073 #include <vector>
0074
0075 static std::once_flag applyOnce;
0076 static std::once_flag applyOnceEnd;
0077 static std::once_flag applyOnceGDML;
0078
0079
0080 namespace {
0081 std::atomic<int> thread_counter{0};
0082
0083 int get_new_thread_index() { return thread_counter++; }
0084
0085 bool createWatchers(const edm::ParameterSet& iP,
0086 SimActivityRegistry* iReg,
0087 std::vector<std::shared_ptr<SimWatcher>>& oWatchers,
0088 std::vector<std::shared_ptr<SimProducer>>& oProds,
0089 int threadID) {
0090 std::vector<edm::ParameterSet> ws = iP.getParameter<std::vector<edm::ParameterSet>>("Watchers");
0091 if (ws.empty()) {
0092 return false;
0093 }
0094
0095 for (auto& watcher : ws) {
0096 std::unique_ptr<SimWatcherMakerBase> maker(
0097 SimWatcherFactory::get()->create(watcher.getParameter<std::string>("type")));
0098 if (maker == nullptr) {
0099 throw cms::Exception("Configuration")
0100 << "RunManagerMTWorker::createWatchers: "
0101 << "Unable to find the requested Watcher " << watcher.getParameter<std::string>("type");
0102 } else {
0103 std::shared_ptr<SimWatcher> watcherTemp;
0104 std::shared_ptr<SimProducer> producerTemp;
0105 maker->make(watcher, *(iReg), watcherTemp, producerTemp);
0106 if (nullptr != watcherTemp) {
0107 if (!watcherTemp->isMT() && 0 < threadID) {
0108 throw cms::Exception("Configuration")
0109 << "RunManagerMTWorker::createWatchers: "
0110 << "Unable to use Watcher " << watcher.getParameter<std::string>("type") << " if number of threads > 1";
0111 } else {
0112 oWatchers.push_back(watcherTemp);
0113 if (nullptr != producerTemp) {
0114 oProds.push_back(producerTemp);
0115 }
0116 }
0117 }
0118 }
0119 }
0120 return (!oWatchers.empty());
0121 }
0122 }
0123
0124 struct RunManagerMTWorker::TLSData {
0125 std::unique_ptr<G4RunManagerKernel> kernel;
0126 std::unique_ptr<RunAction> userRunAction;
0127 std::unique_ptr<SimRunInterface> runInterface;
0128 std::unique_ptr<SimActivityRegistry> registry;
0129 std::unique_ptr<SimTrackManager> trackManager;
0130 std::vector<SensitiveTkDetector*> sensTkDets;
0131 std::vector<SensitiveCaloDetector*> sensCaloDets;
0132 std::vector<std::shared_ptr<SimWatcher>> watchers;
0133 std::vector<std::shared_ptr<SimProducer>> producers;
0134
0135
0136
0137 G4Run* currentRun = nullptr;
0138 std::unique_ptr<G4Event> currentEvent;
0139 edm::RunNumber_t currentRunNumber = 0;
0140 bool threadInitialized = false;
0141 bool runTerminated = false;
0142
0143 TLSData() {}
0144
0145 ~TLSData() = default;
0146 };
0147
0148
0149
0150
0151
0152
0153
0154
0155 RunManagerMTWorker::RunManagerMTWorker(const edm::ParameterSet& p, edm::ConsumesCollector&& iC)
0156 : m_generator(p.getParameter<edm::ParameterSet>("Generator")),
0157 m_generator3(p.getParameter<edm::ParameterSet>("Generator")),
0158 m_InToken(iC.consumes<edm::HepMCProduct>(
0159 p.getParameter<edm::ParameterSet>("Generator").getParameter<edm::InputTag>("HepMCProductLabel"))),
0160 m_InToken3(iC.consumes<edm::HepMC3Product>(
0161 p.getParameter<edm::ParameterSet>("Generator").getParameter<edm::InputTag>("HepMCProductLabel"))),
0162 m_theLHCTlinkToken(iC.consumes<edm::LHCTransportLinkContainer>(p.getParameter<edm::InputTag>("theLHCTlinkTag"))),
0163 m_nonBeam(p.getParameter<bool>("NonBeamEvent")),
0164 m_UseG4EventManager(p.getParameter<bool>("UseG4EventManager")),
0165 m_pUseMagneticField(p.getParameter<bool>("UseMagneticField")),
0166 m_LHCTransport(p.getParameter<bool>("LHCTransport")),
0167 m_thread_index{(get_new_thread_index())},
0168 m_pField(p.getParameter<edm::ParameterSet>("MagneticField")),
0169 m_pRunAction(p.getParameter<edm::ParameterSet>("RunAction")),
0170 m_pEventAction(p.getParameter<edm::ParameterSet>("EventAction")),
0171 m_pStackingAction(p.getParameter<edm::ParameterSet>("StackingAction")),
0172 m_pTrackingAction(p.getParameter<edm::ParameterSet>("TrackingAction")),
0173 m_pSteppingAction(p.getParameter<edm::ParameterSet>("SteppingAction")),
0174 m_G4Commands(p.getParameter<std::vector<std::string>>("G4Commands")),
0175 m_G4CommandsEndRun(p.getParameter<std::vector<std::string>>("G4CommandsEndRun")),
0176 m_p(p) {
0177 int id = getThreadIndex();
0178 edm::LogVerbatim("SimG4CoreApplication") << "RunManagerMTWorker for the thread " << id;
0179
0180
0181 G4Threading::G4SetThreadId(id);
0182 G4UImanager::GetUIpointer()->SetUpForAThread(id);
0183 auto iPset = p.getUntrackedParameter<edm::ParameterSet>("CustomUIsession");
0184 const std::string& uitype = iPset.getUntrackedParameter<std::string>("Type");
0185 if (uitype == "MessageLogger") {
0186 m_UIsession = new CustomUIsession();
0187 } else if (uitype == "MessageLoggerThreadPrefix") {
0188 m_UIsession = new CustomUIsessionThreadPrefix(iPset.getUntrackedParameter<std::string>("ThreadPrefix"), id);
0189 } else if (uitype == "FilePerThread") {
0190 m_UIsession = new CustomUIsessionToFile(iPset.getUntrackedParameter<std::string>("ThreadFile"), id);
0191 } else {
0192 throw cms::Exception("Configuration")
0193 << "RunManagerMTWorker::initializeG4: Invalid value of CustomUIsession.Type '" << uitype
0194 << "', valid are MessageLogger, MessageLoggerThreadPrefix, FilePerThread";
0195 }
0196 G4UImanager::GetUIpointer()->SetCoutDestination(m_UIsession);
0197
0198
0199
0200
0201 std::vector<std::string> onlySDs = p.getParameter<std::vector<std::string>>("OnlySDs");
0202 m_sdMakers = sim::sensitiveDetectorMakers(p, iC, onlySDs);
0203
0204
0205 initializeTLS();
0206 if (m_hasWatchers) {
0207 for (auto& watcher : m_tls->watchers) {
0208 watcher->registerConsumes(iC);
0209 }
0210 }
0211 if (m_LHCTransport) {
0212 m_LHCToken = iC.consumes<edm::HepMCProduct>(edm::InputTag("LHCTransport"));
0213 }
0214 if (m_pUseMagneticField) {
0215 m_MagField = iC.esConsumes<MagneticField, IdealMagneticFieldRecord, edm::Transition::BeginRun>();
0216 }
0217 edm::LogVerbatim("SimG4CoreApplication") << "RunManagerMTWorker is constructed for the thread " << id;
0218 unsigned int k = 0;
0219 for (std::unordered_map<std::string, std::unique_ptr<SensitiveDetectorMakerBase>>::const_iterator itr =
0220 m_sdMakers.begin();
0221 itr != m_sdMakers.end();
0222 ++itr, ++k) {
0223 edm::LogVerbatim("SimG4CoreApplication") << "SD[" << k << "] " << itr->first;
0224 }
0225 }
0226
0227 RunManagerMTWorker::~RunManagerMTWorker() {
0228 m_tls = nullptr;
0229 delete m_UIsession;
0230 }
0231
0232 void RunManagerMTWorker::beginRun(edm::EventSetup const& es) {
0233 int id = getThreadIndex();
0234 edm::LogVerbatim("SimG4CoreApplication") << "RunManagerMTWorker::beginRun for the thread " << id;
0235 for (auto& maker : m_sdMakers) {
0236 maker.second->beginRun(es);
0237 }
0238 if (m_pUseMagneticField) {
0239 m_pMagField = &es.getData(m_MagField);
0240 }
0241 if (m_hasWatchers) {
0242 for (auto& watcher : m_tls->watchers) {
0243 watcher->beginRun(es);
0244 }
0245 }
0246 edm::LogVerbatim("SimG4CoreApplication") << "RunManagerMTWorker::beginRun done for the thread " << id;
0247 }
0248
0249 void RunManagerMTWorker::endRun() {
0250 int id = getThreadIndex();
0251 edm::LogVerbatim("SimG4CoreApplication") << "RunManagerMTWorker::endRun for the thread " << id;
0252 terminateRun();
0253 }
0254
0255 void RunManagerMTWorker::initializeTLS() {
0256 if (nullptr != m_tls) {
0257 return;
0258 }
0259
0260 m_tls = new TLSData();
0261 m_tls->registry = std::make_unique<SimActivityRegistry>();
0262
0263 edm::Service<SimActivityRegistry> otherRegistry;
0264
0265
0266 int thisID = getThreadIndex();
0267 if (otherRegistry) {
0268 m_tls->registry->connect(*otherRegistry);
0269 if (thisID > 0) {
0270 throw cms::Exception("Configuration")
0271 << "RunManagerMTWorker::initializeTLS : "
0272 << "SimActivityRegistry service (i.e. visualization) is not supported for more than 1 thread. "
0273 << " \n If this use case is needed, RunManagerMTWorker has to be updated.";
0274 }
0275 }
0276 m_hasWatchers = createWatchers(m_p, m_tls->registry.get(), m_tls->watchers, m_tls->producers, thisID);
0277 }
0278
0279 void RunManagerMTWorker::initializeG4(RunManagerMT* runManagerMaster, const edm::EventSetup& es) {
0280 if (m_tls->threadInitialized)
0281 return;
0282
0283 G4Timer timer;
0284 timer.Start();
0285
0286
0287 initializeTLS();
0288
0289 int thisID = getThreadIndex();
0290 edm::LogVerbatim("SimG4CoreApplication") << "RunManagerMTWorker::initializeG4 in thread " << thisID << " is started";
0291
0292
0293 G4WorkerThread::BuildGeometryAndPhysicsVector();
0294
0295
0296 m_tls->kernel.reset(G4WorkerRunManagerKernel::GetRunManagerKernel());
0297 if (nullptr == m_tls->kernel) {
0298 m_tls->kernel = std::make_unique<G4WorkerRunManagerKernel>();
0299 }
0300
0301
0302 double th = m_p.getParameter<double>("ThresholdForGeometryExceptions") * CLHEP::GeV;
0303 bool tr = m_p.getParameter<bool>("TraceExceptions");
0304 G4StateManager::GetStateManager()->SetExceptionHandler(new ExceptionHandler(th, tr));
0305
0306
0307 auto worldPV = runManagerMaster->world().GetWorldVolume();
0308 m_tls->kernel->WorkerDefineWorldVolume(worldPV);
0309 G4TransportationManager* tM = G4TransportationManager::GetTransportationManager();
0310 tM->SetWorldForTracking(worldPV);
0311
0312
0313 int verbose = m_p.getParameter<int>("EventVerbose");
0314 m_tls->trackManager = std::make_unique<SimTrackManager>(&m_simEvent, verbose);
0315
0316
0317 if (m_pUseMagneticField) {
0318 const GlobalPoint g(0.f, 0.f, 0.f);
0319
0320 sim::FieldBuilder fieldBuilder(m_pMagField, m_pField);
0321
0322 CMSFieldManager* fieldManager = new CMSFieldManager();
0323 tM->SetFieldManager(fieldManager);
0324 fieldBuilder.build(fieldManager, tM->GetPropagatorInField());
0325
0326 std::string fieldFile = m_p.getUntrackedParameter<std::string>("FileNameField", "");
0327 if (!fieldFile.empty()) {
0328 std::call_once(applyOnce, [this]() { m_dumpMF = true; });
0329 if (m_dumpMF) {
0330 edm::LogVerbatim("SimG4CoreApplication")
0331 << "RunManagerMTWorker::InitializeG4: Dump magnetic field to file " << fieldFile;
0332 DumpMagneticField(tM->GetFieldManager()->GetDetectorField(), fieldFile);
0333 }
0334 }
0335 }
0336
0337
0338 auto sensDets = sim::attachSD(
0339 m_sdMakers, es, runManagerMaster->catalog(), m_p, m_tls->trackManager.get(), *(m_tls->registry.get()));
0340
0341 m_tls->sensTkDets = sensDets.first;
0342 m_tls->sensCaloDets = sensDets.second;
0343
0344 edm::LogVerbatim("SimG4CoreApplication")
0345 << "RunManagerMTWorker::InitializeG4: Sensitive Detectors are built in thread " << thisID << " found "
0346 << m_tls->sensTkDets.size() << " Tk type SD, and " << m_tls->sensCaloDets.size() << " Calo type SD";
0347
0348
0349 G4String writeFile = (G4String)m_p.getUntrackedParameter<std::string>("FileNameGDML");
0350 if (!writeFile.empty()) {
0351 std::call_once(applyOnceGDML, [this]() { m_dumpGDML = true; });
0352 edm::LogVerbatim("SimG4CoreApplication") << "DumpGDML:" << m_dumpGDML;
0353 if (m_dumpGDML) {
0354 G4int thID = G4Threading::G4GetThreadId();
0355 edm::LogVerbatim("SimG4CoreApplication") << "ThreadID=" << thID;
0356 G4Threading::G4SetThreadId(-1);
0357 G4GDMLParser gdml;
0358 gdml.SetRegionExport(true);
0359 gdml.SetEnergyCutsExport(true);
0360 gdml.SetSDExport(true);
0361 gdml.Write(writeFile, worldPV, true);
0362 G4Threading::G4SetThreadId(thID);
0363 }
0364 }
0365
0366
0367 bool scorer = m_p.getParameter<bool>("UseCommandBaseScorer");
0368 if (scorer) {
0369 G4ScoringManager* scManager = G4ScoringManager::GetScoringManager();
0370 scManager->SetVerboseLevel(1);
0371 }
0372
0373
0374 PhysicsList* physicsList = runManagerMaster->physicsListForWorker();
0375 m_isPhase2 = runManagerMaster->isPhase2();
0376
0377 edm::LogVerbatim("SimG4CoreApplication")
0378 << "RunManagerMTWorker::InitializeG4: start initialisation of PhysicsList for the thread " << thisID;
0379
0380
0381 if (!runManagerMaster->G4Commands().empty()) {
0382 G4cout << "RunManagerMTWorker::InitializeG4: Requested UI commands: " << G4endl;
0383 for (const std::string& command : runManagerMaster->G4Commands()) {
0384 G4cout << " " << command << G4endl;
0385 G4UImanager::GetUIpointer()->ApplyCommand(command);
0386 }
0387 }
0388 G4StateManager::GetStateManager()->SetNewState(G4State_Init);
0389
0390 physicsList->InitializeWorker();
0391 m_tls->kernel->SetPhysics(physicsList);
0392 m_tls->kernel->InitializePhysics();
0393
0394 if (!m_tls->kernel->RunInitialization()) {
0395 throw cms::Exception("Configuration")
0396 << "RunManagerMTWorker::InitializeG4: Geant4 kernel initialization failed in thread " << thisID;
0397 }
0398
0399
0400 BeginOfJob aBeginOfJob(&es);
0401 m_tls->registry->beginOfJobSignal_(&aBeginOfJob);
0402
0403 G4int sv = m_p.getUntrackedParameter<int>("SteppingVerbosity");
0404
0405 if (sv > 0) {
0406 G4double elim = m_p.getUntrackedParameter<double>("StepVerboseThreshold", 0.1) * CLHEP::GeV;
0407 std::vector<int> ve = m_p.getUntrackedParameter<std::vector<int>>("VerboseEvents");
0408 std::vector<int> vn = m_p.getUntrackedParameter<std::vector<int>>("VertexNumber");
0409 std::vector<int> vt = m_p.getUntrackedParameter<std::vector<int>>("VerboseTracks");
0410 m_sVerbose = std::make_unique<CMSSteppingVerbose>(sv, elim, ve, vn, vt);
0411 }
0412 if (!m_UseG4EventManager)
0413 m_evtManager = std::make_unique<CMSSimEventManager>(m_p);
0414 initializeUserActions();
0415
0416 G4StateManager::GetStateManager()->SetNewState(G4State_Idle);
0417
0418 timer.Stop();
0419 edm::LogVerbatim("SimG4CoreApplication")
0420 << "RunManagerMTWorker::initializeG4 done for the thread " << thisID << " " << timer;
0421 m_tls->threadInitialized = true;
0422 }
0423
0424 void RunManagerMTWorker::initializeUserActions() {
0425 m_tls->runInterface = std::make_unique<SimRunInterface>(this, false);
0426 m_tls->userRunAction = std::make_unique<RunAction>(m_pRunAction, m_tls->runInterface.get(), false);
0427 m_tls->userRunAction->SetMaster(false);
0428 Connect(m_tls->userRunAction.get());
0429
0430 G4int ver = m_p.getParameter<int>("EventVerbose");
0431 G4EventManager* eventManager = m_tls->kernel->GetEventManager();
0432 eventManager->SetVerboseLevel(ver);
0433
0434 auto userEventAction =
0435 new EventAction(m_pEventAction, m_tls->runInterface.get(), m_tls->trackManager.get(), m_sVerbose.get());
0436 Connect(userEventAction);
0437 if (m_UseG4EventManager) {
0438 eventManager->SetUserAction(userEventAction);
0439 } else {
0440 m_evtManager->SetUserAction(userEventAction);
0441 }
0442
0443 auto userTrackingAction = new TrackingAction(m_tls->trackManager.get(), m_sVerbose.get(), m_pTrackingAction);
0444 Connect(userTrackingAction);
0445 if (m_UseG4EventManager) {
0446 eventManager->SetUserAction(userTrackingAction);
0447 } else {
0448 m_evtManager->SetUserAction(userTrackingAction);
0449 }
0450
0451
0452 G4UserSteppingAction* userSteppingAction;
0453 bool dd4hep = m_p.getParameter<bool>("g4GeometryDD4hepSource");
0454 if (m_isPhase2) {
0455 auto ptr = new Phase2SteppingAction(m_sVerbose.get(), m_pSteppingAction, m_hasWatchers, dd4hep);
0456 Connect(ptr);
0457 userSteppingAction = (G4UserSteppingAction*)ptr;
0458 } else {
0459 auto ptr = new SteppingAction(m_sVerbose.get(), m_pSteppingAction, m_hasWatchers, dd4hep);
0460 Connect(ptr);
0461 userSteppingAction = (G4UserSteppingAction*)ptr;
0462 }
0463 if (m_UseG4EventManager) {
0464 eventManager->SetUserAction(userSteppingAction);
0465 } else {
0466 m_evtManager->SetUserAction(userSteppingAction);
0467 }
0468
0469 auto userStackingAction = new StackingAction(userTrackingAction, m_pStackingAction, m_sVerbose.get());
0470 if (m_UseG4EventManager) {
0471 eventManager->SetUserAction(userStackingAction);
0472 } else {
0473 m_evtManager->SetUserAction(userStackingAction);
0474 }
0475 }
0476
0477 void RunManagerMTWorker::Connect(RunAction* runAction) {
0478 runAction->m_beginOfRunSignal.connect(m_tls->registry->beginOfRunSignal_);
0479 runAction->m_endOfRunSignal.connect(m_tls->registry->endOfRunSignal_);
0480 }
0481
0482 void RunManagerMTWorker::Connect(EventAction* eventAction) {
0483 eventAction->m_beginOfEventSignal.connect(m_tls->registry->beginOfEventSignal_);
0484 eventAction->m_endOfEventSignal.connect(m_tls->registry->endOfEventSignal_);
0485 }
0486
0487 void RunManagerMTWorker::Connect(TrackingAction* trackingAction) {
0488 trackingAction->m_beginOfTrackSignal.connect(m_tls->registry->beginOfTrackSignal_);
0489 trackingAction->m_endOfTrackSignal.connect(m_tls->registry->endOfTrackSignal_);
0490 }
0491
0492 void RunManagerMTWorker::Connect(SteppingAction* steppingAction) {
0493 steppingAction->m_g4StepSignal.connect(m_tls->registry->g4StepSignal_);
0494 }
0495
0496 void RunManagerMTWorker::Connect(Phase2SteppingAction* steppingAction) {
0497 steppingAction->m_g4StepSignal.connect(m_tls->registry->g4StepSignal_);
0498 }
0499
0500 SimTrackManager* RunManagerMTWorker::getSimTrackManager() {
0501 initializeTLS();
0502 return m_tls->trackManager.get();
0503 }
0504 std::vector<SensitiveTkDetector*>& RunManagerMTWorker::sensTkDetectors() {
0505 initializeTLS();
0506 return m_tls->sensTkDets;
0507 }
0508 std::vector<SensitiveCaloDetector*>& RunManagerMTWorker::sensCaloDetectors() {
0509 initializeTLS();
0510 return m_tls->sensCaloDets;
0511 }
0512 std::vector<std::shared_ptr<SimProducer>>& RunManagerMTWorker::producers() {
0513 initializeTLS();
0514 return m_tls->producers;
0515 }
0516
0517 void RunManagerMTWorker::initializeRun() {
0518 m_tls->currentRun = new G4Run();
0519 G4StateManager::GetStateManager()->SetNewState(G4State_GeomClosed);
0520 if (nullptr != m_tls->userRunAction) {
0521 m_tls->userRunAction->BeginOfRunAction(m_tls->currentRun);
0522 }
0523 int id = getThreadIndex();
0524 edm::LogVerbatim("SimG4CoreApplication") << "RunManagerMTWorker::initializeRun done for thread " << id;
0525 }
0526
0527 void RunManagerMTWorker::terminateRun() {
0528 int id = getThreadIndex();
0529 edm::LogVerbatim("SimG4CoreApplication") << "RunManagerMTWorker::terminateRun for thread " << id;
0530 if (nullptr == m_tls || m_tls->runTerminated) {
0531 return;
0532 }
0533
0534
0535 if (!m_G4CommandsEndRun.empty()) {
0536 std::call_once(applyOnceEnd, [this]() { m_endOfRun = true; });
0537 if (m_endOfRun) {
0538 edm::LogVerbatim("SimG4CoreApplication") << "RunManagerMTWorker: Requested end of run UI commands: ";
0539 for (const std::string& command : m_G4CommandsEndRun) {
0540 edm::LogVerbatim("SimG4CoreApplication") << " " << command;
0541 G4UImanager::GetUIpointer()->ApplyCommand(command);
0542 }
0543 }
0544 }
0545 if (m_tls->userRunAction) {
0546 m_tls->userRunAction->EndOfRunAction(m_tls->currentRun);
0547 m_tls->userRunAction.reset();
0548 }
0549 m_tls->currentEvent.reset();
0550 if (m_tls->kernel) {
0551 m_tls->kernel->RunTermination();
0552 }
0553 m_tls->runTerminated = true;
0554 edm::LogVerbatim("SimG4CoreApplication") << "RunManagerMTWorker::terminateRun done for thread " << id;
0555 }
0556
0557 TmpSimEvent* RunManagerMTWorker::produce(const edm::Event& inpevt,
0558 const edm::EventSetup& es,
0559 RunManagerMT& runManagerMaster) {
0560
0561
0562
0563 edm::LogVerbatim("SimG4CoreApplication") << "RunManagerMTWorker::produce: start EventID=" << inpevt.id().event();
0564
0565 assert(m_tls != nullptr and m_tls->threadInitialized);
0566
0567 if (inpevt.id().run() != m_tls->currentRunNumber) {
0568 edm::LogVerbatim("SimG4CoreApplication")
0569 << "RunManagerMTWorker::produce: RunID= " << inpevt.id().run() << " TLS RunID= " << m_tls->currentRunNumber;
0570 if (m_tls->currentRunNumber != 0 && !m_tls->runTerminated) {
0571
0572
0573 terminateRun();
0574 }
0575 initializeRun();
0576 m_tls->currentRunNumber = inpevt.id().run();
0577 }
0578
0579
0580
0581 m_tls->currentEvent.reset(generateEvent(inpevt));
0582 m_simEvent.clear();
0583 m_simEvent.setHepEvent(m_generator.genEvent());
0584 m_simEvent.setWeight(m_generator.eventWeight());
0585
0586 if (m_generator.genVertex() != nullptr) {
0587 auto genVertex = m_generator.genVertex();
0588 m_simEvent.collisionPoint(math::XYZTLorentzVectorD(genVertex->x() / CLHEP::cm,
0589 genVertex->y() / CLHEP::cm,
0590 genVertex->z() / CLHEP::cm,
0591 genVertex->t() / CLHEP::second));
0592 }
0593 if (m_tls->currentEvent->GetNumberOfPrimaryVertex() == 0) {
0594 throw cms::Exception("EventCorruption")
0595 << "RunManagerMTWorker::produce: event " << inpevt.id().event() << " with no G4PrimaryVertices"
0596 << " StreamID=" << inpevt.streamID() << " threadIndex=" << getThreadIndex();
0597
0598 } else {
0599 edm::LogVerbatim("SimG4CoreApplication")
0600 << "RunManagerMTWorker::produce: start EventID=" << inpevt.id().event() << " StreamID=" << inpevt.streamID()
0601 << " threadIndex=" << getThreadIndex() << " weight=" << m_simEvent.weight()
0602 << " Nprimary: " << m_tls->currentEvent->GetNumberOfPrimaryVertex() << " vertices and " << m_simEvent.nTracks()
0603 << " particles";
0604
0605 if (m_UseG4EventManager) {
0606 m_tls->kernel->GetEventManager()->ProcessOneEvent(m_tls->currentEvent.get());
0607 } else {
0608 m_evtManager->ProcessOneEvent(m_tls->currentEvent.get());
0609 }
0610 }
0611
0612
0613 m_tls->currentEvent.reset();
0614 for (auto& sd : m_tls->sensCaloDets) {
0615 sd->reset();
0616 }
0617
0618 edm::LogVerbatim("SimG4CoreApplication") << "RunManagerMTWorker::produce: ended Event " << inpevt.id().event();
0619 return &m_simEvent;
0620 }
0621
0622 void RunManagerMTWorker::abortEvent() {
0623 if (m_tls->runTerminated) {
0624 return;
0625 }
0626 G4Track* t = m_tls->kernel->GetEventManager()->GetTrackingManager()->GetTrack();
0627 t->SetTrackStatus(fStopAndKill);
0628
0629
0630
0631 TrackingAction* uta = static_cast<TrackingAction*>(m_tls->kernel->GetEventManager()->GetUserTrackingAction());
0632 uta->PostUserTrackingAction(t);
0633
0634 m_tls->currentEvent->SetEventAborted();
0635 m_tls->kernel->GetEventManager()->GetStackManager()->clear();
0636 m_tls->kernel->GetEventManager()->GetTrackingManager()->EventAborted();
0637 }
0638
0639 void RunManagerMTWorker::abortRun(bool softAbort) {
0640 if (!softAbort) {
0641 abortEvent();
0642 }
0643 m_tls->currentRun = nullptr;
0644 terminateRun();
0645 }
0646
0647 G4Event* RunManagerMTWorker::generateEvent(const edm::Event& inpevt) {
0648 m_tls->currentEvent.reset();
0649
0650
0651 G4int evtid = (G4int)inpevt.id().event();
0652 G4Event* evt = new G4Event(evtid);
0653
0654
0655
0656 resetGenParticleId(inpevt);
0657
0658 edm::Handle<edm::HepMCProduct> HepMCEvt;
0659 bool found = inpevt.getByToken(m_InToken, HepMCEvt);
0660
0661 if (found) {
0662
0663 m_generator.setGenEvent(HepMCEvt->GetEvent());
0664
0665 if (!m_nonBeam) {
0666 m_generator.HepMC2G4(HepMCEvt->GetEvent(), evt);
0667 if (m_LHCTransport) {
0668 edm::Handle<edm::HepMCProduct> LHCMCEvt;
0669 inpevt.getByToken(m_LHCToken, LHCMCEvt);
0670 m_generator.nonCentralEvent2G4(LHCMCEvt->GetEvent(), evt);
0671 }
0672 } else {
0673 m_generator.nonCentralEvent2G4(HepMCEvt->GetEvent(), evt);
0674 }
0675
0676 } else {
0677
0678 edm::Handle<edm::HepMC3Product> HepMCEvt3;
0679 inpevt.getByToken(m_InToken3, HepMCEvt3);
0680
0681 HepMC3::GenEvent* genevt3 = new HepMC3::GenEvent();
0682 genevt3->read_data(*HepMCEvt3->GetEvent());
0683 m_generator3.setGenEvent(genevt3);
0684
0685 if (!m_nonBeam) {
0686 m_generator3.HepMC2G4(genevt3, evt);
0687 if (m_LHCTransport) {
0688 edm::Handle<edm::HepMC3Product> LHCMCEvt;
0689 inpevt.getByToken(m_LHCToken, LHCMCEvt);
0690
0691 }
0692 } else {
0693
0694 }
0695 }
0696 return evt;
0697 }
0698
0699 void RunManagerMTWorker::resetGenParticleId(const edm::Event& inpevt) {
0700 edm::Handle<edm::LHCTransportLinkContainer> theLHCTlink;
0701 inpevt.getByToken(m_theLHCTlinkToken, theLHCTlink);
0702 if (theLHCTlink.isValid()) {
0703 m_tls->trackManager->setLHCTransportLink(theLHCTlink.product());
0704 }
0705 }
0706
0707 void RunManagerMTWorker::DumpMagneticField(const G4Field* field, const std::string& file) const {
0708 std::ofstream fout(file.c_str(), std::ios::out);
0709 if (fout.fail()) {
0710 edm::LogWarning("SimG4CoreApplication")
0711 << "MTWorker::DumpMagneticField: error opening file <" << file << "> for magnetic field";
0712 } else {
0713
0714 double rmax = 9000 * CLHEP::mm;
0715 double zmax = 24000 * CLHEP::mm;
0716
0717 double dr = 1 * CLHEP::cm;
0718 double dz = 5 * CLHEP::cm;
0719
0720 int nr = (int)(rmax / dr);
0721 int nz = 2 * (int)(zmax / dz);
0722
0723 double r = 0.0;
0724 double z0 = -zmax;
0725 double z;
0726
0727 double phi = 0.0;
0728 double cosf = cos(phi);
0729 double sinf = sin(phi);
0730
0731 double point[4] = {0.0, 0.0, 0.0, 0.0};
0732 double bfield[3] = {0.0, 0.0, 0.0};
0733
0734 fout << std::setprecision(6);
0735 for (int i = 0; i <= nr; ++i) {
0736 z = z0;
0737 for (int j = 0; j <= nz; ++j) {
0738 point[0] = r * cosf;
0739 point[1] = r * sinf;
0740 point[2] = z;
0741 field->GetFieldValue(point, bfield);
0742 fout << "R(mm)= " << r / CLHEP::mm << " phi(deg)= " << phi / CLHEP::degree << " Z(mm)= " << z / CLHEP::mm
0743 << " Bz(tesla)= " << bfield[2] / CLHEP::tesla
0744 << " Br(tesla)= " << (bfield[0] * cosf + bfield[1] * sinf) / CLHEP::tesla
0745 << " Bphi(tesla)= " << (bfield[0] * sinf - bfield[1] * cosf) / CLHEP::tesla << G4endl;
0746 z += dz;
0747 }
0748 r += dr;
0749 }
0750
0751 fout.close();
0752 }
0753 }