How to modify a geometry using messengers in interactive mode

_Geant4 Version: V11.2.2
_Operating System Ubuntu 24.04 LTS

I would like to modify the geometry of my detector using commands in interactive mode. These commands are defined by messengers.

The modifications are:

  1. either to change the number of rows or columns in a detector matrix
  2. or to choose between two types of sub-detectors

In the first case, I defined two commands in the constructor to define two variables (double): nCols and nRows

In the second case, I defined two commands to define two Boolean variables to initiate the construction of one or two options: isCherenkov (false by default), isScintillator (false by default).

When I use these commands, the variable changes are correctly taken into account in the code.

However, I can’t visualize the geometry after the commands.

Once the geometry of the detector is modified using messengers commands as

/detector/Cherenkov true

/detector/nRow 20

i run the following sequence of commands,

/run/reinitialyseGeometry
/run/initialize

but nothing happens…

i try also following sequences

/run/reinitialyseGeometry
/vis/scene/notifyHandler
/run/initialize

Hereafter the main

#include <iostream>

#include "G4RunManager.hh"
#include "G4MTRunManager.hh"
#include "G4UImanager.hh"
#include "G4VisManager.hh"
#include "G4VisExecutive.hh"
#include "G4UIExecutive.hh"

#include "construction.hh"
#include "physics.hh"
#include "action.hh"

int main(int argc, char** argv)
{

    G4UIExecutive *ui = 0;

    #ifdef G4MULTITHREADED
      G4MTRunManager *runManager = new G4MTRunManager();
    #else
      G4RunManager *runManager = new G4RunManager();
    #endif

    runManager->SetUserInitialization(new MyDetectorConstruction());
    runManager->SetUserInitialization(new MyPhysicsList());
    runManager->SetUserInitialization(new MyActionInitialization());

    G4cout << "argc = " <<  argc <<  G4endl;


    if(argc == 1)
    {
        ui = new G4UIExecutive(argc,argv);
        G4cout << "path #1" <<  G4endl;
    }

    G4VisManager *visManager = new G4VisExecutive();
    visManager->Initialize();

    G4UImanager *UImanager = G4UImanager::GetUIpointer();

    if(ui)
    {
        G4cout << "path #2" <<  G4endl;
        UImanager->ApplyCommand("/control/execute vis.mac");
        ui->SessionStart();

    }
    else
    {
        G4cout << "path #2" <<  G4endl;
        G4String command = "/control/execute ";
        G4String fileName = argv[1];
        UImanager->ApplyCommand(command+fileName);

    }

    return 0;
}

the detector construction

#include "construction.hh"

MyDetectorConstruction::MyDetectorConstruction()
{

        nCols = 10;
        nRows = 10;

        fMessenger = new G4GenericMessenger(this, "/detector/", "Detector Construction");

        fMessenger->DeclareProperty("nCols",nCols, "Number of columns");
        fMessenger->DeclareProperty("nRows",nRows, "Number of rows");
        fMessenger->DeclareProperty("Cherenkov",isCherenkov, "Toogle Cherenkov Setup");
        fMessenger->DeclareProperty("Scintillator",isScintillator, "Toogle Scintillator Setup");

        DefineMaterial();

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

        isCherenkov = false;
        isScintillator = false;
}

MyDetectorConstruction::~MyDetectorConstruction()
{}

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

        SiO2 = new G4Material("SiO2", 2.201*g/cm3, 2);
        SiO2->AddElement(nist->FindOrBuildElement("Si"),1);
        SiO2->AddElement(nist->FindOrBuildElement("O"),2);

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

        C = nist->FindOrBuildElement("C");

        Aerogel = new G4Material("Aerogel", 0.200*g/cm3, 3);
        Aerogel->AddMaterial(SiO2, 62.5*perCent);
        Aerogel->AddMaterial(H2O, 37.4*perCent);
        Aerogel->AddElement(C, 0.1*perCent);

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

        G4double energy[2] {1.239841939*eV/0.9, 1.239841939*eV/0.2};
        G4double rindexAerogel[2] {1.1, 1.1};
        G4double rindexWorld[2] {1.0, 1.0};

        G4MaterialPropertiesTable *mptAerogel = new G4MaterialPropertiesTable();
        mptAerogel->AddProperty("RINDEX", energy, rindexAerogel, 2);

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

        Aerogel->SetMaterialPropertiesTable(mptAerogel);

        worldMat->SetMaterialPropertiesTable(mptWorld);
}


void MyDetectorConstruction::ConstructCherenkov()
{
        solidRadiator = new G4Box("solidRadiator", 0.4*m, 0.4*m, 0.01*m);
        logicRadiator = new G4LogicalVolume(solidRadiator,Aerogel,"logicalRadiator");

        fScoringVolume = logicRadiator;

        physRadiator = new G4PVPlacement(0, G4ThreeVector(0., 0., 0.25*m), logicRadiator, "physRadiator", logicWorld, false, 0, true);

        solidDetector = new G4Box("solidDetector", xWorld/nRows, yWorld/nCols, 0.01*m);

        logicDetector = new G4LogicalVolume(solidDetector, worldMat, "logicDetector");

        G4cout<<"nCols"<<nCols<<"nRows" <<nRows<< G4endl;

        for(G4int i = 0; i < nRows; i++)
        {
                for(G4int j = 0; j < nCols; j++)
                {
                        physDetector = new G4PVPlacement(0,G4ThreeVector(-0.5*m+(i+0.5)*m/nRows,
                                                                         -0.5*m+(j+0.5)*m/nCols, 0.49*m),
                                                         logicDetector, "physDetector", logicWorld, false,
                                                         j+i*nCols, true);

                        G4double xx =-0.5*m+(i+0.5)*m/nRows;
                        G4double yy =-0.5*m+(j+0.5)*m/nCols;
                        G4double zz =0.49*m;




                        G4cout << "Capteur " << " i = " << i << " j = " << j << "  Capteur Position : " << " x =" << xx << " y = " << yy << " z = " << zz << G4endl;
                }
        }
}

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);

        G4cout << "Construction Cherenkov 1" << G4endl;

        if(isCherenkov)
        {
                ConstructCherenkov();
                G4cout << "Construction Cherenkov 2" << G4endl;
        }



        return physWorld;
}

