Check duplicate issues.
Description
I think we've hit a bug in TGeoManager::Import of GDML (geom/gdml, TGDMLParse).
When a GDML file contains an <element> and a <material>
whose names are identical after TGDMLParse::NameShort() strips the 0x…
pointer suffix (e.g. element Iron0xaaa and material Iron0xccc), every
<fraction> referencing that element is silently dropped on import: a pure
material referencing it imports as a TGeoMixture with zero elements,
and multi-element mixtures lose that component (remaining weights left
unnormalised). No warning or error is emitted.
This naming pattern is produced routinely by Geant4's G4GDMLParser::Write,
since pure-metal G4Materials are conventionally named after their element
(Iron, Copper, Tungsten, …) and the writer appends pointer suffixes to both.
A simple reproducer below. In the reproducer, renaming only the material (Iron0xccc → IronBlock0xccc)
makes everything import correctly (Iron: [FE], Alloy: [FE 0.5, NI 0.5]).
The element form is irrelevant (reproduces with both isotope-composed and
simple <atom> elements).
Expected behaviour: the element reference should resolve to the element regardless
of a like-named material — or at minimum the import should fail loudly
instead of silently producing element-less materials.
Impact: a Geant4-exported detector geometry imported into TGeo lost Fe,
W, Ta, Cu, Si and Pb entirely (element-less materials, mangled alloys).
Downstream consumers deriving physics from material composition (in our
case the GENIE event generator's ROOTGeomAnalyzer target list) silently
produce wrong physics — for SHiP the neutrino target and muon shield became
invisible as interaction targets.
Suspected cause: the per-type name maps in TGDMLParse are keyed by the
NameShort()-stripped string; the fraction-reference resolution in the
material/mixture handling apparently consults a map where the material entry
shadows the element entry (or inserts a null placeholder via the
TGDMAssignmentHelper on first miss).
Reproducer
import ROOT
geo = ROOT.TGeoManager.Import("collide.gdml")
for m in geo.GetListOfMaterials():
print(m.GetName(), m.GetNelements(),
[m.GetElement(i).GetName() for i in range(m.GetNelements())])
# Iron 0 [] <- expected 1 element (FE)
# Alloy 1 ['NI'] (weight 0.5) <- expected FE 0.5 + NI 0.5
with collide.gdml:
<?xml version="1.0"?>
<gdml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<define/>
<materials>
<element Z="26" formula="FE" name="Iron0xaaa"><atom unit="g/mole" value="55.845"/></element>
<element Z="28" formula="NI" name="Nickel0xbbb"><atom unit="g/mole" value="58.693"/></element>
<material name="Iron0xccc" state="solid"> <!-- name collides with the element -->
<D unit="g/cm3" value="7.87"/><fraction n="1" ref="Iron0xaaa"/>
</material>
<material name="Alloy0xddd" state="solid">
<D unit="g/cm3" value="8.2"/>
<fraction n="0.5" ref="Iron0xaaa"/><fraction n="0.5" ref="Nickel0xbbb"/>
</material>
</materials>
<solids>
<box lunit="mm" name="world0x1a" x="1000" y="1000" z="1000"/>
<box lunit="mm" name="cube0x1b" x="100" y="100" z="100"/>
</solids>
<structure>
<volume name="ironVol0x2a"><materialref ref="Iron0xccc"/><solidref ref="cube0x1b"/></volume>
<volume name="World0x2c"><materialref ref="Alloy0xddd"/><solidref ref="world0x1a"/>
<physvol name="ironPV"><volumeref ref="ironVol0x2a"/></physvol></volume>
</structure>
<setup name="Default" version="1.0"><world ref="World0x2c"/></setup>
</gdml>
ROOT version
ROOT 6.40.02
Installation method
conda-forge
Operating system
Linux, distribution independent (conda-forge toolchain/env)
Additional context
No response
Check duplicate issues.
Description
I think we've hit a bug in
TGeoManager::Importof GDML (geom/gdml,TGDMLParse).When a GDML file contains an
<element>and a<material>whose names are identical after
TGDMLParse::NameShort()strips the0x…pointer suffix (e.g. element
Iron0xaaaand materialIron0xccc), every<fraction>referencing that element is silently dropped on import: a purematerial referencing it imports as a
TGeoMixturewith zero elements,and multi-element mixtures lose that component (remaining weights left
unnormalised). No warning or error is emitted.
This naming pattern is produced routinely by Geant4's
G4GDMLParser::Write,since pure-metal
G4Materials are conventionally named after their element(Iron, Copper, Tungsten, …) and the writer appends pointer suffixes to both.
A simple reproducer below. In the reproducer, renaming only the material (
Iron0xccc→IronBlock0xccc)makes everything import correctly (
Iron: [FE],Alloy: [FE 0.5, NI 0.5]).The element form is irrelevant (reproduces with both isotope-composed and
simple
<atom>elements).Expected behaviour: the element reference should resolve to the element regardless
of a like-named material — or at minimum the import should fail loudly
instead of silently producing element-less materials.
Impact: a Geant4-exported detector geometry imported into TGeo lost Fe,
W, Ta, Cu, Si and Pb entirely (element-less materials, mangled alloys).
Downstream consumers deriving physics from material composition (in our
case the GENIE event generator's
ROOTGeomAnalyzertarget list) silentlyproduce wrong physics — for SHiP the neutrino target and muon shield became
invisible as interaction targets.
Suspected cause: the per-type name maps in
TGDMLParseare keyed by theNameShort()-stripped string; the fraction-reference resolution in thematerial/mixture handling apparently consults a map where the material entry
shadows the element entry (or inserts a null placeholder via the
TGDMAssignmentHelperon first miss).Reproducer
with collide.gdml:
ROOT version
ROOT 6.40.02
Installation method
conda-forge
Operating system
Linux, distribution independent (conda-forge toolchain/env)
Additional context
No response