Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-10 10:11:50

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file geocel/GeantGeoParams.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <memory>
0010 #include <string>
0011 
0012 #include "corecel/Macros.hh"
0013 #include "corecel/data/ParamsDataInterface.hh"
0014 
0015 #include "BoundingBox.hh"
0016 #include "GeoParamsInterface.hh"
0017 #include "ScopedGeantExceptionHandler.hh"
0018 #include "ScopedGeantLogger.hh"
0019 #include "Types.hh"
0020 #include "g4/GeantGeoData.hh"
0021 
0022 #if !CELERITAS_USE_GEANT4
0023 #    include "inp/Model.hh"
0024 #endif
0025 
0026 class G4VPhysicalVolume;
0027 class G4LogicalSurface;
0028 
0029 namespace celeritas
0030 {
0031 //---------------------------------------------------------------------------//
0032 /*!
0033  * Shared Geant4 geometry model wrapper.
0034  *
0035  * This can be constructed directly by loading a GDML file, or in-memory using
0036  * an existing physical volume. The \c make_model_input function returns the
0037  * geometry hierarchy including surface definitions for optical physics.
0038  *
0039  * The \c VolumeId used by Celeritas is equal to the index of a \c
0040  * G4LogicalVolume in the \c G4LogicalVolumeStore. Due to potential resetting
0041  * of the geometry, the "volume instance ID" for the logical volume may be
0042  * offset from this index.
0043  *
0044  * Analogously, the \c G4VPhysicalVolume is equivalent to the index in its
0045  * store. Due to the way Geant4 represents "parameterised" and "replicated"
0046  * placements, a single PV may correspond to multiple spatial placements and is
0047  * disambiguated with \c ReplicaId , which corresponds to the PV's "copy
0048  * number".
0049  *
0050  * Each \c SurfaceId maps to a \c G4LogicalSurface instance, which is ether a
0051  * \c G4LogicalBorderSurface (an "interface" surface between two volume
0052  * instances) or a \c G4LogicalSkinSurface (a "boundary" surrounding a single
0053  * logical volume). To ensure reproducible surface IDs across runs, we put
0054  * boundaries before interfaces, and sort within each set by volume IDs (not by
0055  * Geant4 object pointers, which is what the Geant4 implementation stores in a
0056  * table).  Surface labels are accessed via the SurfaceParams object, which can
0057  * be created by the model input returned by this class.
0058  */
0059 class GeantGeoParams final : public GeoParamsInterface,
0060                              public ParamsDataInterface<GeantGeoParamsData>
0061 {
0062   public:
0063     //!@{
0064     //! \name Type aliases
0065     using ReplicaId = GeantPhysicalInstance::ReplicaId;
0066     //!@}
0067 
0068   public:
0069     // Create from a running Geant4 application
0070     static std::shared_ptr<GeantGeoParams> from_tracking_manager();
0071 
0072     // Construct from a GDML filename
0073     explicit GeantGeoParams(std::string const& gdml_filename);
0074 
0075     // Create a VecGeom model from an already-loaded Geant4 geometry
0076     // TODO: also take model input? see #1815
0077     explicit GeantGeoParams(G4VPhysicalVolume const* world);
0078 
0079     CELER_DEFAULT_MOVE_DELETE_COPY(GeantGeoParams);
0080 
0081     // Clean up on destruction
0082     ~GeantGeoParams() final;
0083 
0084     //// GEOMETRY INTERFACE ////
0085 
0086     //! Whether safety distance calculations are accurate and precise
0087     bool supports_safety() const final { return true; }
0088 
0089     //! Outer bounding box of geometry
0090     BBox const& bbox() const final { return bbox_; }
0091 
0092     // Maximum nested scene/volume depth
0093     LevelId::size_type max_depth() const final { return max_depth_; }
0094 
0095     // Create model parameters corresponding to our internal representation
0096     inp::Model make_model_input() const final;
0097 
0098     //// VOLUMES ////
0099 
0100     // Get (logical) volume metadata
0101     inline VolumeMap const& volumes() const final;
0102 
0103     // Get (physical) volume instance metadata
0104     inline VolInstanceMap const& volume_instances() const final;
0105 
0106     // Get the volume ID corresponding to a Geant4 logical volume
0107     VolumeId find_volume(G4LogicalVolume const* volume) const final;
0108 
0109     // Get the Geant4 physical volume corresponding to a volume instance ID
0110     GeantPhysicalInstance id_to_geant(VolumeInstanceId vol_id) const final;
0111 
0112     // Get the Geant4 logical volume corresponding to a volume ID
0113     G4LogicalVolume const* id_to_geant(VolumeId vol_id) const;
0114 
0115     //// SURFACES ////
0116 
0117     //! Get the number of surfaces (TODO: maybe live in surface params?)
0118     SurfaceId::size_type num_surfaces() const { return surfaces_.size(); }
0119 
0120     // Get the Geant4 logical surface corresponding to a surface ID
0121     inline G4LogicalSurface const* id_to_geant(SurfaceId surf_id) const;
0122 
0123     // DEPRECATED
0124     using GeoParamsInterface::find_volume;
0125 
0126     //! Offset of logical volume ID after reloading geometry
0127     VolumeId::size_type lv_offset() const { return data_.lv_offset; }
0128 
0129     //! Offset of physical volume ID after reloading geometry
0130     VolumeInstanceId::size_type pv_offset() const { return data_.pv_offset; }
0131 
0132     //! Offset of material index after reloading geometry
0133     GeoMatId::size_type mat_offset() const { return data_.mat_offset; }
0134 
0135     //// G4 ACCESSORS ////
0136 
0137     //! Get the volume ID corresponding to a Geant4 logical volume
0138     VolumeId geant_to_id(G4LogicalVolume const& volume) const
0139     {
0140         return this->find_volume(&volume);
0141     }
0142 
0143     // Get the volume ID corresponding to a Geant4 physical volume
0144     VolumeInstanceId geant_to_id(G4VPhysicalVolume const& volume) const;
0145 
0146     // Get the replica ID corresponding to a Geant4 physical volume
0147     ReplicaId replica_id(G4VPhysicalVolume const& volume) const;
0148 
0149     //!@{
0150     //! Access the world volume
0151     G4VPhysicalVolume const* world() const { return data_.world; }
0152     G4VPhysicalVolume* world() { return data_.world; }
0153     //!@}
0154 
0155     // Get the world extents in Geant4 units
0156     BoundingBox<double> get_clhep_bbox() const;
0157 
0158     // Initialize thread-local mutable copy numbers for "replica" volumes
0159     void reset_replica_data() const;
0160 
0161     //// DATA ACCESS ////
0162 
0163     //! Access geometry data on host
0164     HostRef const& host_ref() const final { return data_; }
0165 
0166     //! No GPU support code
0167     DeviceRef const& device_ref() const final
0168     {
0169         CELER_NOT_IMPLEMENTED("Geant4 on GPU");
0170     }
0171 
0172   private:
0173     //// DATA ////
0174 
0175     bool loaded_gdml_{false};
0176     bool closed_geometry_{false};
0177     std::unique_ptr<ScopedGeantLogger> scoped_logger_;
0178     std::unique_ptr<ScopedGeantExceptionHandler> scoped_exceptions_;
0179 
0180     // Host metadata/access
0181     VolumeMap volumes_;
0182     VolInstanceMap vol_instances_;
0183     std::vector<G4LogicalSurface const*> surfaces_;
0184     BBox bbox_;
0185     LevelId::size_type max_depth_{0};
0186 
0187     // Storage
0188     HostRef data_;
0189 
0190     //// HELPER FUNCTIONS ////
0191 
0192     // Complete geometry construction
0193     void build_tracking();
0194 
0195     // Construct labels and other host-only metadata
0196     void build_metadata();
0197 };
0198 
0199 //---------------------------------------------------------------------------//
0200 // Set non-owning reference to global tracking geometry instance
0201 void geant_geo(GeantGeoParams const&);
0202 
0203 // Global tracking geometry instance: may be nullptr
0204 GeantGeoParams const* geant_geo();
0205 
0206 //---------------------------------------------------------------------------//
0207 // INLINE DEFINITIONS
0208 //---------------------------------------------------------------------------//
0209 /*!
0210  * Get volume metadata.
0211  *
0212  * Volumes correspond directly to Geant4 logical volumes.
0213  */
0214 auto GeantGeoParams::volumes() const -> VolumeMap const&
0215 {
0216     return volumes_;
0217 }
0218 
0219 //---------------------------------------------------------------------------//
0220 /*!
0221  * Get volume instance metadata.
0222  *
0223  * Volume instances correspond directly to Geant4 physical volumes.
0224  */
0225 auto GeantGeoParams::volume_instances() const -> VolInstanceMap const&
0226 {
0227     return vol_instances_;
0228 }
0229 
0230 //---------------------------------------------------------------------------//
0231 /*!
0232  * Get the Geant4 logical surface corresponding to a surface ID.
0233  */
0234 G4LogicalSurface const* GeantGeoParams::id_to_geant(SurfaceId id) const
0235 {
0236     CELER_EXPECT(!id || id < surfaces_.size());
0237     if (!id)
0238     {
0239         return {};
0240     }
0241 
0242     return surfaces_[id.unchecked_get()];
0243 }
0244 
0245 //---------------------------------------------------------------------------//
0246 #if !CELERITAS_USE_GEANT4 && !defined(__DOXYGEN__)
0247 inline void geant_geo(GeantGeoParams const&)
0248 {
0249     CELER_ASSERT_UNREACHABLE();
0250 }
0251 inline GeantGeoParams const* geant_geo()
0252 {
0253     return nullptr;
0254 }
0255 //-----------------------------------//
0256 
0257 inline GeantGeoParams::GeantGeoParams(G4VPhysicalVolume const*)
0258 {
0259     CELER_NOT_CONFIGURED("Geant4");
0260 }
0261 inline GeantGeoParams::GeantGeoParams(std::string const&)
0262 {
0263     CELER_NOT_CONFIGURED("Geant4");
0264 }
0265 inline std::shared_ptr<GeantGeoParams>
0266 GeantGeoParams::GeantGeoParams::from_tracking_manager()
0267 {
0268     CELER_NOT_CONFIGURED("Geant4");
0269 }
0270 
0271 //-----------------------------------//
0272 inline GeantGeoParams::~GeantGeoParams() {}
0273 
0274 //-----------------------------------//
0275 inline inp::Model GeantGeoParams::make_model_input() const
0276 {
0277     CELER_ASSERT_UNREACHABLE();
0278 }
0279 inline VolumeId GeantGeoParams::find_volume(G4LogicalVolume const*) const
0280 {
0281     CELER_ASSERT_UNREACHABLE();
0282 }
0283 inline GeantPhysicalInstance GeantGeoParams::id_to_geant(VolumeInstanceId) const
0284 {
0285     CELER_ASSERT_UNREACHABLE();
0286 }
0287 inline G4LogicalVolume const* GeantGeoParams::id_to_geant(VolumeId) const
0288 {
0289     CELER_ASSERT_UNREACHABLE();
0290 }
0291 inline VolumeInstanceId
0292 GeantGeoParams::geant_to_id(G4VPhysicalVolume const&) const
0293 {
0294     CELER_ASSERT_UNREACHABLE();
0295 }
0296 inline GeantGeoParams::ReplicaId
0297 GeantGeoParams::replica_id(G4VPhysicalVolume const&) const
0298 {
0299     CELER_ASSERT_UNREACHABLE();
0300 }
0301 inline BoundingBox<double> GeantGeoParams::get_clhep_bbox() const
0302 {
0303     CELER_ASSERT_UNREACHABLE();
0304 }
0305 
0306 #endif
0307 //---------------------------------------------------------------------------//
0308 }  // namespace celeritas