Best practice for material initialization in 3D voxelized geometries using G4VPVParameterisation

Hi everyone,

I am working on a 3D voxelized geometry where I use G4VPVParameterisation to manage a large number of voxels. Each voxel can have a different material assigned dynamically via the ComputeMaterial() method.

I am facing an issue with material initialization. Even though I define all possible materials using G4NistManager::FindOrBuildMaterial() during the detector construction, I get a Segmentation Fault (specifically a Zero Page Read in PostStepGetPhysicalInteractionLength) when the particle enters a voxel.

It seems that if a material is not explicitly attached to a “static” G4LogicalVolume during the setup, Geant4 does not fully initialize its internal physics tables, leading to the crash when the navigator requested it.

As a workaround, I created a dummy “tiny volume” placed far away where I place all my materials, but this feels like a “dirty” solution.

My questions are:

  1. Is there a standard way to force the initialization of all materials in the physics tables without creating dummy volumes?

  2. Should I be storing the pointers in a specific way within the DetectorConstruction to ensure they are persistent and initialized?

  3. Is there a specific method I should call after building the materials to “register” them for the physics processes?

Thanks in advance for your help!

G4Region has an AddMaterials method and I think that would avoid having to create a dummy tiny volume. I am not sure if that is the canon answer but it would not violate the principle of least surprise if someone else looked at your code. G4Region tends to be an abstract way to link volumes with very different materials in a unified way. Much like your parameterisation.

I think it needs to be done in your Construct() method to avoid threading issues if you are running MT mode.

You can refer to example ICRP145phantom from extended example.

Hello,

I’m using mostly G4VNestedParameterisation, but believe anchestor G4VPVParameterisation should be the same. The idea is that that “fake tiny volumes for materials” from the user perspective is exactly the two other functions ..::GetMaterial() and ..::GetNumberOfMaterials() must be defined for, where you list once and only once all the materials you’re using. These methods are automatically called. So,

  1. define materials first from DetectorConstruction before the same way (FindOrBuildMaterial, BuildMaterialWithNewDensity from G4NistManager), that’s needed

  2. push or bypass that list directly (I’m using explicit std::vector<G4Material*>) to the constructor of you parameterisation class and just return it in the GetMaterial and the length of that vector in GetNumberOfMaterials, the order is no matter actually, just be sure, that you have all of them. It’s like list of uniques.

  3. and only after that make your ComputeMaterials returning the needed material from the actual list which is dependent on you actual geometry.

I can check it also in a straightforward way: put smth like G4cout in the GetMaterial (not ComputeMaterial), and add like /tracking/verbose 2 or higher in your .mac or by UImanager and just purely chech if the material that you crashed on is really listed in the GetMaterial list. I always got crashes by that fact only and usually it was lead by that I put my inconsistent inputs after standalone parsers or manually edited once, where the geometry-based table for compute materials had an update, but explicit list for GetMaterial don’t or the GetNumberOfMaterials somehow returning lower number that the actual size of that vector.

Thnaks a lot !! I’ll try your ideas !!