How to add in a geometry some volume from a gdml file and declare it sensitive

_Geant4 Version:_V11.3.1
_Operating System:_Linux Ubuntu 24LTS

Hi,
I want to add to an already existing geometry described by a constructor class, a volume from a gdml file
As an test case, i try to add a simple cube of water described by a gdml file

<?xml version="1.0" encoding="UTF-8"?>
<gdml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="http://cern.ch/Geant4/GDML/Schema/gdml.xsd">

  <define>
    <position name="cubePos" x="0" y="0" z="-10" unit="cm"/>
  </define>

  <materials>
    <element name="H" formula="H" Z="1">
      <atom unit="g/mole" value="1.00794"/>
    </element>
    <element name="O" formula="O" Z="8">
      <atom unit="g/mole" value="15.999"/>
    </element>

    <material name="Water" state="liquid">
      <D value="1.0" unit="g/cm3"/>
      <composite n="2" ref="H"/>
      <composite n="1" ref="O"/>
    </material>
  </materials>

  <solids>
    <box name="WaterCube" x="1" y="1" z="1" lunit="cm"/>
  </solids>

  <structure>
    <volume name="logicWaterCube">
      <materialref ref="Water"/>
      <solidref ref="WaterCube"/>
    </volume>

    <volume name="world">
      <materialref ref="G4_AIR"/>
      <solidref ref="WaterCube"/>
      <physvol>
        <volumeref ref="logicWaterCube"/>
        <positionref ref="cubePos"/>
      </physvol>
    </volume>
  </structure>

  <setup name="Default" version="1.0">
    <world ref="world"/>
  </setup>

</gdml>

here after are the detector.hh and .cc

#ifndef CONSTRUCTION_HH
#define CONSTRUCTION_HH

#include "G4VUserDetectorConstruction.hh"
#include "G4VPhysicalVolume.hh"
#include "G4LogicalVolume.hh"
#include "G4UnionSolid.hh"
#include "G4Box.hh"
#include "G4Tubs.hh"
#include "G4PVPlacement.hh"
#include "G4NistManager.hh"
#include "G4SDManager.hh"
#include "G4SystemOfUnits.hh"

#include "G4GenericMessenger.hh"
#include "detector.hh"

class MyDetectorMessenger;

class MyDetectorConstruction : public G4VUserDetectorConstruction{
    public:
        MyDetectorConstruction();
        ~MyDetectorConstruction();

        G4LogicalVolume *GetScoringVolume() const {return fScoringVolume;}

        virtual G4VPhysicalVolume *Construct();

        void SetGDML(const G4bool isGDML );
        G4bool GetGDML() const { return fisGDML; }

        void SetScintillator(const G4bool isScintillator );
        G4bool GetScintillator() const { return fisScintillator; }

        void SetPetriBox(const G4bool isPetriBox );
        G4bool GetPetriBox() const { return fisPetriBox; }

        void SetPosSource(const G4double PosSource );
        G4double GetPosSource() const { return fPosSource; }

        void SetLevelWater(const G4double LevelWater );
        G4double GetLevelWater() const { return fLevelWater; }

        void ConstructScintillator();
        void ConstructPetriBox();
        void ConstructGDML();


    private:
        G4Box *solidWorld,*solidRadiator,*solidDetector;
        G4Tubs *solidScintillator,*tubeCell,*solidWater;

        G4LogicalVolume *logicWorld,*logicRadiator,*logicDetector,*logicScintillator,*logicPetriBox;
        G4LogicalVolume *logicWater, *tubeCell_log, *gdmlVolume, *logicWaterCube;

        G4VPhysicalVolume *physWorld,*physRadiator,*physDetector,*physScintillator,*physPetriBox;
        G4VPhysicalVolume *tubeCell_phys, *physWater;

        G4Material *SiO2,*H2O,*worldMat,*Aerogel,*NaI, *C8H8;
        G4Element *C,*Na,*I;

        void DefineMaterial();
        virtual void ConstructSDandField();

        MyDetectorMessenger *fMessenger;

        G4LogicalVolume *fScoringVolume;

        G4double xWorld, yWorld, zWorld;

        G4bool fisScintillator, fisPetriBox, fisGDML;

