Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add new vecgeom tests to emulate CMS run 3 issues #800

Merged
merged 24 commits into from
Jun 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
50ba78f
Don't volume check union/intersection
sethrj Jun 2, 2023
e7bfb77
Allow only importing volumes from Geant4
sethrj Jun 2, 2023
8e06ea5
Add the ability to disable signal handlers
sethrj Jun 2, 2023
1e5e927
Only compare volumes when environment variable is set
sethrj Jun 3, 2023
cbdb416
Load test geometry without suffixes
sethrj Jun 5, 2023
e673527
Improve G4GDML logging
sethrj Jun 5, 2023
bdc6636
Add a test of imported geant4 volume name mapping
sethrj Jun 5, 2023
38041c9
Save import data from reflected volumes
sethrj Jun 2, 2023
3326347
Reflect a unique logical volume
sethrj Jun 5, 2023
cddf69d
Use unique solids
sethrj Jun 5, 2023
7d90da0
Add test of importing solids with and without physics, with and witho…
sethrj Jun 5, 2023
8b299e3
fixup! Use unique solids
sethrj Jun 5, 2023
d7265e2
Add test of in-memory mapping
sethrj Jun 6, 2023
fd74e80
Revert "Improve G4GDML logging"
sethrj Jun 7, 2023
1059247
Merge remote-tracking branch 'upstream/develop' into vecgeom-testing
sethrj Jun 7, 2023
49a3eab
Fix failure when geant4 is disabled
sethrj Jun 7, 2023
b3870a1
Reproduce Geant4 'There exists more than ONE logical volume in store'…
sethrj Jun 7, 2023
31de5a7
Revert "Add the ability to disable signal handlers"
sethrj Jun 8, 2023
80f9580
Revert "Save import data from reflected volumes"
sethrj Jun 8, 2023
9f4fa4a
fixup! Reproduce Geant4 'There exists more than ONE logical volume in…
sethrj Jun 8, 2023
fdf2474
fixup! Revert "Save import data from reflected volumes"
sethrj Jun 8, 2023
43d8102
Fix build when geant4 is disabled
sethrj Jun 8, 2023
1360e4c
Merge remote-tracking branch 'upstream/develop' into vecgeom-testing
sethrj Jun 8, 2023
c3e1e20
Fix maybe unused variable
sethrj Jun 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/accel/SharedParams.cc
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,9 @@ void SharedParams::initialize_core(SetupOptions const& options)
import_opts.unique_volumes = options.geometry_file.empty();
return std::make_shared<ImportData>(load_geant_data(import_opts));
}();
CELER_ASSERT(imported && *imported);
CELER_ASSERT(imported && !imported->particles.empty()
&& !imported->materials.empty()
&& !imported->processes.empty() && !imported->volumes.empty());

