From 3e1c4a4580c23090140c5356d667fe36e5409839 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Mon, 26 Jan 2026 09:46:17 -0500 Subject: [PATCH 01/14] Add GeantTrackView and refactor LocalTransporter - Create GeantTrackView.hh to wrap G4Track with Celeritas units - Provides particle() method returning GeantParticleView - Implements position(), direction(), energy(), time(), weight() accessors - Refactor LocalTransporter::Push to use GeantTrackView - Update AGENTS.md with clearer commit workflow instructions Assisted-by: GitHub Copilot (Claude Sonnet 4.5) --- src/accel/LocalTransporter.cc | 50 ++++++------ src/celeritas/ext/GeantTrackView.hh | 113 ++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 27 deletions(-) create mode 100644 src/celeritas/ext/GeantTrackView.hh diff --git a/src/accel/LocalTransporter.cc b/src/accel/LocalTransporter.cc index 8248fc4f49..d4c206da30 100644 --- a/src/accel/LocalTransporter.cc +++ b/src/accel/LocalTransporter.cc @@ -35,6 +35,7 @@ #include "celeritas/Quantities.hh" #include "celeritas/Types.hh" #include "celeritas/ext/GeantSd.hh" +#include "celeritas/ext/GeantTrackView.hh" #include "celeritas/ext/GeantUnits.hh" #include "celeritas/ext/detail/HitProcessor.hh" #include "celeritas/global/ActionSequence.hh" @@ -245,56 +246,51 @@ void LocalTransporter::Push(G4Track& g4track) ScopedProfiling profile_this{"push"}; - if (Real3 pos = convert_from_geant(g4track.GetPosition(), 1); - !is_inside(bbox_, pos)) + GeantTrackView track_view{g4track}; + + if (!is_inside(bbox_, track_view.position())) { // Primary may have been created by a particle generator outside the // geometry - double energy - = convert_from_geant(g4track.GetKineticEnergy(), CLHEP::MeV); CELER_LOG_LOCAL(error) - << "Discarding track outside world bounds: " << energy - << " MeV from " << g4track.GetDefinition()->GetParticleName() - << " at " << pos << " along " - << convert_from_geant(g4track.GetMomentumDirection(), 1); + << "Discarding track outside world bounds: " + << track_view.energy().value() << " " + << GeantTrackView::Energy::unit_type::label() << " from " + << track_view.particle().name() << " at " << track_view.position() + << " along " << track_view.direction(); - buffer_accum_.lost_energy += energy; + buffer_accum_.lost_energy += track_view.energy().value(); ++buffer_accum_.lost_primaries; return; } - Primary track; - - PDGNumber const pdg{g4track.GetDefinition()->GetPDGEncoding()}; - track.particle_id = particles_->find(pdg); + Primary offloaded; // Generate Celeritas-specific PrimaryID if (hit_processor_) { - track.primary_id + offloaded.primary_id = hit_processor_->track_processor().register_primary(g4track); } - track.energy = units::MevEnergy( - convert_from_geant(g4track.GetKineticEnergy(), CLHEP::MeV)); + offloaded.energy = track_view.energy(); + offloaded.particle_id = particles_->find(track_view.particle().pdg()); + offloaded.position = track_view.position(); + offloaded.direction = track_view.direction(); + offloaded.time = track_view.time(); + offloaded.weight = track_view.weight(); - CELER_VALIDATE(track.particle_id, - << "cannot offload '" - << g4track.GetDefinition()->GetParticleName() + CELER_VALIDATE(offloaded.particle_id, + << "cannot offload '" << track_view.particle().name() << "' particles"); - track.position = convert_from_geant(g4track.GetPosition(), clhep_length); - track.direction = convert_from_geant(g4track.GetMomentumDirection(), 1); - track.time = convert_from_geant(g4track.GetGlobalTime(), clhep_time); - track.weight = g4track.GetWeight(); - /*! * \todo Eliminate event ID from primary. */ - track.event_id = EventId{0}; + offloaded.event_id = EventId{0}; - buffer_.push_back(track); - buffer_accum_.energy += track.energy.value(); + buffer_.push_back(offloaded); + buffer_accum_.energy += offloaded.energy.value(); if (buffer_.size() >= auto_flush_) { this->Flush(); diff --git a/src/celeritas/ext/GeantTrackView.hh b/src/celeritas/ext/GeantTrackView.hh new file mode 100644 index 0000000000..422b92b14f --- /dev/null +++ b/src/celeritas/ext/GeantTrackView.hh @@ -0,0 +1,113 @@ +//------------------------------- -*- C++ -*- -------------------------------// +// Copyright Celeritas contributors: see top-level COPYRIGHT file for details +// SPDX-License-Identifier: (Apache-2.0 OR MIT) +//---------------------------------------------------------------------------// +//! \file celeritas/ext/GeantTrackView.hh +//---------------------------------------------------------------------------// +#pragma once + +#include +#include + +#include "corecel/Types.hh" +#include "corecel/math/Quantity.hh" +#include "geocel/g4/Convert.hh" +#include "celeritas/UnitTypes.hh" + +#include "GeantParticleView.hh" +#include "GeantUnits.hh" + +namespace celeritas +{ +//---------------------------------------------------------------------------// +/*! + * Access track data from Geant4 with Celeritas units. + * + * This provides a uniform interface to G4Track data using Celeritas types and + * units. Geant4 data are all in double precision. + */ +class GeantTrackView +{ + public: + //!@{ + //! \name Type aliases + using Energy = Quantity; + using real_type = double; + //!@} + + public: + // Construct from G4Track + explicit GeantTrackView(G4Track const& track) : track_(track) {} + + // Get particle definition view + inline GeantParticleView particle() const; + + // Position in native Celeritas length units + inline Real3 position() const; + + // Momentum direction (unit vector) + inline Real3 direction() const; + + // Kinetic energy [MeV] + inline Energy energy() const; + + // Global time in native Celeritas time units + inline real_type time() const; + + //! Statistical weight + real_type weight() const { return track_.GetWeight(); } + + private: + G4Track const& track_; +}; + +//---------------------------------------------------------------------------// +// INLINE DEFINITIONS +//---------------------------------------------------------------------------// +/*! + * Get particle definition view. + */ +GeantParticleView GeantTrackView::particle() const +{ + CELER_EXPECT(track_.GetDefinition()); + return GeantParticleView{*track_.GetDefinition()}; +} + +//---------------------------------------------------------------------------// +/*! + * Get position in native Celeritas length units. + */ +Real3 GeantTrackView::position() const +{ + return convert_from_geant(track_.GetPosition(), clhep_length); +} + +//---------------------------------------------------------------------------// +/*! + * Get momentum direction. + */ +Real3 GeantTrackView::direction() const +{ + return convert_from_geant(track_.GetMomentumDirection(), 1); +} + +//---------------------------------------------------------------------------// +/*! + * Get kinetic energy in MeV. + */ +GeantTrackView::Energy GeantTrackView::energy() const +{ + return Energy{convert_from_geant(track_.GetKineticEnergy(), CLHEP::MeV)}; +} + +//---------------------------------------------------------------------------// +/*! + * Get global time in native Celeritas time units. + */ +real_type GeantTrackView::time() const +{ + return convert_from_geant(track_.GetGlobalTime(), clhep_time); +} + +//---------------------------------------------------------------------------// +} // namespace celeritas From 18fc471989aa4c5f68abccb53faad205bf216c02 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Mon, 26 Jan 2026 10:10:30 -0500 Subject: [PATCH 02/14] Add notes about killing and tracking cut --- src/celeritas/global/detail/KillActive.cc | 3 +++ src/celeritas/global/detail/KillActive.hh | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/celeritas/global/detail/KillActive.cc b/src/celeritas/global/detail/KillActive.cc index a2856801d0..12b1316207 100644 --- a/src/celeritas/global/detail/KillActive.cc +++ b/src/celeritas/global/detail/KillActive.cc @@ -21,6 +21,9 @@ namespace detail //---------------------------------------------------------------------------// /*! * Mark all active tracks as "errored". + * + * These will then be killed by the \c TrackingCutAction at the end of the + * step. */ void kill_active(CoreParams const& params, CoreState& state) { diff --git a/src/celeritas/global/detail/KillActive.hh b/src/celeritas/global/detail/KillActive.hh index 3952b9d343..6131741f0e 100644 --- a/src/celeritas/global/detail/KillActive.hh +++ b/src/celeritas/global/detail/KillActive.hh @@ -25,6 +25,9 @@ namespace detail //---------------------------------------------------------------------------// /*! * Mark active tracks as "errored". + * + * This is invoked by the \c kill_active free function, which implements + * \c Stepper::kill_active . */ struct KillActiveExecutor { From 0a78d743b654f3a7204394113ecc0fc290d268c0 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Mon, 26 Jan 2026 12:23:39 -0500 Subject: [PATCH 03/14] Rename pos/dir for consistency with geo track view --- src/accel/LocalTransporter.cc | 33 ++++++++++++++--------------- src/celeritas/ext/GeantTrackView.hh | 6 +++--- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/accel/LocalTransporter.cc b/src/accel/LocalTransporter.cc index d4c206da30..76ffaf3566 100644 --- a/src/accel/LocalTransporter.cc +++ b/src/accel/LocalTransporter.cc @@ -246,20 +246,19 @@ void LocalTransporter::Push(G4Track& g4track) ScopedProfiling profile_this{"push"}; - GeantTrackView track_view{g4track}; + GeantTrackView gtv{g4track}; - if (!is_inside(bbox_, track_view.position())) + if (!is_inside(bbox_, gtv.pos())) { // Primary may have been created by a particle generator outside the // geometry - CELER_LOG_LOCAL(error) - << "Discarding track outside world bounds: " - << track_view.energy().value() << " " - << GeantTrackView::Energy::unit_type::label() << " from " - << track_view.particle().name() << " at " << track_view.position() - << " along " << track_view.direction(); - - buffer_accum_.lost_energy += track_view.energy().value(); + CELER_LOG_LOCAL(error) << "Discarding track outside world bounds: " + << gtv.energy().value() << " " + << GeantTrackView::Energy::unit_type::label() + << " from " << gtv.particle().name() << " at " + << gtv.pos() << " along " << gtv.direction(); + + buffer_accum_.lost_energy += gtv.energy().value(); ++buffer_accum_.lost_primaries; return; } @@ -273,15 +272,15 @@ void LocalTransporter::Push(G4Track& g4track) = hit_processor_->track_processor().register_primary(g4track); } - offloaded.energy = track_view.energy(); - offloaded.particle_id = particles_->find(track_view.particle().pdg()); - offloaded.position = track_view.position(); - offloaded.direction = track_view.direction(); - offloaded.time = track_view.time(); - offloaded.weight = track_view.weight(); + offloaded.energy = gtv.energy(); + offloaded.particle_id = particles_->find(gtv.particle().pdg()); + offloaded.position = gtv.pos(); + offloaded.direction = gtv.direction(); + offloaded.time = gtv.time(); + offloaded.weight = gtv.weight(); CELER_VALIDATE(offloaded.particle_id, - << "cannot offload '" << track_view.particle().name() + << "cannot offload '" << gtv.particle().name() << "' particles"); /*! diff --git a/src/celeritas/ext/GeantTrackView.hh b/src/celeritas/ext/GeantTrackView.hh index 422b92b14f..a18a735552 100644 --- a/src/celeritas/ext/GeantTrackView.hh +++ b/src/celeritas/ext/GeantTrackView.hh @@ -43,10 +43,10 @@ class GeantTrackView inline GeantParticleView particle() const; // Position in native Celeritas length units - inline Real3 position() const; + inline Real3 pos() const; // Momentum direction (unit vector) - inline Real3 direction() const; + inline Real3 dir() const; // Kinetic energy [MeV] inline Energy energy() const; @@ -77,7 +77,7 @@ GeantParticleView GeantTrackView::particle() const /*! * Get position in native Celeritas length units. */ -Real3 GeantTrackView::position() const +Real3 GeantTrackView::pos() const { return convert_from_geant(track_.GetPosition(), clhep_length); } From 92f133af4cb32e25508768aa4bf48e267f85034e Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Mon, 26 Jan 2026 14:09:11 -0500 Subject: [PATCH 04/14] Add GeantStepView and GeantStepPointView classes Create unified view interfaces for G4Step and G4StepPoint with: - Getters/setters using Celeritas types and units - Consistent API pattern with GeantTrackView - update_from_volume() methods to encapsulate LV attribute updates Refactor HitProcessor to use these views instead of direct G4 calls. Also fix GeantTrackView::dir() implementation name. Assisted-by: GitHub Copilot (Claude Sonnet 4.5) --- src/celeritas/ext/GeantStepPointView.hh | 208 +++++++++++++++++++++++ src/celeritas/ext/GeantStepView.hh | 106 ++++++++++++ src/celeritas/ext/GeantTrackView.hh | 2 +- src/celeritas/ext/detail/HitProcessor.cc | 78 +++++---- 4 files changed, 353 insertions(+), 41 deletions(-) create mode 100644 src/celeritas/ext/GeantStepPointView.hh create mode 100644 src/celeritas/ext/GeantStepView.hh diff --git a/src/celeritas/ext/GeantStepPointView.hh b/src/celeritas/ext/GeantStepPointView.hh new file mode 100644 index 0000000000..e77e4815f4 --- /dev/null +++ b/src/celeritas/ext/GeantStepPointView.hh @@ -0,0 +1,208 @@ +//------------------------------- -*- C++ -*- -------------------------------// +// Copyright Celeritas contributors: see top-level COPYRIGHT file for details +// SPDX-License-Identifier: (Apache-2.0 OR MIT) +//---------------------------------------------------------------------------// +//! \file celeritas/ext/GeantStepPointView.hh +//---------------------------------------------------------------------------// +#pragma once + +#include +#include +#include + +#include "corecel/Types.hh" +#include "corecel/math/Quantity.hh" +#include "geocel/g4/Convert.hh" +#include "celeritas/UnitTypes.hh" + +#include "GeantUnits.hh" + +namespace celeritas +{ +//---------------------------------------------------------------------------// +/*! + * Access and modify step point data from Geant4 with Celeritas units. + * + * This provides a uniform interface to G4StepPoint data using Celeritas types + * and units. Geant4 data are all in double precision. + */ +class GeantStepPointView +{ + public: + //!@{ + //! \name Type aliases + using Energy = Quantity; + using real_type = double; + //!@} + + public: + // Construct from G4StepPoint + explicit GeantStepPointView(G4StepPoint* step_point) + : step_point_(step_point) + { + } + + //!@{ + //! \name Getters + + // Position in native Celeritas length units + inline Real3 pos() const; + + // Momentum direction (unit vector) + inline Real3 dir() const; + + // Kinetic energy [MeV] + inline Energy energy() const; + + // Global time in native Celeritas time units + inline real_type time() const; + + //! Statistical weight + real_type weight() const { return step_point_->GetWeight(); } + + //!@} + //!@{ + //! \name Setters + + // Set position in native Celeritas length units + inline void pos(Real3 const& position); + + // Set momentum direction (unit vector) + inline void dir(Real3 const& direction); + + // Set kinetic energy [MeV] + inline void energy(Energy kinetic_energy); + + // Set global time in native Celeritas time units + inline void time(real_type global_time); + + // Set statistical weight + void weight(real_type w) { step_point_->SetWeight(w); } + + // Update attributes from logical volume + inline void update_from_volume(G4LogicalVolume const* lv); + + // Update attributes from touchable's logical volume + inline void update_from_volume(); + + //!@} + + private: + G4StepPoint* step_point_; +}; + +//---------------------------------------------------------------------------// +// INLINE DEFINITIONS +//---------------------------------------------------------------------------// +/*! + * Get position in native Celeritas length units. + */ +Real3 GeantStepPointView::pos() const +{ + return convert_from_geant(step_point_->GetPosition(), clhep_length); +} + +//---------------------------------------------------------------------------// +/*! + * Get momentum direction. + */ +Real3 GeantStepPointView::dir() const +{ + return convert_from_geant(step_point_->GetMomentumDirection(), 1); +} + +//---------------------------------------------------------------------------// +/*! + * Get kinetic energy in MeV. + */ +GeantStepPointView::Energy GeantStepPointView::energy() const +{ + return Energy{ + convert_from_geant(step_point_->GetKineticEnergy(), CLHEP::MeV)}; +} + +//---------------------------------------------------------------------------// +/*! + * Get global time in native Celeritas time units. + */ +real_type GeantStepPointView::time() const +{ + return convert_from_geant(step_point_->GetGlobalTime(), clhep_time); +} + +//---------------------------------------------------------------------------// +/*! + * Set position in native Celeritas length units. + */ +void GeantStepPointView::pos(Real3 const& position) +{ + step_point_->SetPosition(convert_to_geant(position, clhep_length)); +} + +//---------------------------------------------------------------------------// +/*! + * Set momentum direction. + */ +void GeantStepPointView::dir(Real3 const& direction) +{ + step_point_->SetMomentumDirection(convert_to_geant(direction, 1)); +} + +//---------------------------------------------------------------------------// +/*! + * Set kinetic energy in MeV. + */ +void GeantStepPointView::energy(Energy kinetic_energy) +{ + step_point_->SetKineticEnergy( + convert_to_geant(kinetic_energy.value(), CLHEP::MeV)); +} + +//---------------------------------------------------------------------------// +/*! + * Set global time in native Celeritas time units. + */ +void GeantStepPointView::time(real_type global_time) +{ + step_point_->SetGlobalTime(convert_to_geant(global_time, clhep_time)); +} + +//---------------------------------------------------------------------------// +/*! + * Update attributes from logical volume. + * + * If the logical volume is null, no updates are performed. + */ +void GeantStepPointView::update_from_volume(G4LogicalVolume const* lv) +{ + if (lv) + { + step_point_->SetMaterial(lv->GetMaterial()); + step_point_->SetMaterialCutsCouple(lv->GetMaterialCutsCouple()); + step_point_->SetSensitiveDetector(lv->GetSensitiveDetector()); + } +} + +//---------------------------------------------------------------------------// +/*! + * Update attributes from touchable's logical volume. + * + * The post-step volume is fetched from the touchable. The physical volume + * could be null if post-step is outside the geometry. + */ +void GeantStepPointView::update_from_volume() +{ + G4LogicalVolume const* lv = nullptr; + if (auto* touch = step_point_->GetTouchable()) + { + // The physical volume could be null if post-step is outside + if (auto* pv = touch->GetVolume()) + { + lv = pv->GetLogicalVolume(); + } + } + this->update_from_volume(lv); +} + +//---------------------------------------------------------------------------// +} // namespace celeritas diff --git a/src/celeritas/ext/GeantStepView.hh b/src/celeritas/ext/GeantStepView.hh new file mode 100644 index 0000000000..dbf8dc561e --- /dev/null +++ b/src/celeritas/ext/GeantStepView.hh @@ -0,0 +1,106 @@ +//------------------------------- -*- C++ -*- -------------------------------// +// Copyright Celeritas contributors: see top-level COPYRIGHT file for details +// SPDX-License-Identifier: (Apache-2.0 OR MIT) +//---------------------------------------------------------------------------// +//! \file celeritas/ext/GeantStepView.hh +//---------------------------------------------------------------------------// +#pragma once + +#include +#include + +#include "corecel/math/Quantity.hh" +#include "geocel/g4/Convert.hh" +#include "celeritas/UnitTypes.hh" + +#include "GeantUnits.hh" + +namespace celeritas +{ +//---------------------------------------------------------------------------// +/*! + * Access and modify step data from Geant4 with Celeritas units. + * + * This provides a uniform interface to G4Step data using Celeritas types and + * units. Geant4 data are all in double precision. + */ +class GeantStepView +{ + public: + //!@{ + //! \name Type aliases + using MevEnergy = Quantity; + using Energy = MevEnergy; + using real_type = double; + //!@} + + public: + // Construct from G4Step + explicit GeantStepView(G4Step* step) : step_(step) {} + + //!@{ + //! \name Getters + + // Total energy deposited during step [MeV] + inline MevEnergy energy_deposition() const; + + // Step length in native Celeritas length units + inline real_type step_length() const; + + //!@} + //!@{ + //! \name Setters + + // Set total energy deposited during step [MeV] + inline void energy_deposition(MevEnergy edep); + + // Set step length in native Celeritas length units + inline void step_length(real_type length); + + //!@} + + private: + G4Step* step_; +}; + +//---------------------------------------------------------------------------// +// INLINE DEFINITIONS +//---------------------------------------------------------------------------// +/*! + * Get total energy deposited during step in MeV. + */ +GeantStepView::MevEnergy GeantStepView::energy_deposition() const +{ + return MevEnergy{ + convert_from_geant(step_->GetTotalEnergyDeposit(), CLHEP::MeV)}; +} + +//---------------------------------------------------------------------------// +/*! + * Get step length in native Celeritas length units. + */ +real_type GeantStepView::step_length() const +{ + return convert_from_geant(step_->GetStepLength(), clhep_length); +} + +//---------------------------------------------------------------------------// +/*! + * Set total energy deposited during step in MeV. + */ +void GeantStepView::energy_deposition(MevEnergy edep) +{ + step_->SetTotalEnergyDeposit(convert_to_geant(edep.value(), CLHEP::MeV)); +} + +//---------------------------------------------------------------------------// +/*! + * Set step length in native Celeritas length units. + */ +void GeantStepView::step_length(real_type length) +{ + step_->SetStepLength(convert_to_geant(length, clhep_length)); +} + +//---------------------------------------------------------------------------// +} // namespace celeritas diff --git a/src/celeritas/ext/GeantTrackView.hh b/src/celeritas/ext/GeantTrackView.hh index a18a735552..132b5478f3 100644 --- a/src/celeritas/ext/GeantTrackView.hh +++ b/src/celeritas/ext/GeantTrackView.hh @@ -86,7 +86,7 @@ Real3 GeantTrackView::pos() const /*! * Get momentum direction. */ -Real3 GeantTrackView::direction() const +Real3 GeantTrackView::dir() const { return convert_from_geant(track_.GetMomentumDirection(), 1); } diff --git a/src/celeritas/ext/detail/HitProcessor.cc b/src/celeritas/ext/detail/HitProcessor.cc index 63f75ae4bb..5011658842 100644 --- a/src/celeritas/ext/detail/HitProcessor.cc +++ b/src/celeritas/ext/detail/HitProcessor.cc @@ -28,13 +28,13 @@ #include "corecel/sys/ScopedProfiling.hh" #include "corecel/sys/TraceCounter.hh" #include "geocel/GeantGeoParams.hh" -#include "geocel/g4/Convert.hh" #include "celeritas/Types.hh" #include "celeritas/user/DetectorSteps.hh" #include "celeritas/user/StepData.hh" #include "LevelTouchableUpdater.hh" -#include "../GeantUnits.hh" +#include "../GeantStepPointView.hh" +#include "../GeantStepView.hh" namespace celeritas { @@ -243,19 +243,19 @@ void HitProcessor::operator()(DetectorStepOutput const& out, size_type i) const { CELER_EXPECT(!out.detector.empty()); CELER_EXPECT(i < out.size()); -#define HP_SET(SETTER, OUT, UNITS) \ - do \ - { \ - if (!OUT.empty()) \ - { \ - SETTER(convert_to_geant(OUT[i], UNITS)); \ - } \ - } while (0) G4LogicalVolume const* lv = this->detector_volume(out.detector[i]); - HP_SET(step_->SetTotalEnergyDeposit, out.energy_deposition, CLHEP::MeV); - HP_SET(step_->SetStepLength, out.step_length, clhep_length); + GeantStepView step_view{step_}; + if (!out.energy_deposition.empty()) + { + step_view.energy_deposition( + GeantStepView::MevEnergy{out.energy_deposition[i]}); + } + if (!out.step_length.empty()) + { + step_view.step_length(out.step_length[i]); + } for (auto sp : range(StepPoint::size_)) { @@ -276,46 +276,44 @@ void HitProcessor::operator()(DetectorStepOutput const& out, size_type i) const // Inconsistent touchable: skip this energy deposition CELER_LOG_LOCAL(error) << "Omitting energy deposition of " - << step_->GetTotalEnergyDeposit() / CLHEP::MeV << " [MeV]"; + << step_view.energy_deposition().value() << ' ' + << GeantStepView::Energy::unit_type::label(); return; } } - HP_SET(g4sp->SetGlobalTime, out.points[sp].time, clhep_time); - HP_SET(g4sp->SetPosition, out.points[sp].pos, clhep_length); - HP_SET(g4sp->SetKineticEnergy, out.points[sp].energy, CLHEP::MeV); - HP_SET(g4sp->SetMomentumDirection, out.points[sp].dir, 1); + auto const& celer_sp = out.points[sp]; + GeantStepPointView sp_view{g4sp}; + +#define HP_SET_STEP_POINT_ATTR(ATTR) \ + if (!celer_sp.ATTR.empty()) \ + { \ + sp_view.ATTR(celer_sp.ATTR[i]); \ + } + HP_SET_STEP_POINT_ATTR(time); + HP_SET_STEP_POINT_ATTR(pos); + HP_SET_STEP_POINT_ATTR(energy); + HP_SET_STEP_POINT_ATTR(dir); if (!out.weight.empty()) { - g4sp->SetWeight(out.weight[i]); + // Celeritas weight does not currently change across a step + sp_view.weight(out.weight[i]); } - G4LogicalVolume const* point_lv = [&]() -> G4LogicalVolume const* { - if (sp == StepPoint::pre) - return lv; - - // NOTE: post-step volume is only fetched if we're locating the - // touchable - if (auto* touch = g4sp->GetTouchable()) - { - // The physical volume could be null if post-step is outside - if (auto* pv = touch->GetVolume()) - { - return pv->GetLogicalVolume(); - } - } - return nullptr; - }(); +#undef HP_SET_STEP_POINT_ATTR - if (point_lv) + // Copy attributes from logical volume + if (sp == StepPoint::pre) + { + // Use lv already known from the in-volume detector + sp_view.update_from_volume(lv); + } + else { - // Copy attributes from logical volume - g4sp->SetMaterial(point_lv->GetMaterial()); - g4sp->SetMaterialCutsCouple(point_lv->GetMaterialCutsCouple()); - g4sp->SetSensitiveDetector(point_lv->GetSensitiveDetector()); + // Look up LV from the touchable + sp_view.update_from_volume(); } } -#undef HP_SET if (!out.particle.empty()) { From c532b5110b028e47006d8c12e3852a4edc46034e Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Mon, 26 Jan 2026 14:55:25 -0500 Subject: [PATCH 05/14] Add mutable geant track view --- src/celeritas/ext/GeantTrackView.hh | 111 ++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 6 deletions(-) diff --git a/src/celeritas/ext/GeantTrackView.hh b/src/celeritas/ext/GeantTrackView.hh index 132b5478f3..e1a0458e91 100644 --- a/src/celeritas/ext/GeantTrackView.hh +++ b/src/celeritas/ext/GeantTrackView.hh @@ -19,14 +19,25 @@ namespace celeritas { +//---------------------------------------------------------------------------// +template +class GeantTrackView +{ + static_assert(W != Ownership::value, "GeantTrackView cannot own data"); +}; + //---------------------------------------------------------------------------// /*! * Access track data from Geant4 with Celeritas units. * * This provides a uniform interface to G4Track data using Celeritas types and * units. Geant4 data are all in double precision. + * + * The const_reference version provides read-only access, while the reference + * version adds setters. */ -class GeantTrackView +template<> +class GeantTrackView { public: //!@{ @@ -57,17 +68,69 @@ class GeantTrackView //! Statistical weight real_type weight() const { return track_.GetWeight(); } + //! Access the G4 track directly + G4Track const& track() const { return track_; } + private: G4Track const& track_; }; +//---------------------------------------------------------------------------// +/*! + * Mutable track view with setters. + */ +template<> +class GeantTrackView + : public GeantTrackView +{ + using Base = GeantTrackView; + + public: + //!@{ + //! \name Type aliases + using Energy = typename Base::Energy; + using real_type = typename Base::real_type; + //!@} + + public: + // Construct from mutable G4Track + explicit GeantTrackView(G4Track& track) : Base(track) {} + + // Bring base class getters into scope + using Base::dir; + using Base::energy; + using Base::pos; + using Base::time; + using Base::weight; + + // Setters + inline void pos(Real3 const& position); + inline void dir(Real3 const& direction); + inline void energy(Energy e); + inline void time(real_type t); + + //! Set statistical weight + void weight(real_type w) { this->mtrack().SetWeight(w); } + + private: + //! Access mutable track reference (safe: constructed from non-const) + G4Track& mtrack() { return const_cast(this->track()); } +}; + +//---------------------------------------------------------------------------// +// TYPE ALIASES +//---------------------------------------------------------------------------// + +using GeantTrackViewConst = GeantTrackView; +using GeantTrackViewMutable = GeantTrackView; + //---------------------------------------------------------------------------// // INLINE DEFINITIONS //---------------------------------------------------------------------------// /*! * Get particle definition view. */ -GeantParticleView GeantTrackView::particle() const +GeantParticleView GeantTrackView::particle() const { CELER_EXPECT(track_.GetDefinition()); return GeantParticleView{*track_.GetDefinition()}; @@ -77,7 +140,7 @@ GeantParticleView GeantTrackView::particle() const /*! * Get position in native Celeritas length units. */ -Real3 GeantTrackView::pos() const +Real3 GeantTrackView::pos() const { return convert_from_geant(track_.GetPosition(), clhep_length); } @@ -86,7 +149,7 @@ Real3 GeantTrackView::pos() const /*! * Get momentum direction. */ -Real3 GeantTrackView::dir() const +Real3 GeantTrackView::dir() const { return convert_from_geant(track_.GetMomentumDirection(), 1); } @@ -95,7 +158,7 @@ Real3 GeantTrackView::dir() const /*! * Get kinetic energy in MeV. */ -GeantTrackView::Energy GeantTrackView::energy() const +auto GeantTrackView::energy() const -> Energy { return Energy{convert_from_geant(track_.GetKineticEnergy(), CLHEP::MeV)}; } @@ -104,10 +167,46 @@ GeantTrackView::Energy GeantTrackView::energy() const /*! * Get global time in native Celeritas time units. */ -real_type GeantTrackView::time() const +real_type GeantTrackView::time() const { return convert_from_geant(track_.GetGlobalTime(), clhep_time); } +//---------------------------------------------------------------------------// +/*! + * Set position in native Celeritas length units. + */ +void GeantTrackView::pos(Real3 const& position) +{ + this->mtrack().SetPosition(convert_to_geant(position, clhep_length)); +} + +//---------------------------------------------------------------------------// +/*! + * Set momentum direction. + */ +void GeantTrackView::dir(Real3 const& direction) +{ + this->mtrack().SetMomentumDirection(convert_to_geant(direction, 1)); +} + +//---------------------------------------------------------------------------// +/*! + * Set kinetic energy in MeV. + */ +void GeantTrackView::energy(Energy e) +{ + this->mtrack().SetKineticEnergy(convert_to_geant(e.value(), CLHEP::MeV)); +} + +//---------------------------------------------------------------------------// +/*! + * Set global time in native Celeritas time units. + */ +void GeantTrackView::time(real_type t) +{ + this->mtrack().SetGlobalTime(convert_to_geant(t, clhep_time)); +} + //---------------------------------------------------------------------------// } // namespace celeritas From 8b9504c0f63a451cc839e5c5a3f558de47279de0 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Mon, 26 Jan 2026 14:58:36 -0500 Subject: [PATCH 06/14] Add deduction guides --- src/celeritas/ext/GeantTrackView.hh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/celeritas/ext/GeantTrackView.hh b/src/celeritas/ext/GeantTrackView.hh index e1a0458e91..111f2b0920 100644 --- a/src/celeritas/ext/GeantTrackView.hh +++ b/src/celeritas/ext/GeantTrackView.hh @@ -124,6 +124,16 @@ class GeantTrackView using GeantTrackViewConst = GeantTrackView; using GeantTrackViewMutable = GeantTrackView; +//---------------------------------------------------------------------------// +// DEDUCTION GUIDES +//---------------------------------------------------------------------------// + +// Deduce const_reference from const G4Track& +GeantTrackView(G4Track const&) -> GeantTrackView; + +// Deduce reference from mutable G4Track& +GeantTrackView(G4Track&) -> GeantTrackView; + //---------------------------------------------------------------------------// // INLINE DEFINITIONS //---------------------------------------------------------------------------// From ecce6d785d760ffcab35326f28958c7c7f1bc803 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Mon, 26 Jan 2026 19:03:24 -0500 Subject: [PATCH 07/14] Add update methods to synchronize track/step/steppoint --- src/celeritas/ext/GeantStepPointView.hh | 24 +++-- src/celeritas/ext/GeantStepView.hh | 116 ++++++++++++++++++++--- src/celeritas/ext/GeantTrackView.hh | 1 - src/celeritas/ext/detail/HitProcessor.cc | 54 ++--------- 4 files changed, 126 insertions(+), 69 deletions(-) diff --git a/src/celeritas/ext/GeantStepPointView.hh b/src/celeritas/ext/GeantStepPointView.hh index e77e4815f4..8b90eee350 100644 --- a/src/celeritas/ext/GeantStepPointView.hh +++ b/src/celeritas/ext/GeantStepPointView.hh @@ -15,6 +15,7 @@ #include "geocel/g4/Convert.hh" #include "celeritas/UnitTypes.hh" +#include "GeantParticleView.hh" #include "GeantUnits.hh" namespace celeritas @@ -85,6 +86,9 @@ class GeantStepPointView // Update attributes from touchable's logical volume inline void update_from_volume(); + // Update mass and charge from particle definition + inline void update_from_particle(GeantParticleView const& particle); + //!@} private: @@ -175,12 +179,10 @@ void GeantStepPointView::time(real_type global_time) */ void GeantStepPointView::update_from_volume(G4LogicalVolume const* lv) { - if (lv) - { - step_point_->SetMaterial(lv->GetMaterial()); - step_point_->SetMaterialCutsCouple(lv->GetMaterialCutsCouple()); - step_point_->SetSensitiveDetector(lv->GetSensitiveDetector()); - } + CELER_EXPECT(lv); + step_point_->SetMaterial(lv->GetMaterial()); + step_point_->SetMaterialCutsCouple(lv->GetMaterialCutsCouple()); + step_point_->SetSensitiveDetector(lv->GetSensitiveDetector()); } //---------------------------------------------------------------------------// @@ -204,5 +206,15 @@ void GeantStepPointView::update_from_volume() this->update_from_volume(lv); } +//---------------------------------------------------------------------------// +/*! + * Update mass and charge from particle definition. + */ +void GeantStepPointView::update_from_particle(GeantParticleView const& particle) +{ + step_point_->SetMass(particle.mass().value() * CLHEP::MeV); + step_point_->SetCharge(particle.charge().value() * CLHEP::eplus); +} + //---------------------------------------------------------------------------// } // namespace celeritas diff --git a/src/celeritas/ext/GeantStepView.hh b/src/celeritas/ext/GeantStepView.hh index dbf8dc561e..e9c042c6a7 100644 --- a/src/celeritas/ext/GeantStepView.hh +++ b/src/celeritas/ext/GeantStepView.hh @@ -9,11 +9,14 @@ #include #include +#include "corecel/Assert.hh" #include "corecel/math/Quantity.hh" #include "geocel/g4/Convert.hh" +#include "celeritas/Types.hh" #include "celeritas/UnitTypes.hh" -#include "GeantUnits.hh" +#include "GeantStepPointView.hh" +#include "GeantTrackView.hh" namespace celeritas { @@ -29,38 +32,52 @@ class GeantStepView public: //!@{ //! \name Type aliases - using MevEnergy = Quantity; - using Energy = MevEnergy; + using Energy = Quantity; using real_type = double; //!@} public: // Construct from G4Step - explicit GeantStepView(G4Step* step) : step_(step) {} + explicit GeantStepView(G4Step& step) : step_(step) + { + CELER_EXPECT(step.GetTrack()); + } //!@{ //! \name Getters // Total energy deposited during step [MeV] - inline MevEnergy energy_deposition() const; + inline Energy energy_deposition() const; // Step length in native Celeritas length units inline real_type step_length() const; + // Pre-step point accessor + inline GeantStepPointView pre_step() const; + + // Post-step point accessor + inline GeantStepPointView post_step() const; + + // Step point accessor by enum + inline GeantStepPointView step_point(StepPoint sp) const; + //!@} //!@{ //! \name Setters // Set total energy deposited during step [MeV] - inline void energy_deposition(MevEnergy edep); + inline void energy_deposition(Energy edep); // Set step length in native Celeritas length units inline void step_length(real_type length); + // Update track from step data + inline void update_track(); + //!@} private: - G4Step* step_; + G4Step& step_; }; //---------------------------------------------------------------------------// @@ -69,10 +86,10 @@ class GeantStepView /*! * Get total energy deposited during step in MeV. */ -GeantStepView::MevEnergy GeantStepView::energy_deposition() const +GeantStepView::Energy GeantStepView::energy_deposition() const { - return MevEnergy{ - convert_from_geant(step_->GetTotalEnergyDeposit(), CLHEP::MeV)}; + return Energy{ + convert_from_geant(step_.GetTotalEnergyDeposit(), CLHEP::MeV)}; } //---------------------------------------------------------------------------// @@ -81,16 +98,16 @@ GeantStepView::MevEnergy GeantStepView::energy_deposition() const */ real_type GeantStepView::step_length() const { - return convert_from_geant(step_->GetStepLength(), clhep_length); + return convert_from_geant(step_.GetStepLength(), clhep_length); } //---------------------------------------------------------------------------// /*! * Set total energy deposited during step in MeV. */ -void GeantStepView::energy_deposition(MevEnergy edep) +void GeantStepView::energy_deposition(Energy edep) { - step_->SetTotalEnergyDeposit(convert_to_geant(edep.value(), CLHEP::MeV)); + step_.SetTotalEnergyDeposit(convert_to_geant(edep.value(), CLHEP::MeV)); } //---------------------------------------------------------------------------// @@ -99,7 +116,78 @@ void GeantStepView::energy_deposition(MevEnergy edep) */ void GeantStepView::step_length(real_type length) { - step_->SetStepLength(convert_to_geant(length, clhep_length)); + step_.SetStepLength(convert_to_geant(length, clhep_length)); + // Set on track as well + step_.GetTrack()->SetStepLength(step_.GetStepLength()); +} + +//---------------------------------------------------------------------------// +/*! + * Get pre-step point. + */ +GeantStepPointView GeantStepView::pre_step() const +{ + return GeantStepPointView{step_.GetPreStepPoint()}; +} + +//---------------------------------------------------------------------------// +/*! + * Get post-step point. + */ +GeantStepPointView GeantStepView::post_step() const +{ + return GeantStepPointView{step_.GetPostStepPoint()}; +} + +//---------------------------------------------------------------------------// +/*! + * Get step point by enum. + */ +GeantStepPointView GeantStepView::step_point(StepPoint sp) const +{ + CELER_EXPECT(sp != StepPoint::size_); + return GeantStepPointView{sp == StepPoint::pre ? this->pre_step() + : this->post_step()}; +} + +//---------------------------------------------------------------------------// +/*! + * Update track from step data. + * + * Copies step length and step point data to the track. This is similar to + * \c G4Step::UpdateTrack but applies only to attributes we know about and + * safely handles null pointers. + */ +void GeantStepView::update_track() +{ + CELER_EXPECT(step_.GetTrack()); + + GeantTrackView track{*step_.GetTrack()}; + GeantParticleView particle_view = track.particle(); + + // Update pre-step point if present + if (G4StepPoint* pre_step = step_.GetPreStepPoint()) + { + GeantStepPointView{pre_step}.update_from_particle(particle_view); + track.mtrack().SetTouchableHandle(pre_step->GetTouchableHandle()); + } + + // Update post-step point and track from post-step if present + if (G4StepPoint* post_step = step_.GetPostStepPoint()) + { + GeantStepPointView post_view{post_step}; + post_view.update_from_particle(particle_view); + + // Copy post-step state to track + track.time(post_view.time()); + track.pos(post_view.pos()); + track.energy(post_view.energy()); + track.dir(post_view.dir()); + track.weight(post_view.weight()); + + track.mtrack().SetNextTouchableHandle(post_step->GetTouchableHandle()); + track.mtrack().SetVelocity(post_step->GetVelocity()); + } } //---------------------------------------------------------------------------// diff --git a/src/celeritas/ext/GeantTrackView.hh b/src/celeritas/ext/GeantTrackView.hh index 111f2b0920..23e1a4e755 100644 --- a/src/celeritas/ext/GeantTrackView.hh +++ b/src/celeritas/ext/GeantTrackView.hh @@ -112,7 +112,6 @@ class GeantTrackView //! Set statistical weight void weight(real_type w) { this->mtrack().SetWeight(w); } - private: //! Access mutable track reference (safe: constructed from non-const) G4Track& mtrack() { return const_cast(this->track()); } }; diff --git a/src/celeritas/ext/detail/HitProcessor.cc b/src/celeritas/ext/detail/HitProcessor.cc index 5011658842..b060c03884 100644 --- a/src/celeritas/ext/detail/HitProcessor.cc +++ b/src/celeritas/ext/detail/HitProcessor.cc @@ -35,6 +35,7 @@ #include "LevelTouchableUpdater.hh" #include "../GeantStepPointView.hh" #include "../GeantStepView.hh" +#include "../GeantTrackView.hh" namespace celeritas { @@ -239,7 +240,7 @@ void HitProcessor::operator()(DetectorStepOutput const& out) const /*! * Generate and call a single hit. */ -void HitProcessor::operator()(DetectorStepOutput const& out, size_type i) const +void HitProcessor::operator()(DetectorStepOutput const& out, size_t i) const { CELER_EXPECT(!out.detector.empty()); CELER_EXPECT(i < out.size()); @@ -250,7 +251,7 @@ void HitProcessor::operator()(DetectorStepOutput const& out, size_type i) const if (!out.energy_deposition.empty()) { step_view.energy_deposition( - GeantStepView::MevEnergy{out.energy_deposition[i]}); + GeantStepView::Energy{out.energy_deposition[i]}); } if (!out.step_length.empty()) { @@ -320,7 +321,9 @@ void HitProcessor::operator()(DetectorStepOutput const& out, size_type i) const G4Track& g4track = track_processor_.restore_track( out.particle[i], !out.primary_id.empty() ? out.primary_id[i] : PrimaryId{}); - this->update_track(g4track); + CELER_ASSERT(&g4track == step_->GetTrack()); + // Copy step information to the corresponding track + GeantStepView{*step_}.update_track(); } if (step_post_status_) @@ -335,51 +338,6 @@ void HitProcessor::operator()(DetectorStepOutput const& out, size_type i) const this->detector(out.detector[i])->Hit(step_); } -//---------------------------------------------------------------------------// -/*! - * Recreate the track from the particle ID and saved post-step data. - * - * This is a bit like \c G4Step::UpdateTrack . - */ -void HitProcessor::update_track(G4Track& track) const -{ - // Copy data from step to track - track.SetStepLength(step_->GetStepLength()); - - G4ParticleDefinition const& pd = *track.GetParticleDefinition(); - - for (G4StepPoint* p : step_points_) - { - if (!p) - { - continue; - } - - // Copy data from track to step points - p->SetMass(pd.GetPDGMass()); - p->SetCharge(pd.GetPDGCharge()); - } - - if (G4StepPoint* pre_step = step_points_[StepPoint::pre]) - { - // Copy data from post-step to track - track.SetTouchableHandle(pre_step->GetTouchableHandle()); - } - - if (G4StepPoint* post_step = step_points_[StepPoint::post]) - { - // Copy data from post-step to track - track.SetGlobalTime(post_step->GetGlobalTime()); - track.SetPosition(post_step->GetPosition()); - track.SetKineticEnergy(post_step->GetKineticEnergy()); - track.SetMomentumDirection(post_step->GetMomentumDirection()); - track.SetWeight(post_step->GetWeight()); - - track.SetNextTouchableHandle(post_step->GetTouchableHandle()); - track.SetVelocity(post_step->GetVelocity()); - } -} - //---------------------------------------------------------------------------// } // namespace detail } // namespace celeritas From 6f38c4534d8a8c799aca758e4644753b6169cbbb Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Mon, 26 Jan 2026 19:22:06 -0500 Subject: [PATCH 08/14] Move methods into step point view, use references --- src/accel/LocalTransporter.cc | 12 ++-- src/celeritas/CMakeLists.txt | 2 + src/celeritas/ext/GeantStepPointView.cc | 65 +++++++++++++++++++ src/celeritas/ext/GeantStepPointView.hh | 79 +++++------------------- src/celeritas/ext/GeantStepView.cc | 14 +++++ src/celeritas/ext/GeantStepView.hh | 24 +++---- src/celeritas/ext/GeantTrackView.hh | 4 +- src/celeritas/ext/detail/HitProcessor.cc | 4 +- 8 files changed, 120 insertions(+), 84 deletions(-) create mode 100644 src/celeritas/ext/GeantStepPointView.cc create mode 100644 src/celeritas/ext/GeantStepView.cc diff --git a/src/accel/LocalTransporter.cc b/src/accel/LocalTransporter.cc index 76ffaf3566..e202646f40 100644 --- a/src/accel/LocalTransporter.cc +++ b/src/accel/LocalTransporter.cc @@ -25,6 +25,7 @@ #include "corecel/cont/Span.hh" #include "corecel/io/BuildOutput.hh" #include "corecel/io/Logger.hh" +#include "corecel/math/QuantityIO.hh" #include "corecel/sys/Device.hh" #include "corecel/sys/ScopedProfiling.hh" #include "corecel/sys/ScopedSignalHandler.hh" @@ -252,11 +253,10 @@ void LocalTransporter::Push(G4Track& g4track) { // Primary may have been created by a particle generator outside the // geometry - CELER_LOG_LOCAL(error) << "Discarding track outside world bounds: " - << gtv.energy().value() << " " - << GeantTrackView::Energy::unit_type::label() - << " from " << gtv.particle().name() << " at " - << gtv.pos() << " along " << gtv.direction(); + CELER_LOG_LOCAL(error) + << "Discarding track outside world bounds: " << gtv.energy() + << " from " << gtv.particle().name() << " at " << gtv.pos() + << " along " << gtv.dir(); buffer_accum_.lost_energy += gtv.energy().value(); ++buffer_accum_.lost_primaries; @@ -275,7 +275,7 @@ void LocalTransporter::Push(G4Track& g4track) offloaded.energy = gtv.energy(); offloaded.particle_id = particles_->find(gtv.particle().pdg()); offloaded.position = gtv.pos(); - offloaded.direction = gtv.direction(); + offloaded.direction = gtv.dir(); offloaded.time = gtv.time(); offloaded.weight = gtv.weight(); diff --git a/src/celeritas/CMakeLists.txt b/src/celeritas/CMakeLists.txt index 555e15cc39..09677cd0ad 100644 --- a/src/celeritas/CMakeLists.txt +++ b/src/celeritas/CMakeLists.txt @@ -224,6 +224,8 @@ if(CELERITAS_USE_Geant4) ext/GeantSd.cc ext/GeantSdOutput.cc ext/GeantSetup.cc + ext/GeantStepPointView.cc + ext/GeantStepView.cc ext/detail/EmStandardPhysics.cc ext/detail/GeantMicroXsCalculator.cc ext/detail/GeantModelImporter.cc diff --git a/src/celeritas/ext/GeantStepPointView.cc b/src/celeritas/ext/GeantStepPointView.cc new file mode 100644 index 0000000000..c7bfa88199 --- /dev/null +++ b/src/celeritas/ext/GeantStepPointView.cc @@ -0,0 +1,65 @@ +//------------------------------- -*- C++ -*- -------------------------------// +// Copyright Celeritas contributors: see top-level COPYRIGHT file for details +// SPDX-License-Identifier: (Apache-2.0 OR MIT) +//---------------------------------------------------------------------------// +//! \file celeritas/ext/GeantStepPointView.cc +//---------------------------------------------------------------------------// +#include "GeantStepPointView.hh" + +namespace celeritas +{ +//---------------------------------------------------------------------------// +/*! + * Update attributes from logical volume. + * + * If the logical volume is null, no updates are performed. + */ +void GeantStepPointView::update_from_volume(G4LogicalVolume const* lv) +{ + step_point_.SetMaterial(lv->GetMaterial()); + step_point_.SetMaterialCutsCouple(lv->GetMaterialCutsCouple()); + step_point_.SetSensitiveDetector(lv->GetSensitiveDetector()); +} + +//---------------------------------------------------------------------------// +/*! + * Update attributes from touchable's logical volume if possible. + * + * The post-step volume is fetched from the touchable. The physical volume + * could be null if post-step is outside the geometry. + */ +void GeantStepPointView::update_from_volume() +{ + G4LogicalVolume const* lv = nullptr; + if (auto* touch = step_point_.GetTouchable()) + { + // The physical volume could be null if post-step is outside + if (auto* pv = touch->GetVolume()) + { + lv = pv->GetLogicalVolume(); + } + } + if (lv) + { + this->update_from_volume(lv); + } + else + { + step_point_.SetMaterial(nullptr); + step_point_.SetMaterialCutsCouple(nullptr); + step_point_.SetSensitiveDetector(nullptr); + } +} + +//---------------------------------------------------------------------------// +/*! + * Update mass and charge from particle definition. + */ +void GeantStepPointView::update_from_particle(GeantParticleView const& particle) +{ + step_point_.SetMass(particle.mass().value() * CLHEP::MeV); + step_point_.SetCharge(particle.charge().value() * CLHEP::eplus); +} + +//---------------------------------------------------------------------------// +} // namespace celeritas diff --git a/src/celeritas/ext/GeantStepPointView.hh b/src/celeritas/ext/GeantStepPointView.hh index 8b90eee350..ca4d4a26d4 100644 --- a/src/celeritas/ext/GeantStepPointView.hh +++ b/src/celeritas/ext/GeantStepPointView.hh @@ -38,13 +38,13 @@ class GeantStepPointView public: // Construct from G4StepPoint - explicit GeantStepPointView(G4StepPoint* step_point) + explicit GeantStepPointView(G4StepPoint& step_point) : step_point_(step_point) { } //!@{ - //! \name Getters + //! \name Accessors // Position in native Celeritas length units inline Real3 pos() const; @@ -59,11 +59,11 @@ class GeantStepPointView inline real_type time() const; //! Statistical weight - real_type weight() const { return step_point_->GetWeight(); } + real_type weight() const { return step_point_.GetWeight(); } //!@} //!@{ - //! \name Setters + //! \name Mutators // Set position in native Celeritas length units inline void pos(Real3 const& position); @@ -78,21 +78,21 @@ class GeantStepPointView inline void time(real_type global_time); // Set statistical weight - void weight(real_type w) { step_point_->SetWeight(w); } + void weight(real_type w) { step_point_.SetWeight(w); } // Update attributes from logical volume - inline void update_from_volume(G4LogicalVolume const* lv); + void update_from_volume(G4LogicalVolume const* lv); // Update attributes from touchable's logical volume - inline void update_from_volume(); + void update_from_volume(); // Update mass and charge from particle definition - inline void update_from_particle(GeantParticleView const& particle); + void update_from_particle(GeantParticleView const& particle); //!@} private: - G4StepPoint* step_point_; + G4StepPoint& step_point_; }; //---------------------------------------------------------------------------// @@ -103,7 +103,7 @@ class GeantStepPointView */ Real3 GeantStepPointView::pos() const { - return convert_from_geant(step_point_->GetPosition(), clhep_length); + return convert_from_geant(step_point_.GetPosition(), clhep_length); } //---------------------------------------------------------------------------// @@ -112,7 +112,7 @@ Real3 GeantStepPointView::pos() const */ Real3 GeantStepPointView::dir() const { - return convert_from_geant(step_point_->GetMomentumDirection(), 1); + return convert_from_geant(step_point_.GetMomentumDirection(), 1); } //---------------------------------------------------------------------------// @@ -122,7 +122,7 @@ Real3 GeantStepPointView::dir() const GeantStepPointView::Energy GeantStepPointView::energy() const { return Energy{ - convert_from_geant(step_point_->GetKineticEnergy(), CLHEP::MeV)}; + convert_from_geant(step_point_.GetKineticEnergy(), CLHEP::MeV)}; } //---------------------------------------------------------------------------// @@ -131,7 +131,7 @@ GeantStepPointView::Energy GeantStepPointView::energy() const */ real_type GeantStepPointView::time() const { - return convert_from_geant(step_point_->GetGlobalTime(), clhep_time); + return convert_from_geant(step_point_.GetGlobalTime(), clhep_time); } //---------------------------------------------------------------------------// @@ -140,7 +140,7 @@ real_type GeantStepPointView::time() const */ void GeantStepPointView::pos(Real3 const& position) { - step_point_->SetPosition(convert_to_geant(position, clhep_length)); + step_point_.SetPosition(convert_to_geant(position, clhep_length)); } //---------------------------------------------------------------------------// @@ -149,7 +149,7 @@ void GeantStepPointView::pos(Real3 const& position) */ void GeantStepPointView::dir(Real3 const& direction) { - step_point_->SetMomentumDirection(convert_to_geant(direction, 1)); + step_point_.SetMomentumDirection(convert_to_geant(direction, 1)); } //---------------------------------------------------------------------------// @@ -158,7 +158,7 @@ void GeantStepPointView::dir(Real3 const& direction) */ void GeantStepPointView::energy(Energy kinetic_energy) { - step_point_->SetKineticEnergy( + step_point_.SetKineticEnergy( convert_to_geant(kinetic_energy.value(), CLHEP::MeV)); } @@ -168,52 +168,7 @@ void GeantStepPointView::energy(Energy kinetic_energy) */ void GeantStepPointView::time(real_type global_time) { - step_point_->SetGlobalTime(convert_to_geant(global_time, clhep_time)); -} - -//---------------------------------------------------------------------------// -/*! - * Update attributes from logical volume. - * - * If the logical volume is null, no updates are performed. - */ -void GeantStepPointView::update_from_volume(G4LogicalVolume const* lv) -{ - CELER_EXPECT(lv); - step_point_->SetMaterial(lv->GetMaterial()); - step_point_->SetMaterialCutsCouple(lv->GetMaterialCutsCouple()); - step_point_->SetSensitiveDetector(lv->GetSensitiveDetector()); -} - -//---------------------------------------------------------------------------// -/*! - * Update attributes from touchable's logical volume. - * - * The post-step volume is fetched from the touchable. The physical volume - * could be null if post-step is outside the geometry. - */ -void GeantStepPointView::update_from_volume() -{ - G4LogicalVolume const* lv = nullptr; - if (auto* touch = step_point_->GetTouchable()) - { - // The physical volume could be null if post-step is outside - if (auto* pv = touch->GetVolume()) - { - lv = pv->GetLogicalVolume(); - } - } - this->update_from_volume(lv); -} - -//---------------------------------------------------------------------------// -/*! - * Update mass and charge from particle definition. - */ -void GeantStepPointView::update_from_particle(GeantParticleView const& particle) -{ - step_point_->SetMass(particle.mass().value() * CLHEP::MeV); - step_point_->SetCharge(particle.charge().value() * CLHEP::eplus); + step_point_.SetGlobalTime(convert_to_geant(global_time, clhep_time)); } //---------------------------------------------------------------------------// diff --git a/src/celeritas/ext/GeantStepView.cc b/src/celeritas/ext/GeantStepView.cc new file mode 100644 index 0000000000..172215c022 --- /dev/null +++ b/src/celeritas/ext/GeantStepView.cc @@ -0,0 +1,14 @@ +//------------------------------- -*- C++ -*- -------------------------------// +// Copyright Celeritas contributors: see top-level COPYRIGHT file for details +// SPDX-License-Identifier: (Apache-2.0 OR MIT) +//---------------------------------------------------------------------------// +//! \file celeritas/ext/GeantStepView.cc +//---------------------------------------------------------------------------// +#include "GeantStepView.hh" + +namespace celeritas +{ +//---------------------------------------------------------------------------// + +//---------------------------------------------------------------------------// +} // namespace celeritas diff --git a/src/celeritas/ext/GeantStepView.hh b/src/celeritas/ext/GeantStepView.hh index e9c042c6a7..848250fb13 100644 --- a/src/celeritas/ext/GeantStepView.hh +++ b/src/celeritas/ext/GeantStepView.hh @@ -38,13 +38,10 @@ class GeantStepView public: // Construct from G4Step - explicit GeantStepView(G4Step& step) : step_(step) - { - CELER_EXPECT(step.GetTrack()); - } + explicit GeantStepView(G4Step& step) : step_(step) {} //!@{ - //! \name Getters + //! \name Accessors // Total energy deposited during step [MeV] inline Energy energy_deposition() const; @@ -63,7 +60,7 @@ class GeantStepView //!@} //!@{ - //! \name Setters + //! \name Mutators // Set total energy deposited during step [MeV] inline void energy_deposition(Energy edep); @@ -117,8 +114,11 @@ void GeantStepView::energy_deposition(Energy edep) void GeantStepView::step_length(real_type length) { step_.SetStepLength(convert_to_geant(length, clhep_length)); - // Set on track as well - step_.GetTrack()->SetStepLength(step_.GetStepLength()); + if (step_.GetTrack()) + { + // Set on track as well + step_.GetTrack()->SetStepLength(step_.GetStepLength()); + } } //---------------------------------------------------------------------------// @@ -127,7 +127,7 @@ void GeantStepView::step_length(real_type length) */ GeantStepPointView GeantStepView::pre_step() const { - return GeantStepPointView{step_.GetPreStepPoint()}; + return GeantStepPointView{*step_.GetPreStepPoint()}; } //---------------------------------------------------------------------------// @@ -136,7 +136,7 @@ GeantStepPointView GeantStepView::pre_step() const */ GeantStepPointView GeantStepView::post_step() const { - return GeantStepPointView{step_.GetPostStepPoint()}; + return GeantStepPointView{*step_.GetPostStepPoint()}; } //---------------------------------------------------------------------------// @@ -168,14 +168,14 @@ void GeantStepView::update_track() // Update pre-step point if present if (G4StepPoint* pre_step = step_.GetPreStepPoint()) { - GeantStepPointView{pre_step}.update_from_particle(particle_view); + GeantStepPointView{*pre_step}.update_from_particle(particle_view); track.mtrack().SetTouchableHandle(pre_step->GetTouchableHandle()); } // Update post-step point and track from post-step if present if (G4StepPoint* post_step = step_.GetPostStepPoint()) { - GeantStepPointView post_view{post_step}; + GeantStepPointView post_view{*post_step}; post_view.update_from_particle(particle_view); // Copy post-step state to track diff --git a/src/celeritas/ext/GeantTrackView.hh b/src/celeritas/ext/GeantTrackView.hh index 23e1a4e755..ab85afd1f8 100644 --- a/src/celeritas/ext/GeantTrackView.hh +++ b/src/celeritas/ext/GeantTrackView.hh @@ -96,14 +96,14 @@ class GeantTrackView // Construct from mutable G4Track explicit GeantTrackView(G4Track& track) : Base(track) {} - // Bring base class getters into scope + // Bring base class accessors into scope using Base::dir; using Base::energy; using Base::pos; using Base::time; using Base::weight; - // Setters + // Mutators inline void pos(Real3 const& position); inline void dir(Real3 const& direction); inline void energy(Energy e); diff --git a/src/celeritas/ext/detail/HitProcessor.cc b/src/celeritas/ext/detail/HitProcessor.cc index b060c03884..4f4e1aa7a7 100644 --- a/src/celeritas/ext/detail/HitProcessor.cc +++ b/src/celeritas/ext/detail/HitProcessor.cc @@ -247,7 +247,7 @@ void HitProcessor::operator()(DetectorStepOutput const& out, size_t i) const G4LogicalVolume const* lv = this->detector_volume(out.detector[i]); - GeantStepView step_view{step_}; + GeantStepView step_view{*step_}; if (!out.energy_deposition.empty()) { step_view.energy_deposition( @@ -284,7 +284,7 @@ void HitProcessor::operator()(DetectorStepOutput const& out, size_t i) const } auto const& celer_sp = out.points[sp]; - GeantStepPointView sp_view{g4sp}; + GeantStepPointView sp_view{*g4sp}; #define HP_SET_STEP_POINT_ATTR(ATTR) \ if (!celer_sp.ATTR.empty()) \ From ed6079e10eb4e1e9952ace32af763439c76d88f2 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Mon, 26 Jan 2026 19:43:24 -0500 Subject: [PATCH 09/14] Add docs --- doc/implementation/geant4-interface/low-level.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/implementation/geant4-interface/low-level.rst b/doc/implementation/geant4-interface/low-level.rst index 6106a78f8e..a0d6e3e6d7 100644 --- a/doc/implementation/geant4-interface/low-level.rst +++ b/doc/implementation/geant4-interface/low-level.rst @@ -36,3 +36,13 @@ Utility interfaces .. doxygenclass:: celeritas::ScopedGeantLogger .. doxygenclass:: celeritas::ScopedGeantExceptionHandler + +.. _g4_views: + +Views +^^^^^ + +.. doxygenclass:: celeritas::GeantParticleView +.. doxygenclass:: celeritas::GeantStepPointView +.. doxygenclass:: celeritas::GeantTrackView +.. doxygenclass:: celeritas::GeantStepView From 306660d77523e292d24e76060dc391ee2ac2368d Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Tue, 27 Jan 2026 08:31:54 -0500 Subject: [PATCH 10/14] Address feedbaack and move functions to cc as appropriate --- src/celeritas/ext/GeantParticleView.hh | 12 +++--- src/celeritas/ext/GeantStepPointView.cc | 20 +++++----- src/celeritas/ext/GeantStepPointView.hh | 6 ++- src/celeritas/ext/GeantStepView.cc | 40 +++++++++++++++++++ src/celeritas/ext/GeantStepView.hh | 50 +++--------------------- src/celeritas/ext/GeantTrackView.hh | 21 ++++++---- src/celeritas/ext/detail/HitProcessor.cc | 7 ++-- src/celeritas/ext/detail/HitProcessor.hh | 2 - 8 files changed, 83 insertions(+), 75 deletions(-) diff --git a/src/celeritas/ext/GeantParticleView.hh b/src/celeritas/ext/GeantParticleView.hh index bc46588a20..f6c2e015f8 100644 --- a/src/celeritas/ext/GeantParticleView.hh +++ b/src/celeritas/ext/GeantParticleView.hh @@ -6,13 +6,17 @@ //---------------------------------------------------------------------------// #pragma once +#include #include #include #include "corecel/math/Quantity.hh" +#include "geocel/g4/Convert.hh" #include "celeritas/UnitTypes.hh" #include "celeritas/phys/PDGNumber.hh" +#include "GeantUnits.hh" + namespace celeritas { //---------------------------------------------------------------------------// @@ -72,11 +76,9 @@ auto GeantParticleView::decay_constant() const -> real_type return 0; } - // CLHEP time unit system - using Time = Quantity; - - // Decay constant is 1/lifetime - return 1 / native_value_from(Time{pd_.GetPDGLifeTime()}); + // Decay constant is 1/lifetime (lifetime is in CLHEP time units) + real_type lifetime = convert_from_geant(pd_.GetPDGLifeTime(), clhep_time); + return 1 / lifetime; } //---------------------------------------------------------------------------// diff --git a/src/celeritas/ext/GeantStepPointView.cc b/src/celeritas/ext/GeantStepPointView.cc index c7bfa88199..41ae1a3999 100644 --- a/src/celeritas/ext/GeantStepPointView.cc +++ b/src/celeritas/ext/GeantStepPointView.cc @@ -6,27 +6,27 @@ //---------------------------------------------------------------------------// #include "GeantStepPointView.hh" +#include + namespace celeritas { //---------------------------------------------------------------------------// /*! * Update attributes from logical volume. - * - * If the logical volume is null, no updates are performed. */ -void GeantStepPointView::update_from_volume(G4LogicalVolume const* lv) +void GeantStepPointView::update_from_volume(G4LogicalVolume const& lv) { - step_point_.SetMaterial(lv->GetMaterial()); - step_point_.SetMaterialCutsCouple(lv->GetMaterialCutsCouple()); - step_point_.SetSensitiveDetector(lv->GetSensitiveDetector()); + step_point_.SetMaterial(lv.GetMaterial()); + step_point_.SetMaterialCutsCouple(lv.GetMaterialCutsCouple()); + step_point_.SetSensitiveDetector(lv.GetSensitiveDetector()); } //---------------------------------------------------------------------------// /*! - * Update attributes from touchable's logical volume if possible. + * Update attributes from the touchable's logical volume if possible. * - * The post-step volume is fetched from the touchable. The physical volume - * could be null if post-step is outside the geometry. + * If the step point has an associated touchable, and that touchable is inside + * the geometry, it updates. Otherwise, it clears the corresponding attributes. */ void GeantStepPointView::update_from_volume() { @@ -41,7 +41,7 @@ void GeantStepPointView::update_from_volume() } if (lv) { - this->update_from_volume(lv); + this->update_from_volume(*lv); } else { diff --git a/src/celeritas/ext/GeantStepPointView.hh b/src/celeritas/ext/GeantStepPointView.hh index ca4d4a26d4..4b4d048500 100644 --- a/src/celeritas/ext/GeantStepPointView.hh +++ b/src/celeritas/ext/GeantStepPointView.hh @@ -7,9 +7,9 @@ #pragma once #include -#include #include +#include "corecel/Assert.hh" #include "corecel/Types.hh" #include "corecel/math/Quantity.hh" #include "geocel/g4/Convert.hh" @@ -81,7 +81,7 @@ class GeantStepPointView void weight(real_type w) { step_point_.SetWeight(w); } // Update attributes from logical volume - void update_from_volume(G4LogicalVolume const* lv); + void update_from_volume(G4LogicalVolume const& lv); // Update attributes from touchable's logical volume void update_from_volume(); @@ -158,6 +158,7 @@ void GeantStepPointView::dir(Real3 const& direction) */ void GeantStepPointView::energy(Energy kinetic_energy) { + CELER_EXPECT(kinetic_energy >= zero_quantity()); step_point_.SetKineticEnergy( convert_to_geant(kinetic_energy.value(), CLHEP::MeV)); } @@ -168,6 +169,7 @@ void GeantStepPointView::energy(Energy kinetic_energy) */ void GeantStepPointView::time(real_type global_time) { + CELER_EXPECT(global_time >= 0); step_point_.SetGlobalTime(convert_to_geant(global_time, clhep_time)); } diff --git a/src/celeritas/ext/GeantStepView.cc b/src/celeritas/ext/GeantStepView.cc index 172215c022..7b0dbfe557 100644 --- a/src/celeritas/ext/GeantStepView.cc +++ b/src/celeritas/ext/GeantStepView.cc @@ -6,9 +6,49 @@ //---------------------------------------------------------------------------// #include "GeantStepView.hh" +#include "GeantTrackView.hh" + namespace celeritas { //---------------------------------------------------------------------------// +/*! + * Update track from step data. + * + * Copies step length and step point data to the track. This is similar to + * \c G4Step::UpdateTrack but applies only to attributes we know about and + * safely handles null pointers. + */ +void GeantStepView::update_track() +{ + CELER_EXPECT(step_.GetTrack()); + + GeantTrackView track{*step_.GetTrack()}; + GeantParticleView particle_view = track.particle(); + + // Update pre-step point if present + if (G4StepPoint* pre_step = step_.GetPreStepPoint()) + { + GeantStepPointView{*pre_step}.update_from_particle(particle_view); + track.track().SetTouchableHandle(pre_step->GetTouchableHandle()); + } + + // Update post-step point and track from post-step if present + if (G4StepPoint* post_step = step_.GetPostStepPoint()) + { + GeantStepPointView post_view{*post_step}; + post_view.update_from_particle(particle_view); + + // Copy post-step state to track + track.time(post_view.time()); + track.pos(post_view.pos()); + track.energy(post_view.energy()); + track.dir(post_view.dir()); + track.weight(post_view.weight()); + + track.track().SetNextTouchableHandle(post_step->GetTouchableHandle()); + track.track().SetVelocity(post_step->GetVelocity()); + } +} //---------------------------------------------------------------------------// } // namespace celeritas diff --git a/src/celeritas/ext/GeantStepView.hh b/src/celeritas/ext/GeantStepView.hh index 848250fb13..533295589b 100644 --- a/src/celeritas/ext/GeantStepView.hh +++ b/src/celeritas/ext/GeantStepView.hh @@ -16,7 +16,6 @@ #include "celeritas/UnitTypes.hh" #include "GeantStepPointView.hh" -#include "GeantTrackView.hh" namespace celeritas { @@ -69,7 +68,7 @@ class GeantStepView inline void step_length(real_type length); // Update track from step data - inline void update_track(); + void update_track(); //!@} @@ -83,7 +82,7 @@ class GeantStepView /*! * Get total energy deposited during step in MeV. */ -GeantStepView::Energy GeantStepView::energy_deposition() const +auto GeantStepView::energy_deposition() const -> Energy { return Energy{ convert_from_geant(step_.GetTotalEnergyDeposit(), CLHEP::MeV)}; @@ -127,6 +126,7 @@ void GeantStepView::step_length(real_type length) */ GeantStepPointView GeantStepView::pre_step() const { + CELER_EXPECT(step_.GetPreStepPoint()); return GeantStepPointView{*step_.GetPreStepPoint()}; } @@ -136,6 +136,7 @@ GeantStepPointView GeantStepView::pre_step() const */ GeantStepPointView GeantStepView::post_step() const { + CELER_EXPECT(step_.GetPostStepPoint()); return GeantStepPointView{*step_.GetPostStepPoint()}; } @@ -146,48 +147,7 @@ GeantStepPointView GeantStepView::post_step() const GeantStepPointView GeantStepView::step_point(StepPoint sp) const { CELER_EXPECT(sp != StepPoint::size_); - return GeantStepPointView{sp == StepPoint::pre ? this->pre_step() - : this->post_step()}; -} - -//---------------------------------------------------------------------------// -/*! - * Update track from step data. - * - * Copies step length and step point data to the track. This is similar to - * \c G4Step::UpdateTrack but applies only to attributes we know about and - * safely handles null pointers. - */ -void GeantStepView::update_track() -{ - CELER_EXPECT(step_.GetTrack()); - - GeantTrackView track{*step_.GetTrack()}; - GeantParticleView particle_view = track.particle(); - - // Update pre-step point if present - if (G4StepPoint* pre_step = step_.GetPreStepPoint()) - { - GeantStepPointView{*pre_step}.update_from_particle(particle_view); - track.mtrack().SetTouchableHandle(pre_step->GetTouchableHandle()); - } - - // Update post-step point and track from post-step if present - if (G4StepPoint* post_step = step_.GetPostStepPoint()) - { - GeantStepPointView post_view{*post_step}; - post_view.update_from_particle(particle_view); - - // Copy post-step state to track - track.time(post_view.time()); - track.pos(post_view.pos()); - track.energy(post_view.energy()); - track.dir(post_view.dir()); - track.weight(post_view.weight()); - - track.mtrack().SetNextTouchableHandle(post_step->GetTouchableHandle()); - track.mtrack().SetVelocity(post_step->GetVelocity()); - } + return sp == StepPoint::pre ? this->pre_step() : this->post_step(); } //---------------------------------------------------------------------------// diff --git a/src/celeritas/ext/GeantTrackView.hh b/src/celeritas/ext/GeantTrackView.hh index ab85afd1f8..b3261a4c27 100644 --- a/src/celeritas/ext/GeantTrackView.hh +++ b/src/celeritas/ext/GeantTrackView.hh @@ -71,6 +71,9 @@ class GeantTrackView //! Access the G4 track directly G4Track const& track() const { return track_; } + //! Access the G4 track directly (const) + G4Track const& ctrack() const { return track_; } + private: G4Track const& track_; }; @@ -110,10 +113,12 @@ class GeantTrackView inline void time(real_type t); //! Set statistical weight - void weight(real_type w) { this->mtrack().SetWeight(w); } + void weight(real_type w) { this->track().SetWeight(w); } + using Base::ctrack; + using Base::track; //! Access mutable track reference (safe: constructed from non-const) - G4Track& mtrack() { return const_cast(this->track()); } + G4Track& track() { return const_cast(this->ctrack()); } }; //---------------------------------------------------------------------------// @@ -134,7 +139,7 @@ GeantTrackView(G4Track const&) -> GeantTrackView; GeantTrackView(G4Track&) -> GeantTrackView; //---------------------------------------------------------------------------// -// INLINE DEFINITIONS +// INLINE ACCESSOR DEFINITIONS //---------------------------------------------------------------------------// /*! * Get particle definition view. @@ -181,13 +186,15 @@ real_type GeantTrackView::time() const return convert_from_geant(track_.GetGlobalTime(), clhep_time); } +//---------------------------------------------------------------------------// +// INLINE MUTATOR DEFINITIONS //---------------------------------------------------------------------------// /*! * Set position in native Celeritas length units. */ void GeantTrackView::pos(Real3 const& position) { - this->mtrack().SetPosition(convert_to_geant(position, clhep_length)); + this->track().SetPosition(convert_to_geant(position, clhep_length)); } //---------------------------------------------------------------------------// @@ -196,7 +203,7 @@ void GeantTrackView::pos(Real3 const& position) */ void GeantTrackView::dir(Real3 const& direction) { - this->mtrack().SetMomentumDirection(convert_to_geant(direction, 1)); + this->track().SetMomentumDirection(convert_to_geant(direction, 1)); } //---------------------------------------------------------------------------// @@ -205,7 +212,7 @@ void GeantTrackView::dir(Real3 const& direction) */ void GeantTrackView::energy(Energy e) { - this->mtrack().SetKineticEnergy(convert_to_geant(e.value(), CLHEP::MeV)); + this->track().SetKineticEnergy(convert_to_geant(e.value(), CLHEP::MeV)); } //---------------------------------------------------------------------------// @@ -214,7 +221,7 @@ void GeantTrackView::energy(Energy e) */ void GeantTrackView::time(real_type t) { - this->mtrack().SetGlobalTime(convert_to_geant(t, clhep_time)); + this->track().SetGlobalTime(convert_to_geant(t, clhep_time)); } //---------------------------------------------------------------------------// diff --git a/src/celeritas/ext/detail/HitProcessor.cc b/src/celeritas/ext/detail/HitProcessor.cc index 4f4e1aa7a7..fc1dedce60 100644 --- a/src/celeritas/ext/detail/HitProcessor.cc +++ b/src/celeritas/ext/detail/HitProcessor.cc @@ -35,7 +35,6 @@ #include "LevelTouchableUpdater.hh" #include "../GeantStepPointView.hh" #include "../GeantStepView.hh" -#include "../GeantTrackView.hh" namespace celeritas { @@ -245,8 +244,6 @@ void HitProcessor::operator()(DetectorStepOutput const& out, size_t i) const CELER_EXPECT(!out.detector.empty()); CELER_EXPECT(i < out.size()); - G4LogicalVolume const* lv = this->detector_volume(out.detector[i]); - GeantStepView step_view{*step_}; if (!out.energy_deposition.empty()) { @@ -306,8 +303,10 @@ void HitProcessor::operator()(DetectorStepOutput const& out, size_t i) const // Copy attributes from logical volume if (sp == StepPoint::pre) { + G4LogicalVolume const* lv = this->detector_volume(out.detector[i]); + CELER_ASSERT(lv); // Use lv already known from the in-volume detector - sp_view.update_from_volume(lv); + sp_view.update_from_volume(*lv); } else { diff --git a/src/celeritas/ext/detail/HitProcessor.hh b/src/celeritas/ext/detail/HitProcessor.hh index e7959d56c7..683f7684c0 100644 --- a/src/celeritas/ext/detail/HitProcessor.hh +++ b/src/celeritas/ext/detail/HitProcessor.hh @@ -138,8 +138,6 @@ class HitProcessor //! Accumulated number of hits size_type num_hits_{0}; - - void update_track(G4Track&) const; }; //---------------------------------------------------------------------------// From fad94ee847d3ab6a7b316a59c5f47191d15d36d3 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Tue, 27 Jan 2026 09:46:43 -0500 Subject: [PATCH 11/14] Fix doc errors with doxygen 1.16.1 --- src/celeritas/mucf/executor/detail/TTChannelSelector.hh | 2 +- src/corecel/math/detail/FnvHasher.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/celeritas/mucf/executor/detail/TTChannelSelector.hh b/src/celeritas/mucf/executor/detail/TTChannelSelector.hh index 1f7c0b40ea..dd8372479a 100644 --- a/src/celeritas/mucf/executor/detail/TTChannelSelector.hh +++ b/src/celeritas/mucf/executor/detail/TTChannelSelector.hh @@ -2,7 +2,7 @@ // Copyright Celeritas contributors: see top-level COPYRIGHT file for details // SPDX-License-Identifier: (Apache-2.0 OR MIT) //---------------------------------------------------------------------------// -//! \file celeritas/mucf/executor/detail/TTChannelSelectionHelper.hh +//! \file celeritas/mucf/executor/detail/TTChannelSelector.hh //---------------------------------------------------------------------------// #pragma once diff --git a/src/corecel/math/detail/FnvHasher.hh b/src/corecel/math/detail/FnvHasher.hh index ed95e99ebf..dcb7fdd6f4 100644 --- a/src/corecel/math/detail/FnvHasher.hh +++ b/src/corecel/math/detail/FnvHasher.hh @@ -28,7 +28,7 @@ namespace detail Phong Vo back in 1991. In a subsequent ballot round: Landon Curt Noll improved on their algorithm. Some people tried this hash and found that it worked rather well. In an EMail message to Landon, they named it the - ``Fowler/Noll/Vo'' or FNV hash. + "Fowler/Noll/Vo" or FNV hash. FNV hashes are designed to be fast while maintaining a low collision rate. The FNV speed allows one to quickly hash lots of data while maintaining a From d72fa65d346d1dcd8d1d0e574c892616a822615b Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Tue, 27 Jan 2026 12:20:23 -0500 Subject: [PATCH 12/14] Fix documenation build --- .github/workflows/doc.yml | 3 +-- doc/implementation/geant4-interface/low-level.rst | 2 +- src/celeritas/ext/GeantTrackView.hh | 3 +++ src/celeritas/track/detail/TrackInitAlgorithms.cc | 2 -- src/corecel/random/engine/detail/RanluxppImpl.hh | 4 ++-- src/geocel/vg/detail/SurfNavigator.hh | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 76eefc2e31..dc43e55ef4 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -42,13 +42,12 @@ jobs: fetch-tags: true - name: Configure celeritas # Turn warnings into errors only for PRs - # Disable expensive graphs for PRs also run: | ln -fs scripts/cmake-presets/ci-ubuntu-github.json CMakeUserPresets.json mkdir build && cd build cmake --preset=${CMAKE_PRESET} --log-level=VERBOSE \ ${{ github.workflow == 'pull_request' - && '-DDOXYGEN_WARN_AS_ERROR="YES" -DDOXYGEN_HAVE_DOT="NO"' + && '-DDOXYGEN_WARN_AS_ERROR="YES" -DDOXYGEN_HAVE_DOT="NO" -DDOXYGEN_QUIET="NO"' || ''}} \ .. - name: Build documentation diff --git a/doc/implementation/geant4-interface/low-level.rst b/doc/implementation/geant4-interface/low-level.rst index a0d6e3e6d7..3bfc6694a3 100644 --- a/doc/implementation/geant4-interface/low-level.rst +++ b/doc/implementation/geant4-interface/low-level.rst @@ -44,5 +44,5 @@ Views .. doxygenclass:: celeritas::GeantParticleView .. doxygenclass:: celeritas::GeantStepPointView -.. doxygenclass:: celeritas::GeantTrackView +.. doxygenclass:: celeritas::GeantTrackView .. doxygenclass:: celeritas::GeantStepView diff --git a/src/celeritas/ext/GeantTrackView.hh b/src/celeritas/ext/GeantTrackView.hh index b3261a4c27..24903a0cf5 100644 --- a/src/celeritas/ext/GeantTrackView.hh +++ b/src/celeritas/ext/GeantTrackView.hh @@ -138,6 +138,8 @@ GeantTrackView(G4Track const&) -> GeantTrackView; // Deduce reference from mutable G4Track& GeantTrackView(G4Track&) -> GeantTrackView; +// Doxygen fails to deduce correct templated class +#if !defined(__DOXYGEN__) || __DOXYGEN__ > 0x011600 //---------------------------------------------------------------------------// // INLINE ACCESSOR DEFINITIONS //---------------------------------------------------------------------------// @@ -223,6 +225,7 @@ void GeantTrackView::time(real_type t) { this->track().SetGlobalTime(convert_to_geant(t, clhep_time)); } +#endif //---------------------------------------------------------------------------// } // namespace celeritas diff --git a/src/celeritas/track/detail/TrackInitAlgorithms.cc b/src/celeritas/track/detail/TrackInitAlgorithms.cc index a1c7230e4d..125ff19380 100644 --- a/src/celeritas/track/detail/TrackInitAlgorithms.cc +++ b/src/celeritas/track/detail/TrackInitAlgorithms.cc @@ -21,8 +21,6 @@ namespace detail /*! * Remove all elements in the vacancy vector that were flagged as active * tracks. - * - * \return New size of the vacancy vector */ void remove_if_alive( TrackInitStateData const& init, diff --git a/src/corecel/random/engine/detail/RanluxppImpl.hh b/src/corecel/random/engine/detail/RanluxppImpl.hh index 67c399147c..504166a340 100644 --- a/src/corecel/random/engine/detail/RanluxppImpl.hh +++ b/src/corecel/random/engine/detail/RanluxppImpl.hh @@ -430,7 +430,7 @@ CELER_FUNCTION RanluxppArray18 multiply_9x9(RanluxppArray9 const& in1, * \p out is guaranteed to be smaller than the modulus. * * \param[in] mul product from multiply_9x9 with 18 numbers of 64 bits each - * \param[out] out result with 9 numbers of 64 bits each + * \return result with 9 numbers of 64 bits each */ CELER_FUNCTION RanluxppArray9 compute_modulus(RanluxppArray18 const& mul) { @@ -530,7 +530,7 @@ CELER_FORCEINLINE_FUNCTION RanluxppArray9 compute_mod_multiply( /*! * Compute \c base to the \p 2^log_n modulo m. * - * \param[in] base with 9 numbers of 64 bits each + * \param[in] result base with 9 numbers of 64 bits each * \param[in] log_n log_2 of exponent */ CELER_FUNCTION RanluxppArray9 compute_power_exp_modulus(RanluxppArray9 result, diff --git a/src/geocel/vg/detail/SurfNavigator.hh b/src/geocel/vg/detail/SurfNavigator.hh index d8a3a07f3f..d1abe958bf 100644 --- a/src/geocel/vg/detail/SurfNavigator.hh +++ b/src/geocel/vg/detail/SurfNavigator.hh @@ -50,7 +50,7 @@ class SurfNavigator /// @brief Locates the point in the geometry volume tree /// @param pvol_id Placed volume id to be checked first /// @param point Point to be checked, in the local frame of pvol - /// @param path Path to a parent of pvol that must contain the point + /// @param nav Path to a parent of pvol that must contain the point /// @param top Check first if pvol contains the point /// @param exclude Placed volume id to exclude from the search /// @return Index of the placed volume that contains the point From 81f54ac63b777f8493b828272aa47e7f0e9bb5c8 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Tue, 27 Jan 2026 12:21:52 -0500 Subject: [PATCH 13/14] move more code out of hit processor --- src/celeritas/ext/GeantStepPointView.cc | 39 ++++++++--- src/celeritas/ext/GeantStepPointView.hh | 36 +++++----- src/celeritas/ext/GeantStepView.cc | 34 +++++++-- src/celeritas/ext/GeantStepView.hh | 42 +++++++---- src/celeritas/ext/GeantTrackView.hh | 22 +++--- src/celeritas/ext/detail/HitProcessor.cc | 89 ++++++++---------------- src/celeritas/optical/SimTrackView.hh | 5 ++ 7 files changed, 152 insertions(+), 115 deletions(-) diff --git a/src/celeritas/ext/GeantStepPointView.cc b/src/celeritas/ext/GeantStepPointView.cc index 41ae1a3999..879056f758 100644 --- a/src/celeritas/ext/GeantStepPointView.cc +++ b/src/celeritas/ext/GeantStepPointView.cc @@ -16,9 +16,9 @@ namespace celeritas */ void GeantStepPointView::update_from_volume(G4LogicalVolume const& lv) { - step_point_.SetMaterial(lv.GetMaterial()); - step_point_.SetMaterialCutsCouple(lv.GetMaterialCutsCouple()); - step_point_.SetSensitiveDetector(lv.GetSensitiveDetector()); + sp_.SetMaterial(lv.GetMaterial()); + sp_.SetMaterialCutsCouple(lv.GetMaterialCutsCouple()); + sp_.SetSensitiveDetector(lv.GetSensitiveDetector()); } //---------------------------------------------------------------------------// @@ -31,7 +31,7 @@ void GeantStepPointView::update_from_volume(G4LogicalVolume const& lv) void GeantStepPointView::update_from_volume() { G4LogicalVolume const* lv = nullptr; - if (auto* touch = step_point_.GetTouchable()) + if (auto* touch = sp_.GetTouchable()) { // The physical volume could be null if post-step is outside if (auto* pv = touch->GetVolume()) @@ -45,9 +45,9 @@ void GeantStepPointView::update_from_volume() } else { - step_point_.SetMaterial(nullptr); - step_point_.SetMaterialCutsCouple(nullptr); - step_point_.SetSensitiveDetector(nullptr); + sp_.SetMaterial(nullptr); + sp_.SetMaterialCutsCouple(nullptr); + sp_.SetSensitiveDetector(nullptr); } } @@ -57,8 +57,29 @@ void GeantStepPointView::update_from_volume() */ void GeantStepPointView::update_from_particle(GeantParticleView const& particle) { - step_point_.SetMass(particle.mass().value() * CLHEP::MeV); - step_point_.SetCharge(particle.charge().value() * CLHEP::eplus); + sp_.SetMass(particle.mass().value() * CLHEP::MeV); + sp_.SetCharge(particle.charge().value() * CLHEP::eplus); +} + +//---------------------------------------------------------------------------// +/*! + * Clear unsupported attributes to invalid sentinel values. + * + * This sets attributes that Celeritas does not currently track to sentinel + * values to indicate they are unavailable to sensitive detectors. + */ +void GeantStepPointView::clear_unsupported() +{ + // Time since track was created + sp_.SetLocalTime(std::numeric_limits::infinity()); + // Time in rest frame since track was created + sp_.SetProperTime(std::numeric_limits::infinity()); + // Speed (TODO: use ParticleView) + sp_.SetVelocity(std::numeric_limits::infinity()); + // Safety distance + sp_.SetSafety(std::numeric_limits::infinity()); + // Polarization (default to zero) + sp_.SetPolarization(G4ThreeVector()); } //---------------------------------------------------------------------------// diff --git a/src/celeritas/ext/GeantStepPointView.hh b/src/celeritas/ext/GeantStepPointView.hh index 4b4d048500..f6d54f9593 100644 --- a/src/celeritas/ext/GeantStepPointView.hh +++ b/src/celeritas/ext/GeantStepPointView.hh @@ -38,10 +38,7 @@ class GeantStepPointView public: // Construct from G4StepPoint - explicit GeantStepPointView(G4StepPoint& step_point) - : step_point_(step_point) - { - } + explicit GeantStepPointView(G4StepPoint& step_point) : sp_(step_point) {} //!@{ //! \name Accessors @@ -59,7 +56,7 @@ class GeantStepPointView inline real_type time() const; //! Statistical weight - real_type weight() const { return step_point_.GetWeight(); } + real_type weight() const { return sp_.GetWeight(); } //!@} //!@{ @@ -78,7 +75,7 @@ class GeantStepPointView inline void time(real_type global_time); // Set statistical weight - void weight(real_type w) { step_point_.SetWeight(w); } + void weight(real_type w) { sp_.SetWeight(w); } // Update attributes from logical volume void update_from_volume(G4LogicalVolume const& lv); @@ -89,10 +86,16 @@ class GeantStepPointView // Update mass and charge from particle definition void update_from_particle(GeantParticleView const& particle); + // Clear unsupported attributes to invalid sentinel values + void clear_unsupported(); + //!@} + //! Access underlying G4 object + G4StepPoint& step_point() { return sp_; } + private: - G4StepPoint& step_point_; + G4StepPoint& sp_; }; //---------------------------------------------------------------------------// @@ -103,7 +106,7 @@ class GeantStepPointView */ Real3 GeantStepPointView::pos() const { - return convert_from_geant(step_point_.GetPosition(), clhep_length); + return convert_from_geant(sp_.GetPosition(), clhep_length); } //---------------------------------------------------------------------------// @@ -112,7 +115,7 @@ Real3 GeantStepPointView::pos() const */ Real3 GeantStepPointView::dir() const { - return convert_from_geant(step_point_.GetMomentumDirection(), 1); + return convert_from_geant(sp_.GetMomentumDirection(), 1); } //---------------------------------------------------------------------------// @@ -121,8 +124,7 @@ Real3 GeantStepPointView::dir() const */ GeantStepPointView::Energy GeantStepPointView::energy() const { - return Energy{ - convert_from_geant(step_point_.GetKineticEnergy(), CLHEP::MeV)}; + return Energy{convert_from_geant(sp_.GetKineticEnergy(), CLHEP::MeV)}; } //---------------------------------------------------------------------------// @@ -131,7 +133,7 @@ GeantStepPointView::Energy GeantStepPointView::energy() const */ real_type GeantStepPointView::time() const { - return convert_from_geant(step_point_.GetGlobalTime(), clhep_time); + return convert_from_geant(sp_.GetGlobalTime(), clhep_time); } //---------------------------------------------------------------------------// @@ -140,7 +142,7 @@ real_type GeantStepPointView::time() const */ void GeantStepPointView::pos(Real3 const& position) { - step_point_.SetPosition(convert_to_geant(position, clhep_length)); + sp_.SetPosition(convert_to_geant(position, clhep_length)); } //---------------------------------------------------------------------------// @@ -149,7 +151,7 @@ void GeantStepPointView::pos(Real3 const& position) */ void GeantStepPointView::dir(Real3 const& direction) { - step_point_.SetMomentumDirection(convert_to_geant(direction, 1)); + sp_.SetMomentumDirection(convert_to_geant(direction, 1)); } //---------------------------------------------------------------------------// @@ -159,8 +161,8 @@ void GeantStepPointView::dir(Real3 const& direction) void GeantStepPointView::energy(Energy kinetic_energy) { CELER_EXPECT(kinetic_energy >= zero_quantity()); - step_point_.SetKineticEnergy( - convert_to_geant(kinetic_energy.value(), CLHEP::MeV)); + sp_.SetKineticEnergy(convert_to_geant(kinetic_energy.value(), CLHEP::MeV)); + // TODO: update speed based on mass, KE } //---------------------------------------------------------------------------// @@ -170,7 +172,7 @@ void GeantStepPointView::energy(Energy kinetic_energy) void GeantStepPointView::time(real_type global_time) { CELER_EXPECT(global_time >= 0); - step_point_.SetGlobalTime(convert_to_geant(global_time, clhep_time)); + sp_.SetGlobalTime(convert_to_geant(global_time, clhep_time)); } //---------------------------------------------------------------------------// diff --git a/src/celeritas/ext/GeantStepView.cc b/src/celeritas/ext/GeantStepView.cc index 7b0dbfe557..e1889ce32e 100644 --- a/src/celeritas/ext/GeantStepView.cc +++ b/src/celeritas/ext/GeantStepView.cc @@ -20,20 +20,20 @@ namespace celeritas */ void GeantStepView::update_track() { - CELER_EXPECT(step_.GetTrack()); + CELER_EXPECT(s_.GetTrack()); - GeantTrackView track{*step_.GetTrack()}; + GeantTrackView track{*s_.GetTrack()}; GeantParticleView particle_view = track.particle(); // Update pre-step point if present - if (G4StepPoint* pre_step = step_.GetPreStepPoint()) + if (G4StepPoint* pre_step = s_.GetPreStepPoint()) { GeantStepPointView{*pre_step}.update_from_particle(particle_view); track.track().SetTouchableHandle(pre_step->GetTouchableHandle()); } // Update post-step point and track from post-step if present - if (G4StepPoint* post_step = step_.GetPostStepPoint()) + if (G4StepPoint* post_step = s_.GetPostStepPoint()) { GeantStepPointView post_view{*post_step}; post_view.update_from_particle(particle_view); @@ -50,5 +50,31 @@ void GeantStepView::update_track() } } +//---------------------------------------------------------------------------// +/*! + * Delete a step point. + * + * This sets the step point to null if supported by the Geant4 version, + * otherwise does nothing (no reset available before v11.0.3). + */ +void GeantStepView::delete_step_point(StepPoint sp) +{ + CELER_EXPECT(sp != StepPoint::size_); + +#if G4VERSION_NUMBER >= 1103 + if (sp == StepPoint::pre) + { + s_.ResetPreStepPoint(nullptr); + } + else + { + s_.ResetPostStepPoint(nullptr); + } +#else + // No "reset" available before v11.0.3 + CELER_DISCARD(sp); +#endif +} + //---------------------------------------------------------------------------// } // namespace celeritas diff --git a/src/celeritas/ext/GeantStepView.hh b/src/celeritas/ext/GeantStepView.hh index 533295589b..bda885e3a1 100644 --- a/src/celeritas/ext/GeantStepView.hh +++ b/src/celeritas/ext/GeantStepView.hh @@ -37,7 +37,7 @@ class GeantStepView public: // Construct from G4Step - explicit GeantStepView(G4Step& step) : step_(step) {} + explicit GeantStepView(G4Step& step) : s_(step) {} //!@{ //! \name Accessors @@ -54,6 +54,9 @@ class GeantStepView // Post-step point accessor inline GeantStepPointView post_step() const; + // Whether the step point is valid (not null) + inline bool has_step_point(StepPoint sp) const; + // Step point accessor by enum inline GeantStepPointView step_point(StepPoint sp) const; @@ -70,10 +73,13 @@ class GeantStepView // Update track from step data void update_track(); + // Delete a step point (set to null or clear based on Geant4 version) + void delete_step_point(StepPoint sp); + //!@} private: - G4Step& step_; + G4Step& s_; }; //---------------------------------------------------------------------------// @@ -84,8 +90,7 @@ class GeantStepView */ auto GeantStepView::energy_deposition() const -> Energy { - return Energy{ - convert_from_geant(step_.GetTotalEnergyDeposit(), CLHEP::MeV)}; + return Energy{convert_from_geant(s_.GetTotalEnergyDeposit(), CLHEP::MeV)}; } //---------------------------------------------------------------------------// @@ -94,7 +99,7 @@ auto GeantStepView::energy_deposition() const -> Energy */ real_type GeantStepView::step_length() const { - return convert_from_geant(step_.GetStepLength(), clhep_length); + return convert_from_geant(s_.GetStepLength(), clhep_length); } //---------------------------------------------------------------------------// @@ -103,7 +108,7 @@ real_type GeantStepView::step_length() const */ void GeantStepView::energy_deposition(Energy edep) { - step_.SetTotalEnergyDeposit(convert_to_geant(edep.value(), CLHEP::MeV)); + s_.SetTotalEnergyDeposit(convert_to_geant(edep.value(), CLHEP::MeV)); } //---------------------------------------------------------------------------// @@ -112,11 +117,11 @@ void GeantStepView::energy_deposition(Energy edep) */ void GeantStepView::step_length(real_type length) { - step_.SetStepLength(convert_to_geant(length, clhep_length)); - if (step_.GetTrack()) + s_.SetStepLength(convert_to_geant(length, clhep_length)); + if (s_.GetTrack()) { // Set on track as well - step_.GetTrack()->SetStepLength(step_.GetStepLength()); + s_.GetTrack()->SetStepLength(s_.GetStepLength()); } } @@ -126,8 +131,8 @@ void GeantStepView::step_length(real_type length) */ GeantStepPointView GeantStepView::pre_step() const { - CELER_EXPECT(step_.GetPreStepPoint()); - return GeantStepPointView{*step_.GetPreStepPoint()}; + CELER_EXPECT(this->has_step_point(StepPoint::pre)); + return GeantStepPointView{*s_.GetPreStepPoint()}; } //---------------------------------------------------------------------------// @@ -136,8 +141,19 @@ GeantStepPointView GeantStepView::pre_step() const */ GeantStepPointView GeantStepView::post_step() const { - CELER_EXPECT(step_.GetPostStepPoint()); - return GeantStepPointView{*step_.GetPostStepPoint()}; + CELER_EXPECT(this->has_step_point(StepPoint::post)); + return GeantStepPointView{*s_.GetPostStepPoint()}; +} + +//---------------------------------------------------------------------------// +/*! + * Whether the step point is valid (not null). + */ +bool GeantStepView::has_step_point(StepPoint sp) const +{ + CELER_EXPECT(sp != StepPoint::size_); + return (sp == StepPoint::pre ? s_.GetPreStepPoint() : s_.GetPostStepPoint()) + != nullptr; } //---------------------------------------------------------------------------// diff --git a/src/celeritas/ext/GeantTrackView.hh b/src/celeritas/ext/GeantTrackView.hh index 24903a0cf5..18d1f37590 100644 --- a/src/celeritas/ext/GeantTrackView.hh +++ b/src/celeritas/ext/GeantTrackView.hh @@ -48,7 +48,7 @@ class GeantTrackView public: // Construct from G4Track - explicit GeantTrackView(G4Track const& track) : track_(track) {} + explicit GeantTrackView(G4Track const& track) : t_(track) {} // Get particle definition view inline GeantParticleView particle() const; @@ -66,16 +66,16 @@ class GeantTrackView inline real_type time() const; //! Statistical weight - real_type weight() const { return track_.GetWeight(); } + real_type weight() const { return t_.GetWeight(); } //! Access the G4 track directly - G4Track const& track() const { return track_; } + G4Track const& track() const { return t_; } //! Access the G4 track directly (const) - G4Track const& ctrack() const { return track_; } + G4Track const& ctrack() const { return t_; } private: - G4Track const& track_; + G4Track const& t_; }; //---------------------------------------------------------------------------// @@ -148,8 +148,8 @@ GeantTrackView(G4Track&) -> GeantTrackView; */ GeantParticleView GeantTrackView::particle() const { - CELER_EXPECT(track_.GetDefinition()); - return GeantParticleView{*track_.GetDefinition()}; + CELER_EXPECT(t_.GetDefinition()); + return GeantParticleView{*t_.GetDefinition()}; } //---------------------------------------------------------------------------// @@ -158,7 +158,7 @@ GeantParticleView GeantTrackView::particle() const */ Real3 GeantTrackView::pos() const { - return convert_from_geant(track_.GetPosition(), clhep_length); + return convert_from_geant(t_.GetPosition(), clhep_length); } //---------------------------------------------------------------------------// @@ -167,7 +167,7 @@ Real3 GeantTrackView::pos() const */ Real3 GeantTrackView::dir() const { - return convert_from_geant(track_.GetMomentumDirection(), 1); + return convert_from_geant(t_.GetMomentumDirection(), 1); } //---------------------------------------------------------------------------// @@ -176,7 +176,7 @@ Real3 GeantTrackView::dir() const */ auto GeantTrackView::energy() const -> Energy { - return Energy{convert_from_geant(track_.GetKineticEnergy(), CLHEP::MeV)}; + return Energy{convert_from_geant(t_.GetKineticEnergy(), CLHEP::MeV)}; } //---------------------------------------------------------------------------// @@ -185,7 +185,7 @@ auto GeantTrackView::energy() const -> Energy */ real_type GeantTrackView::time() const { - return convert_from_geant(track_.GetGlobalTime(), clhep_time); + return convert_from_geant(t_.GetGlobalTime(), clhep_time); } //---------------------------------------------------------------------------// diff --git a/src/celeritas/ext/detail/HitProcessor.cc b/src/celeritas/ext/detail/HitProcessor.cc index fc1dedce60..23c48ef7d2 100644 --- a/src/celeritas/ext/detail/HitProcessor.cc +++ b/src/celeritas/ext/detail/HitProcessor.cc @@ -25,6 +25,7 @@ #include "corecel/cont/EnumArray.hh" #include "corecel/cont/Range.hh" #include "corecel/io/Logger.hh" +#include "corecel/math/QuantityIO.hh" #include "corecel/sys/ScopedProfiling.hh" #include "corecel/sys/TraceCounter.hh" #include "geocel/GeantGeoParams.hh" @@ -106,72 +107,40 @@ HitProcessor::HitProcessor(SPConstVecLV detector_volumes, CELER_LOG(debug) << "Setting up thread-local hit processor for " << detector_volumes_->size() << " sensitive detectors"; -#if G4VERSION_NUMBER >= 1103 -# define HP_CLEAR_STEP_POINT(CMD) step_->CMD(nullptr) -#else -# define HP_CLEAR_STEP_POINT(CMD) /* no "reset" before v11.0.3 */ -#endif - -#define HP_SETUP_POINT(LOWER, TITLE) \ - do \ - { \ - if (!selection.points[StepPoint::LOWER]) \ - { \ - HP_CLEAR_STEP_POINT(Reset##TITLE##StepPoint); \ - } \ - else \ - { \ - auto* sp = step_->Get##TITLE##StepPoint(); \ - sp->SetStepStatus(fUserDefinedLimit); \ - step_points_[StepPoint::LOWER] = sp; \ - } \ - } while (0) - - HP_SETUP_POINT(pre, Pre); - HP_SETUP_POINT(post, Post); -#undef HP_SETUP_POINT -#undef HP_CLEAR_STEP_POINT - - for (auto p : range(StepPoint::size_)) + GeantStepView step_view{*step_}; + for (auto sp : range(StepPoint::size_)) { - if (locate_touchable[p]) + if (!selection.points[sp]) { - // Create touchable handle for this step point - touch_handle_[p] = new G4TouchableHistory; - CELER_ASSERT(step_points_[p]); - step_points_[p]->SetTouchableHandle(touch_handle_[p]); + step_view.delete_step_point(sp); + CELER_ASSERT(!locate_touchable[sp]); } - if (locate_touchable[p] && !update_touchable_) + else { - CELER_EXPECT(selection.points[p].volume_instance_ids); - // FIXME: pass geant geo into this constructor - auto ggeo = ::celeritas::global_geant_geo().lock(); - CELER_ASSERT(ggeo); - update_touchable_ - = std::make_unique(std::move(ggeo)); + auto point_view = step_view.step_point(sp); + point_view.clear_unsupported(); + step_points_[sp] = &point_view.step_point(); + if (locate_touchable[sp]) + { + // Create touchable handle for this step point + touch_handle_[sp] = new G4TouchableHistory; + step_points_[sp]->SetTouchableHandle(touch_handle_[sp]); + if (!update_touchable_) + { + CELER_EXPECT(selection.points[sp].volume_instance_ids); + // FIXME: pass geant geo into this constructor + auto ggeo = ::celeritas::global_geant_geo().lock(); + CELER_ASSERT(ggeo); + update_touchable_ = std::make_unique( + std::move(ggeo)); + } + } } } // Set invalid values for unsupported SD attributes step_->SetNonIonizingEnergyDeposit( -std::numeric_limits::infinity()); - for (G4StepPoint* p : step_points_) - { - if (!p) - { - continue; - } - // Time since track was created - p->SetLocalTime(std::numeric_limits::infinity()); - // Time in rest frame since track was created - p->SetProperTime(std::numeric_limits::infinity()); - // Speed (TODO: use ParticleView) - p->SetVelocity(std::numeric_limits::infinity()); - // Safety distance - p->SetSafety(std::numeric_limits::infinity()); - // Polarization (default to zero) - p->SetPolarization(G4ThreeVector()); - } // Convert logical volumes (global) to sensitive detectors (thread local) detectors_.resize(detector_volumes_->size()); @@ -239,7 +208,7 @@ void HitProcessor::operator()(DetectorStepOutput const& out) const /*! * Generate and call a single hit. */ -void HitProcessor::operator()(DetectorStepOutput const& out, size_t i) const +void HitProcessor::operator()(DetectorStepOutput const& out, size_type i) const { CELER_EXPECT(!out.detector.empty()); CELER_EXPECT(i < out.size()); @@ -272,10 +241,8 @@ void HitProcessor::operator()(DetectorStepOutput const& out, size_t i) const if (CELER_UNLIKELY(!success)) { // Inconsistent touchable: skip this energy deposition - CELER_LOG_LOCAL(error) - << "Omitting energy deposition of " - << step_view.energy_deposition().value() << ' ' - << GeantStepView::Energy::unit_type::label(); + CELER_LOG_LOCAL(error) << "Omitting energy deposition of " + << step_view.energy_deposition(); return; } } diff --git a/src/celeritas/optical/SimTrackView.hh b/src/celeritas/optical/SimTrackView.hh index 77cc5451eb..2e7ac08e70 100644 --- a/src/celeritas/optical/SimTrackView.hh +++ b/src/celeritas/optical/SimTrackView.hh @@ -19,6 +19,11 @@ namespace optical //---------------------------------------------------------------------------// /*! * Simulation properties for a single track. + * + * Celeritas currently stores only the global time in the lab frame: the time + * since the creation of a track should be handled separately, and the + * "proper time" (local time in the inertial frame of the track since its + * creation) is not currently tracked. */ class SimTrackView { From 0b6afc311d61de2f02728d9a1772c04bdad349ab Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Tue, 27 Jan 2026 12:39:09 -0500 Subject: [PATCH 14/14] REVERTME: move doc fixes to another branch --- .github/workflows/doc.yml | 3 ++- src/celeritas/global/detail/KillActive.cc | 3 --- src/celeritas/global/detail/KillActive.hh | 3 --- src/celeritas/mucf/executor/detail/TTChannelSelector.hh | 2 +- src/celeritas/track/detail/TrackInitAlgorithms.cc | 2 ++ src/corecel/math/detail/FnvHasher.hh | 2 +- src/corecel/random/engine/detail/RanluxppImpl.hh | 4 ++-- src/geocel/vg/detail/SurfNavigator.hh | 2 +- 8 files changed, 9 insertions(+), 12 deletions(-) diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index dc43e55ef4..76eefc2e31 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -42,12 +42,13 @@ jobs: fetch-tags: true - name: Configure celeritas # Turn warnings into errors only for PRs + # Disable expensive graphs for PRs also run: | ln -fs scripts/cmake-presets/ci-ubuntu-github.json CMakeUserPresets.json mkdir build && cd build cmake --preset=${CMAKE_PRESET} --log-level=VERBOSE \ ${{ github.workflow == 'pull_request' - && '-DDOXYGEN_WARN_AS_ERROR="YES" -DDOXYGEN_HAVE_DOT="NO" -DDOXYGEN_QUIET="NO"' + && '-DDOXYGEN_WARN_AS_ERROR="YES" -DDOXYGEN_HAVE_DOT="NO"' || ''}} \ .. - name: Build documentation diff --git a/src/celeritas/global/detail/KillActive.cc b/src/celeritas/global/detail/KillActive.cc index 12b1316207..a2856801d0 100644 --- a/src/celeritas/global/detail/KillActive.cc +++ b/src/celeritas/global/detail/KillActive.cc @@ -21,9 +21,6 @@ namespace detail //---------------------------------------------------------------------------// /*! * Mark all active tracks as "errored". - * - * These will then be killed by the \c TrackingCutAction at the end of the - * step. */ void kill_active(CoreParams const& params, CoreState& state) { diff --git a/src/celeritas/global/detail/KillActive.hh b/src/celeritas/global/detail/KillActive.hh index 6131741f0e..3952b9d343 100644 --- a/src/celeritas/global/detail/KillActive.hh +++ b/src/celeritas/global/detail/KillActive.hh @@ -25,9 +25,6 @@ namespace detail //---------------------------------------------------------------------------// /*! * Mark active tracks as "errored". - * - * This is invoked by the \c kill_active free function, which implements - * \c Stepper::kill_active . */ struct KillActiveExecutor { diff --git a/src/celeritas/mucf/executor/detail/TTChannelSelector.hh b/src/celeritas/mucf/executor/detail/TTChannelSelector.hh index dd8372479a..1f7c0b40ea 100644 --- a/src/celeritas/mucf/executor/detail/TTChannelSelector.hh +++ b/src/celeritas/mucf/executor/detail/TTChannelSelector.hh @@ -2,7 +2,7 @@ // Copyright Celeritas contributors: see top-level COPYRIGHT file for details // SPDX-License-Identifier: (Apache-2.0 OR MIT) //---------------------------------------------------------------------------// -//! \file celeritas/mucf/executor/detail/TTChannelSelector.hh +//! \file celeritas/mucf/executor/detail/TTChannelSelectionHelper.hh //---------------------------------------------------------------------------// #pragma once diff --git a/src/celeritas/track/detail/TrackInitAlgorithms.cc b/src/celeritas/track/detail/TrackInitAlgorithms.cc index 125ff19380..a1c7230e4d 100644 --- a/src/celeritas/track/detail/TrackInitAlgorithms.cc +++ b/src/celeritas/track/detail/TrackInitAlgorithms.cc @@ -21,6 +21,8 @@ namespace detail /*! * Remove all elements in the vacancy vector that were flagged as active * tracks. + * + * \return New size of the vacancy vector */ void remove_if_alive( TrackInitStateData const& init, diff --git a/src/corecel/math/detail/FnvHasher.hh b/src/corecel/math/detail/FnvHasher.hh index dcb7fdd6f4..ed95e99ebf 100644 --- a/src/corecel/math/detail/FnvHasher.hh +++ b/src/corecel/math/detail/FnvHasher.hh @@ -28,7 +28,7 @@ namespace detail Phong Vo back in 1991. In a subsequent ballot round: Landon Curt Noll improved on their algorithm. Some people tried this hash and found that it worked rather well. In an EMail message to Landon, they named it the - "Fowler/Noll/Vo" or FNV hash. + ``Fowler/Noll/Vo'' or FNV hash. FNV hashes are designed to be fast while maintaining a low collision rate. The FNV speed allows one to quickly hash lots of data while maintaining a diff --git a/src/corecel/random/engine/detail/RanluxppImpl.hh b/src/corecel/random/engine/detail/RanluxppImpl.hh index 504166a340..67c399147c 100644 --- a/src/corecel/random/engine/detail/RanluxppImpl.hh +++ b/src/corecel/random/engine/detail/RanluxppImpl.hh @@ -430,7 +430,7 @@ CELER_FUNCTION RanluxppArray18 multiply_9x9(RanluxppArray9 const& in1, * \p out is guaranteed to be smaller than the modulus. * * \param[in] mul product from multiply_9x9 with 18 numbers of 64 bits each - * \return result with 9 numbers of 64 bits each + * \param[out] out result with 9 numbers of 64 bits each */ CELER_FUNCTION RanluxppArray9 compute_modulus(RanluxppArray18 const& mul) { @@ -530,7 +530,7 @@ CELER_FORCEINLINE_FUNCTION RanluxppArray9 compute_mod_multiply( /*! * Compute \c base to the \p 2^log_n modulo m. * - * \param[in] result base with 9 numbers of 64 bits each + * \param[in] base with 9 numbers of 64 bits each * \param[in] log_n log_2 of exponent */ CELER_FUNCTION RanluxppArray9 compute_power_exp_modulus(RanluxppArray9 result, diff --git a/src/geocel/vg/detail/SurfNavigator.hh b/src/geocel/vg/detail/SurfNavigator.hh index d1abe958bf..d8a3a07f3f 100644 --- a/src/geocel/vg/detail/SurfNavigator.hh +++ b/src/geocel/vg/detail/SurfNavigator.hh @@ -50,7 +50,7 @@ class SurfNavigator /// @brief Locates the point in the geometry volume tree /// @param pvol_id Placed volume id to be checked first /// @param point Point to be checked, in the local frame of pvol - /// @param nav Path to a parent of pvol that must contain the point + /// @param path Path to a parent of pvol that must contain the point /// @param top Check first if pvol contains the point /// @param exclude Placed volume id to exclude from the search /// @return Index of the placed volume that contains the point