Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new capabilities to run CMS with sensitive detectors #713

Merged
merged 17 commits into from
Apr 10, 2023
Merged
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
30 changes: 24 additions & 6 deletions app/demo-geant-integration/DetectorConstruction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ G4VPhysicalVolume* DetectorConstruction::Construct()
CELER_LOG_LOCAL(status) << "Loading detector geometry";

G4GDMLParser gdml_parser;
gdml_parser.SetStripFlag(false);
gdml_parser.SetStripFlag(GlobalSetup::Instance()->StripGDMLPointers());

std::string const& filename = GlobalSetup::Instance()->GetGeometryFile();
if (filename.empty())
Expand All @@ -77,7 +77,7 @@ G4VPhysicalVolume* DetectorConstruction::Construct()
{
if (aux.type == "SensDet")
{
detectors_.emplace_back(lv_vecaux.first, aux.value);
detectors_.insert({aux.value, lv_vecaux.first});
}
}
}
Expand All @@ -89,14 +89,32 @@ G4VPhysicalVolume* DetectorConstruction::Construct()
//---------------------------------------------------------------------------//
void DetectorConstruction::ConstructSDandField()
{
CELER_LOG_LOCAL(debug) << "Loading sensitive detectors";
CELER_LOG_LOCAL(status) << "Loading sensitive detectors";

G4SDManager* sd_manager = G4SDManager::GetSDMpointer();

for (auto& lv_name : detectors_)
auto iter = detectors_.begin();
while (iter != detectors_.end())
{
auto detector = std::make_unique<SensitiveDetector>(lv_name.second);
lv_name.first->SetSensitiveDetector(detector.get());
// Find the end of the current range of keys
auto stop = iter;
do
{
++stop;
} while (stop != detectors_.end() && iter->first == stop->first);

// Create one detector for all the volumes
auto detector = std::make_unique<SensitiveDetector>(iter->first);

// Attach sensitive detectors
for (; iter != stop; ++iter)
{
CELER_LOG_LOCAL(debug) << "Attaching " << iter->first << " to "
<< iter->second->GetName();
iter->second->SetSensitiveDetector(detector.get());
}

// Hand SD to the manager
sd_manager->AddNewDetector(detector.release());
}
}
Expand Down
5 changes: 2 additions & 3 deletions app/demo-geant-integration/DetectorConstruction.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
//---------------------------------------------------------------------------//
#pragma once

#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <G4VUserDetectorConstruction.hh>

class G4LogicalVolume;
Expand All @@ -32,7 +31,7 @@ class DetectorConstruction final : public G4VUserDetectorConstruction

private:
std::unique_ptr<G4VPhysicalVolume> world_;
std::vector<std::pair<G4LogicalVolume*, std::string>> detectors_;
std::multimap<std::string, G4LogicalVolume*> detectors_;
};

//---------------------------------------------------------------------------//
Expand Down
7 changes: 7 additions & 0 deletions app/demo-geant-integration/GlobalSetup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ GlobalSetup::GlobalSetup()
cmd.SetGuidance("Write a ROOT output file with hits from the SDs");
cmd.SetDefaultValue("false");
}
{
auto& cmd = messenger_->DeclareProperty("stripGDMLPointers",
strip_gdml_pointers_);
cmd.SetGuidance(
"Remove pointer suffix from input logical volume names");
cmd.SetDefaultValue("false");
}
{
auto& cmd = messenger_->DeclareProperty("outputFile",
options_->output_file);
Expand Down
2 changes: 2 additions & 0 deletions app/demo-geant-integration/GlobalSetup.hh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class GlobalSetup
std::string const& GetEventFile() const { return event_file_; }
int GetRootBufferSize() const { return root_buffer_size_; }
bool GetWriteSDHits() const { return write_sd_hits_; }
bool StripGDMLPointers() const { return strip_gdml_pointers_; }
//!@}

//! Get a mutable reference to the setup options for DetectorConstruction
Expand Down Expand Up @@ -72,6 +73,7 @@ class GlobalSetup
std::string event_file_;
int root_buffer_size_{128000};
bool write_sd_hits_{false};
bool strip_gdml_pointers_{false};
G4ThreeVector field_;

std::unique_ptr<G4GenericMessenger> messenger_;
Expand Down
8 changes: 8 additions & 0 deletions app/demo-geant-integration/HitRootIO.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ HitRootIO::HitRootIO()
std::regex("\\.json$"),
".root");

