@@ -241,10 +241,16 @@ G4VPhysicalVolume* DetectorConstruction::GetPhysicalVolume(const G4String& physi
241241 for (physicalVolume = physicalVolumeStore->begin (); physicalVolume != physicalVolumeStore->end ();
242242 physicalVolume++) {
243243 auto name = (*physicalVolume)->GetName ();
244- auto alternativeName = (G4String)geometryInfo.GetAlternativeNameFromGeant4PhysicalName (name);
245- if (name == physicalVolumeName || alternativeName == physicalVolumeName) {
244+ if (name == physicalVolumeName) {
246245 return *physicalVolume;
247246 }
247+ // physical volumes with the same Geant4 name are the same G4VPhysicalVolume pointer
248+ auto alternativeNames = geometryInfo.GetAlternativeNamesFromGeant4PhysicalName (name);
249+ for (const auto & alternativeName : alternativeNames) {
250+ if ((G4String)alternativeName == physicalVolumeName) {
251+ return *physicalVolume;
252+ }
253+ }
248254 }
249255
250256 return nullptr ;
@@ -312,40 +318,65 @@ void TRestGeant4GeometryInfo::PopulateFromGeant4World(const G4VPhysicalVolume* w
312318 auto detector = (DetectorConstruction*)G4RunManager::GetRunManager ()->GetUserDetectorConstruction ();
313319 TRestGeant4Metadata* restG4Metadata = detector->fSimulationManager ->GetRestMetadata ();
314320
315- const size_t n = int (world->GetLogicalVolume ()->GetNoDaughters ());
316- for (size_t i = 0 ; i < n + 1 ; i++) { // world is the + 1
317- G4VPhysicalVolume* volume;
318- if (i == n) {
319- volume = const_cast <G4VPhysicalVolume*>(world);
320- } else {
321- volume = world->GetLogicalVolume ()->GetDaughter (i);
322- }
323- TString namePhysical = (TString)volume->GetName ();
324- if (fGdmlNewPhysicalNames .size () > i) {
325- // it has been filled
326- fGeant4PhysicalNameToNewPhysicalNameMap [namePhysical] = fGdmlNewPhysicalNames [i];
327- }
328- TString physicalNewName = GetAlternativeNameFromGeant4PhysicalName (namePhysical);
329- TString nameLogical = (TString)volume->GetLogicalVolume ()->GetName ();
330- TString nameMaterial = (TString)volume->GetLogicalVolume ()->GetMaterial ()->GetName ();
331- auto position = volume->GetTranslation ();
332-
333- fPhysicalToLogicalVolumeMap [physicalNewName] = nameLogical;
334- fLogicalToMaterialMap [nameLogical] = nameMaterial;
335- fLogicalToPhysicalMap [nameLogical].emplace_back (namePhysical);
336- fPhysicalToPositionInWorldMap [physicalNewName] = {position.x (), position.y (), position.z ()};
337- InsertVolumeName (i, physicalNewName);
338-
339- if (!fIsAssembly && GetAlternativeNameFromGeant4PhysicalName (namePhysical) != namePhysical) {
340- fIsAssembly = true ;
341-
342- const auto geant4MajorVersionNumber = restG4Metadata->GetGeant4VersionMajor ();
343- if (geant4MajorVersionNumber < 11 ) {
344- cout << " User geometry consists of assembly which is not supported for this rest / Geant4 "
345- " version combination. Please upgrade to Geant4 11.0.0 or more to use this feature"
346- << endl;
347- // exit(1);
321+ // Recursive function to traverse the nested volume geometry
322+ std::function<void (const G4VPhysicalVolume*, size_t &, const G4String pathSoFar, const G4ThreeVector&)>
323+ ProcessVolumeRecursively = [&](const G4VPhysicalVolume* volume, size_t & index,
324+ const G4String pathSoFar, const G4ThreeVector& parentPosition) {
325+ G4String currentPath = pathSoFar;
326+ if (volume->GetName () != world->GetName ()) { // avoid all paths including 'world_PV/' at the
327+ // beginning
328+ currentPath += (currentPath.empty () ? " " : fPathSeparator .Data ()) + volume->GetName ();
348329 }
349- }
350- }
330+ G4ThreeVector positionInWorld = volume->GetTranslation () + parentPosition;
331+
332+ // First process the daughters to have the same order in volume IDs as before
333+ G4LogicalVolume* logVol = volume->GetLogicalVolume ();
334+ for (size_t i = 0 ; i < logVol->GetNoDaughters (); ++i) {
335+ G4VPhysicalVolume* daughter = logVol->GetDaughter (i);
336+ ProcessVolumeRecursively (daughter, index, currentPath, positionInWorld);
337+ }
338+
339+ // Process this volume
340+ G4String namePhysical = volume->GetName ();
341+ TString physicalNewName = GetAlternativePathFromGeant4Path (currentPath);
342+ if (namePhysical == world->GetName ()) {
343+ physicalNewName = namePhysical; // avoid blank name for World_PV
344+ }
345+ fNewPhysicalToGeant4PhysicalNameMap [physicalNewName] = namePhysical;
346+
347+ TString nameLogical = (TString)volume->GetLogicalVolume ()->GetName ();
348+ TString nameMaterial = (TString)volume->GetLogicalVolume ()->GetMaterial ()->GetName ();
349+ fPhysicalToLogicalVolumeMap [physicalNewName] = nameLogical;
350+ fLogicalToMaterialMap [nameLogical] = nameMaterial;
351+ fLogicalToPhysicalMap [nameLogical].emplace_back (namePhysical);
352+ fPhysicalToPositionInWorldMap [physicalNewName] = {positionInWorld.x (), positionInWorld.y (),
353+ positionInWorld.z ()};
354+ InsertVolumeName (index, physicalNewName);
355+ /*
356+ std::cout << "Index: " << index << std::endl;
357+ std::cout << "\tG4name: " << namePhysical << std::endl;
358+ std::cout << "\tgdmlName: " << physicalNewName << std::endl;
359+ std::cout << "\tLogical: " << nameLogical << std::endl;
360+ std::cout << "\tMaterial: " << nameMaterial << std::endl;
361+ std::cout << "\tPosition: (" << positionInWorld.x() << ", " << positionInWorld.y() << ", " <<
362+ positionInWorld.z() << ")mm" << std::endl;
363+ */
364+ if (!fIsAssembly &&
365+ GetAlternativeNameFromGeant4PhysicalName (namePhysical).Data () != namePhysical) {
366+ fIsAssembly = true ;
367+ const auto geant4MajorVersionNumber = restG4Metadata->GetGeant4VersionMajor ();
368+ if (geant4MajorVersionNumber < 11 ) {
369+ cout
370+ << " User geometry consists of assembly which is not supported for this rest / Geant4 "
371+ " version combination. Please upgrade to Geant4 11.0.0 or more to use this feature"
372+ << endl;
373+ // exit(1);
374+ }
375+ }
376+ ++index;
377+ };
378+
379+ // Start recursion from world volume
380+ size_t index = 0 ;
381+ ProcessVolumeRecursively (world, index, " " , G4ThreeVector (0 , 0 , 0 ));
351382}
0 commit comments