if (!options.physics_output_file.empty())
{
Expand Down
111 changes: 81 additions & 30 deletions src/celeritas/ext/GeantGeoUtils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,55 @@
#include "corecel/cont/Range.hh"
#include "corecel/io/Logger.hh"
#include "corecel/io/ScopedStreamRedirect.hh"
#include "corecel/io/ScopedTimeLog.hh"
#include "corecel/sys/ScopedMem.hh"

#include "ScopedGeantExceptionHandler.hh"
#include "ScopedGeantLogger.hh"

namespace celeritas
{
namespace
{
//---------------------------------------------------------------------------//
/*!
* Load a gdml input file, creating a pointer owned by Geant4.
*
* Geant4's constructors for physical/logical volumes register \c this pointers
* in a vector which is cleaned up manually. Yuck.
*
* \return the world volume
*/
G4VPhysicalVolume*
load_geant_geometry_impl(std::string const& filename, bool strip_pointer_ext)
{
CELER_LOG(info) << "Loading Geant4 geometry from GDML at " << filename;
ScopedMem record_mem("load_geant_geometry");

{
// I have no idea why, but creating the GDML parser resets the
// ScopedGeantLogger on its first instantiation (geant4@11.0)
G4GDMLParser temp_parser_init;
}

ScopedGeantLogger scoped_logger;
ScopedGeantExceptionHandler scoped_exceptions;

G4GDMLParser gdml_parser;
// Note that material and element names (at least as
// of Geant4@11.0) are *always* stripped: only volumes and solids keep
// their extension.
gdml_parser.SetStripFlag(strip_pointer_ext);

gdml_parser.Read(filename, /* validate_gdml_schema = */ false);

G4VPhysicalVolume* result(gdml_parser.GetWorldVolume());
CELER_ENSURE(result);
return result;
}

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

//---------------------------------------------------------------------------//
/*!
* Print detailed information about the touchable history.
Expand Down Expand Up @@ -59,41 +100,32 @@ std::ostream& operator<<(std::ostream& os, PrintableNavHistory const& pnh)

//---------------------------------------------------------------------------//
/*!
* Load a gdml input file, creating a pointer owned by Geant4.
* Load a Geant4 geometry, leaving the pointer suffixes intact for VecGeom.
*
* Geant4's constructors for physical/logical volumes register \c this pointers
* in a vector which is cleaned up manually. Yuck.
* Do *not* strip `0x` extensions since those are needed to deduplicate complex
* geometries (e.g. CMS) when loaded separately by VGDML and Geant4. The
* pointer-based deduplication is handled by the Label and LabelIdMultiMap.
*
* \return the world volume
* \return Geant4-owned world volume
*/
G4VPhysicalVolume* load_geant_geometry(std::string const& filename)
{
CELER_LOG(info) << "Loading Geant4 geometry from GDML at " << filename;
ScopedMem record_mem("load_geant_geometry");
ScopedTimeLog scoped_time;

{
// I have no idea why, but creating the GDML parser resets the
// ScopedGeantLogger on its first instantiation (geant4@11.0): so
// create and destroy one before doing anything else.
G4GDMLParser temp_parser_init;
}
ScopedGeantLogger scoped_logger;
ScopedGeantExceptionHandler scoped_exceptions;

// Create parser; do *not* strip `0x` extensions since those are needed to
// deduplicate complex geometries (e.g. CMS) and are handled by the Label
// and LabelIdMultiMap. Note that material and element names (at least as
// of Geant4@11.0) are *always* stripped: only volumes and solids keep
// their extension.
G4GDMLParser gdml_parser;
gdml_parser.SetStripFlag(false);

gdml_parser.Read(filename, /* validate_gdml_schema = */ false);
return load_geant_geometry_impl(filename, false);
}

G4VPhysicalVolume* result(gdml_parser.GetWorldVolume());
CELER_ENSURE(result);
return result;
//---------------------------------------------------------------------------//
/*!
* Load a Geant4 geometry, stripping suffixes like a typical Geant4 app.
*
* With this implementation, we let Geant4 strip the uniquifying pointers,
* which allows our application to construct its own based on the actual
* in-memory addresses.
*
* \return Geant4-owned world volume
*/
G4VPhysicalVolume* load_geant_geometry_native(std::string const& filename)
{
return load_geant_geometry_impl(filename, true);
}

//---------------------------------------------------------------------------//
Expand Down Expand Up @@ -122,5 +154,24 @@ void reset_geant_geometry()
}
}

//---------------------------------------------------------------------------//
/*!
* Get a view to the Geant4 LV store.
*
* This includes all volumes, potentially null ones as well.
*/
Span<G4LogicalVolume*> geant_logical_volumes()
{
G4LogicalVolumeStore* lv_store = G4LogicalVolumeStore::GetInstance();
CELER_ASSERT(lv_store);
auto start = lv_store->data();
auto stop = start + lv_store->size();
while (start != stop && *start == nullptr)
{
++start;
}
return {start, stop};
}

//---------------------------------------------------------------------------//
} // namespace celeritas
9 changes: 9 additions & 0 deletions src/celeritas/ext/GeantGeoUtils.hh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

#include "celeritas_config.h"
#include "corecel/Assert.hh"
#include "corecel/cont/Span.hh"

class G4LogicalVolume;
class G4VPhysicalVolume;
class G4VTouchable;

Expand All @@ -34,10 +36,17 @@ std::ostream& operator<<(std::ostream& os, PrintableNavHistory const& pnh);
// Load a GDML file and return the world volume (Geant4 owns!)
G4VPhysicalVolume* load_geant_geometry(std::string const& gdml_filename);

// Load a GDML file, stripping pointers
G4VPhysicalVolume* load_geant_geometry_native(std::string const& gdml_filename);

//---------------------------------------------------------------------------//
// Reset all Geant4 geometry stores if *not* using RunManager
void reset_geant_geometry();

//---------------------------------------------------------------------------//
// Get a view to the Geant4 LV store
Span<G4LogicalVolume*> geant_logical_volumes();

