Skip to content

Commit

Permalink
Use Celeritas error and output handling in celer-g4 app (celeritas-pr…
Browse files Browse the repository at this point in the history
…oject#1013)

* Add convenience functino for getting number of threads from geant4 run manager

* Add log messages

* Add `to_color_code` for logger levels

* Move g4 exception disabling to GeantUtils

* Add additional diagnostics to g4-only output registry

* Use Celeritas error handling and logging for celer-g4

* Add scoped profiling to actual run

* Fix no-geant4 inline functions

* Add field validation

* Pass more data instead of using global static

* Mark manager thread from local logger to distinguish from global CELER_LOG

* Fix recursive mutex deadlock
  • Loading branch information
sethrj committed Nov 20, 2023
1 parent 5de4bb9 commit bad52d7
Show file tree
Hide file tree
Showing 33 changed files with 445 additions and 189 deletions.
26 changes: 23 additions & 3 deletions app/celer-g4/ActionInitialization.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "ActionInitialization.hh"

#include "corecel/io/Logger.hh"
#include "accel/HepMC3PrimaryGenerator.hh"
#include "accel/LocalTransporter.hh"

#include "EventAction.hh"
Expand All @@ -31,8 +32,26 @@ ActionInitialization::ActionInitialization(SPParams params)
: params_{std::move(params)}, init_shared_{true}
{
CELER_EXPECT(params_);

// Create Geant4 diagnostics to be shared across worker threads
diagnostics_ = std::make_shared<GeantDiagnostics>();

auto const& inp = GlobalSetup::Instance()->input();
CELER_VALIDATE(inp.primary_options || !inp.event_file.empty(),
<< "no event input file nor primary options were "
"specified");

if (!inp.event_file.empty())
{
hepmc_gen_ = std::make_shared<HepMC3PrimaryGenerator>(inp.event_file);
num_events_ = hepmc_gen_->NumEvents();
}
else
{
num_events_ = inp.primary_options.num_events;
}

CELER_ENSURE(num_events_ > 0);
}

//---------------------------------------------------------------------------//
Expand Down Expand Up @@ -68,13 +87,14 @@ void ActionInitialization::Build() const
CELER_LOG_LOCAL(status) << "Constructing user actions on worker threads";

// Primary generator emits source particles
if (!GlobalSetup::Instance()->GetEventFile().empty())
if (hepmc_gen_)
{
this->SetUserAction(new HepMC3PrimaryGeneratorAction());
this->SetUserAction(new HepMC3PrimaryGeneratorAction(hepmc_gen_));
}
else
{
this->SetUserAction(new PGPrimaryGeneratorAction());
this->SetUserAction(new PGPrimaryGeneratorAction(
GlobalSetup::Instance()->input().primary_options));
}

// Create thread-local transporter to share between actions
Expand Down
6 changes: 6 additions & 0 deletions app/celer-g4/ActionInitialization.hh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

namespace celeritas
{
class HepMC3PrimaryGenerator;
namespace app
{
//---------------------------------------------------------------------------//
Expand All @@ -36,9 +37,14 @@ class ActionInitialization final : public G4VUserActionInitialization
void BuildForMaster() const final;
void Build() const final;

//! Get the number of events to be transported
int num_events() const { return num_events_; }

private:
SPParams params_;
SPDiagnostics diagnostics_;
std::shared_ptr<HepMC3PrimaryGenerator> hepmc_gen_;
int num_events_{0};
mutable bool init_shared_;
};

Expand Down
1 change: 1 addition & 0 deletions app/celer-g4/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ if(CELERITAS_USE_Geant4)
GeantDiagnostics.cc
GlobalSetup.cc
HepMC3PrimaryGeneratorAction.cc
LocalLogger.cc
PGPrimaryGeneratorAction.cc
RunAction.cc
RunInput.cc
Expand Down
9 changes: 2 additions & 7 deletions app/celer-g4/DetectorConstruction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,8 @@ auto DetectorConstruction::construct_geo() const -> GeoData
gdml_parser.SetStripFlag(true);

std::string const& filename = GlobalSetup::Instance()->GetGeometryFile();
if (filename.empty())
{
G4Exception("DetectorConstruction::Construct()",
"",
FatalException,
"No GDML file was specified with /celerg4/geometryFile");
}
CELER_VALIDATE(!filename.empty(),
<< "no GDML input file was specified (geometry_file)");
constexpr bool validate_gdml_schema = false;
gdml_parser.Read(filename, validate_gdml_schema);

Expand Down
8 changes: 2 additions & 6 deletions app/celer-g4/EventAction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <G4Event.hh>

#include "corecel/Macros.hh"
#include "accel/ExceptionConverter.hh"

#include "GlobalSetup.hh"
#include "RootIO.hh"
Expand Down Expand Up @@ -50,9 +49,7 @@ void EventAction::BeginOfEventAction(G4Event const* event)
return;

// Set event ID in local transporter
ExceptionConverter call_g4exception{"celer0002"};
CELER_TRY_HANDLE(transport_->SetEventId(event->GetEventID()),
call_g4exception);
transport_->SetEventId(event->GetEventID());
}

//---------------------------------------------------------------------------//
Expand All @@ -66,8 +63,7 @@ void EventAction::EndOfEventAction(G4Event const* event)
if (!SharedParams::CeleritasDisabled())
{
// Transport any tracks left in the buffer
ExceptionConverter call_g4exception{"celer0004", params_.get()};
CELER_TRY_HANDLE(transport_->Flush(), call_g4exception);
transport_->Flush();
}

if (RootIO::use_root())
Expand Down
19 changes: 19 additions & 0 deletions app/celer-g4/GeantDiagnostics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,20 @@

#include "corecel/io/BuildOutput.hh"
#include "corecel/io/Logger.hh"
#include "corecel/sys/Environment.hh"
#include "corecel/sys/MemRegistry.hh"
#include "celeritas/Types.hh"
#include "celeritas/global/CoreParams.hh"

#include "G4RunManager.hh"
#include "GlobalSetup.hh"

#if CELERITAS_USE_JSON
# include "corecel/io/OutputInterfaceAdapter.hh"
# include "corecel/sys/EnvironmentIO.json.hh"
# include "corecel/sys/MemRegistryIO.json.hh"
#endif

namespace celeritas
{
namespace app
Expand Down Expand Up @@ -54,6 +62,17 @@ GeantDiagnostics::GeantDiagnostics(SharedParams const& params)
if (!params)
{
// Celeritas core params didn't add system metadata: do it ourselves
#if CELERITAS_USE_JSON
// Save system diagnostic information
output_reg->insert(OutputInterfaceAdapter<MemRegistry>::from_const_ref(
OutputInterface::Category::system,
"memory",
celeritas::mem_registry()));
output_reg->insert(OutputInterfaceAdapter<Environment>::from_const_ref(
OutputInterface::Category::system,
"environ",
celeritas::environment()));
#endif
output_reg->insert(std::make_shared<BuildOutput>());
}

Expand Down
15 changes: 0 additions & 15 deletions app/celer-g4/GlobalSetup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include "corecel/io/StringUtils.hh"
#include "corecel/sys/Device.hh"
#include "celeritas/field/RZMapFieldInput.hh"
#include "accel/ExceptionConverter.hh"
#include "accel/SetupOptionsMessenger.hh"

#include "HepMC3PrimaryGeneratorAction.hh"
Expand Down Expand Up @@ -128,7 +127,6 @@ void GlobalSetup::ReadInput(std::string const& filename)
std::ifstream infile(filename);
CELER_VALIDATE(infile, << "failed to open '" << filename << "'");
nlohmann::json::parse(infile).get_to(input_);
CELER_ASSERT(input_);

// Input options
if (CELERITAS_CORE_GEO == CELERITAS_CORE_GEO_ORANGE)
Expand Down Expand Up @@ -181,19 +179,6 @@ void GlobalSetup::ReadInput(std::string const& filename)
"written because ROOT is disabled";
}

// Get the number of events
if (!input_.event_file.empty())
{
// Load the input file
CELER_TRY_HANDLE(
num_events_ = HepMC3PrimaryGeneratorAction::NumEvents(),
ExceptionConverter{"celer-g4000"});
}
else
{
num_events_ = input_.primary_options.num_events;
}

// Start the timer for setup time
get_setup_time_ = {};
}
Expand Down
9 changes: 0 additions & 9 deletions app/celer-g4/GlobalSetup.hh
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ class GlobalSetup
//!@{
//! \name Demo setup options (DEPRECATED: use direct interface to input)
std::string const& GetGeometryFile() const { return input_.geometry_file; }
std::string const& GetEventFile() const { return input_.event_file; }
PrimaryGeneratorOptions const& GetPrimaryGeneratorOptions() const
{
return input_.primary_options;
}
GeantPhysicsOptions const& GetPhysicsOptions() const
{
return input_.physics_options;
Expand All @@ -58,9 +53,6 @@ class GlobalSetup
}
//!@}