        G4double fPosSource;
        G4double fLevelWater;
};
#endif
#include "construction.hh"

#include "G4NistManager.hh"
#include "G4RunManager.hh"
#include "G4SDManager.hh"

#include "G4VisAttributes.hh"
#include "G4Colour.hh"

#include "messenger.hh"

#include "G4SystemOfUnits.hh"

#include "G4GDMLParser.hh"
#include "G4Region.hh"

MyDetectorConstruction::MyDetectorConstruction()
{
        fLevelWater = 2.5*mm;

        fisScintillator = false;
        fisPetriBox     = false;
        fisGDML         = true;

        fMessenger = new MyDetectorMessenger(this);

        DefineMaterial();

        xWorld = 0.5*m;
        yWorld = 0.5*m;
        zWorld = 0.5*m;
}

MyDetectorConstruction::~MyDetectorConstruction()
{
       delete fMessenger ;
}

void MyDetectorConstruction::SetScintillator(const G4bool isScintillator ){
        fisScintillator   = isScintillator;
        G4RunManager::GetRunManager()->ReinitializeGeometry();
}

void MyDetectorConstruction::SetPetriBox(const G4bool isPetriBox ){
        fisPetriBox   = isPetriBox;
        G4RunManager::GetRunManager()->ReinitializeGeometry();
}

void MyDetectorConstruction::SetGDML(const G4bool isGDML ){
        fisGDML   = isGDML;
        G4RunManager::GetRunManager()->ReinitializeGeometry();
}

void MyDetectorConstruction::SetPosSource(const G4double PosSource ){
        fPosSource  = PosSource;
        G4RunManager::GetRunManager()->ReinitializeGeometry();
}

void MyDetectorConstruction::SetLevelWater(const G4double LevelWater ){
        fLevelWater  = LevelWater;
        G4RunManager::GetRunManager()->ReinitializeGeometry();
}


void MyDetectorConstruction::DefineMaterial()
{
        G4NistManager *nist = G4NistManager::Instance();

        H2O = new G4Material("H2O", 1.0000*g/cm3, 2);
        H2O->AddElement(nist->FindOrBuildElement("H"),2);
        H2O->AddElement(nist->FindOrBuildElement("O"),1);

        worldMat = nist ->FindOrBuildMaterial("G4_AIR");

        G4double energy[2] {1.239841939*eV/0.9, 1.239841939*eV/0.2};

        G4double rindexWorld[2] {1.0, 1.0};

        G4MaterialPropertiesTable *mptWorld = new G4MaterialPropertiesTable();
        mptWorld->AddProperty("RINDEX", energy, rindexWorld, 2);

        worldMat->SetMaterialPropertiesTable(mptWorld);

        Na = nist->FindOrBuildElement("Na");
        I  = nist->FindOrBuildElement("I");
        NaI = new G4Material("NaI",3.67*g/cm3,2);
        NaI->AddElement(Na,1);
        NaI->AddElement(I,1);

        C8H8 = nist->FindOrBuildMaterial("G4_POLYSTYRENE");
        H2O  = nist->FindOrBuildMaterial("G4_WATER");

}

