Bug #1790

G4Navigator->LocateGlobalPointAndSetup() segfaults when using GDML Geometry

Added by Greis, Jan about 7 years ago. Updated over 6 years ago.

Global Reconstruction
Target version:
Start date:
03 November 2015
Due date:
% Done:


Estimated time:
New Issue


It works fine using legacy geometry, but when using GDML it segfaults.
I'm calling it as

G4Navigator* g4navigator =
G4VPhysicalVolume* volume =
g4navigator->LocateGlobalPointAndSetup(posvector, &momvector);

The two vectors passed are checked to be good (i.e. all 3 components are sensible)

Initially I got the following output from the segfault:

#5  0x00007f898d2b6022 in
G4VPhysicalVolume const*, int, CLHEP::Hep3Vector const&,
CLHEP::Hep3Vector const*, bool, CLHEP::Hep3Vector&) () from
#6  0x00007f898d2af494 in
G4Navigator::LocateGlobalPointAndSetup(CLHEP::Hep3Vector const&,
CLHEP::Hep3Vector const*, bool, bool) () from
#7  0x00007f898fd04ad9 in MAUS::GlobalTools::propagate(double*, double,
BTField const*, double, MAUS::DataStructure::Global::PID, bool) () from
#8  0x00007f898fd084c2 in
std::string) () from
#9  0x00007f89859a1d72 in
MAUS::MapCppGlobalTrackMatching::_process(MAUS::Data*) const () from
#10 0x00007f89859a9654 in
MAUS::MapBase<MAUS::Data>::process_pyobj(_object*) const () from
#11 0x00007f89859a3b73 in
_object*, _object*) () from
#12 0x00007f89998bec2c in call_function (oparg=<optimised out>,
pp_stack=0x7fff46de5a10) at Python/ceval.c:4013

After a recompile of Geant4 in Debug mode this changed to

#5  0x00007f80da39391e in G4SmartVoxelHeader::GetParamAxis (this=0x0) at /home/jan/MICE/.MAUSSTABLE/maus-v1.2.0/third_party/source/geant4.9.6.p02/source/geometry/management/include/G4SmartVoxelHeader.icc:67
#6  0x00007f80da393d74 in G4ParameterisedNavigation::ParamVoxelLocate (this=0x3cf94a0, pHead=0x0, localPoint=...) at /home/jan/MICE/.MAUSSTABLE/maus-v1.2.0/third_party/source/geant4.9.6.p02/source/geometry/navigation/include/G4ParameterisedNavigation.icc:65
#7  0x00007f80da3983d6 in G4ParameterisedNavigation::LevelLocate (this=0x3cf94a0, history=..., blockedVol=0x0, blockedNum=-1, globalPoint=..., globalDirection=0x7ffdf39d01b0, pLocatedOnEdge=false, localPoint=...) at /home/jan/MICE/.MAUSSTABLE/maus-v1.2.0/third_party/source/geant4.9.6.p02/source/geometry/navigation/src/
#8  0x00007f80da38d80b in G4Navigator::LocateGlobalPointAndSetup (this=0x3cf9220, globalPoint=..., pGlobalDirection=0x7ffdf39d01b0, relativeSearch=true, ignoreDirection=true) at /home/jan/MICE/.MAUSSTABLE/maus-v1.2.0/third_party/source/geant4.9.6.p02/source/geometry/navigation/src/
#9  0x00007f80dcdcdfcf in MAUS::GlobalTools::propagate(double*, double, BTField const*, double, MAUS::DataStructure::Global::PID, bool) () from /home/jan/MICE/MAUS/maus-temp1.2.0/build/
#10 0x00007f80dcdd148f in MAUS::recon::global::TrackMatching::USTrack(MAUS::GlobalEvent*, std::string) () from /home/jan/MICE/MAUS/maus-temp1.2.0/build/
#11 0x00007f80ce203d42 in MAUS::MapCppGlobalTrackMatching::_process(MAUS::Data*) const () from /home/jan/MICE/MAUS/maus-temp1.2.0/build/
#12 0x00007f80ce20b424 in MAUS::MapBase<MAUS::Data>::process_pyobj(_object*) const () from /home/jan/MICE/MAUS/maus-temp1.2.0/build/
#13 0x00007f80ce2059a3 in MAUS::PyWrapMapBase<MAUS::MapCppGlobalTrackMatching>::process(_object*, _object*, _object*) () from /home/jan/MICE/MAUS/maus-temp1.2.0/build/
#14 0x00007f80e6aabc2c in call_function (oparg=<optimised out>, pp_stack=0x7ffdf39d0f10) at Python/ceval.c:4013

Ryan has suggested the code above might be violating some strange G4 casting rules by making a copy of a physical volume but I have very little understanding of either the GDML Geometry or Geant4 so I don't know where to go from here.


Updated by Dobbs, Adam about 7 years ago

  • Category set to Global Reconstruction
  • Assignee changed from Dobbs, Adam to Bayes, Ryan
  • Target version set to Future MAUS release

My suspicion would be a fault in our geometry, such that GEANT4 ends with NULL pointers to volumes (note the 0x0 appearing a few times in the debug output). This is backed up by the legacy geometry working. Do not know how to fix myself - Ryan, Chris R, any thoughts?


Updated by Bayes, Ryan about 7 years ago

