#include #include #include #include #include #include #include #include #include #include #include #include using CLHEP::ns; using CLHEP::s; using CLHEP::h; using CLHEP::day; using CLHEP::yr; namespace RAT { GsimMessenger::GsimMessenger(Gsim* pGsim) : fGsim(pGsim) { fDiscardCmd = new G4UIcmdWithABool("/tracking/discardOpticalPhotons", this); fDiscardCmd->SetGuidance("Do not store optical photons tracks in data structure"); fDiscardCmd->SetParameterName("state", true, false); fDiscardCmd->SetDefaultValue(true); // -- Series of commands to define MC run with time management instead of number of events // Build UI commands G4UIdirectory* RunDir = new G4UIdirectory("/rat/run/"); RunDir->SetGuidance(" Run control commands"); fRunDurationCmd= new G4UIcmdWithADoubleAndUnit("/rat/run/duration",this); fRunDurationCmd->SetGuidance("Define duration of the run duration."); fRunDurationCmd->SetParameterName("duration", false); fRunDurationCmd->SetUnitCategory("Time"); fRunDurationCmd->SetRange("duration>0.0"); fRunDurationCmd->AvailableForStates(G4State_PreInit,G4State_Init,G4State_Idle); // Make this parameter as similar to beamOn as possible // with the exception that now the number of events can be bypassed fRunStartCmd= new G4UIcommand("/rat/run/start",this); fRunStartCmd->SetGuidance("Start the run."); fRunStartCmd->SetGuidance("This command is a placeholder for /run/BeamOn."); G4UIparameter *p1 = new G4UIparameter("n_events",'i',true); p1->SetDefaultValue(0); fRunStartCmd->SetParameter(p1); G4UIparameter *p2 = new G4UIparameter("macroFile",'s',true); p2->SetDefaultValue("***NULL***"); fRunStartCmd->SetParameter(p2); G4UIparameter* p3 = new G4UIparameter("nSelect",'i',true); p3->SetDefaultValue(-1); p3->SetParameterRange("nSelect>=-1"); fRunStartCmd->SetParameter(p3); fRunStartCmd->AvailableForStates(G4State_Idle); } GsimMessenger::~GsimMessenger() { delete fDiscardCmd; } void GsimMessenger::SetNewValue(G4UIcommand * command, G4String newValue) { if(command == fDiscardCmd) { bool state = G4UIcmdWithABool::GetNewBoolValue(newValue); if (state) detail << "GsimMessenger::SetNewValue: Tracking: Discarding optical photons from track storage" << newline; else detail << "GsimMessenger::SetNewValue: Tracking: Retaining optical photons in track storage" << newline; fGsim->SetDiscardOpticalPhotons(state); } else if (command == fRunDurationCmd ) { G4double runDuration = fRunDurationCmd->GetNewDoubleValue(newValue); // -- try to be smart about the presentation of the time double time_human = runDuration/day; string unit_human = "days"; if (time_human > (365.25/2.0)) { // more than half-year. Switch to years time_human = runDuration/yr; unit_human = "yr"; } else if ((time_human < 1.0) && (runDuration/s > 3600.)) { // more than 1 hour and less than a day, switch to hours time_human = runDuration/h; unit_human = "h"; } else if ((runDuration/s < 3600.) && (runDuration/s > 1.)) { // less than 1 h, more than 1 second time_human = runDuration/s; unit_human = "s"; } else { // keep it in ns time_human = runDuration/ns; unit_human = "ns"; } detail << "GsimMessenger::SetNewValue: Setting run to be time controlled with a duration of " << time_human << " " << unit_human << " (" << runDuration/ns << " ns )." << newline; // Internally the duration is controlled in nanoseconds // not the best of units to simulate years of data, but // allows to avoid further complications since unit specification // is not the strongest point in RAT fGsim->SetRunDuration(runDuration/ns); } else if (command == fRunStartCmd) { detail << "GsimMessenger::SetNewValue: Command \'/rat/run/start\' invoked." << newline; detail << "GsimMessenger::SetNewValue: Full command \'/rat/run/start " << newValue <<"\' invoked." << newline; // Call directly the beamOn from here // Be sure to parse all the possible parameters and to check that // if no number of events is given, the type of run is set to timed // IMPORTANT: If the run is set to be timed this takes precedence over // a the number of events // First check the database if the timed_run flag is set. // If so, pass the duration term to the relevant objects int timed_run_cmdL = DB::Get()->GetLink( "IO" )->GetI( "timed_run" ); std::string duration = "/rat/run/duration "; duration += DB::Get()->GetLink( "IO" )->GetS("timed_duration"); if (timed_run_cmdL == 1) { // Check if the duration was also set in the macro // If so, by now the Gsim::IsTimedRun should already be true. // In that case die if (fGsim->IsTimedRun()) { Log::Die("GsimMessenger::SetNewValue Run time set in macro and by command line, choose one method."); } G4UImanager* theUI = G4UImanager::GetUIpointer(); theUI->ApplyCommand(duration); } // default number of events if this is a timed run G4int bigNumber = INT_MAX; G4int n_events = 0; G4String macro = ""; G4int n_select = -1; std::istringstream is(newValue.data()); is >> n_events >> macro >> n_select; int defaultNumEvents = DB::Get()->GetLink( "IO" )->GetI( "default_num_events" ); if( (n_events > 0 && fGsim->IsTimedRun()) || (defaultNumEvents != -1 && fGsim->IsTimedRun())) // Incompatible setting Log::Die( "GsimMessenger::SetNewValue cannot set a number of events and a run duration." ); else if( fGsim->IsTimedRun() ) n_events = bigNumber; else if( n_events > 0 && defaultNumEvents != -1 ) Log::Die( "GsimMessenger::SetNewValue Number of events set in macro and by command line, choose one method." ); else if( n_events == 0 ) // Use the default number of events value n_events = defaultNumEvents; // Get the run manager to kindly to the work G4RunManager *theRunManager = G4RunManager::GetRunManager(); detail << "GsimMessenger::SetNewValue Calling beam On with parameters:" << newline; detail << " n_events : " << n_events << newline; detail << " macro : " << macro << newline; detail << " n_select : " << n_select << newline; // Taken exactly as it was from Geant4 G4RunMessenger.hh if (macro =="***NULL***") { theRunManager->BeamOn(n_events); } else { theRunManager->BeamOn(n_events,macro,n_select); } } else Log::Die("GsimMessenger::SetNewValue: sent unknown set command: "+command->GetCommandPath()); } } // namespace RAT