Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 5 additions & 10 deletions Detectors/FastSim/include/FastSim/G4FastSimulation.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
/// `G4.fastSimRegions` overrides the walk with an explicit space-separated list
/// of media, for when a model should see less than a whole subtree.

#include "TG4RunConfiguration.h"
#include "TG4VUserFastSimulation.h"
#include "TG4VUserPostDetConstruction.h"

Expand All @@ -53,15 +52,11 @@ class G4FastSimulation : public TG4VUserFastSimulation
double mMinEnergy = 1.;
};

/// Supplies Geant4-VMC with the fast simulation models and their regions.
/// Returns nullptr when no model is configured, so nothing is set up.
class G4RunConfiguration : public TG4RunConfiguration
{
public:
using TG4RunConfiguration::TG4RunConfiguration;
TG4VUserFastSimulation* CreateUserFastSimulation() override;
TG4VUserPostDetConstruction* CreateUserPostDetConstruction() override;
};
/// The fast simulation for Geant4-VMC, or nullptr when `G4.fastSimModels` is empty.
TG4VUserFastSimulation* createFastSimulation();

/// The construction of the fast simulation regions, or nullptr when `G4.fastSimModels` is empty.
TG4VUserPostDetConstruction* createFastSimRegionConstruction();

} // namespace o2::fastsim

Expand Down
6 changes: 3 additions & 3 deletions Detectors/FastSim/src/G4FastSimulation.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void G4FastSimulation::Construct()
}

//_____________________________________________________________________________
TG4VUserFastSimulation* G4RunConfiguration::CreateUserFastSimulation()
TG4VUserFastSimulation* createFastSimulation()
{
const auto& params = o2::conf::G4Params::Instance();
auto models = split(params.fastSimModels, ',');
Expand All @@ -79,12 +79,12 @@ TG4VUserFastSimulation* G4RunConfiguration::CreateUserFastSimulation()
}

//_____________________________________________________________________________
TG4VUserPostDetConstruction* G4RunConfiguration::CreateUserPostDetConstruction()
TG4VUserPostDetConstruction* createFastSimRegionConstruction()
{
const auto& params = o2::conf::G4Params::Instance();
auto models = split(params.fastSimModels, ',');
if (models.empty()) {
return TG4RunConfiguration::CreateUserPostDetConstruction();
return nullptr;
}
std::vector<FastSimRegionConstruction::ModelRegions> wanted;
wanted.reserve(models.size());
Expand Down
2 changes: 1 addition & 1 deletion Detectors/gconfig/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ o2_add_library(G3Setup
)

o2_add_library(G4Setup
SOURCES src/G4Config.cxx
SOURCES src/G4Config.cxx src/G4RunConfiguration.cxx src/G4LocalFieldConstruction.cxx
PUBLIC_LINK_LIBRARIES MC::Geant4VMC MC::Geant4 FairRoot::Base O2::SimulationDataFormat O2::Generators O2::SimSetup O2::FastSim
)

Expand Down
13 changes: 6 additions & 7 deletions Detectors/gconfig/g4Config.C
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ R__LOAD_LIBRARY(libgeant4vmc)
#include "G4ScoringManager.hh"
#include "G4VScoringMesh.hh"
#include <unistd.h>
#include "FastSim/G4FastSimulation.h"
#include "SimSetup/G4RunConfiguration.h"
#endif
#include "commonConfig.C"

Expand Down Expand Up @@ -119,12 +119,11 @@ void Config()
LOG(fatal) << "Unsupported geometry navigation mode";
}