A similar process is used in the GeometryNavigator without an apparent problem.

I note that the initialization is a little different in that case. Specifically

G4Navigator* _navigator = new G4Navigator();

And there is a method that uses this precise method GeometryNavigator::_setPoint(G4ThreeVector pos) which Jan requires (G4Navigator::LocateGlobalPointAndSetup()).

If I use this method in MAUSGeant4Manager immediately after the definition of the geometry exactly as Jan does, there is no problem. If I use a point inside one of the quadrupole volumes I get the logical volume back --- no errors. If I pick a position outside of the geometry then I get a null volume; I query the output volume name and it returns nothing. Could it be possible that Jan is asking for a point outside of the defined geometry and getting a NULL pointer as a result? In that case it should be noted that the geometry is only well defined for z > 0 and no volume will register for abs(x) > 2000 mm and abs(y) > 2000 mm.

To summarize, my guess is that Jan is trying to access a portion of the geometry where no G4LogicalVolume. The segfault can probably be avoided rather simply by checking that the output pointer does exist.


Updated by Bayes, Ryan about 7 years ago

Happily, I have now been able to reproduce Jan's error using the merge branch targeting a test point that sits in the world volume of the geometry, but not in any sub volume. I was able to circumvent the seg fault by requiring that the G4LogicalVolume is not NULL and the simulation proceeded as normal. It seems that the world volume in the GDML parser returns a NULL pointer to a logical volume --- I don't know what wise person thought that this was a good idea, but it is annoying. As it stands it is just something that the programmer needs to be aware of and take steps to mitigate.


Updated by Greis, Jan about 7 years ago

Somehow I can't seem to be able to reproduce the error now. Not even if I force the position vector to be outside of any subvolumes... I'll keep my eyes open in case it pops up again. I'm not sure how checking the volume to not be null would help though because the segfault occured while running LocateGlobalPointAndSetup(), not later, and I'm not actually doing anything with the returned volume.


Updated by Rogers, Chris over 6 years ago

I did some digging. It looks like the issue arises due to some problem in Geant4 handling of trackers:

  1. G4ParameterisedNavigation::LevelLocate(G4NavigationHistory& is a navigator class for parameterised volumes as in the tracker
  2. I removed trackers by hand from the GDML files and everything worked okay

Obviously G4 itself can get through trackers okay, so maybe some problem with the way the geometry is being dealt with? Will keep digging...


Updated by Rogers, Chris over 6 years ago

Looking at the code and stack trace with G4 in debug; for some reason G4LogicalVolume::GetSmartVoxelHeader() is returning NULL for the mother of the parameterised volumes at line 588 of, i.e. motherVoxelHeader = motherLogical->GetVoxelHeader();. This is something to do with the meshing of the parameterised volume mother, so not sure why that would not work out.


Updated by Rogers, Chris over 6 years ago

A bit more digging... the geometry close procedure does not really finalise the geometry. There is some more set up that needs to be done. Either we can call G4RunManager::ReOptimize(G4VLogicalVolume*) to finalise a specific logical volume object or G4RunManager::BeamOn() to finish closing the entire geometry, as per patch:

=== modified file 'src/common_cpp/Simulation/'
--- src/common_cpp/Simulation/    2015-11-16 10:57:06 +0000
+++ src/common_cpp/Simulation/    2016-03-22 13:23:06 +0000
@@ -289,9 +289,9 @@
   // close the geometry
-  G4RunManager::GetRunManager()->Initialize();  // makes a G4 segv
-  // std::cout << "Dumping new geometry" << std::endl;  // need verbose level 0
-  // G4RunManager::GetRunManager()->DumpRegion();
+  G4RunManager::GetRunManager()->Initialize();
+  // Ack! G4 does some setup at RunBeam time
+  G4RunManager::GetRunManager()->BeamOn(0);

 void DetectorConstruction::AddDaughter

I think this is okay, but will continue digging just in case there is something else.


Updated by Rogers, Chris over 6 years ago

Interestingly, the patch described in comment 7 does not work. The following patch does. Not sure why. I have not checked with valgrind:

=== modified file 'src/common_cpp/Simulation/'
--- src/common_cpp/Simulation/    2015-06-19 16:33:31 +0000
+++ src/common_cpp/Simulation/    2016-03-22 14:23:24 +0000
@@ -20,6 +20,7 @@

 #include <string>

+#include "Geant4/G4RunManager.hh" 
 #include "CLHEP/Units/SystemOfUnits.h" 
 #include "src/common_cpp/Utils/Exception.hh" 

@@ -63,6 +64,8 @@
     _navigator = new G4Navigator();
+  // Ack! G4 does some setup at BeamOn time
+  G4RunManager::GetRunManager()->BeamOn(0);
     this->_setPoint(G4ThreeVector(0.0, 0.0, 0.0));

Updated by Greis, Jan over 6 years ago

  • Assignee changed from Bayes, Ryan to Rogers, Chris

I'm afraid while it doesn't segfault anymore, G4RunManager::GetRunManager()->BeamOn(0); gets executed every time g4navigator->LocateGlobalPointAndSetup(posvector, &momvector); is called, i.e. at every step. It takes about 7 milliseconds to execute each time, which brings the propagation time between tracker and TOF0 to about 30 seconds... Any ideas?


Updated by Greis, Jan over 6 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

Also available in: Atom PDF