//---------------------------------------------------------------------------//
// INLINE DEFINITIONS
//---------------------------------------------------------------------------//
Expand Down
42 changes: 30 additions & 12 deletions src/celeritas/ext/GeantImporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
#include <G4ParticleTable.hh>
#include <G4ProcessManager.hh>
#include <G4ProcessType.hh>
#include <G4PropagatorInField.hh>
#include <G4ProcessVector.hh>
#include <G4ProductionCuts.hh>
#include <G4ProductionCutsTable.hh>
#include <G4PropagatorInField.hh>
#include <G4RToEConvForElectron.hh>
#include <G4RToEConvForGamma.hh>
#include <G4RToEConvForPositron.hh>
Expand Down Expand Up @@ -61,6 +61,7 @@
#include "celeritas/io/SeltzerBergerReader.hh"
#include "celeritas/phys/PDGNumber.hh"

#include "ScopedGeantExceptionHandler.hh"
#include "detail/AllElementReader.hh"
#include "detail/GeantProcessImporter.hh"
#include "detail/GeantVolumeVisitor.hh"
Expand Down Expand Up @@ -629,7 +630,8 @@ G4VPhysicalVolume const* GeantImporter::get_world_volume()
auto* nav = man->GetNavigatorForTracking();
CELER_ASSERT(nav);
auto* world = nav->GetWorldVolume();
CELER_ENSURE(world);
CELER_VALIDATE(world,
<< "no world volume has been defined in the navigator");
return world;
}

Expand Down Expand Up @@ -659,22 +661,39 @@ GeantImporter::GeantImporter(GeantSetup&& setup) : setup_(std::move(setup))
*/
ImportData GeantImporter::operator()(DataSelection const& selected)
{
CELER_VALIDATE(
(selected.materials && selected.particles != DataSelection::none)
|| selected.processes == DataSelection::none,
<< "materials and particles must be enabled if requesting processes");
ScopedMem record_mem("GeantImporter.load");
ImportData imported;

{
CELER_LOG(status) << "Transferring data from Geant4";
ScopedGeantExceptionHandler scoped_exceptions;
ScopedTimeLog scoped_time;
imported.particles = import_particles(selected.particles);
imported.elements = import_elements();
imported.materials = import_materials(selected.particles);
std::tie(imported.processes, imported.msc_models)
= import_processes(selected.processes,
imported.particles,
imported.elements,
imported.materials);
if (selected.particles != DataSelection::none)
{
imported.particles = import_particles(selected.particles);
}
if (selected.materials)
{
imported.elements = import_elements();
imported.materials = import_materials(selected.particles);
}
if (selected.processes != DataSelection::none)
{
std::tie(imported.processes, imported.msc_models)
= import_processes(selected.processes,
imported.particles,
imported.elements,
imported.materials);
}
imported.volumes = this->import_volumes(selected.unique_volumes);
imported.trans_params = import_trans_parameters(selected.particles);
if (selected.particles != DataSelection::none)
{
imported.trans_params = import_trans_parameters(selected.particles);
}
if (selected.processes & DataSelection::em)
{
imported.em_params = import_em_parameters();
Expand Down Expand Up @@ -717,7 +736,6 @@ ImportData GeantImporter::operator()(DataSelection const& selected)
}
}

CELER_ENSURE(imported);
return imported;
}

Expand Down
2 changes: 2 additions & 0 deletions src/celeritas/ext/GeantImporter.hh
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct GeantImportDataSelection
using Flags = unsigned int;
enum : unsigned int
{
none = 0x0,
dummy = 0x1, //!< Dummy particles+processes
em_basic = 0x2, //!< Electron, positron, gamma
em_ex = 0x4, //!< Extended EM particles
Expand All @@ -35,6 +36,7 @@ struct GeantImportDataSelection
};

Flags particles = em;
bool materials = true;
Flags processes = em;

//! Change volume names to match exported GDML file
Expand Down
26 changes: 18 additions & 8 deletions src/celeritas/ext/detail/GeantGeoConverter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
#include "corecel/math/Algorithms.hh"
#include "corecel/math/SoftEqual.hh"
#include "corecel/sys/TypeDemangler.hh"
#include "corecel/sys/Environment.hh"
#include "celeritas/ext/VecgeomData.hh"

#include "GenericSolid.hh"
Expand Down Expand Up @@ -255,11 +256,17 @@ LogicalVolume* GeantGeoConverter::convert(G4LogicalVolume const* g4lv_mom)
CELER_ASSERT(remaining_daughters <= 0
|| remaining_daughters == (int)g4lv_mom->GetNoDaughters());