if (file_name_.empty())
{
file_name_ = "demo-geant-integration.root";
}

if (G4Threading::IsWorkerThread())
{
file_name_ += std::to_string(G4Threading::G4GetThreadId());
Expand All @@ -50,6 +55,9 @@ HitRootIO::HitRootIO()
if (G4Threading::IsWorkerThread()
|| !G4Threading::IsMultithreadedApplication())
{
CELER_LOG_LOCAL(info)
<< "Creating ROOT event output file at '" << file_name_ << "'";

file_.reset(TFile::Open(file_name_.c_str(), "recreate"));
CELER_VALIDATE(file_->IsOpen(), << "failed to open " << file_name_);
tree_.reset(new TTree(
Expand Down
3 changes: 2 additions & 1 deletion app/demo-geant-integration/RunAction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ void RunAction::BeginOfRunAction(G4Run const* run)
// celeritas
if (!CELERITAS_USE_VECGEOM)
{
// For testing purposes, pass the GDML input filename to Celeritas
// To allow ORANGE to work for testing purposes, pass the GDML
// input filename to Celeritas
const_cast<celeritas::SetupOptions&>(*options_).geometry_file
= GlobalSetup::Instance()->GetGeometryFile();
}
Expand Down
2 changes: 2 additions & 0 deletions app/demo-geant-integration/demo-geant-integration.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ void run(std::string const& macro_filename)
ui->ApplyCommand("/control/execute " + macro_filename);

// Initialize run and process events
CELER_LOG(status) << "Initializing run manager";
run_manager->Initialize();

// Load the input file
Expand All @@ -86,6 +87,7 @@ void run(std::string const& macro_filename)
num_events = demo_geant::PrimaryGeneratorAction::NumEvents(),
celeritas::ExceptionConverter{"demo-geant000"});

CELER_LOG(status) << "Transporting " << num_events << " events";
run_manager->BeamOn(num_events);
}

Expand Down
11 changes: 7 additions & 4 deletions scripts/cmake-presets/goldfinger.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
"binaryDir": "${sourceDir}/build-${presetName}",
"cacheVariables": {
"CELERITAS_USE_CUDA": {"type": "BOOL", "value": "OFF"},
"CELERITAS_USE_HepMC3": {"type": "BOOL", "value": "ON"},
"CELERITAS_USE_HIP": {"type": "BOOL", "value": "OFF"},
"CELERITAS_USE_JSON": {"type": "BOOL", "value": "ON"},
"CELERITAS_USE_Geant4": {"type": "BOOL", "value": "ON"},
"CELERITAS_USE_JSON": {"type": "BOOL", "value": "ON"},
"CELERITAS_USE_Geant4": {"type": "BOOL", "value": "ON"},
"CELERITAS_USE_MPI": {"type": "BOOL", "value": "OFF"},
"CELERITAS_USE_SWIG": {"type": "BOOL", "value": "OFF"},
"CMAKE_BUILD_TYPE": {"type": "STRING", "value": "Debug"},
Expand Down Expand Up @@ -60,7 +61,8 @@
"inherits": [".reldeb", "vecgeom"],
"cacheVariables": {
"CELERITAS_BUILD_DEMOS": {"type": "BOOL", "value": "ON"},
"CELERITAS_BUILD_TESTS": {"type": "BOOL", "value": "ON"}
"CELERITAS_BUILD_TESTS": {"type": "BOOL", "value": "ON"},
"CELERITAS_USE_ROOT": {"type": "BOOL", "value": "ON"}
}
},
{
Expand All @@ -69,7 +71,8 @@
"inherits": [".ndebug", "vecgeom"],
"cacheVariables": {
"CELERITAS_BUILD_DEMOS": {"type": "BOOL", "value": "ON"},
"CELERITAS_BUILD_TESTS": {"type": "BOOL", "value": "OFF"}
"CELERITAS_BUILD_TESTS": {"type": "BOOL", "value": "OFF"},
"CELERITAS_USE_ROOT": {"type": "BOOL", "value": "ON"}
}
}
],
Expand Down
6 changes: 6 additions & 0 deletions src/accel/SetupOptions.hh
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ struct SetupOptions
using SPConstAction = std::shared_ptr<ExplicitActionInterface const>;
using AlongStepFactory
= std::function<SPConstAction(AlongStepFactoryInput const&)>;
using IntAccessor = std::function<int()>;
using VecString = std::vector<std::string>;
//!@}

Expand All @@ -81,6 +82,8 @@ struct SetupOptions
std::string geometry_file;
//! Filename for JSON diagnostic output
std::string output_file;
//! Filename for ROOT dump of physics data
std::string physics_output_file;
//!@}

//!@{
Expand All @@ -99,6 +102,9 @@ struct SetupOptions
bool sync{false};
//!@}

//! Set the number of streams (defaults to run manager # threads)
IntAccessor get_num_streams;

//!@{
//! \name Stepping actions
AlongStepFactory make_along_step;
Expand Down
39 changes: 24 additions & 15 deletions src/accel/SharedParams.cc
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,9 @@ void SharedParams::initialize_core(SetupOptions const& options)
}();
CELER_ASSERT(imported && *imported);