//! Get the number of events
int GetNumEvents() { return num_events_; }

//! Get a mutable reference to the setup options for DetectorConstruction
SDSetupOptions& GetSDSetupOptions() { return options_->sd; }

Expand Down Expand Up @@ -102,7 +94,6 @@ class GlobalSetup
std::shared_ptr<SetupOptions> options_;
RunInput input_;
Stopwatch get_setup_time_;
int num_events_{0};

std::unique_ptr<G4GenericMessenger> messenger_;
};
Expand Down
32 changes: 5 additions & 27 deletions app/celer-g4/HepMC3PrimaryGeneratorAction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <G4Event.hh>

#include "corecel/Macros.hh"
#include "accel/ExceptionConverter.hh"
#include "accel/HepMC3PrimaryGenerator.hh"

#include "GlobalSetup.hh"
Expand All @@ -19,33 +18,14 @@ namespace celeritas
{
namespace app
{
namespace
{
//---------------------------------------------------------------------------//
/*!
* Global HepMC3 file reader shared across threads.
*
* The first time this is called, the reader will be initialized from the
* GlobalSetup event file argument.
*/
HepMC3PrimaryGenerator& shared_reader()
{
static HepMC3PrimaryGenerator reader{
GlobalSetup::Instance()->GetEventFile()};
return reader;
}
//---------------------------------------------------------------------------//
} // namespace

//---------------------------------------------------------------------------//
/*!
* Get the total number of events available in the HepMC3 file.
*
* This will load the HepMC3 file if not already active.
* Construct from a shared generator.
*/
int HepMC3PrimaryGeneratorAction::NumEvents()
HepMC3PrimaryGeneratorAction::HepMC3PrimaryGeneratorAction(SPGenerator gen)
: generator_{std::move(gen)}
{
return shared_reader().NumEvents();
CELER_EXPECT(generator_);
}

//---------------------------------------------------------------------------//
Expand All @@ -54,9 +34,7 @@ int HepMC3PrimaryGeneratorAction::NumEvents()
*/
void HepMC3PrimaryGeneratorAction::GeneratePrimaries(G4Event* event)
{
ExceptionConverter call_g4exception{"celer0000"};
CELER_TRY_HANDLE(shared_reader().GeneratePrimaryVertex(event),
call_g4exception);
generator_->GeneratePrimaryVertex(event);
}

//---------------------------------------------------------------------------//
Expand Down
16 changes: 12 additions & 4 deletions app/celer-g4/HepMC3PrimaryGeneratorAction.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
//---------------------------------------------------------------------------//
#pragma once

#include <memory>
#include <G4VUserPrimaryGeneratorAction.hh>

namespace celeritas
{
class HepMC3PrimaryGenerator;
namespace app
{
//---------------------------------------------------------------------------//
Expand All @@ -20,14 +22,20 @@ namespace app
class HepMC3PrimaryGeneratorAction final : public G4VUserPrimaryGeneratorAction
{
public:
// Get the total number of events available in the HepMC3 file
static int NumEvents();
//!@{
//! \name Type aliases
using SPGenerator = std::shared_ptr<HepMC3PrimaryGenerator>;
//!@}

// Construct primary action
HepMC3PrimaryGeneratorAction() = default;
public:
// Construct from a shared generator
explicit HepMC3PrimaryGeneratorAction(SPGenerator);

// Generate events
void GeneratePrimaries(G4Event* event) final;

private:
SPGenerator generator_;
};

//---------------------------------------------------------------------------//
Expand Down
51 changes: 51 additions & 0 deletions app/celer-g4/LocalLogger.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//----------------------------------*-C++-*----------------------------------//
// Copyright 2023 UT-Battelle, LLC, and other Celeritas developers.
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
//---------------------------------------------------------------------------//
//! \file celer-g4/LocalLogger.cc
//---------------------------------------------------------------------------//
#include "LocalLogger.hh"

#include <G4Threading.hh>

#include "corecel/io/ColorUtils.hh"

namespace celeritas
{
namespace app
{
//---------------------------------------------------------------------------//
/*!
* Write a log message.
*/
void LocalLogger::operator()(Provenance prov, LogLevel lev, std::string msg)
{
int local_thread = G4Threading::G4GetThreadId();
std::clog << color_code('W') << '[';
if (local_thread >= 0)
{
std::clog << local_thread + 1;
}
else
{
std::clog << 'M';
}
std::clog << '/' << num_threads_ << "] " << color_code(' ');

if (lev == LogLevel::debug || lev >= LogLevel::warning)
{
// Output problem line/file for debugging or high level
std::clog << color_code('x') << prov.file;
if (prov.line)
std::clog << ':' << prov.line;
std::clog << color_code(' ') << ": ";
}

std::clog << to_color_code(lev) << to_cstring(lev) << ": "
<< color_code(' ') << msg << std::endl;
}

//---------------------------------------------------------------------------//
} // namespace app
} // namespace celeritas

0 comments on commit bad52d7

Please sign in to comment.