// Cross check geometry using cubic volume property: very slow for union
// solids and a few others
if (!dynamic_cast<GenericSolidBase const*>(shape_mom)
// Cross check geometry using cubic volume property: skip stochastically
// sampled comparisons due to performance and frequent false positives
static bool const compare_volumes = [] {
std::string var = celeritas::getenv("CELER_COMPARE_VOLUMES");
return !var.empty() || var == "0";
}();
if (compare_volumes && !dynamic_cast<GenericSolidBase const*>(shape_mom)
&& !dynamic_cast<UnplacedScaledShape const*>(shape_mom)
&& !is_unknown_shape)
&& !dynamic_cast<UnplacedBooleanVolume<kSubtraction> const*>(shape_mom)
&& !dynamic_cast<UnplacedBooleanVolume<kIntersection> const*>(shape_mom)
&& !dynamic_cast<UnplacedBooleanVolume<kUnion> const*>(shape_mom))
{
auto vg_cap = vglv_mom->GetUnplacedVolume()->Capacity();
CELER_ASSERT(vg_cap > 0);
Expand All @@ -281,6 +288,10 @@ LogicalVolume* GeantGeoConverter::convert(G4LogicalVolume const* g4lv_mom)
{
// The *constituent* (unreflected) logical volume is actually tied to
// the sensitive detectors: save this as well
CELER_LOG(debug) << "Mapping constituent volume '" << lv->GetName()
<< "'@" << static_cast<void const*>(lv)
<< " to volume ID for volume '" << g4lv_mom->GetName()
<< "'@" << static_cast<void const*>(g4lv_mom);
g4logvol_id_map_[lv] = volid;
}

Expand Down Expand Up @@ -741,10 +752,9 @@ VUnplacedVolume* GeantGeoConverter::convert(G4VSolid const* shape)
{
G4VSolid* underlying = refl->GetConstituentMovedSolid();
CELER_ASSERT(underlying);
CELER_LOG(debug) << "Converting reflected solid '"
<< refl->GetName() << "' (underlying "
<< underlying->GetEntityType() << " solid: '"
<< underlying->GetName() << "')";
CELER_LOG(debug) << "Converting reflected solid '" << refl->GetName()
<< "' (underlying " << underlying->GetEntityType()
<< " solid: '" << underlying->GetName() << "')";
unplaced_volume = this->convert(underlying);
}

Expand Down
6 changes: 0 additions & 6 deletions src/celeritas/io/ImportData.hh
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,6 @@ struct ImportData
ImportSBMap sb_data;
ImportLivermorePEMap livermore_pe_data;
ImportAtomicRelaxationMap atomic_relaxation_data;

explicit operator bool() const
{
return !particles.empty() && !elements.empty() && !materials.empty()
&& !volumes.empty();
}
};

//---------------------------------------------------------------------------//
Expand Down
2 changes: 1 addition & 1 deletion src/celeritas/mat/MaterialParams.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ MatterState to_matter_state(ImportMaterialState state)
std::shared_ptr<MaterialParams>
MaterialParams::from_import(ImportData const& data)
{
CELER_EXPECT(data);
CELER_EXPECT(!data.materials.empty());

// Create MaterialParams input for its constructor
MaterialParams::Input input;
Expand Down
2 changes: 1 addition & 1 deletion src/celeritas/phys/CutoffParams.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ CutoffParams::from_import(ImportData const& data,
SPConstParticles particle_params,
SPConstMaterials material_params)
{
CELER_EXPECT(data);
CELER_EXPECT(!data.materials.empty());
CELER_EXPECT(particle_params);
CELER_EXPECT(material_params);

Expand Down
2 changes: 1 addition & 1 deletion src/celeritas/phys/ParticleParams.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace celeritas
std::shared_ptr<ParticleParams>
ParticleParams::from_import(ImportData const& data)
{
CELER_EXPECT(data);
CELER_EXPECT(!data.particles.empty());

Input defs(data.particles.size());

Expand Down
1 change: 0 additions & 1 deletion src/celeritas/track/SimParams.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ namespace celeritas
std::shared_ptr<SimParams>
SimParams::from_import(ImportData const& data, SPConstParticles particle_params)
{
CELER_EXPECT(data);
CELER_EXPECT(particle_params);
CELER_EXPECT(data.trans_params);
CELER_EXPECT(data.trans_params.looping.size() == particle_params->size());
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ celeritas_add_test(celeritas/ext/GeantImporter.test.cc
"TestEm3*"
"OneSteelSphere.*"
"OneSteelSphereGG.*"
"Solids.*"
)
celeritas_add_test(celeritas/ext/GeantVolumeMapper.test.cc ${_needs_geant4}
LINK_LIBRARIES ${Geant4_LIBRARIES} Celeritas::orange)
Expand Down
Loading