if (CELERITAS_USE_ROOT && options.output_file.size() > 5)
if (!options.physics_output_file.empty())
{
std::string root_out{options.output_file.begin(),
options.output_file.end() - 5};
root_out += ".root";
RootExporter export_root(root_out.c_str());
RootExporter export_root(options.physics_output_file.c_str());
export_root(*imported);
}

Expand Down Expand Up @@ -348,16 +345,28 @@ void SharedParams::initialize_core(SetupOptions const& options)
return std::make_shared<TrackInitParams>(std::move(input));
}();

// Set maximum number of streams based on Geant4 multithreading
// Hit processors *must* be allocated on the thread they're used because of
// geant4 thread-local SDs. There must be one per thread.
params.max_streams = [] {
auto* run_man = G4RunManager::GetRunManager();
CELER_VALIDATE(run_man,
<< "G4RunManager was not created before initializing "
"SharedParams");
return celeritas::get_num_threads(*run_man);
}();
if (options.get_num_streams)
{
int num_streams = options.get_num_streams();
CELER_VALIDATE(num_streams > 0,
<< "nonpositive number of streams (" << num_streams
<< ") returned by SetupOptions.get_num_streams");
params.max_streams = num_streams;
}
else
{
// Default to setting the maximum number of streams based on Geant4
// multithreading.
// Hit processors *must* be allocated on the thread they're used
// because of geant4 thread-local SDs. There must be one per thread.
params.max_streams = [] {
auto* run_man = G4RunManager::GetRunManager();
CELER_VALIDATE(run_man,
<< "G4RunManager was not created before "
"initializing SharedParams");
return celeritas::get_num_threads(*run_man);
}();
}

// Construct along-step action
params.action_reg->insert([&params, &options, &imported] {
Expand Down
45 changes: 6 additions & 39 deletions src/accel/detail/HitManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include "HitManager.hh"

#include <utility>
#include <G4LogicalVolume.hh>
#include <G4LogicalVolumeStore.hh>
#include <G4RunManager.hh>
#include <G4Threading.hh>
Expand All @@ -21,9 +20,8 @@
#include "corecel/io/Logger.hh"
#include "celeritas/Types.hh"
#include "celeritas/ext/GeantSetup.hh"
#include "celeritas/ext/detail/GeantVolumeVisitor.hh"
#include "celeritas/ext/GeantVolumeMapper.hh"
#include "celeritas/geo/GeoParams.hh" // IWYU pragma: keep
#include "celeritas/io/ImportVolume.hh"
#include "accel/SetupOptions.hh"

#include "HitProcessor.hh"
Expand All @@ -42,6 +40,7 @@ void update_selection(StepPointSelection* selection,
selection->pos = options.position;
selection->energy = options.kinetic_energy;
}

//---------------------------------------------------------------------------//
} // namespace

Expand All @@ -68,10 +67,8 @@ HitManager::HitManager(GeoParams const& geo, SDSetupOptions const& setup)
// Logical volumes to pass to hit processor
std::vector<G4LogicalVolume*> geant_vols;

// Helper class to extract GDML names+labels from Geant4 volume
GeantVolumeVisitor visitor(true);

// Loop over all logical volumes
// Loop over all logical volumes and map detectors to Volume IDS
GeantVolumeMapper g4_to_celer{geo};
G4LogicalVolumeStore* lv_store = G4LogicalVolumeStore::GetInstance();
CELER_ASSERT(lv_store);
for (G4LogicalVolume* lv : *lv_store)
Expand All @@ -85,39 +82,9 @@ HitManager::HitManager(GeoParams const& geo, SDSetupOptions const& setup)
continue;
}

