Skip to content

Commit d5e712f

Browse files
authored
Handle converted G4VPVParameterised/G4PVReplica volumes from G4VG in geometry checks (apt-sim#351)
The latest updates to G4VG allow Geant4 parametrised/replica volumes to be converted to a VecGeom representation by direct placements. The need for this comes from the Delta Assessment "B5" example that uses these structures and for which there is no direct VecGeom equivalent except by making a direct placement for each copy. That's supported as of [G4VG 1.0.3](https://github.com/celeritas-project/g4vg/releases/tag/v1.0.3), but using this in AdePT and trying out B5 still leads to errors from `AdePTG4Integration::visitGeometry`. That's sort of expected as the translation between Geant4 and VecGeom means that there will be N VecGeom placements for each replicated volume, N corresponding to the total number of replicas. Consequently, the checks in `visitGeometry` fail as: 1. The number of daughters in a given LV may be larger 2. Volume transformations may not match up as the original "parent" volume in Geant4 is compared against some copy of the replicated volume in VecGeom The changes here address this, at least as far as the B5 geometry is concerned: 1. The number of LV daughters on the Geant4 side are counted as the sum of daughter multiplicities - For ordinary volumes this should be identical - It should also work for a mix of daughters (some standard, some parametrised), but this is untested. 2. The transformation problem is a bit hacky, though pretty much copies what is done on the G4VG side: - If the Geant4 PV provides a `G4VPVParametrisation`, use that to transform it using the copy number of the compared VecGeom PV before extracting the transform from the Geant4 PV - If the Geant4 PV is a `G4PVReplica` use a `G4ReplicaNavigation` to do the same as above. - The hacky bit here is that use of this method requires a `const_cast` on the Geant4 PV as the transform step is non-const... - This does modify the underlying PV, but I think that's o.k (?) as it's only relevant for the navigation stage. Testing with a local build against B5 shows this to now run to completion without error, but full validation has not been done yet (that's probably best addressed separately).
1 parent b24ef76 commit d5e712f

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

CMakeLists.txt

+3-2
Original file line numberDiff line numberDiff line change
@@ -157,15 +157,16 @@ if(Geant4_FOUND)
157157
FetchContent_Declare(
158158
g4vg
159159
GIT_REPOSITORY https://github.com/celeritas-project/g4vg
160-
GIT_TAG 638c273b744c7ac0fa865ddb15c161b853a4029b)
160+
GIT_TAG f4308d392a502b7bd7468938f8d9a63198d3d866 # v1.0.3
161+
)
161162
# G4VG builds static by default, so change this to shared to match current
162163
# way AdePT is built.
163164
# could also configure for PIC mode static.
164165
set(BUILD_SHARED_LIBS ON)
165166
FetchContent_MakeAvailable(g4vg)
166167
message(STATUS "Using FetchContent to build G4VG as part of AdePT")
167168
else()
168-
find_package(G4VG 1.0.1 REQUIRED)
169+
find_package(G4VG 1.0.3 REQUIRED)
169170
message(STATUS "Found G4VG: ${G4VG_DIR}")
170171
endif()
171172
endif()

src/AdePTGeant4Integration.cpp

+30-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <G4FieldManager.hh>
1818
#include <G4RegionStore.hh>
1919
#include <G4TouchableHandle.hh>
20+
#include <G4PVReplica.hh>
21+
#include <G4ReplicaNavigation.hh>
2022

2123
#include <G4HepEmState.hh>
2224
#include <G4HepEmData.hh>
@@ -183,16 +185,42 @@ void visitGeometry(G4VPhysicalVolume const *g4_pvol, vecgeom::VPlacedVolume cons
183185
const auto g4_lvol = g4_pvol->GetLogicalVolume();
184186
const auto vg_lvol = vg_pvol->GetLogicalVolume();
185187

186-
const size_t nd = g4_lvol->GetNoDaughters();
188+
// Geant4 Parameterised/Replica volumes are represented with direct placements in VecGeom
189+
// To accurately compare the number of daughters, we need to sum multiplicity on Geant4 side
190+
const size_t nd = g4_lvol->GetNoDaughters();
191+
size_t nd_converted = 0;
192+
for (size_t daughter_id = 0; daughter_id < nd; ++daughter_id) {
193+
const G4VPhysicalVolume *daughter_pvol = g4_lvol->GetDaughter(daughter_id);
194+
nd_converted += daughter_pvol->GetMultiplicity();
195+
}
196+
187197
const auto daughters = vg_lvol->GetDaughters();
188198

189-
if (nd != daughters.size()) throw std::runtime_error("Fatal: CheckGeometry: Mismatch in number of daughters");
199+
if (nd_converted != daughters.size())
200+
throw std::runtime_error("Fatal: CheckGeometry: Mismatch in number of daughters");
201+
190202
// Check if transformations are matching
203+
// As above, with Parameterized/Replica volumes, we need to compare the transforms between
204+
// the VG direct placement and that for the Parameterised/Replicated volume given the same copy
205+
// number as that of the VG physical volume.
206+
// NOTE:
207+
// 1. Nasty const_cast as currently known way to get transform is to directly transform the
208+
// Geant4 phys vol before extracting, which is non-const....
209+
// 2. ...this does modify the physical volume, but this is _probably_ o.k. as actual navigation
210+
// will reset things o.k.
211+
if (G4VPVParameterisation *param = g4_pvol->GetParameterisation()) {
212+
param->ComputeTransformation(vg_pvol->GetCopyNo(), const_cast<G4VPhysicalVolume *>(g4_pvol));
213+
} else if (auto *replica = dynamic_cast<G4PVReplica *>(const_cast<G4VPhysicalVolume *>(g4_pvol))) {
214+
G4ReplicaNavigation nav;
215+
nav.ComputeTransformation(vg_pvol->GetCopyNo(), replica);
216+
}
217+
191218
const auto g4trans = g4_pvol->GetTranslation();
192219
const G4RotationMatrix *g4rot = g4_pvol->GetRotation();
193220
G4RotationMatrix idrot;
194221
const auto vgtransformation = vg_pvol->GetTransformation();
195222
constexpr double epsil = 1.e-8;
223+
196224
for (int i = 0; i < 3; ++i) {
197225
if (std::abs(g4trans[i] - vgtransformation->Translation(i)) > epsil)
198226
throw std::runtime_error(

0 commit comments

Comments
 (0)