Volume Names for Daughter Volumes in GDML Export

Hello all-

I am working with the geometry library to produce a detector model that I would like to export in GDML format for simulation in Geant4. I have a couple of questions about the GDML output and the geometry definition. I’m using ROOT 6.04/00.

At the end of this message is a short (but complete) function that produces output illustrating my questions.

This code attempts to create a silicon solid state detector that has a single active detector pixel embedded into a larger silicon crystal. If I have understood the documentation in TGeoVolume correctly (https://root.cern.ch/root/html/TGeoVolume.html), declaring the active volume and adding it as a daughter of the crystal volume is acceptable and will not create an overlapping volume problem. This should effectively create a single piece of silicon with two regions that I can look at separately: the pixel region and the framing region around it. Ultimately I will want to retrieve the amount of energy deposited in each region by simulated events.

My first question is, is my understanding about placing daughter volumes correct?

Second, when I do this, the resulting GDML file does not name the any of the physvols. When Geant loads this it gives a default name of _PV. This is okay, but creates confusion if I use multiple instances of a logical volume, for example if I wanted to create multiple pixels of the same shape inside the parent silicon volume. I could go through the GDML file and manually name every daughter volume, but I’m wondering if there is a better way. There is additional confusion if I create multiple instances of the parent volume as now any name assigned to the daughter volumes would be replicated!

The alternative is to have a completely flat description in which every volume is independently added to the top volume. To do this I would also have to create cutouts of the pixel volumes in the parent silicon.

I would appreciate any advice/tips/suggestions/insights/better ways that anyone might be able to offer.
Thank you,

TGeoVolume * minEx(void){
	// load and initialize the geometry library
	new TGeoManager("world", "simulation world");

	// define materials
	TGeoElementTable * etbl = gGeoManager->GetElementTable();              
	TGeoMaterial * vac_mat = new TGeoMaterial("Vacuum",       1,  1, 1.0e-25);
	TGeoMaterial *  si_mat = new TGeoMaterial("Silicon",  etbl->FindElement("Silicon"),   2.33);
	TGeoMedium *    Vacuum = new TGeoMedium("Vacuum",    1, vac_mat);	
	TGeoMedium *   Silicon = new TGeoMedium("Silicon",   1, si_mat);

	// create the world
	TGeoVolume * top = gGeoManager->MakeBox("Top_s", Vacuum, 10., 10., 10.);

	// detector parameters
	double D4_th(0.015); // thickness of silicon detector
	double D4_w(0.7);   // width of pixel active area
	double D4_h(1.12);  // height of pixel active area
	double D4_ws(1.1);  // width of silicon crystal
	double D4_hs(1.52); // width of silicon crystal

	// define the detector solids
	// TGeoBBox                               name               dx/2        dy/2        dz/2
	TGeoBBox *      D4Active_s = new TGeoBBox("D4Active_s",      D4_th/2,    D4_w/2,     D4_h/2);
	TGeoBBox * D4SiliconMain_s = new TGeoBBox("D4SiliconMain_s", D4_th/2,    D4_ws/2,    D4_hs/2);
	// define the logical volumes
	TGeoVolume *   D4Active = new TGeoVolume("D4Active",   D4Active_s,      Silicon);
	TGeoVolume * D4Detector = new TGeoVolume("D4Detector", D4SiliconMain_s, Silicon);

	// add the active region to the main detector crystal
	D4Detector->AddNode(D4Active, 1);

	// add the detector to the world
	top->AddNode(D4Detector, 1);
	// close up the geometry
	// export the geometry to GDML
	// return the world volume
	return top;

Partial GDML output:

    <volume name="D4Active">
      <materialref ref="Silicon"/>
      <solidref ref="D4Active_s"/>
    <volume name="D4Detector">
      <materialref ref="Silicon"/>
      <solidref ref="D4SiliconMain_s"/>
        <volumeref ref="D4Active"/>
        <positionref ref="D4Active_1inD4Detectorpos"/>
    <volume name="Top">
      <materialref ref="Vacuum"/>
      <solidref ref="Top_s"/>
        <volumeref ref="D4Detector"/>
        <positionref ref="D4Detector_1inToppos"/>
1 Like

Hi, please see below:

[quote]My first question is, is my understanding about placing daughter volumes correct?
Yes, this is correct

Indeed, root is not generating physical volumes with names, but this should not pose problems unless you want to use the name to uniquely identify the volume (which can be expensive). Instead you should use in Geant4 the function GetCopyNo() of G4VPhysicalVolume which should return you a unique number within the same mother logical volume. So if you put several of your pixels, this should return you 0,1,2, …, allowing you to identify them at tracking time.

[quote][The alternative is to have a completely flat description in which every volume is independently added to the top volume. To do this I would also have to create cutouts of the pixel volumes in the parent silicon./quote]
Not adviseable, it will hurt performance and make the code difficult to read.


Thanks Andrei for your reply. I appreciate your response particularly since this is a ROOT forum and not really a Geant forum!

If I understand what you’ve written correctly, I should be able uniquely identify each physical instance with the copy number that I specify when I call AddNode (in ROOT) to add a daughter volume to the mother. That makes sense to me. If I then wanted to create multiple instances of the mother volume, then I would have a unique pair of copy numbers, one for the mother and one for the pixel within the mother, to identify a given pixel.

One follow up question, I don’t see the copy number in the GDML output (actually, I do see it in the names of the associated positions and rotations, but not in the volume names or definitions). So, is it correct to assume that Geant will regenerate these copy numbers when it processes the GDML file?


Hi Chad,

I would expect Geant4 gdml parser to add a copy number to physical volumes when adding them to logical ones, otherwise we have a problem… However I would not expect these numbers to match the copy numbers you define in ROOT. Well, I’m not even sure gdml schema allows for defining copy numbers. I’m maintaining the geometry package in root but I’m not the author (or an expert) of the gdml writer, so I’m just guessing here. I suggest that you try the generated G4 structure and check the copy number values. If you get just zeros then we need to fix this…


I will try to test this out in the coming week and will report back.

I’ve finally had a chance to check this out. I’m still working to make sure that I haven’t made a mistake in my coding, but my test just shows 0’s for the copy number. Admittedly, I’m using Geant 9.6.2 which is not the most recent version (I am using this version for compatibility with colleagues).

I’ll describe my experiment a little bit. I have a GDML file with the following structure section. It’s basically one piece of silicon with two pixels embedded in it. Both pixels are defined by the same logical volume.

    <volume name="D1Active">
      <materialref ref="Silicon"/>
      <solidref ref="D1Active_s"/>
    <volume name="D1Silicon">
      <materialref ref="Silicon"/>
      <solidref ref="D1SiliconMain_s"/>
        <volumeref ref="D1Active"/>
        <positionref ref="D1Active_0inD1Siliconpos"/>
        <rotationref ref="D1Active_0inD1Siliconrot"/>
        <volumeref ref="D1Active"/>
        <positionref ref="D1Active_1inD1Siliconpos"/>
        <rotationref ref="D1Active_1inD1Siliconrot"/>
    <volume name="Top">
      <materialref ref="Vacuum"/>
      <solidref ref="Top_s"/>
        <volumeref ref="D1Silicon"/>
        <positionref ref="D1Silicon_1inToppos"/>

After loading the geometry into geant, I have the following function which gets the volume store, and then loops through it printing out the name and copy number of each physical volume:

void GRASGeometryUtil::ListPhysicalVolumes()
  G4PhysicalVolumeStore* store = G4PhysicalVolumeStore::GetInstance();
  if (store==0) {
    G4cout << "[GRASGeometryUtil::ListPhysicalVolumes] G4PhysicalVolumeStore not accessible"<< G4endl;
  unsigned int length = store->size();
  G4cout << "[GRASGeometryUtil::ListPhysicalVolumes]: " << length << " volumes in the store" << G4endl;
  for (unsigned int iVol = 0; iVol < length; iVol++) {
    G4String volName = ((*store)[iVol])->GetName();
	G4int copyNo = ((*store)[iVol])->GetCopyNo();
    G4cout << "   Volume <" << volName << ":" << copyNo << ">";
    G4cout << G4endl;

The previous function produces the following output. You can see that the copy number for both instances of D1Active_PV are given as 0.

[GRASGeometryUtil::ListPhysicalVolumes]: 4 volumes in the store
Volume <D1Active_PV:0>
Volume <D1Active_PV:0>
Volume <D1Silicon_PV:0>
Volume <Top_PV:0>

Is it possible that this has been addressed in a more recent version of Geant?

Since this appears to be more of a Geant question now than a root question, should we perhaps move this discussion to another forum? I will mark the thread as solved since my initial ROOT related question has been answered.

Thanks again for your input on this.

Thanks Chad for looking into this. Your test looks fine. Yes, this is more a Geant4 question on how to input copy numbers via GDML, so you can surely ask it in a G4 forum. I will also investigate on my side.


Dear Chad, here is the follow-up on this:

I discussed the issue with Witold Pokorski who maintains the GDML package, and he implemented support for replicas in both Geant4 GDML reader and writer. This change was approved and will be available in the next G4 patch release (which I don’t know when it will get out). On my side, I just commited to the Root master the same support (both for node names and copy numbers) in the GDML import/export of TGeoManager. So the feature is now complete.