// Convert volume name to GPU geometry ID
auto label = Label::from_geant(lv->GetName());
if (label.ext.empty())
{
// Label doesn't have a pointer address attached: we probably need
// to regenerate to match the exported GDML file
label = Label::from_geant(visitor.generate_name(*lv));
}

auto id = geo.find_volume(label);
if (!id)
{
// Fallback to skipping the extension
id = geo.find_volume(label.name);
if (id)
{
CELER_LOG(warning)
<< "Failed to find " << celeritas_geometry
<< " volume corresponding to Geant4 volume '"
<< lv->GetName() << "'; found '" << geo.id_to_label(id)
<< "' by omitting the extension";
}
else
{
// Try regenerating the name even if we *did* have a pointer
// address attached (in case the original volume name already
// had a pointer suffix and we added another)
label = Label::from_geant(visitor.generate_name(*lv));
id = geo.find_volume(label.name);
}
}
auto id = g4_to_celer(*lv);
CELER_VALIDATE(id,
<< "failed to find " << celeritas_geometry
<< "failed to find a unique " << celeritas_geometry
<< " volume corresponding to Geant4 volume '"
<< lv->GetName() << "'");
CELER_LOG(debug) << "Mapped sensitive detector '" << sd->GetName()
Expand Down
11 changes: 8 additions & 3 deletions src/celeritas/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,12 @@ if(CELERITAS_USE_CUDA OR CELERITAS_USE_HIP)
endif()

if(CELERITAS_USE_Geant4)
set(_cg4_libs Celeritas::corecel XercesC::XercesC ${Geant4_LIBRARIES})
celeritas_add_object_library(celeritas_geant4
ext/LoadGdml.cc
ext/GeantImporter.cc
ext/GeantSetup.cc
ext/GeantVolumeMapper.cc
ext/detail/GeantBremsstrahlungProcess.cc
ext/detail/GeantExceptionHandler.cc
ext/detail/GeantGeoExporter.cc
Expand All @@ -120,9 +122,12 @@ if(CELERITAS_USE_Geant4)
ext/detail/GeantProcessImporter.cc
ext/detail/GeantVolumeVisitor.cc
)
target_link_libraries(celeritas_geant4
PRIVATE Celeritas::corecel XercesC::XercesC ${Geant4_LIBRARIES}
)
if(CELERITAS_USE_VecGeom)
list(APPEND _cg4_libs VecGeom::vecgeom)
else()
list(APPEND _cg4_libs Celeritas::orange)
endif()
target_link_libraries(celeritas_geant4 PRIVATE ${_cg4_libs})
list(APPEND SOURCES $<TARGET_OBJECTS:celeritas_geant4>)
list(APPEND PRIVATE_DEPS celeritas_geant4)
endif()
Expand Down
4 changes: 3 additions & 1 deletion src/celeritas/ext/GeantImporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,9 @@ GeantImporter::import_volumes(bool unique_volumes) const
visitor.visit(*world_->GetLogicalVolume());

auto volumes = visitor.build_volume_vector();
CELER_LOG(debug) << "Loaded " << volumes.size() << " volumes";
CELER_LOG(debug) << "Loaded " << volumes.size() << " volumes with "
<< (unique_volumes ? "uniquified" : "original")
<< " names";
return volumes;
}

Expand Down
Loading