void MyDetectorConstruction::ConstructSDandField()
{

        MySensitiveDetector *sensDet = new MySensitiveDetector("SensitiveDetector");
        if(isCherenkov)
                logicDetector->SetSensitiveDetector(sensDet);

        G4cout << "isCherenkov " <<  isCherenkov <<  G4endl;
}

the definition of the sensitive volume

#include "detector.hh"

MySensitiveDetector::MySensitiveDetector(G4String name) :
G4VSensitiveDetector(name)
{
    quEff = new G4PhysicsOrderedFreeVector();

    std::ifstream datafile;
    datafile.open("eff.dat");

    while(1)
    {
        G4double wlen, queff;
        datafile >> wlen >> queff;

        if(datafile.eof())
            break;

        G4cout << wlen << " " << queff << G4endl;
        quEff->InsertValues(wlen, queff/100.);
    }

    datafile.close();

    //quEff->SetSpline(false);

}

MySensitiveDetector::~MySensitiveDetector()
{}

G4bool MySensitiveDetector::ProcessHits(G4Step *aStep,
                                G4TouchableHistory *ROhist)
{
    G4Track *track = aStep->GetTrack();


    track->SetTrackStatus(fStopAndKill);

    G4StepPoint *preStepPoint  = aStep->GetPreStepPoint();
    G4StepPoint *postStepPoint = aStep->GetPostStepPoint();

    G4ThreeVector posPhoton = preStepPoint->GetPosition();
    G4ThreeVector momPhoton = preStepPoint->GetMomentum();

    G4double wlen = (1.239841939*eV/momPhoton.mag())*1E+03;

    //G4cout << "Photon position: " << posPhoton << G4endl;

    const G4VTouchable *touchable = aStep->GetPreStepPoint()->GetTouchable();

    G4int copyNo = touchable->GetCopyNumber();
    //G4cout << "Copy number: " << copyNo << G4endl;

    G4VPhysicalVolume *physVol = touchable->GetVolume();
    G4ThreeVector posDetector = physVol->GetTranslation();

    //#ifndef G4MULTITHREATED
    //G4cout << "Detector position: " << posDetector << G4endl;
    //#endif


    G4int evt = G4RunManager::GetRunManager()->GetCurrentEvent()->GetEventID();

    G4cout << "Event Number: " << evt << G4endl;


    G4AnalysisManager *man = G4AnalysisManager::Instance();

    man->FillNtupleIColumn(0,0,evt);
    man->FillNtupleDColumn(0,1,posPhoton[0]);
    man->FillNtupleDColumn(0,2,posPhoton[1]);
    man->FillNtupleDColumn(0,3,posPhoton[2]);
    man->FillNtupleDColumn(0,4,wlen);
    man->AddNtupleRow(0);

    if(G4UniformRand() < quEff->Value(wlen))
    {
        man->FillNtupleIColumn(1,0,evt);
        man->FillNtupleDColumn(1,1,posDetector[0]);
        man->FillNtupleDColumn(1,2,posDetector[1]);
        man->FillNtupleDColumn(1,3,posDetector[2]);
        man->AddNtupleRow(1);
    }


    return true;
}

the macro to initialize the visualization

/run/initialize
/vis/open OGL
/vis/viewer/set/viewpointVector 1 1 1
/vis/drawVolume
/vis/viewer/set/autoRefresh false
/vis/scene/add/trajectories smooth
/vis/scene/add/scale 10 cm
/vis/scene/add/axes
/vis/scene/add/eventID
#/vis/scene/endOfEventAction accumulate

Where is the bug ? How can we redraw the modified geometry ?


I think the command is

/run/reinitializeGeometry

Does that help?

I do use the correct command since i use the predfined command..

I deeply insight in the forum and found that same problem appear from time to time

the most recent one use same type of code as me

but never been solved…

i am wondering if it is possible to redraw a geometry even it had been changed or not ..

It should be possible. I don’t know where the problem resides; it might be a vis issue, it might not. I am happy to look into this on the vis side if someone can send me an example app (simplified as much as possible). I have asked before. Can you send me the source code of something that runs “out of the box” if I follow Geant4 standard build procedures?

Dear @montarou

Thank you for your post.

The feature you are looking for is explained step by step in the Geant4 beginners course [1]. Recordings of the 2024 are available in CDS, and the code in github (links are found in each time slot of the indico event)

Best,
Alvaro

[1] First steps with Geant4 (15-19 April 2024): Timetable · Indico

Dear Alvaro

Thank’s a lot for this information. I will look at this carefully
gerard

Hi Gerard

This issue seems to arise a lot. If you find a solution, either from Alvaro’s advice or anywhere, please post it here.

Also, we may be able to improve the documentation, Dynamic Geometry Setups — Book For Application Developers 11.3 documentation. Is it, perhaps, not adequate? Let us know.

Good luck
John