// o2::fastsim::G4RunConfiguration differs from TG4RunConfiguration only in
// providing the fast-simulation hook; with G4.fastSimModels empty it behaves
// identically.
auto runConfiguration = new o2::fastsim::G4RunConfiguration(geomNavStr, physicsSetup,
"stepLimiter+specialCuts",
specialStacking, mtMode);
// o2::g4config::G4RunConfiguration adds the fast-simulation hook and the local
// magnetic fields; with neither configured it behaves like TG4RunConfiguration.
auto runConfiguration = new o2::g4config::G4RunConfiguration(geomNavStr, physicsSetup,
"stepLimiter+specialCuts",
specialStacking, mtMode);
if (g4Params.g4scoring) {
runConfiguration->SetUseOfG4Scoring();
if (g4Params.g4fluenceweight) {
Expand Down
29 changes: 25 additions & 4 deletions Detectors/gconfig/g4config.in
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,33 @@
/process/em/transportationWithMsc Disabled

#
# Adding extra lines for fixing tracking bias
#
# Field integration (O2-7198)
# a tight deltaIntersection removes the 1/pT bias from chord-to-boundary placement (ALIROOT-7121)
/mcMagField/setDeltaIntersection 1.0e-05 mm
/mcMagField/setMinimumEpsilonStep 0.5e-05
/mcMagField/setMaximumEpsilonStep 1.0e-05
# the epsilons do not change the bias; minimumEpsilon sets the accuracy of long steps,
# which only the muon spectrometer needs (it keeps the tight value as a local field)
/mcMagField/setMinimumEpsilonStep 1.0e-04
/mcMagField/setMaximumEpsilonStep 1.0e-03
/mcMagField/printParameters
# the muon spectrometer keeps tight epsilons as local fields (see G4LocalFieldConstruction)
/mcDet/createMagFieldParameters YOUT1
/mcMagField/YOUT1/stepperType NystromRK4
/mcMagField/YOUT1/setConstDistance 1 mm
/mcMagField/YOUT1/setDeltaIntersection 1.0e-05 mm
/mcMagField/YOUT1/setMinimumEpsilonStep 0.5e-05
/mcMagField/YOUT1/setMaximumEpsilonStep 1.0e-05
/mcDet/createMagFieldParameters DDIP
/mcMagField/DDIP/stepperType NystromRK4
/mcMagField/DDIP/setConstDistance 1 mm
/mcMagField/DDIP/setDeltaIntersection 1.0e-05 mm
/mcMagField/DDIP/setMinimumEpsilonStep 0.5e-05
/mcMagField/DDIP/setMaximumEpsilonStep 1.0e-05
/mcDet/createMagFieldParameters YOUT2
/mcMagField/YOUT2/stepperType NystromRK4
/mcMagField/YOUT2/setConstDistance 1 mm
/mcMagField/YOUT2/setDeltaIntersection 1.0e-05 mm
/mcMagField/YOUT2/setMinimumEpsilonStep 0.5e-05
/mcMagField/YOUT2/setMaximumEpsilonStep 1.0e-05

# Change default parameters for killing looping particles
#
Expand Down
37 changes: 37 additions & 0 deletions Detectors/gconfig/include/SimSetup/G4LocalFieldConstruction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

#ifndef O2_SIMSETUP_G4LOCALFIELDCONSTRUCTION_H_
#define O2_SIMSETUP_G4LOCALFIELDCONSTRUCTION_H_

#include "TG4VUserPostDetConstruction.h"

#include <memory>

namespace o2::g4config
{

/// Gives every volume with its own field parameters (/mcDet/createMagFieldParameters <vol>)
/// a local copy of the global field, so that the /mcMagField/<vol>/ settings take effect.
class G4LocalFieldConstruction : public TG4VUserPostDetConstruction
{
public:
/// next is another construction step run first (may be nullptr); it is owned
explicit G4LocalFieldConstruction(TG4VUserPostDetConstruction* next) : mNext(next) {}
void Construct() override;

private:
std::unique_ptr<TG4VUserPostDetConstruction> mNext;
};

} // namespace o2::g4config

#endif // O2_SIMSETUP_G4LOCALFIELDCONSTRUCTION_H_
31 changes: 31 additions & 0 deletions Detectors/gconfig/include/SimSetup/G4RunConfiguration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

#ifndef O2_SIMSETUP_G4RUNCONFIGURATION_H_
#define O2_SIMSETUP_G4RUNCONFIGURATION_H_

#include "TG4RunConfiguration.h"

namespace o2::g4config
{

/// The Geant4 VMC run configuration of O2: adds the fast simulation and the local magnetic fields.
class G4RunConfiguration : public TG4RunConfiguration
{
public:
using TG4RunConfiguration::TG4RunConfiguration;
TG4VUserFastSimulation* CreateUserFastSimulation() override;
TG4VUserPostDetConstruction* CreateUserPostDetConstruction() override;
};

} // namespace o2::g4config

#endif // O2_SIMSETUP_G4RUNCONFIGURATION_H_
87 changes: 87 additions & 0 deletions Detectors/gconfig/src/G4LocalFieldConstruction.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

#include "SimSetup/G4LocalFieldConstruction.h"
#include "SimConfig/G4Params.h"

#include "TG4GeometryManager.h"

#include <G4UIcommandTree.hh>
#include <G4UImanager.hh>
#include <TGeoManager.h>
#include <TVirtualMC.h>
#include <fairlogger/Logger.h>

#include <string>
#include <unordered_set>

namespace o2::g4config
{

namespace
{
// First volume in the subtree of vol whose medium has no magnetic field (ifield = 0)
const TGeoVolume* findZeroFieldVolume(const TGeoVolume* vol, std::unordered_set<const TGeoVolume*>& visited)
{
if (!visited.insert(vol).second) {
return nullptr;
}
auto med = vol->GetMedium();
if (med && !vol->IsAssembly() && med->GetParam(1) == 0) {
return vol;
}
for (int i = 0; i < vol->GetNdaughters(); ++i) {
if (auto nf = findZeroFieldVolume(vol->GetNode(i)->GetVolume(), visited)) {
return nf;
}
}
return nullptr;
}
} // namespace

void G4LocalFieldConstruction::Construct()
{
if (mNext) {
mNext->Construct();
}
auto tree = G4UImanager::GetUIpointer()->GetTree()->FindCommandTree("/mcMagField/");
auto field = TVirtualMC::GetMC()->GetMagField();
if (!tree || !field) {
return;
}
int nattached = 0;
for (int i = 1; i <= tree->GetTreeEntry(); ++i) {
std::string path = tree->GetTree(i)->GetPathName(); // "/mcMagField/<vol>/"
auto name = path.substr(12, path.size() - 13);
auto vol = gGeoManager->GetVolume(name.c_str());
if (!vol) {
LOG(warn) << "local field: no volume " << name << "; its field parameters are unused";
continue;
}
// Geant4 VMC forces a local field onto all daughters, which would override zero-field media
std::unordered_set<const TGeoVolume*> visited;
if (auto nf = findZeroFieldVolume(vol, visited)) {
LOG(warn) << "local field: volume " << name << " contains the zero-field volume " << nf->GetName() << "; skipped";
continue;
}
vol->SetField(field);
LOG(info) << "local field: volume " << name << " uses the parameters in /mcMagField/" << name << "/";
++nattached;
}
if (nattached > 0) {
TG4GeometryManager::Instance()->SetIsLocalField(true);
if (o2::conf::G4Params::Instance().navmode != o2::conf::EG4Nav::kTGeo) {
LOG(warn) << "local field: Geant4 VMC builds local fields only with TGeo navigation; the global field applies everywhere";
}
}
}

} // namespace o2::g4config
30 changes: 30 additions & 0 deletions Detectors/gconfig/src/G4RunConfiguration.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

#include "SimSetup/G4RunConfiguration.h"
#include "SimSetup/G4LocalFieldConstruction.h"
#include "FastSim/G4FastSimulation.h"

namespace o2::g4config
{

TG4VUserFastSimulation* G4RunConfiguration::CreateUserFastSimulation()
{
return o2::fastsim::createFastSimulation();
}

TG4VUserPostDetConstruction* G4RunConfiguration::CreateUserPostDetConstruction()
{
auto fastSimRegions = o2::fastsim::createFastSimRegionConstruction();
return new G4LocalFieldConstruction(fastSimRegions ? fastSimRegions : TG4RunConfiguration::CreateUserPostDetConstruction());
}

} // namespace o2::g4config
Loading