void MyDetectorConstruction::ConstructPetriBox()
{
        G4double petribottomfaceRmin = 0*mm;
        G4double petribottomfaceRmax = 25*mm;
        G4double petribottomfaceDz   = 0.5*mm;

        G4double petrisidefaceRmin = 24*mm;
        G4double petrisidefaceRmax = 25*mm;
        G4double petrisidefaceDz   = 7.5*mm;

        G4double PosPetriBox = 10*mm;

        G4Tubs* petribottomface = new G4Tubs("PetriBottomFace",petribottomfaceRmin,petribottomfaceRmax,petribottomfaceDz,0*deg,360*deg);
        G4Tubs* petrisideface   = new G4Tubs("PetriSideFace",petrisidefaceRmin,petrisidefaceRmax,petrisidefaceDz,0*deg,360*deg);

        G4ThreeVector zTrans(0,0,petribottomfaceDz+petrisidefaceDz);

        G4UnionSolid* solidPetriBoxMoved  = new G4UnionSolid("PetriBottomFace+PetriSideFaceMoved",petribottomface,petrisideface,0,zTrans);

        logicPetriBox = new G4LogicalVolume(solidPetriBoxMoved,C8H8,"logicPetriBox");

        physPetriBox = new G4PVPlacement(0,G4ThreeVector(0.,0.,PosPetriBox),logicPetriBox,"physPetriBox",logicWorld,false,0,true);

        G4VisAttributes *PetriBoxAtt = new G4VisAttributes(G4Colour(0.,0.,1.));
        PetriBoxAtt->SetForceWireframe(true);
        logicPetriBox->SetVisAttributes(PetriBoxAtt);

        G4double CellRmin = 0*mm;
        G4double CellRmax = 24*mm;
        G4double CellDz = 0.5*mm;

        G4cout<<"    CellRmin  =  "<<CellRmin<<"   CellRmax  =  "<<CellRmax<<G4endl;

        G4double PosTubeCell = PosPetriBox  + CellDz;

        G4cout<<"    PosPetriBox  =  "<<PosPetriBox<<"   PosTubeCell  =  "<<PosTubeCell<<G4endl;

        tubeCell = new G4Tubs("TubeCell",CellRmin,CellRmax,CellDz,0*deg,360*deg);

        tubeCell_log  = new G4LogicalVolume(tubeCell,H2O,"logicTubeCell",0,0,0);

        tubeCell_phys = new G4PVPlacement(0,G4ThreeVector(0.,0.,PosTubeCell),tubeCell_log,"physTubeCell",logicWorld,false,0,true);

        G4VisAttributes *TubeCellAtt = new G4VisAttributes(G4Colour(1.,1.,0.));
        TubeCellAtt->SetForceSolid(true);
        tubeCell_log->SetVisAttributes(TubeCellAtt);

        G4double PosTubeWater = PosTubeCell + CellDz + fLevelWater;

        solidWater = new G4Tubs("solidWater",CellRmin,CellRmax,fLevelWater,0*deg,360*deg);
        logicWater = new G4LogicalVolume(solidWater,H2O,"logicalWater",0,0,0);
        physWater  = new G4PVPlacement(0,G4ThreeVector(0.,0.,PosTubeWater),logicWater,"physWater",logicWorld,false,0,true);

        G4VisAttributes *TubeWaterAtt = new G4VisAttributes(G4Colour(1.,0.,0.));
        TubeWaterAtt->SetForceSolid(true);
        logicWater->SetVisAttributes(TubeWaterAtt);



        G4cout<<"LevelWater  =  "<<fLevelWater<<"PosTubeWater  =  "<<PosTubeWater<<G4endl;

}

void MyDetectorConstruction::ConstructScintillator()
{
        solidScintillator = new G4Tubs("solidScintillator",10*cm,20*cm,30*cm,0*deg,360*deg);
        logicScintillator = new G4LogicalVolume(solidScintillator,NaI,"logicalScintillator");

        fScoringVolume = logicScintillator;

        physScintillator = new G4PVPlacement(0,G4ThreeVector(0.,0.,0.),logicScintillator,
                                            "physScintillator",logicWorld,false,0,true);
}

