GenericMessenger的使用
除了在B5中,B2中也有使用Messenger,两者的使用方法是不同的,在B2中通过Messenger改变材料和步长等附属属性,而B5中则直接更改了整体的Geometry,不清楚两者目的的区别是否对使用方法有更深的影响,但是可以肯定的是在B5中的语句
G4RunManager::GetRunManager()->GeometryHasBeenModified();
显然是与Geometry的Run共享的特性相关的,必须要声明Geometry的修改。
回到主题,B2和B5中的Messenger不同使用方法
B2是在G4UIMessenger的基础上进行自定义,而B5直接调用了G4GenericMessenger。
// B2
class DetectorMessenger: public G4UImessenger
{
// ...
}
DetectorConstruction::DetectorConstruction()
{
fMessenger = new DetectorMessenger(this);
// ...
}
// --------------------------------------------------------------
// B5
fMessenger = new G4GenericMessenger(this,
"/B5/detector/",
"Detector control");
然后是调用命令的方式。B2使用的是G4UIcmdWithAString,通过String在UI界面调用cmd,而通过cmd的SetNewValue调用命令。而B5直接通过G4GenericMessenger中传递给DeclareMethodWithUnits命令的地址
// B2
DetectorMessenger::DetectorMessenger(DetectorConstruction* det){
// ...
fTargMatCmd = new G4UIcmdWithAString("/B2/det/setTargetMaterial",this);
fTargMatCmd->SetGuidance("Select Material of the Target.");
fTargMatCmd->SetParameterName("choice",false);
// ...
}
void DetectorMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
{
if( command == fTargMatCmd )
{ fDetectorConstruction->SetTargetMaterial(newValue);}
// ...
}
// B5
auto& armAngleCmd
= fMessenger->DeclareMethodWithUnit("armAngle","deg",
&DetectorConstruction::SetArmAngle,
"Set rotation angle of the second arm.");
SetNewValue和DeclareMethodWithUnit的头文件如下
void SetNewValue(G4UIcommand* command, G4String newValue) override;
// The concrete, generic implementation of this method converts
// the string "newValue" to action.
Command& DeclareMethodWithUnit(const G4String& name,
const G4String& defaultUnit,
const G4AnyMethod& fun,
const G4String& doc = "");
最后是命令的内容
void DetectorConstruction::SetTargetMaterial(G4String materialName)
{
// ...
fLogicTarget->SetMaterial(fTargetMaterial);
// ...
}
void DetectorConstruction::SetArmAngle(G4double val)
{
*fArmRotation = G4RotationMatrix(); // make it unit vector
fArmRotation->rotateY(fArmAngle);
auto x = -5.*m * std::sin(fArmAngle);
auto z = 5.*m * std::cos(fArmAngle);
fSecondArmPhys->SetTranslation(G4ThreeVector(x,0.,z));
// tell G4RunManager that we change the geometry
G4RunManager::GetRunManager()->GeometryHasBeenModified();
}
补充:VisAttributes的使用
// DetectorConstruction.hh
std::vector<G4VisAttributes*> fVisAttributes;
// DetectorConstruction.cc
auto visAttributes = new G4VisAttributes(G4Colour(1.0,1.0,1.0));
visAttributes->SetVisibility(false);
worldLogical->SetVisAttributes(visAttributes);
fVisAttributes.push_back(visAttributes);
补充:设置步长限制
// DetectorConstruction::Construct
// set step limit in tube with magnetic field
auto userLimits = new G4UserLimits(1 * m);
fMagneticLogical->SetUserLimits(userLimits);