void MyDetectorConstruction::ConstructGDML()
{
        // Chargement du Parser
        G4GDMLParser parser;
        parser.Read("geometry_1.gdml", false); // false -> pour ne pas valider le schema

        // Récupération du volume monde
        G4VPhysicalVolume* importedWorld = parser.GetWorldVolume();
        if (!importedWorld) {
                G4Exception("MyDetectorConstruction::ConstructGDML", "GDML02", FatalException,
                            "Le volume monde du fichier GDML est introuvable.");
        }

        // Récupération du volume logique d'intérêt (ex: logicWater)
        G4LogicalVolume* logicWaterCube = parser.GetVolume("logicWaterCube");
        if (!logicWaterCube) {
                G4Exception("MyDetectorConstruction::ConstructGDML", "GDML01", FatalException,
                            "Volume logicWaterCube non trouvé dans le fichier GDML.");
        }

        G4cout<<" *********************************** Test logicWorld ****************************************"<<G4endl;


        if (!logicWorld) {
                G4cout<<"ERREUR "<<" logicWorld "<<G4endl;
        }
        else
                G4cout<<" logicWorld definie"<<G4endl;

        G4cout<<" *************************************Test logicWaterCube ***************************************"<<G4endl;

        if (!logicWaterCube) {
                G4cout<<"ERREUR "<<" gdmlVolume "<<G4endl;
        }
        else
                G4cout<<" gdmlVolume definie"<<G4endl;


        // Positionner ce volume dans la géométrie existante (ex: dans logicWorld)
        new G4PVPlacement(nullptr,                      // pas de rotation
                          G4ThreeVector(0,0,-20*cm),    // position (exemple)
        logicWaterCube,                   // volume logique GDML
        "physFromGDML",               // nom physique
        logicWorld,                   // volume parent
        false,                        // pas de multiple placements
        0,                            // copy number
        true);                        // check overlaps

        // Optionnel : couleur pour visualisation
        G4VisAttributes* visAttr = new G4VisAttributes(G4Colour(1, 0, 0));
        visAttr->SetVisibility(true);
        visAttr->SetForceSolid(true);
        logicWaterCube->SetVisAttributes(visAttr);
}


G4VPhysicalVolume *MyDetectorConstruction::Construct()
{
        solidWorld = new G4Box("solidWorld", xWorld, yWorld, zWorld);
        logicWorld = new G4LogicalVolume(solidWorld, worldMat, "logicWorld");
        physWorld = new G4PVPlacement(0, G4ThreeVector(0.,0.,0.),logicWorld,"physWord",0,false,0,true);

        if(fisScintillator)
        {
                ConstructScintillator();
                G4cout << "Construction Scintillator" << G4endl;
        }

        if(fisPetriBox)
        {
                ConstructPetriBox();
                G4cout << "Construction PetriBox" << G4endl;
        }

        if(fisGDML)
        {
                ConstructGDML();
                G4cout << "Construction GDML" << G4endl;
        }


        return physWorld;
}

void MyDetectorConstruction::ConstructSDandField()
{

        // Recupere le SDManager
        G4SDManager*  sdManager = G4SDManager::GetSDMpointer();

        // Création d'une instance du Sensitive logicDetector
        auto sd = new MySensitiveDetector("MySD","MyHitsCollection");
        G4SDManager::GetSDMpointer()->AddNewDetector(sd);

        // Attachement conditionnel si GDML est actif
        if (fisGDML && logicWaterCube) {
                G4cout<<" ************************************* GDML Sensible ***************************************"<<G4endl;
                logicWaterCube->SetSensitiveDetector(sd);
        }

        // Autres cas : boîte de Petri, scintillateur, etc.
        if (fisPetriBox && tubeCell_log) {
                G4cout<<" ************************************* Petri Box Sensible ***************************************"<<G4endl;
                tubeCell_log->SetSensitiveDetector(sd);
        }

        if (fisScintillator && logicScintillator) {
                G4cout<<" ************************************* Scintillator Sensible ***************************************"<<G4endl;
                logicScintillator->SetSensitiveDetector(sd);
        }

}

i extract the logicWterCube and place it in my geometry using G4Vplacement…OK

Then i want to declare it sensitive using the following line in my construction

// Attachement conditionnel si GDML est actif
if (fisGDML && logicWaterCube) {
        G4cout<<" ************************************* GDML Sensible ***************************************"<<G4endl;
        logicWaterCube->SetSensitiveDetector(sd);
}

when i use the G4V11.2.2 it’s OK
but i need for other part of the project to go to G4V11.3.1

for the program (same lines to attach the gdml solid to sd) i have a segmentation fault now

i looked on the forum and see taht we can use additional auxiliarly conditions in gdml to declare sensitive some volume but these operative way was already in use for G4V11.2.2

does some body have infos that can help me

Dear @montarou,

Thank you for your post!

You might find this well-structured example helpful, I think it show the kind of implementation you’re looking for [1].

I hope this helps. If you have any further questions, feel free to ask!

Best,
Alvaro
[1] HGCALTB/src/HGCALTBDetConstruction.cc at d8d6a571f037070d6f8166cdb67bacad04b7cfb3 · geant-val/HGCALTB · GitHub

thank’s a lot for the infos…i ll look on it carefully