Import Geant4 10.7.0 source tree

This commit is contained in:
Gabriele Cosmo
2020-12-04 12:30:43 +01:00
parent 67ba86d073
commit dab42d2018
3770 changed files with 226369 additions and 286486 deletions
@@ -0,0 +1,90 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRActionInitialization.cc
// Action initialization class
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRActionInitialization.hh"
#include "GRRunAction.hh"
#include "GRPrimaryGeneratorAction.hh"
#include "G4GenericMessenger.hh"
GRActionInitialization::GRActionInitialization()
{
generatorMsg = new G4GenericMessenger(this,"/gorad/generator/",
"primary particle generator selection");
auto& useParticleGunCmd = generatorMsg->DeclareProperty("useParticleGun",
useParticleGun, "use Particle Gun");
useParticleGunCmd.SetStates(G4State_PreInit);
useParticleGunCmd.SetToBeBroadcasted(false);
auto& useParticleSourceCmd = generatorMsg->DeclareProperty("useParticleSource",
useParticleSource, "use General Particle Source");
useParticleSourceCmd.SetStates(G4State_PreInit);
useParticleSourceCmd.SetToBeBroadcasted(false);
filler = new G4TScoreHistFiller<G4AnalysisManager>;
}
GRActionInitialization::~GRActionInitialization()
{
delete generatorMsg;
delete filler;
}
void GRActionInitialization::BuildForMaster() const
{
SetUserAction(new GRRunAction);
}
void GRActionInitialization::Build() const
{
SetUserAction(new GRRunAction);
if(!useParticleGun && !useParticleSource)
{
G4ExceptionDescription ed;
ed << "Neither Particle Gun nor General Particle Source is selected.\n"
<< "No way to generate primary particle!!!\n"
<< "Use /gorad/generator/useParticleGun or /gorad/generator/useParticleSource command.";
G4Exception("GRActionInitialization::Build()","GORAD0001",FatalException,ed);
}
else
{ SetUserAction(new GRPrimaryGeneratorAction(useParticleGun,useParticleSource)); }
}
@@ -0,0 +1,435 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRDetectorConstruction.cc
// Read a GDML file to set up the geometry.
// This class also takes care of several utility methods on geometry
// and creates a parallel world for geometry importance biasing if
// requested.
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRDetectorConstruction.hh"
#include "G4GDMLParser.hh"
#include "GRDetectorConstructionMessenger.hh"
#include "GRGeomImpBiasWorld.hh"
#include "G4VPhysicalVolume.hh"
#include "G4RunManager.hh"
#include "G4LogicalVolume.hh"
#include "G4Box.hh"
#include <algorithm>
G4double GRDetectorConstruction::worldSize = -1.;
GRDetectorConstruction::GRDetectorConstruction()
: gdmlFile("noName"), fWorld(nullptr), initialized(false)
{
messenger = new GRDetectorConstructionMessenger(this);
parser = new G4GDMLParser();
}
GRDetectorConstruction::~GRDetectorConstruction()
{
delete messenger;
delete parser;
}
G4VPhysicalVolume* GRDetectorConstruction::Construct()
{
if(!initialized)
{
Read();
if(applyGeomImpBias)
{
G4String wName = "GeomBias";
geomImpBiasWorld = new GRGeomImpBiasWorld(wName,this);
RegisterParallelWorld(geomImpBiasWorld);
}
}
return fWorld;
}
void GRDetectorConstruction::ConstructSDAndField()
{ ; }
G4bool GRDetectorConstruction::SetGDMLFile(G4String& gdml)
{
G4bool valid = true; // parser->IsValid(gdml); ## GDML parser fix needed
if(valid)
{
if(initialized)
{
parser->Clear();
G4RunManager::GetRunManager()->ReinitializeGeometry(true);
}
gdmlFile = gdml;
}
return valid;
}
void GRDetectorConstruction::Read()
{
parser->Read(gdmlFile);
fWorld = parser->GetWorldVolume();
const G4Box* worldBox = dynamic_cast<const G4Box*>(fWorld->GetLogicalVolume()->GetSolid());
if(!worldBox)
{
G4ExceptionDescription ed;
ed << "PANIC!!! World volume defined in "<<gdmlFile<<" is not Box!!!";
G4Exception("GRDetectorConstruction::Read()","GOoradGeom00012",FatalException,ed);
}
worldSize = std::min( {worldBox->GetXHalfLength(), worldBox->GetYHalfLength(), worldBox->GetZHalfLength()},
[](G4double a,G4double b) {return a<b;} );
initialized = true;
}
#include "G4UnitsTable.hh"
#include "G4VSolid.hh"
#include "G4SolidStore.hh"
void GRDetectorConstruction::ListSolids(G4int lvl)
{
G4cout << "*********** List of registered solids *************" << G4endl;
auto store = G4SolidStore::GetInstance();
auto itr = store->begin();
for(;itr!=store->end();itr++)
{
switch(lvl)
{
case 0:
G4cout << (*itr)->GetName() << G4endl;
break;
case 1:
G4cout << (*itr)->GetName()
<< "\t volume = " << G4BestUnit((*itr)->GetCubicVolume(),"Volume")
<< "\t surface = " << G4BestUnit((*itr)->GetSurfaceArea(),"Surface")
<< G4endl;
break;
default:
(*itr)->DumpInfo();
break;
}
}
}
#include "G4LogicalVolume.hh"
#include "G4LogicalVolumeStore.hh"
#include "G4Material.hh"
#include "G4VSensitiveDetector.hh"
void GRDetectorConstruction::ListLogVols(G4int lvl)
{
G4cout << "*********** List of registered logical volumes *************" << G4endl;
auto store = G4LogicalVolumeStore::GetInstance();
auto itr = store->begin();
for(;itr!=store->end();itr++)
{
G4cout << (*itr)->GetName() << "\t Solid = " << (*itr)->GetSolid()->GetName();
if((*itr)->GetMaterial())
{ G4cout << "\t Material = " << (*itr)->GetMaterial()->GetName() << G4endl; }
else
{ G4cout << "\t Material : not defined " << G4endl; }
if(lvl<1) continue;
G4cout << "\t region = ";
if((*itr)->GetRegion())
{ G4cout << (*itr)->GetRegion()->GetName(); }
else
{ G4cout << "not defined"; }
G4cout << "\t sensitive detector = ";
if((*itr)->GetSensitiveDetector())
{ G4cout << (*itr)->GetSensitiveDetector()->GetName(); }
else
{ G4cout << "not defined"; }
G4cout << G4endl;
G4cout << "\t daughters = " << (*itr)->GetNoDaughters();
if((*itr)->GetNoDaughters()>0)
{
switch((*itr)->CharacteriseDaughters())
{
case kNormal:
G4cout << " (placement)"; break;
case kReplica:
G4cout << " (replica : " << (*itr)->GetDaughter(0)->GetMultiplicity() << ")"; break;
case kParameterised:
G4cout << " (parameterized : " << (*itr)->GetDaughter(0)->GetMultiplicity() << ")"; break;
default:
;
}
}
G4cout << G4endl;
if(lvl<2) continue;
if((*itr)->GetMaterial())
{ G4cout << "\t weight = " << G4BestUnit((*itr)->GetMass(),"Mass") << G4endl; }
else
{ G4cout << "\t weight : not available" << G4endl; }
}
}
#include "G4VPhysicalVolume.hh"
#include "G4PhysicalVolumeStore.hh"
void GRDetectorConstruction::ListPhysVols(G4int lvl)
{
G4cout << "*********** List of registered physical volumes *************" << G4endl;
auto store = G4PhysicalVolumeStore::GetInstance();
auto itr = store->begin();
for(;itr!=store->end();itr++)
{
switch(lvl)
{
case 0:
G4cout << (*itr)->GetName() << G4endl;
break;
case 1:
G4cout << (*itr)->GetName()
<< "\t logical volume = " << (*itr)->GetLogicalVolume()->GetName()
<< "\t mother logical = ";
if((*itr)->GetMotherLogical())
{ G4cout << (*itr)->GetMotherLogical()->GetName(); }
else
{ G4cout << "not defined"; }
G4cout << G4endl;
break;
default:
G4cout << (*itr)->GetName()
<< "\t logical volume = " << (*itr)->GetLogicalVolume()->GetName()
<< "\t mother logical = ";
if((*itr)->GetMotherLogical())
{ G4cout << (*itr)->GetMotherLogical()->GetName(); }
else
{ G4cout << "not defined"; }
G4cout << "\t type = ";
switch((*itr)->VolumeType())
{
case kNormal:
G4cout << "placement"; break;
case kReplica:
G4cout << "replica"; break;
case kParameterised:
G4cout << "parameterized"; break;
default:
;
}
G4cout << G4endl;
}
}
}
G4bool GRDetectorConstruction::CheckOverlap(G4String& physVolName, G4int nSpots,
G4int maxErr, G4double tol)
{
G4cout << "*********** Checking overlap for <" << physVolName << "> *************" << G4endl;
G4bool checkAll = (physVolName=="**ALL**");
auto store = G4PhysicalVolumeStore::GetInstance();
auto itr = store->begin();
G4VPhysicalVolume* physVol = nullptr;
for(;itr!=store->end();itr++)
{
if(checkAll || (*itr)->GetName()==physVolName)
{
physVol = (*itr);
physVol->CheckOverlaps(nSpots,tol,true,maxErr);
if(!checkAll) break;
}
}
return (physVol!=nullptr);
}
#include "G4Region.hh"
#include "G4RegionStore.hh"
#include "G4RunManagerKernel.hh"
void GRDetectorConstruction::ListRegions(G4int lvl)
{
if(lvl==2)
{
G4RunManagerKernel::GetRunManagerKernel()->DumpRegion();
return;
}
G4cout << "*********** List of registered regions *************" << G4endl;
auto store = G4RegionStore::GetInstance();
auto itr = store->begin();
for(;itr!=store->end();itr++)
{
G4cout << (*itr)->GetName();
if((*itr)->GetWorldPhysical())
{
G4cout << "\t in the world volume <" << (*itr)->GetWorldPhysical()->GetName() << "> ";
if((*itr)->IsInMassGeometry()) G4cout << "-- mass world";
if((*itr)->IsInParallelGeometry()) G4cout << "-- parallel world";
}
else
{ G4cout << " -- is not associated to any world."; }
G4cout << G4endl;
if(lvl==0) continue;
G4cout << "\t\t Root logical volume(s) : ";
size_t nRootLV = (*itr)->GetNumberOfRootVolumes();
std::vector<G4LogicalVolume*>::iterator lvItr = (*itr)->GetRootLogicalVolumeIterator();
for(size_t j=0;j<nRootLV;j++)
{ G4cout << (*lvItr)->GetName() << " "; lvItr++; }
G4cout << G4endl;
G4cout << "\t\t Pointers : G4VUserRegionInformation[" << (*itr)->GetUserInformation()
<< "], G4UserLimits[" << (*itr)->GetUserLimits()
<< "], G4FastSimulationManager[" << (*itr)->GetFastSimulationManager()
<< "], G4UserSteppingAction[" << (*itr)->GetRegionalSteppingAction() << "]" << G4endl;
}
}
G4bool GRDetectorConstruction::CreateRegion(G4String& regionName,G4String& logVolName)
{
auto logVolStore = G4LogicalVolumeStore::GetInstance();
auto itr = logVolStore->begin();
G4LogicalVolume* logVol = nullptr;
for(;itr!=logVolStore->end();itr++)
{
if((*itr)->GetName() == logVolName)
{ logVol = (*itr); break; }
}
if(!logVol) return false;
auto regionStore = G4RegionStore::GetInstance();
auto region = regionStore->FindOrCreateRegion(regionName);
logVol->SetRegion(region);
region->AddRootLogicalVolume(logVol);
return true;
}
#include "G4MaterialTable.hh"
void GRDetectorConstruction::ListAllMaterial()
{
auto materialTable = G4Material::GetMaterialTable();
auto matItr = materialTable->begin();
G4cout << "*********** List of instantiated materials **************" << G4endl;
G4int i = 0;
for(;matItr!=materialTable->end();matItr++)
{
G4cout << (*matItr)->GetName() << "\t";
if(++i%5==0) G4cout << G4endl;
}
G4cout << G4endl;
}
G4bool GRDetectorConstruction::ListMaterial(G4String& matName)
{
auto materialTable = G4Material::GetMaterialTable();
auto matItr = materialTable->begin();
for(;matItr!=materialTable->end();matItr++)
{
if((*matItr)->GetName()==matName)
{
G4cout << *matItr << G4endl;
return true;
}
}
return false;
}
#include "G4NistManager.hh"
void GRDetectorConstruction::DumpNistMaterials()
{
auto nameVec = G4NistManager::Instance()->GetNistMaterialNames();
auto itr = nameVec.begin();
G4int i = 0;
for(;itr!=nameVec.end();itr++)
{
G4cout << std::setw(26) << *itr;
if(++i%3==0) G4cout << G4endl;
}
G4cout << G4endl;
}
G4bool GRDetectorConstruction::CreateMaterial(G4String& matName)
{
auto mat = G4NistManager::Instance()->FindOrBuildMaterial(matName);
return (mat!=nullptr);
}
G4bool GRDetectorConstruction::GetMaterial(G4String& logVol)
{
auto store = G4LogicalVolumeStore::GetInstance();
std::vector<G4LogicalVolume*>::iterator itr = store->begin();
for(;itr!=store->end();itr++)
{
if((*itr)->GetName()==logVol)
{
G4cout << "Logical volume <" << (*itr)->GetName() << "> is made of <"
<< (*itr)->GetMaterial()->GetName() << ">" << G4endl;
return true;
}
}
return false;
}
G4int GRDetectorConstruction::SetMaterial(G4String& logVolName,G4String& matName)
{
G4LogicalVolume* logVol = nullptr;
G4Material* mat = nullptr;
auto store = G4LogicalVolumeStore::GetInstance();
auto itr = store->begin();
for(;itr!=store->end();itr++)
{
if((*itr)->GetName()==logVolName)
{
logVol = *itr;
break;
}
}
auto materialTable = G4Material::GetMaterialTable();
auto matItr = materialTable->begin();
for(;matItr!=materialTable->end();matItr++)
{
if((*matItr)->GetName()==matName)
{
mat = *matItr;
break;
}
}
G4int retVal = 0;
if(!logVol && !mat)
{ retVal = 3; }
else if(!logVol)
{ retVal = 1; }
else if(!mat)
{ retVal = 2; }
else
{ logVol->SetMaterial(mat); }
return retVal;
}
@@ -0,0 +1,334 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRDetectorConstructionMessenger.cc
// A messenger class that handles geometry configuration.
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRDetectorConstructionMessenger.hh"
#include "GRDetectorConstruction.hh"
#include "G4UIcommand.hh"
#include "G4UIparameter.hh"
#include "G4UIdirectory.hh"
#include "G4UIcmdWithAString.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4UIcmdWithoutParameter.hh"
GRDetectorConstructionMessenger::GRDetectorConstructionMessenger(GRDetectorConstruction* dc)
: pDC(dc)
{
G4UIparameter* para = nullptr;
geomDir = new G4UIdirectory("/gorad/geometry/");
geomDir->SetGuidance("GORAD geometry selection");
selectCmd = new G4UIcmdWithAString("/gorad/geometry/selectGDML",this);
selectCmd->SetGuidance("Select GDML file");
selectCmd->SetParameterName("gdml",false);
selectCmd->AvailableForStates(G4State_PreInit);
selectCmd->SetToBeBroadcasted(false);
listSolidCmd = new G4UIcmdWithAnInteger("/gorad/geometry/listSolids",this);
listSolidCmd->SetGuidance("List all the registered solids");
listSolidCmd->SetParameterName("level",true);
listSolidCmd->SetDefaultValue(0);
listSolidCmd->SetRange("level>=0 && level<=2");
listSolidCmd->AvailableForStates(G4State_Idle);
listSolidCmd->SetToBeBroadcasted(false);
listLogVolCmd = new G4UIcmdWithAnInteger("/gorad/geometry/listLogicalVolumes",this);
listLogVolCmd->SetGuidance("List all the registered logical volumes");
listLogVolCmd->SetParameterName("level",true);
listLogVolCmd->SetDefaultValue(0);
listLogVolCmd->SetRange("level>=0 && level<=2");
listLogVolCmd->AvailableForStates(G4State_Idle);
listLogVolCmd->SetToBeBroadcasted(false);
listPhysVolCmd = new G4UIcmdWithAnInteger("/gorad/geometry/listPhysicalVolumes",this);
listPhysVolCmd->SetGuidance("List all the registered physical volumes");
listPhysVolCmd->SetParameterName("level",true);
listPhysVolCmd->SetDefaultValue(0);
listPhysVolCmd->SetRange("level>=0 && level<=2");
listPhysVolCmd->AvailableForStates(G4State_Idle);
listPhysVolCmd->SetToBeBroadcasted(false);
listRegionCmd = new G4UIcmdWithAnInteger("/gorad/geometry/listRegions",this);
listRegionCmd->SetGuidance("List all the registered regions");
listRegionCmd->SetParameterName("level",true);
listRegionCmd->SetDefaultValue(0);
listRegionCmd->SetRange("level>=0 && level<=2");
listRegionCmd->AvailableForStates(G4State_Idle);
listRegionCmd->SetToBeBroadcasted(false);
createRegionCmd = new G4UIcommand("/gorad/geometry/createRegion",this);
createRegionCmd->SetGuidance("Create a region and set the root logical volume to it.");
createRegionCmd->SetGuidance("Region propagates to the daughter volumes. So, only the root logical volume (i.e. top of the hierarchy) should be defined.");
createRegionCmd->SetGuidance("If two isolated root logical volumes should share the same region, the same region name can be used.");
createRegionCmd->SetGuidance("Region must not be set to the world volume.");
para = new G4UIparameter("regionName",'s',false);
para->SetGuidance("Name of the region to be created");
createRegionCmd->SetParameter(para);
para = new G4UIparameter("logVolName",'s',false);
para->SetGuidance("Name of the root logical volume");
createRegionCmd->SetParameter(para);
createRegionCmd->AvailableForStates(G4State_Idle);
createRegionCmd->SetToBeBroadcasted(false);
//// This command is fragile for large-scale geometry - temporally disabled
////checkOverlapCmd = new G4UIcommand("/gorad/geometry/checkOverlap",this);
////checkOverlapCmd->SetGuidance("Check volume overlap with existing volumes");
////checkOverlapCmd->SetGuidance(" i.e. with mother volume for protrusion and with other siblings for overlap.");
////checkOverlapCmd->SetGuidance(" - This command is valid only for placement and parameterized volumes. If this command is");
////checkOverlapCmd->SetGuidance(" used for other physical volume type, e.g. replica, command will be simply ignored.");
////checkOverlapCmd->SetGuidance(" If \"**ALL**\" is used as the volume name, all physical volumes are examined (SLOW!!).");
////checkOverlapCmd->SetGuidance(" - nSpots specifies number of spots on the surface of the volume to be examined.");
////checkOverlapCmd->SetGuidance(" The more spots used, the more chances to detect overlaps, but the more time it takes.");
////checkOverlapCmd->SetGuidance(" - maxErr specifies maximum number of errors to be generated (default 1) before quiting.");
////para = new G4UIparameter("physVol",'s',true);
////para->SetDefaultValue("**ALL**");
////checkOverlapCmd->SetParameter(para);
////para = new G4UIparameter("nSpots",'i',true);
////para->SetDefaultValue(1000);
////para->SetGuidance("Number of trial spots on the volume surface");
////checkOverlapCmd->SetParameter(para);
////para = new G4UIparameter("maxErr",'i',true);
////para->SetDefaultValue(1);
////para->SetParameterRange("maxErr > 0");
////para->SetGuidance("Maxinum number of report to be generated");
////checkOverlapCmd->SetParameter(para);
////para = new G4UIparameter("tolerance",'d',true);
////para->SetDefaultValue(0.);
////para->SetParameterRange("tolerance >= 0.");
////para->SetGuidance("Tolerance (default 0.)");
////checkOverlapCmd->SetParameter(para);
////para = new G4UIparameter("unit",'s',true);
////para->SetDefaultUnit("mm");
////checkOverlapCmd->SetParameter(para);
////checkOverlapCmd->AvailableForStates(G4State_Idle);
////checkOverlapCmd->SetToBeBroadcasted(false);
materialDir = new G4UIdirectory("/gorad/material/");
materialDir->SetGuidance("GORAD material commands");
listMatCmd = new G4UIcmdWithAString("/gorad/material/list",this);
listMatCmd->SetGuidance("List material property");
listMatCmd->SetGuidance(" If material name is not specified, this command list all registered materials");
listMatCmd->SetParameterName("matName",true);
listMatCmd->SetDefaultValue("**ALL**");
listMatCmd->AvailableForStates(G4State_Idle);
listMatCmd->SetToBeBroadcasted(false);
dumpMatCmd = new G4UIcmdWithoutParameter("/gorad/material/dumpNistMaterials",this);
dumpMatCmd->SetGuidance("List all pre-defined material names in G4NistManager.");
dumpMatCmd->SetGuidance(" Note : a material has to be instantiated with /gorad/material/create before setting it to a logical volume");
dumpMatCmd->AvailableForStates(G4State_Idle);
dumpMatCmd->SetToBeBroadcasted(false);
createMatCmd = new G4UIcmdWithAString("/gorad/material/create",this);
createMatCmd->SetGuidance("Instantiate a material defined in G4NistManager");
createMatCmd->SetGuidance(" If the material has already existed, this command does nothing.");
createMatCmd->SetParameterName("matName",false);
createMatCmd->AvailableForStates(G4State_Idle);
createMatCmd->SetToBeBroadcasted(false);
getMatCmd = new G4UIcmdWithAString("/gorad/material/show",this);
getMatCmd->SetGuidance("Show the current material of the specified logical volume");
getMatCmd->SetParameterName("logVol",false);
getMatCmd->AvailableForStates(G4State_Idle);
getMatCmd->SetToBeBroadcasted(false);
setMatCmd = new G4UIcommand("/gorad/material/set",this);
setMatCmd->SetGuidance("Set the material to the logical volume. The material has to be instantiated in advance.");
setMatCmd->SetGuidance(" [usage] /gorad/material/set logicalVolumeName materialName");
para = new G4UIparameter("logVol",'s',false);
setMatCmd->SetParameter(para);
para = new G4UIparameter("matName",'s',false);
setMatCmd->SetParameter(para);
setMatCmd->AvailableForStates(G4State_Idle);
setMatCmd->SetToBeBroadcasted(false);
}
GRDetectorConstructionMessenger::~GRDetectorConstructionMessenger()
{
delete selectCmd;
delete listSolidCmd;
delete listLogVolCmd;
delete listPhysVolCmd;
delete listRegionCmd;
delete createRegionCmd;
////delete checkOverlapCmd;
delete geomDir;
delete listMatCmd;
delete dumpMatCmd;
delete createMatCmd;
delete getMatCmd;
delete setMatCmd;
delete materialDir;
}
#include "G4Tokenizer.hh"
void GRDetectorConstructionMessenger::SetNewValue(G4UIcommand* cmd, G4String val)
{
if(cmd==selectCmd)
{
auto valid = pDC->SetGDMLFile(val);
if(!valid)
{
G4ExceptionDescription ed;
ed << "<" << val << "> is not a valid GDML file.";
cmd->CommandFailed(ed);
}
}
else if(cmd==listSolidCmd)
{ pDC->ListSolids(listSolidCmd->GetNewIntValue(val)); }
else if(cmd==listLogVolCmd)
{ pDC->ListLogVols(listLogVolCmd->GetNewIntValue(val)); }
else if(cmd==listPhysVolCmd)
{ pDC->ListPhysVols(listPhysVolCmd->GetNewIntValue(val)); }
else if(cmd==listRegionCmd)
{ pDC->ListRegions(listRegionCmd->GetNewIntValue(val)); }
else if(cmd==createRegionCmd)
{
G4Tokenizer next(val);
G4String regionName = next();
G4String logVolName = next();
auto valid = pDC->CreateRegion(regionName,logVolName);
if(!valid)
{
G4ExceptionDescription ed;
ed << "Logical volume <" << logVolName << "> is not defined. Command ignored.";
cmd->CommandFailed(ed);
}
}
////else if(cmd==checkOverlapCmd)
////{
////G4Tokenizer next(val);
////G4String physVolName = next();
////G4int nSpots = StoI(next());
////G4int maxErr = StoI(next());
////G4String tolStr = next();
////G4double tol = StoD(tolStr);
////if(tol>0.)
////{
////tolStr += " ";
////tolStr += next();
////tol = checkOverlapCmd->ConvertToDimensionedDouble(tolStr);
////}
////auto valid = pDC->CheckOverlap(physVolName,nSpots,maxErr,tol);
////if(!valid)
////{
////G4ExceptionDescription ed;
////ed << "Physical volume <" << physVolName << "> is not defined. Command ignored.";
////cmd->CommandFailed(ed);
////}
////}
else if(cmd==listMatCmd)
{
if(val=="**ALL**")
{ pDC->ListAllMaterial(); }
else
{
auto valid = pDC->ListMaterial(val);
if(!valid)
{
G4ExceptionDescription ed;
ed << "<" << val << "> is not defined. If necessary, create it with /gorad/material/create command.";
cmd->CommandFailed(ed);
}
}
}
else if(cmd==dumpMatCmd)
{ pDC->DumpNistMaterials(); }
else if(cmd==createMatCmd)
{
auto valid = pDC->CreateMaterial(val);
if(!valid)
{
G4ExceptionDescription ed;
ed << "The material name <" << val << "> is not defined in G4NistManager.";
cmd->CommandFailed(ed);
}
}
else if(cmd==getMatCmd)
{
auto valid = pDC->GetMaterial(val);
if(!valid)
{
G4ExceptionDescription ed;
ed << "<" << val << "> is not a name of registered logical volume.\n"
<< "Check existing logical volumes with /gorad/geometry/listLogicalVolumes command.";
cmd->CommandFailed(ed);
}
}
else if(cmd==setMatCmd)
{
G4Tokenizer next(val);
G4String logVolName = next();
G4String matName = next();
auto valid = pDC->SetMaterial(logVolName,matName);
if(valid!=0)
{
G4ExceptionDescription ed;
if(valid==1 || valid==3)
{
ed << "<" << logVolName << "> is not a name of registered logical volume.\n"
<< "Check existing logical volumes with /gorad/geometry/listLogicalVolumes command.\n";
}
if(valid==2 || valid==3)
{
ed << "<" << matName << "> is not defined. If necessary, create it with /gorad/material/create command.";
}
cmd->CommandFailed(ed);
}
}
}
G4String GRDetectorConstructionMessenger::GetCurrentValue(G4UIcommand* cmd)
{
G4String val("");
if(cmd==selectCmd)
{ val = pDC->GetGDMLFile(); }
return val;
}
@@ -0,0 +1,210 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRGeomBiasMessenger.cc
// A messenger class that handles the UI commands for geometry
// imprtance biasing.
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRGeomBiasMessenger.hh"
#include "GRDetectorConstruction.hh"
#include "GRPhysicsList.hh"
#include "G4UIdirectory.hh"
#include "G4UIcommand.hh"
#include "G4UIcmdWith3VectorAndUnit.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4UIcmdWithADouble.hh"
#include "G4UIparameter.hh"
#include "G4Tokenizer.hh"
#include "G4UnitsTable.hh"
GRGeomBiasMessenger::GRGeomBiasMessenger(
GRDetectorConstruction* det,GRPhysicsList* phys,G4int verboseLvl)
: detector(det),physics(phys),verboseLevel(verboseLvl)
{
G4UIparameter* param = nullptr;
biasDir = new G4UIdirectory("/gorad/bias/");
biasDir->SetGuidance("Gorad biasing commands");
geoBiasCmd = new G4UIcommand("/gorad/bias/geomImportance",this);
geoBiasCmd->SetGuidance("Geometry importance biasing");
geoBiasCmd->SetGuidance("This command defines the number of layers and radius of the outermost sphere for geometry importance biasing.");
geoBiasCmd->SetGuidance("If radius is set to -1 (default), actual radius is set to 80% of the world volume");
geoBiasCmd->SetGuidance("Note: There must be at least two layers.");
param = new G4UIparameter("nLayer",'i',false);
param->SetParameterRange("nLayer > 1");
geoBiasCmd->SetParameter(param);
param = new G4UIparameter("radius",'d',true);
param->SetParameterRange("radius == -1.0 || radius > 0.");
param->SetDefaultValue(-1.0);
geoBiasCmd->SetParameter(param);
param = new G4UIparameter("unit",'s',true);
param->SetDefaultUnit("mm");
geoBiasCmd->SetParameter(param);
geoBiasCmd->SetToBeBroadcasted(false);
geoBiasCmd->AvailableForStates(G4State_PreInit);
geoBiasLocCmd = new G4UIcmdWith3VectorAndUnit("/gorad/bias/geomImpLocate",this);
geoBiasLocCmd->SetGuidance("Position of the center of the outermost sphere.");
geoBiasLocCmd->SetGuidance("By default, the sphere is located at the origin of the world volume.");
geoBiasLocCmd->SetGuidance("This command has to follow /gorad/bias/geomImportance command.");
geoBiasLocCmd->SetParameterName("x0","y0","z0",false);
geoBiasLocCmd->SetDefaultUnit("mm");
geoBiasLocCmd->SetToBeBroadcasted(false);
geoBiasLocCmd->AvailableForStates(G4State_PreInit);
geoBiasInRadCmd = new G4UIcmdWithADoubleAndUnit("/gorad/bias/geomImpInnerRadius",this);
geoBiasInRadCmd->SetGuidance("Radius of the innermost sphere.");
geoBiasInRadCmd->SetGuidance("By default it is defined as 1/n of radius of the outermost sphere.");
geoBiasInRadCmd->SetParameterName("rT",false);
geoBiasInRadCmd->SetDefaultUnit("mm");
geoBiasInRadCmd->SetRange("rT > 0.");
geoBiasInRadCmd->SetToBeBroadcasted(false);
geoBiasInRadCmd->AvailableForStates(G4State_PreInit);
geoBiasLocTgtCmd = new G4UIcmdWith3VectorAndUnit("/gorad/bias/geomImpLocTgt",this);
geoBiasLocTgtCmd->SetGuidance("Position of the center of the innermost sphere.");
geoBiasLocTgtCmd->SetGuidance("By default, it is located at the center of the outermost sphere.");
geoBiasLocTgtCmd->SetGuidance("This command has to follow /gorad/bias/geomImportance command.");
geoBiasLocTgtCmd->SetGuidance("Note: distance between (x0,y,0,z0) and (xT,yT,zT) must be smaller than r0*(nLayer-1)/nLayer.");
geoBiasLocTgtCmd->SetGuidance(" (smaller than r0-rT if radius of innermost sphere is set)");
geoBiasLocTgtCmd->SetParameterName("xT","yT","zT",false);
geoBiasLocTgtCmd->SetDefaultUnit("mm");
geoBiasLocTgtCmd->SetToBeBroadcasted(false);
geoBiasLocTgtCmd->AvailableForStates(G4State_PreInit);
geoBiasFucCmd = new G4UIcmdWithAnInteger("/gorad/bias/geomImpFactor",this);
geoBiasFucCmd->SetGuidance("Alternate the geometry importance biasing factor.");
geoBiasFucCmd->SetGuidance("By default the factor is set to 2. We do not recommend the factor to be much larger than 2.");
geoBiasFucCmd->SetGuidance("This command has to follow /gorad/bias/geomImportance command.");
geoBiasFucCmd->SetParameterName("factor",false);
geoBiasFucCmd->SetDefaultValue(2);
geoBiasFucCmd->SetRange("factor > 0");
geoBiasFucCmd->SetToBeBroadcasted(false);
geoBiasFucCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
geoBiasProbCmd = new G4UIcmdWithADouble("/gorad/bias/geomImpProbability",this);
geoBiasProbCmd->SetGuidance("Reduce the probability of geometry importance biasing to avoid over biasing.");
geoBiasProbCmd->SetGuidance("By default the probability is set to 1.0 (i.e. 100%).");
geoBiasProbCmd->SetGuidance("This command has to follow /gorad/bias/geomImportance command.");
geoBiasProbCmd->SetParameterName("prob",true);
geoBiasProbCmd->SetDefaultValue(1.);
geoBiasProbCmd->SetRange("prob > 0. && prob <= 1.0");
geoBiasProbCmd->SetToBeBroadcasted(false);
geoBiasProbCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
if(verboseLevel>0)
{ G4cout << "UI commands /gorad/bias/ instantiated." << G4endl; }
}
GRGeomBiasMessenger::~GRGeomBiasMessenger()
{
delete geoBiasProbCmd;
delete geoBiasFucCmd;
delete geoBiasLocTgtCmd;
delete geoBiasInRadCmd;
delete geoBiasLocCmd;
delete geoBiasCmd;
delete biasDir;
}
void GRGeomBiasMessenger::SetNewValue(G4UIcommand * command,G4String newVal)
{
if(command==geoBiasCmd)
{
G4Tokenizer next(newVal);
G4int nL = StoI(next());
G4String r = next() + " ";
r += next();
detector->GeomImp(nL,geoBiasCmd->ConvertToDimensionedDouble(r));
physics->ApplyGeomImpBias();
}
else
{ // following commands have to come after /gorad/bias/geomImportance command.
G4bool applyGeomImpBias = detector->ApplyGeomImpBias();
if(!applyGeomImpBias)
{
G4ExceptionDescription ed;
ed << "This command has to follow /gorad/bias/geomImportance command. Command failed.";
command->CommandFailed(ed);
}
else if(command==geoBiasLocCmd)
{
detector->GeomImpLocate(geoBiasLocCmd->GetNew3VectorValue(newVal));
}
else if(command==geoBiasInRadCmd)
{
G4double rt = detector->GeomImpInnerRadius(geoBiasInRadCmd->GetNewDoubleValue(newVal));
if(rt<0.)
{
G4ExceptionDescription ed;
ed << "Specified radius is too large. It has to be smaller than the outermost sphere "
<< -rt << " (mm)\n" << "command failed.";
command->CommandFailed(ed);
}
}
else if(command==geoBiasLocTgtCmd)
{
G4double dr = detector->GeomImpLocateTgt(geoBiasLocTgtCmd->GetNew3VectorValue(newVal));
if(dr>0.)
{
G4ExceptionDescription ed;
ed << "Distance between (x0,y,0,z0) and (xT,yT,zT) must be smaller than radius*(nLayer-1)/nLayer, "
<< dr << " (mm)\n" << "command failed.";
command->CommandFailed(ed);
}
}
else if(command==geoBiasFucCmd)
{
detector->GeomImpFactor(StoI(newVal));
}
else if(command==geoBiasProbCmd)
{
detector->GeomImpProb(StoD(newVal));
}
}
}
G4String GRGeomBiasMessenger::GetCurrentValue(G4UIcommand* /*command*/)
{
G4String val;
return val;
}
@@ -0,0 +1,129 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRGeomImpBiasWorld.cc
// A parallel world class that defines the geometry
// of the geometry improtance biasing.
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRGeomImpBiasWorld.hh"
#include "GRDetectorConstruction.hh"
#include "G4Orb.hh"
#include "G4LogicalVolume.hh"
#include "G4VPhysicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4Region.hh"
#include "GRBiasingRegionInfo.hh"
#include "G4UIcommand.hh"
#include "G4VisAttributes.hh"
GRGeomImpBiasWorld::GRGeomImpBiasWorld(G4String& wName,GRDetectorConstruction* det)
: G4VUserParallelWorld(wName),detector(det)
{
stateNotifier = new GRGeomImpBiasWorldStateNotifier(this);
}
GRGeomImpBiasWorld::~GRGeomImpBiasWorld()
{
delete stateNotifier;
}
void GRGeomImpBiasWorld::Construct()
{
if(constructed) return;
constructed = true;
fWorld = GetWorld(); //physical volume of the world volume of parallel world
G4LogicalVolume* motherLog = fWorld->GetLogicalVolume();
biasingRegion = new G4Region(fWorldName+"_Region");
auto biasInfo = new GRBiasingRegionInfo();
biasingRegion->SetUserInformation(biasInfo);
biasingRegion->AddRootLogicalVolume(motherLog);
biasingRegion->SetWorld(fWorld);
G4VisAttributes* wvisatt = new G4VisAttributes(G4Colour(.2,.2,0.));
wvisatt->SetVisibility(false);
motherLog->SetVisAttributes(wvisatt);
G4double r0 = detector->geoImpP.radius;
if(r0 < 0.)
{
// radius of the outermost sphere is not specified, so seting it to the default
// value as the 80% of the world volume.
r0 = GRDetectorConstruction::GetWorldSize() * 0.8;
G4cout<<"############ Radius of the outermost biasing sphere is set to "<<r0<<" (mm)"<<G4endl;
}
G4int nL = detector->geoImpP.nLayer;
G4ThreeVector dp = (detector->geoImpP.posT - detector->geoImpP.pos0) / (nL-1);
G4double rt = detector->geoImpP.radiusT;
if(rt<0.)
{ rt = r0/nL; }
G4double dr = (r0 - rt)/(nL-1);
for(G4int i=0;i<nL;i++)
{
G4double r = r0 - dr*i;
G4String vName = fWorldName + "_" + G4UIcommand::ConvertToString(i);
auto sph = new G4Orb(vName+"_solid",r);
auto lv = new G4LogicalVolume(sph,nullptr,vName+"_lv");
G4ThreeVector pos = detector->geoImpP.pos0;
if(i!=0) pos = dp;
new G4PVPlacement(0,pos,lv,vName+"_pv",motherLog,false,i+1);
motherLog = lv;
G4VisAttributes* visatt = new G4VisAttributes(G4Colour(.7,.7,0.));
visatt->SetVisibility(true);
lv->SetVisAttributes(visatt);
}
return;
}
void GRGeomImpBiasWorld::ConstructSD()
{ ; }
void GRGeomImpBiasWorld::Update()
{
GRBiasingRegionInfo* biasInfo = static_cast<GRBiasingRegionInfo*>(biasingRegion->GetUserInformation());
biasInfo->SetBiasingFactor(detector->geoImpP.factor);
biasInfo->SetProbability(detector->geoImpP.prob);
}
@@ -0,0 +1,138 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRInitialization.hh
// Defines the initialization procedure of Gorad and Geant4
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRInitialization.hh"
#include "GRDetectorConstruction.hh"
#include "GRPhysicsList.hh"
#include "GRActionInitialization.hh"
#include "GRPrimGenActionMessenger.hh"
#include "G4GenericMessenger.hh"
#include "GRGeomBiasMessenger.hh"
#include "GRScoreWriter.hh"
#include "G4RunManager.hh"
#include "G4ScoringManager.hh"
#include "G4UIdirectory.hh"
#include "G4UnitsTable.hh"
#include "G4SystemOfUnits.hh"
GRInitialization::GRInitialization(G4int verboseLvl)
: verboseLevel(verboseLvl)
{
// adding unites
new G4UnitDefinition("milligray","mGy","Dose",1.e-3*gray);
new G4UnitDefinition("microgray","muGy","Dose",1.e-6*gray);
new G4UnitDefinition("nanogray","nGy","Dose",1.e-9*gray);
G4ScoringManager::GetScoringManager()->SetScoreWriter(new GRScoreWriter());
messenger = new G4GenericMessenger(this,"/gorad/","GORAD commands");
auto& initCmd = messenger->DeclareMethod("initialize",
&GRInitialization::Initialize,"Initialize Gorad and G4RunManager");
initCmd.SetToBeBroadcasted(false);
initCmd.SetStates(G4State_PreInit);
detector = new GRDetectorConstruction();
physics = new GRPhysicsList();
actionInitialization = new GRActionInitialization();
sourceMessenger = new GRPrimGenActionMessenger();
geomBiasMessenger = new GRGeomBiasMessenger(detector,physics,verboseLvl);
}
GRInitialization::~GRInitialization()
{
delete geomBiasMessenger;
delete sourceMessenger;
delete messenger;
}
void GRInitialization::Initialize()
{
auto runManager = G4RunManager::GetRunManager();
runManager->SetUserInitialization(detector);
runManager->SetUserInitialization(physics);
runManager->SetUserInitialization(actionInitialization);
if(verboseLevel>0) G4cout << "GORAD is initialized.........." << G4endl;
runManager->Initialize();
sourceMessenger->UpdateParticleList();
}
#include "G4UIExecutive.hh"
#include "G4UIQt.hh"
void GRInitialization::SetWindowText(G4UIExecutive* ui)
{
// If the current GUI is not G4UIQt, do nothing and return.
if(!(ui->IsGUI())) return;
#ifdef G4UI_USE_QT
G4UIQt* qt = dynamic_cast<G4UIQt*>(ui->GetSession());
if(!qt) return;
qt->SetStartPage(std::string("<table width='100%'><tr><td width='50%'></td><td><div ")+
"style='color: rgb(140, 31, 31); font-size: xx-large; font-family: Garamond, serif; "+
"padding-bottom: 0px; font-weight: normal'>GORAD "+
"</div></td></td></tr></table>"+
"<p>&nbsp;</p>"+
"<div><dl>"+
"<dd><b>Gorad (Geant4 Open-source Radiation Analysis and Design) is meant to be "+
"a turn-key application for radiation analysis and spacecraft design "+
"built on top of Geant4. Simulation geometry should be provided in the form of GDML. "+
"Gorad is developed under the NASA JSC contract NNJ15HK11B."+
"</dd></dl></div>"+
"<p>&nbsp;</p>"+
"<div style='background:#EEEEEE;'><b>Tooltips :</b><ul>"+
"<li><b>Start an interactive run :</b><br />"+
"/control/execute <i>run.mac</i><br />"+
"/run/beamOn <i>number_of_events</i></li></ul></div>"+
"<div style='background:#EEEEEE;'><b>Documentation :</b><ul>"+
"<li><i>"+
"<b>GORAD manual</b> and a sample Orion spacecraft shield geometry can be found at<br />"+
"<a href='https://twiki.cern.ch/twiki/bin/view/Geant4/AdvancedExamplesGorad'>"+
"https://twiki.cern.ch/twiki/bin/view/Geant4/AdvancedExamplesGorad"+
"</a></i></li>"+
"</ul></div>"
);
#endif
}
@@ -0,0 +1,172 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRParallelWorldBiasingProcess.cc
// A process that takes care of the geometry importance biasing.
// This class assumes the existance of a parallel world dedicated
// to the geometry importance biasing and biasing parameters are
// associated to the region defined in that parallel world.
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "G4ios.hh"
#include "GRParallelWorldBiasingProcess.hh"
#include "G4Step.hh"
#include "G4Track.hh"
#include "G4Navigator.hh"
#include "G4PathFinder.hh"
#include "G4VTouchable.hh"
#include "G4VPhysicalVolume.hh"
#include "G4ParticleChange.hh"
#include "G4ParticleChangeForNothing.hh"
#include "Randomize.hh"
#include "G4Region.hh"
#include "GRBiasingRegionInfo.hh"
GRParallelWorldBiasingProcess::
GRParallelWorldBiasingProcess(const G4String& processName,G4ProcessType theType)
:G4ParallelWorldProcess(processName,theType)
{
particleChange = new G4ParticleChange();
emptyParticleChange = new G4ParticleChangeForNothing();
}
GRParallelWorldBiasingProcess::~GRParallelWorldBiasingProcess()
{;}
G4VParticleChange* GRParallelWorldBiasingProcess::PostStepDoIt(
const G4Track& track,
const G4Step& step)
{
fOldGhostTouchable = fGhostPostStepPoint->GetTouchableHandle();
CopyStep(step);
if(fOnBoundary)
{
fNewGhostTouchable = fPathFinder->CreateTouchableHandle(fNavigatorID);
}
else
{
fNewGhostTouchable = fOldGhostTouchable;
}
fGhostPreStepPoint->SetTouchableHandle(fOldGhostTouchable);
fGhostPostStepPoint->SetTouchableHandle(fNewGhostTouchable);
if(fNewGhostTouchable->GetVolume() == nullptr)
{
// world volume boundary
emptyParticleChange->Initialize(track);
return emptyParticleChange;
}
if(fNewGhostTouchable->GetVolume() == fOldGhostTouchable->GetVolume())
{
// stayed in the same volume
emptyParticleChange->Initialize(track);
return emptyParticleChange;
}
G4int preStepCopyNo = fOldGhostTouchable->GetReplicaNumber();
G4int postStepCopyNo = fNewGhostTouchable->GetReplicaNumber();
GRBiasingRegionInfo* biasInfo = static_cast<GRBiasingRegionInfo*>
(fNewGhostTouchable->GetVolume()->GetLogicalVolume()->GetRegion()->GetUserInformation());
auto probability = biasInfo->GetProbability();
if(probability < 1.)
{
// skip biasing to avoid over biasing
G4double ran = G4UniformRand();
if(ran > probability)
{
emptyParticleChange->Initialize(track);
return emptyParticleChange;
}
}
G4double trackWeight = track.GetWeight();
particleChange->Initialize(track);
auto biasFactor = biasInfo->GetBiasingFactor();
if(biasFactor==1)
{
// not biasing
emptyParticleChange->Initialize(track);
return emptyParticleChange;
}
if(preStepCopyNo < postStepCopyNo)
{
// getting into more important volume, i.e. do splitting
trackWeight /= biasFactor;
particleChange->ProposeParentWeight(trackWeight);
for(G4int iClone=1;iClone<biasFactor;iClone++)
{
G4Track* clonedTrack = new G4Track(track);
clonedTrack->SetWeight(trackWeight);
particleChange->AddSecondary(clonedTrack);
}
particleChange->SetSecondaryWeightByProcess(true);
}
else if(preStepCopyNo > postStepCopyNo)
{
// getting into less important volume, i.e. do Russian Rouletting
G4double survivalRate = 1.0/biasFactor;
G4double ran = G4UniformRand();
if(ran > survivalRate)
{
// dead
particleChange->ProposeTrackStatus(fStopAndKill);
}
else
{
// survive
trackWeight *= biasFactor;
particleChange->ProposeParentWeight(trackWeight);
}
}
else
{
// This should not happen!!
G4ExceptionDescription ed;
ed << "pre step point : "<<fOldGhostTouchable->GetVolume()->GetName()<<" - copy no. "<<fOldGhostTouchable->GetReplicaNumber()<<"\n"
<< "post step point : "<<fNewGhostTouchable->GetVolume()->GetName()<<" - copy no. "<<fNewGhostTouchable->GetReplicaNumber();
G4Exception("GRParallelWorldBiasingProcess::PostStepDoIt()","GoradProc0001",FatalException,ed);
}
return particleChange;
}
@@ -0,0 +1,91 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRParallelWorldPhysics.cc
// Utility class that adds GRParallelWorldBiasingProcess to the
// process managers of particles
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRParallelWorldPhysics.hh"
#include "G4ParticleDefinition.hh"
#include "G4ProcessManager.hh"
#include "G4TransportationManager.hh"
#include "GRParallelWorldBiasingProcess.hh"
// factory
#include "G4PhysicsConstructorFactory.hh"
//
G4_DECLARE_PHYSCONSTR_FACTORY(GRParallelWorldPhysics);
GRParallelWorldPhysics::GRParallelWorldPhysics(const G4String& name, G4bool layeredMass)
: G4VPhysicsConstructor(name), fLayeredMass(layeredMass)
{;}
GRParallelWorldPhysics::~GRParallelWorldPhysics()
{;}
void GRParallelWorldPhysics::ConstructParticle()
{;}
void GRParallelWorldPhysics::ConstructProcess()
{
// Make sure the parallel world registered
G4TransportationManager::GetTransportationManager()
->GetParallelWorld(namePhysics);
// Add parallel world process
GRParallelWorldBiasingProcess* theParallelWorldProcess
= new GRParallelWorldBiasingProcess(namePhysics);
theParallelWorldProcess->SetParallelWorld(namePhysics);
theParallelWorldProcess->SetLayeredMaterialFlag(fLayeredMass);
auto myParticleIterator=GetParticleIterator();
myParticleIterator->reset();
while( (*myParticleIterator)() ){
G4ParticleDefinition* particle = myParticleIterator->value();
G4ProcessManager* pmanager = particle->GetProcessManager();
pmanager->AddProcess(theParallelWorldProcess);
if(theParallelWorldProcess->IsAtRestRequired(particle))
{pmanager->SetProcessOrdering(theParallelWorldProcess, idxAtRest, 9900);}
pmanager->SetProcessOrderingToSecond(theParallelWorldProcess, idxAlongStep);
pmanager->SetProcessOrdering(theParallelWorldProcess, idxPostStep, 9900);
}
}
@@ -0,0 +1,252 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRPhysicsList.cc
// Gorad Physics List
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRPhysicsList.hh"
#include "GRPhysicsListMessenger.hh"
#include "G4SystemOfUnits.hh"
#include "G4PhysListFactory.hh"
GRPhysicsList::GRPhysicsList()
: PLName("FTFP_BERT"), physList(nullptr),
EM_opt("Op_0"), Had_opt("FTFP_BERT"),
addHP(false), addRDM(false), addRMC(false), addOptical(false),
stepLimit_opt(-1)
{
factory = nullptr;
messenger = new GRPhysicsListMessenger(this);
globalCuts[0] = 0.7*mm; // e-
globalCuts[1] = 0.7*mm; // e+
globalCuts[2] = 0.7*mm; // gamma
globalCuts[3] = 0.7*mm; // proton
}
GRPhysicsList::~GRPhysicsList()
{
delete factory;
if(physList) delete physList;
delete messenger;
}
void GRPhysicsList::ConstructParticle()
{
if(!physList) GeneratePL();
physList->ConstructParticle();
}
void GRPhysicsList::ConstructProcess()
{
if(!physList) GeneratePL();
physList->ConstructProcess();
}
#include "G4Region.hh"
#include "G4ProductionCuts.hh"
void GRPhysicsList::SetCuts()
{
if(!physList) GeneratePL();
physList->SetCutValue(globalCuts[2],"gamma"); // gamma should be defined first!
physList->SetCutValue(globalCuts[0],"e-");
physList->SetCutValue(globalCuts[1],"e+");
physList->SetCutValue(globalCuts[3],"proton");
}
void GRPhysicsList::SetGlobalCuts(G4double val)
{
for(G4int i=0; i<4; i++)
{ SetGlobalCut(i,val); }
if(physList) SetCuts();
}
void GRPhysicsList::SetGlobalCut(G4int i, G4double val)
{
globalCuts[i] = val;
if(physList) SetCuts();
}
void GRPhysicsList::GeneratePLName()
{
G4String plname = Had_opt;
if(addHP && Had_opt != "Shielding") plname += "_HP";
G4String EMopt = "";
if(EM_opt=="Op_1") EMopt = "_EMV";
else if(EM_opt=="Op_3") EMopt = "_EMY";
else if(EM_opt=="Op_4") EMopt = "_EMZ";
else if(EM_opt=="LIV") EMopt = "_LIV";
else if(EM_opt=="LIV_Pol") G4cout << "EM option <LIV_Pol> is under development." << G4endl;
plname += EMopt;
auto valid = factory->IsReferencePhysList(plname);
if(valid)
{ PLName = plname; }
else
{
G4ExceptionDescription ed;
ed << "Physics List <" << plname << "> is not a valid reference physics list.";
G4Exception("GRPhysicsList::GeneratePLName()","GRPHYS0001",
FatalException,ed);
}
}
#include "G4RadioactiveDecayPhysics.hh"
#include "G4OpticalPhysics.hh"
#include "G4StepLimiterPhysics.hh"
#include "G4ParallelWorldPhysics.hh"
#include "G4GenericBiasingPhysics.hh"
#include "GRParallelWorldPhysics.hh"
#include "G4ProcessTable.hh"
#include "G4EmParameters.hh"
#include "G4HadronicParameters.hh"
void GRPhysicsList::GeneratePL()
{
if(physList) return;
factory = new G4PhysListFactory();
GeneratePLName();
physList = factory->GetReferencePhysList(PLName);
G4cout << "Creating " << PLName << " physics list ################ " << applyGeomImpBias << G4endl;
if(addRDM && Had_opt != "Shielding")
{ physList->RegisterPhysics(new G4RadioactiveDecayPhysics());
G4cout << "Adding G4RadioactiveDecayPhysics ################ " << G4endl; }
if(addRMC)
{ G4cout << "Reverse Monte Calro option is under development." << G4endl; }
if(stepLimit_opt>=0)
{ physList->RegisterPhysics(new G4StepLimiterPhysics());
G4cout << "Adding G4StepLimiterPhysics ################ " << G4endl; }
if(addOptical) // Optical processes should come last!
{ physList->RegisterPhysics(new G4OpticalPhysics());
G4cout << "Adding G4OpticalPhysics ################ " << G4endl; }
if(applyGeomImpBias) // Geometry Importance Biasing with parallel world
{
physList->RegisterPhysics(new GRParallelWorldPhysics("GeomBias",false));
G4cout << "Adding G4GenericBiasingPhysics for GeomBias ################ " << G4endl;
}
G4int verbose = G4ProcessTable::GetProcessTable()->GetVerboseLevel();
physList->SetVerboseLevel(verbose);
G4EmParameters::Instance()->SetVerbose(verbose);
G4HadronicParameters::Instance()->SetVerboseLevel(verbose);
}
#include "G4RegionStore.hh"
G4Region* GRPhysicsList::FindRegion(const G4String& reg) const
{
auto store = G4RegionStore::GetInstance();
return store->GetRegion(reg);
}
G4Region* GRPhysicsList::SetLocalCut(const G4String& reg,G4int i,G4double val)
{
auto regPtr = FindRegion(reg);
if(!regPtr) return regPtr;
auto cuts = regPtr->GetProductionCuts();
if(!cuts)
{
cuts = new G4ProductionCuts();
regPtr->SetProductionCuts(cuts);
}
cuts->SetProductionCut(val,i);
return regPtr;
}
G4double GRPhysicsList::GetLocalCut(const G4String& reg,G4int i) const
{
auto regPtr = FindRegion(reg);
G4double val = -1.0;
if(regPtr)
{
auto cuts = regPtr->GetProductionCuts();
if(cuts) val = cuts->GetProductionCut(i);
}
return val;
}
#include "G4UserLimits.hh"
G4Region* GRPhysicsList::SetLocalStepLimit(const G4String& reg,G4double val)
{
auto regPtr = FindRegion(reg);
if(!regPtr) return regPtr;
auto uLim = regPtr->GetUserLimits();
if(!uLim)
{
uLim = new G4UserLimits(val);
regPtr->SetUserLimits(uLim);
}
else
{ uLim->SetMaxAllowedStep(val); }
return regPtr;
}
#include "G4Track.hh"
G4double GRPhysicsList::GetLocalStepLimit(const G4String& reg) const
{
static G4Track dummyTrack;
auto regPtr = FindRegion(reg);
G4double val = -1.0;
if(regPtr)
{
auto uLim = regPtr->GetUserLimits();
if(uLim) val = uLim->GetMaxAllowedStep(dummyTrack);
}
return val;
}
void GRPhysicsList::SetGlobalStepLimit(G4double val)
{ SetLocalStepLimit("DefaultRegionForTheWorld",val); }
G4double GRPhysicsList::GetGlobalStepLimit() const
{ return GetLocalStepLimit("DefaultRegionForTheWorld"); }
@@ -0,0 +1,367 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRPhysicsListMessenger.cc
// A messenger class that handles Gorad physics list options.
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRPhysicsListMessenger.hh"
#include "GRPhysicsList.hh"
#include "G4UIcommand.hh"
#include "G4UIparameter.hh"
#include "G4UIdirectory.hh"
#include "G4UIcmdWithAString.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "G4UIcmdWithoutParameter.hh"
GRPhysicsListMessenger::GRPhysicsListMessenger(GRPhysicsList* pl)
: pPL(pl)
{
G4UIparameter* param = nullptr;
physDir = new G4UIdirectory("/gorad/physics/");
physDir->SetGuidance("GORAD physics selection");
selectEMCmd = new G4UIcmdWithAString("/gorad/physics/EM",this);
selectEMCmd->AvailableForStates(G4State_PreInit);
selectEMCmd->SetToBeBroadcasted(false);
selectEMCmd->SetParameterName("EM_option",true);
selectEMCmd->SetCandidates("Op_0 Op_1 Op_3 Op_4 LIV LIV_Pol");
selectEMCmd->SetDefaultValue("Op_0");
selectEMCmd->SetGuidance("Select EM Physics option");
selectEMCmd->SetGuidance(" Op_0 (default) : Suitable to medium and high energy applications");
selectEMCmd->SetGuidance(" Op_1 : Faster than Op_0 because of less accurate MSC step limitation");
selectEMCmd->SetGuidance(" Op_3 : Suitable for medical applications - more accurate MSC for all particles");
selectEMCmd->SetGuidance(" Op_4 : Most accurate (GS MSC model with Mott correction and error-free stepping for e+/-");
selectEMCmd->SetGuidance(" LIV : Livermore models for e-/gamma below 1 GeV, otherwise Op_0");
selectEMCmd->SetGuidance(" LIV_Pol : Polarized extension of Livermore models (t.b.a.)");
selectHadCmd = new G4UIcmdWithAString("/gorad/physics/Hadronic",this);
selectHadCmd->AvailableForStates(G4State_PreInit);
selectHadCmd->SetToBeBroadcasted(false);
selectHadCmd->SetParameterName("Had_option",true);
selectHadCmd->SetCandidates("FTFP_BERT QGSP_BIC Shielding");
selectHadCmd->SetDefaultValue("FTFP_BERT");
selectHadCmd->SetGuidance("Select Hadronic Physics option");
selectHadCmd->SetGuidance(" FTFP_BERT (default) : Fritiof string + Bertini cascade + Precompound de-excitation");
selectHadCmd->SetGuidance(" suitable to most of midium and high energy applications");
selectHadCmd->SetGuidance(" QGSP_BIC : Quark-Gluon-String + Fritiof string + Binary cascade + Precompound de-excitation");
selectHadCmd->SetGuidance(" suitable for lower energy applications such as medical");
selectHadCmd->SetGuidance(" Shielding : Similar to FTFP+BERT with better ion-ion interactions.");
selectHadCmd->SetGuidance(" High-Precision neutron and Radioactive Decay models are included by default.");
addHPCmd = new G4UIcmdWithoutParameter("/gorad/physics/addHP",this);
addHPCmd->AvailableForStates(G4State_PreInit);
addHPCmd->SetToBeBroadcasted(false);
addHPCmd->SetGuidance("Add High-Precision neutron model.");
addHPCmd->SetGuidance(" Note: Shielding option has already had HP. This command does not make effect to Shielding option.");
addRDMCmd = new G4UIcmdWithoutParameter("/gorad/physics/addRDM",this);
addRDMCmd->AvailableForStates(G4State_PreInit);
addRDMCmd->SetToBeBroadcasted(false);
addRDMCmd->SetGuidance("Add Radioactive Decay model.");
addRDMCmd->SetGuidance(" Note: Shielding option has already had RDM. This command does not make effect to Shielding option.");
addRMCCmd = new G4UIcmdWithoutParameter("/gorad/physics/addRMC",this);
addRMCCmd->AvailableForStates(G4State_PreInit);
addRMCCmd->SetToBeBroadcasted(false);
addRMCCmd->SetGuidance("Add Reverse Monte Carlo.");
addOpticalCmd = new G4UIcmdWithoutParameter("/gorad/physics/addOptical",this);
addOpticalCmd->AvailableForStates(G4State_PreInit);
addOpticalCmd->SetToBeBroadcasted(false);
addOpticalCmd->SetGuidance("Add Optical physics");
addStepLimitCmd = new G4UIcmdWithAString("/gorad/physics/addStepLimit",this);
addStepLimitCmd->AvailableForStates(G4State_PreInit);
addStepLimitCmd->SetToBeBroadcasted(false);
addStepLimitCmd->SetGuidance("Add step-limiter process to artificially limit step length.");
addStepLimitCmd->SetGuidance("Specify particle types to be applied.");
addStepLimitCmd->SetGuidance(" charged (default) : applied only to the charged particles");
addStepLimitCmd->SetGuidance(" neutral : applied only to the neutral particles");
addStepLimitCmd->SetGuidance(" all : applied to all particle types");
addStepLimitCmd->SetGuidance(" e+/- : applied only to e+/e-");
addStepLimitCmd->SetGuidance(" Note: In addition to this command, you need to specify the limitation value by");
addStepLimitCmd->SetGuidance(" /gorad/physics/limit/stepLimit or /gorad/physics/limit/localStepLimt command.");
addStepLimitCmd->SetParameterName("particle",true);
addStepLimitCmd->SetDefaultValue("charged");
addStepLimitCmd->SetCandidates("charged neutral all e+/-");
physLimitDir = new G4UIdirectory("/gorad/physics/limit/");
physLimitDir->SetGuidance("Specify step limitation");
setStepLimitCmd = new G4UIcmdWithADoubleAndUnit("/gorad/physics/limit/stepLimit",this);
setStepLimitCmd->AvailableForStates(G4State_Idle);
setStepLimitCmd->SetToBeBroadcasted(false);
setStepLimitCmd->SetParameterName("length",false);
setStepLimitCmd->SetDefaultUnit("mm");
setStepLimitCmd->SetGuidance("Define the limitation of the step length");
setStepLimitCmd->SetGuidance("This limitation is applied to the entire geometry except regions that has its dedicated limit.");
setRegionStepLimitCmd = new G4UIcommand("/gorad/physics/limit/regionStepLimit",this);
setRegionStepLimitCmd->AvailableForStates(G4State_Idle);
setRegionStepLimitCmd->SetToBeBroadcasted(false);
setRegionStepLimitCmd->SetGuidance("Define the limitation of the step length for the specified region");
setRegionStepLimitCmd->SetGuidance(" [usage] /gorad/physics/limit/regionStepLimit region length [unit]");
setRegionStepLimitCmd->SetGuidance(" region (string) : region name");
setRegionStepLimitCmd->SetGuidance(" Note: Region has to be defined in advance to this command.");
setRegionStepLimitCmd->SetGuidance(" If new region is necessary, use /gorad/geometry/createRegion to create it.");
param = new G4UIparameter("region",'s',false);
setRegionStepLimitCmd->SetParameter(param);
param = new G4UIparameter("length",'d',false);
setRegionStepLimitCmd->SetParameter(param);
param = new G4UIparameter("unit",'s',true);
param->SetDefaultUnit("mm");
setRegionStepLimitCmd->SetParameter(param);
physCutDir = new G4UIdirectory("/gorad/physics/cuts/");
physCutDir->SetGuidance("Specify production thresholds (a.k.a. cuts)");
setCutCmd = new G4UIcmdWithADoubleAndUnit("/gorad/physics/cuts/setCuts",this);
setCutCmd->AvailableForStates(G4State_PreInit, G4State_Idle);
setCutCmd->SetToBeBroadcasted(false);
setCutCmd->SetParameterName("length",false);
setCutCmd->SetDefaultUnit("mm");
setCutCmd->SetGuidance("Specify production thresholds (a.k.a. cuts) that is applied to the entire geometry");
setCutCmd->SetGuidance("This threshold is applied to all of e-, e+, gamma and proton.");
setCutCmd->SetGuidance("Threshold of each particle can be overwitted by /gorad/physics/cuts/setParticleCut command");
setCutParticleCmd = new G4UIcommand("/gorad/physics/cuts/setParticleCut",this);
setCutParticleCmd->AvailableForStates(G4State_PreInit, G4State_Idle);
setCutParticleCmd->SetToBeBroadcasted(false);
setCutParticleCmd->SetGuidance("Specify production threshold (a.k.a. cut) for the specified particle that is applied to the entire geometry");
setCutParticleCmd->SetGuidance(" [usage] /gorad/physics/setParticleCut particle cut unit");
param = new G4UIparameter("particle",'s',false);
param->SetParameterCandidates("e- e+ gamma proton");
setCutParticleCmd->SetParameter(param);
param = new G4UIparameter("cut",'d',false);
setCutParticleCmd->SetParameter(param);
param = new G4UIparameter("unit",'s',true);
param->SetDefaultUnit("mm");
setCutParticleCmd->SetParameter(param);
setCutRegionCmd = new G4UIcommand("/gorad/physics/cuts/setRegionCut",this);
setCutRegionCmd->AvailableForStates(G4State_Idle);
setCutRegionCmd->SetToBeBroadcasted(false);
setCutRegionCmd->SetGuidance("Specify production threshold (a.k.a. cut) that is applied to the specified region");
setCutRegionCmd->SetGuidance(" [usage] /gorad/physics/setRegionCut region cut unit");
setCutRegionCmd->SetGuidance("This threshold is applied to all of e-, e+, gamma and proton.");
setCutRegionCmd->SetGuidance("Threshold of each particle can be overwitted by /gorad/physics/cuts/setRegionParticleCut command");
setCutRegionCmd->SetGuidance(" Note: Region has to be defined in advance to this command.");
setCutRegionCmd->SetGuidance(" If new region is necessary, use /gorad/geometry/createRegion to create it.");
param = new G4UIparameter("region",'s',false);
setCutRegionCmd->SetParameter(param);
param = new G4UIparameter("cut",'d',false);
setCutRegionCmd->SetParameter(param);
param = new G4UIparameter("unit",'s',true);
param->SetDefaultUnit("mm");
setCutRegionCmd->SetParameter(param);
setCutRegionParticleCmd = new G4UIcommand("/gorad/physics/cuts/setRegionParticleCut",this);
setCutRegionParticleCmd->AvailableForStates(G4State_Idle);
setCutRegionParticleCmd->SetToBeBroadcasted(false);
setCutRegionParticleCmd->SetGuidance("Specify production threshold (a.k.a. cut) that is applied to the specified region");
setCutRegionParticleCmd->SetGuidance(" [usage] /gorad/physics/setRegionParticleCut region particle cut unit");
setCutRegionParticleCmd->SetGuidance(" Note: Region has to be defined in advance to this command.");
setCutRegionParticleCmd->SetGuidance(" If new region is necessary, use /gorad/geometry/createRegion to create it.");
param = new G4UIparameter("region",'s',false);
setCutRegionParticleCmd->SetParameter(param);
param = new G4UIparameter("particle",'s',false);
param->SetParameterCandidates("e- e+ gamma proton");
setCutRegionParticleCmd->SetParameter(param);
param = new G4UIparameter("cut",'d',false);
setCutRegionParticleCmd->SetParameter(param);
param = new G4UIparameter("unit",'s',true);
param->SetDefaultUnit("mm");
setCutRegionParticleCmd->SetParameter(param);
}
GRPhysicsListMessenger::~GRPhysicsListMessenger()
{
delete selectEMCmd;
delete selectHadCmd;
delete addHPCmd;
delete addRDMCmd;
delete addRMCCmd;
delete addOpticalCmd;
delete addStepLimitCmd;
delete setStepLimitCmd;
delete setRegionStepLimitCmd;
delete setCutCmd;
delete setCutParticleCmd;
delete setCutRegionCmd;
delete setCutRegionParticleCmd;
delete physLimitDir;
delete physCutDir;
delete physDir;
}
#include "G4Tokenizer.hh"
void GRPhysicsListMessenger::SetNewValue(G4UIcommand* cmd, G4String val)
{
if(cmd==selectEMCmd)
{ pPL->SetEM(val); }
else if(cmd==selectHadCmd)
{ pPL->SetHad(val); }
else if(cmd==addHPCmd)
{ pPL->AddHP(); }
else if(cmd==addRDMCmd)
{ pPL->AddRDM(); }
else if(cmd==addRMCCmd)
{ pPL->AddRMC(); }
else if(cmd==addOpticalCmd)
{ G4cout<<"Not yet implemented."<<G4endl; }
else if(cmd==addStepLimitCmd)
{
G4int opt = 0;
if(val=="neutral") opt = 1;
else if(val=="all") opt = 2;
else if(val=="e+/-") opt = 3;
pPL->AddStepLimit(opt);
}
else if(cmd==setStepLimitCmd)
{ pPL->SetGlobalStepLimit(setStepLimitCmd->GetNewDoubleValue(val)); }
else if(cmd==setRegionStepLimitCmd)
{
G4Tokenizer next(val);
G4String reg = next();
G4String newVal = next();
newVal += " ";
newVal += next();
auto regPtr = pPL->SetLocalStepLimit(reg,setRegionStepLimitCmd->ConvertToDimensionedDouble(newVal));
if(!regPtr)
{
G4ExceptionDescription ed;
ed << "Region <" << reg << "> is not defined. Region has to be defined in advance to this command."
<< "\nIf new region is necessary, use /gorad/geometry/createRegion to create it.";
setRegionStepLimitCmd->CommandFailed(ed);
}
}
else if(cmd==setCutCmd)
{ pPL->SetGlobalCuts(setCutCmd->GetNewDoubleValue(val)); }
else if(cmd==setCutParticleCmd)
{
G4Tokenizer next(val);
G4String pat = next();
G4String newVal = next();
newVal += " ";
newVal += next();
G4int i = 0;
if(pat=="e-") i = 0;
else if(pat=="e+") i = 1;
else if(pat=="gamma") i = 2;
else if(pat=="proton") i = 3;
pPL->SetGlobalCut(i,setCutParticleCmd->ConvertToDimensionedDouble(newVal));
}
else if(cmd==setCutRegionCmd)
{
G4Tokenizer next(val);
G4String reg = next();
G4String newVal = next();
newVal += " ";
newVal += next();
auto regPtr = pPL->SetLocalCuts(reg,setCutRegionCmd->ConvertToDimensionedDouble(newVal));
if(!regPtr)
{
G4ExceptionDescription ed;
ed << "Region <" << reg << "> is not defined. Region has to be defined in advance to this command."
<< "\nIf new region is necessary, use /gorad/geometry/createRegion to create it.";
setRegionStepLimitCmd->CommandFailed(ed);
}
}
else if(cmd==setCutRegionParticleCmd)
{
G4Tokenizer next(val);
G4String reg = next();
G4String pat = next();
G4int i = 0;
if(pat=="e-") i = 0;
else if(pat=="e+") i = 1;
else if(pat=="gamma") i = 2;
else if(pat=="proton") i = 3;
G4String newVal = next();
newVal += " ";
newVal += next();
auto regPtr = pPL->SetLocalCut(reg,i,setCutRegionParticleCmd->ConvertToDimensionedDouble(newVal));
if(!regPtr)
{
G4ExceptionDescription ed;
ed << "Region <" << reg << "> is not defined. Region has to be defined in advance to this command."
<< "\nIf new region is necessary, use /gorad/geometry/createRegion to create it.";
setRegionStepLimitCmd->CommandFailed(ed);
}
}
}
G4String GRPhysicsListMessenger::GetCurrentValue(G4UIcommand* cmd)
{
G4String val("");
if(cmd==selectEMCmd)
{ val = pPL->GetEM(); }
else if(cmd==selectHadCmd)
{ val = pPL->GetHad(); }
else if(cmd==addHPCmd)
{ val = cmd->ConvertToString(pPL->IfHP()); }
else if(cmd==addRDMCmd)
{ val = cmd->ConvertToString(pPL->IfRDM()); }
else if(cmd==addRMCCmd)
{ val = cmd->ConvertToString(pPL->IfRMC()); }
else if(cmd==addOpticalCmd)
{ G4cout<<"Not yet implemented."<<G4endl; }
else if(cmd==addStepLimitCmd)
{
auto opt = pPL->IfStepLimit();
switch(opt)
{
case 0: val = "charged"; break;
case 1: val = "neutral"; break;
case 2: val = "all"; break;
case 3: val = "e+/-"; break;
default : val = "undefined"; break;
}
}
return val;
}
@@ -0,0 +1,202 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRPrimGenActionMessenger.hh
// Header file of a messenger that handles primary generator action.
// Input radiation spectrum file should be in ASCII format and each
// row should have low-end kinetic energy and differential flux
// separated by a space.
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRPrimGenActionMessenger.hh"
#include "G4UIdirectory.hh"
#include "G4UIcommand.hh"
#include "G4UIparameter.hh"
GRPrimGenActionMessenger::GRPrimGenActionMessenger(G4int verboseLvl)
: verboseLevel(verboseLvl)
{
G4UIparameter* param = nullptr;
srcDir = new G4UIdirectory("/gorad/source/");
srcDir->SetGuidance("Define primary particle spectrum.");
defCmd = new G4UIcommand("/gorad/source/define",this);
defCmd->SetGuidance("Define primary particle spectrum.");
defCmd->SetGuidance("[usage] /gorad/source/define pName fName srcType radius unit (x0 y0 z0)");
defCmd->SetGuidance(" pName : Particle name.");
defCmd->SetGuidance(" fName : File name of the spectrum. Directory may be preceded to the file name.");
defCmd->SetGuidance(" srcType : defines how the primaries are generated.");
defCmd->SetGuidance(" Arb : Generate primaries along with the defined spectrum.");
defCmd->SetGuidance(" LW : Generate primaries in flat ditribution with track weight representing the spectrum.");
defCmd->SetGuidance(" radius : Radius of the source sphere. If it is set to -1 (default), radius is set to 98% of the world volume.");
defCmd->SetGuidance(" unit : Unit of radius value.");
defCmd->SetGuidance(" x0,y0,z0 : (Optional) location of the center of the sphere (same unit is applied as radius).");
defCmd->SetGuidance(" By default the sphere is located at the center of the world volume.");
defCmd->SetGuidance("[note] This command is not mandatory but dwialternatively granular /gps/ commands can be used for defining primary particles.");
particlePara = new G4UIparameter("pName",'s',false);
defCmd->SetParameter(particlePara);
param = new G4UIparameter("fName",'s',false);
defCmd->SetParameter(param);
param = new G4UIparameter("srcType",'s',false);
param->SetParameterCandidates("Arb LW");
defCmd->SetParameter(param);
param = new G4UIparameter("radius",'d',true);
param->SetParameterRange("radius == -1. || radius>0.");
param->SetDefaultValue(-1.);
defCmd->SetParameter(param);
param = new G4UIparameter("unit",'s',true);
param->SetDefaultUnit("m");
defCmd->SetParameter(param);
param = new G4UIparameter("x0",'d',true);
param->SetDefaultValue(0.);
defCmd->SetParameter(param);
param = new G4UIparameter("y0",'d',true);
param->SetDefaultValue(0.);
defCmd->SetParameter(param);
param = new G4UIparameter("z0",'d',true);
param->SetDefaultValue(0.);
defCmd->SetParameter(param);
defCmd->AvailableForStates(G4State_Idle);
defCmd->SetToBeBroadcasted(false);
}
GRPrimGenActionMessenger::~GRPrimGenActionMessenger()
{
delete defCmd;
delete srcDir;
}
#include "G4UImanager.hh"
#include "G4Threading.hh"
#include "G4Tokenizer.hh"
#include "G4UnitsTable.hh"
#include <fstream>
#include "GRDetectorConstruction.hh"
void GRPrimGenActionMessenger::SetNewValue(G4UIcommand * command,G4String newVal)
{
auto UI = G4UImanager::GetUIpointer();
if(verboseLevel>0) G4cout << newVal << G4endl;
G4Tokenizer next(newVal);
G4String pName = next();
G4String fName = next();
std::ifstream specFile;
specFile.open(fName,std::ios::in);
if(specFile.fail())
{
G4ExceptionDescription ed;
ed << "ERROR : File <" << fName << "> is not found.";
command->CommandFailed(ed);
return;
}
G4String srcType = next();
G4String radius = next();
G4String unit = next();
G4double r = StoD(radius);
if(r<0.)
{
r = GRDetectorConstruction::GetWorldSize() * 0.98;
radius = DtoS(r);
unit = "mm";
G4cout<<"################ Radius of the GPS sphere is set to "<<r<<" (mm)"<<G4endl;
}
G4String pos = next() + " " + next() + " " + next();
G4String cmd;
G4int ec = 0;
ec = std::max(UI->ApplyCommand("/gps/pos/shape Sphere"),ec);
cmd = "/gps/pos/centre " + pos + " " + unit;
ec = std::max(UI->ApplyCommand(cmd),ec);
cmd = "/gps/pos/radius " + radius + " " + unit;
ec = std::max(UI->ApplyCommand(cmd),ec);
ec = std::max(UI->ApplyCommand("/gps/pos/type Surface"),ec);
ec = std::max(UI->ApplyCommand("/gps/number 1"),ec);
cmd = "/gps/particle " + pName;
ec = std::max(UI->ApplyCommand(cmd),ec);
ec = std::max(UI->ApplyCommand("/gps/ang/type cos"),ec);
ec = std::max(UI->ApplyCommand("/gps/ang/maxtheta 90.0 deg"),ec);
ec = std::max(UI->ApplyCommand("/gps/ang/mintheta 0.0 deg"),ec);
cmd = "/gps/ene/type " + srcType;
ec = std::max(UI->ApplyCommand(cmd),ec);
ec = std::max(UI->ApplyCommand("/gps/hist/type arb"),ec);
enum { bufsize = 128 };
static char* line = new char[bufsize];
while(specFile.good())
{
specFile.getline(line,bufsize);
if(line[(size_t)0]=='#') continue;
G4String valStr(line);
valStr = valStr.strip(G4String::both);
valStr = valStr.strip(G4String::trailing,0x0d);
if(valStr.size()==0) continue;
cmd = "/gps/hist/point " + valStr;
ec = std::max(UI->ApplyCommand(cmd),ec);
if(specFile.eof()) break;
}
ec = std::max(UI->ApplyCommand("/gps/hist/inter Lin"),ec);
if(ec>0)
{
G4ExceptionDescription ed;
ed << "ERROR : Internal error while processing /gorad/source/define command.";
command->CommandFailed(ec,ed);
}
}
G4String GRPrimGenActionMessenger::GetCurrentValue(G4UIcommand* /*command*/)
{
G4String val;
return val;
}
#include "G4ParticleTable.hh"
void GRPrimGenActionMessenger::UpdateParticleList()
{
auto particleTable = G4ParticleTable::GetParticleTable();
G4String candList;
for(G4int i=0;i<particleTable->entries();i++)
{ candList += particleTable->GetParticleName(i) + " "; }
candList += "ion";
particlePara->SetParameterCandidates(candList);
}
@@ -0,0 +1,87 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRPrimaryGeneratorAction.cc
// Gorad primary generator action class
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRPrimaryGeneratorAction.hh"
#include "G4Event.hh"
#include "G4ParticleGun.hh"
#include "G4GeneralParticleSource.hh"
#include "G4ParticleTable.hh"
#include "G4ParticleDefinition.hh"
#include "G4SystemOfUnits.hh"
#include "Randomize.hh"
GRPrimaryGeneratorAction::GRPrimaryGeneratorAction(
G4bool useParticleGun, G4bool useParticleSource)
: G4VUserPrimaryGeneratorAction(),
fParticleGun(nullptr), fParticleSource(nullptr)
{
if(useParticleGun)
{
fParticleGun = new G4ParticleGun(1);
auto particleTable = G4ParticleTable::GetParticleTable();
auto fPion = particleTable->FindParticle("pi+");
fParticleGun->SetParticleDefinition(fPion);
// default particle kinematics
fParticleGun->SetParticlePosition(G4ThreeVector(0.,0.,0.));
fParticleGun->SetParticleMomentumDirection(G4ThreeVector(1.,0.,0.));
fParticleGun->SetParticleEnergy(1.*GeV);
}
if(useParticleSource)
{ fParticleSource = new G4GeneralParticleSource(); }
}
GRPrimaryGeneratorAction::~GRPrimaryGeneratorAction()
{
if(fParticleGun) delete fParticleGun;
if(fParticleSource) delete fParticleSource;
}
void GRPrimaryGeneratorAction::GeneratePrimaries(G4Event* event)
{
if(fParticleGun) fParticleGun->GeneratePrimaryVertex(event);
if(fParticleSource) fParticleSource->GeneratePrimaryVertex(event);
}
+160
View File
@@ -0,0 +1,160 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRRun.cc
// Gorad Run class that handles filling histograms and profile plots
// with scores accumulated by scoeres for each event.
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRRun.hh"
#include "GRRunAction.hh"
#include "GRAnalysis.hh"
#include "G4MultiFunctionalDetector.hh"
#include "G4VPrimitiveScorer.hh"
#include "G4PrimaryVertex.hh"
#include "G4PrimaryParticle.hh"
GRRun::GRRun(GRRunAction* ra) : G4Run(),pRA(ra)
{
;
}
GRRun::~GRRun()
{
;
}
void GRRun::RecordEvent(const G4Event* anEvent)
{
numberOfEvent++; // This is an original line.
G4HCofThisEvent* pHCE = anEvent->GetHCofThisEvent();
auto analysisManager = G4AnalysisManager::Instance();
auto map = pRA->IDMap;
for(auto itr : map)
{
if(itr.second->pplotter!=nullptr) continue; // directly plotted by the PrimitivePlotter
auto cID = itr.second->collID;
auto hID = itr.second->histID;
auto hTyp = itr.second->histType;
if(hTyp==1) // 1D histogram
{
if(cID>=0) // scorer
{
if(!pHCE) continue;
auto score = (G4THitsMap<G4double>*)(pHCE->GetHC(cID));
G4double val = 0.;
for(auto hItr : *score)
{
if(itr.second->idx==-1 || itr.second->idx==hItr.first)
{ val += *(hItr.second); }
}
analysisManager->FillH1(hID,val);
}
else // primary particle
{
auto pv = anEvent->GetPrimaryVertex();
while(pv)
{
auto pp = pv->GetPrimary();
while(pp)
{
auto primE = pp->GetKineticEnergy();
G4double weight = 1.0;
if(itr.second->biasf) weight = pp->GetWeight();
analysisManager->FillH1(hID,primE,weight);
pp = pp->GetNext();
}
pv = pv->GetNext();
}
}
}
else if(hTyp==2) // 1D profile plot
{
if(!pHCE) continue;
auto score = (G4THitsMap<G4double>*)(pHCE->GetHC(cID));
for(auto hItr : *score)
{ analysisManager->FillP1(hID,G4double(hItr.first),*(hItr.second)); }
}
}
auto ntmap = pRA->NTMap;
if(ntmap.size()>0)
{
for(auto ntitr : ntmap)
{
auto colID = ntitr.first;
auto cID = ntitr.second->collID;
G4double val = 0.;
if(cID>=0)
{
if(!pHCE) continue;
auto score = (G4THitsMap<G4double>*)(pHCE->GetHC(cID));
for(auto hItr : *score)
{
if(ntitr.second->idx==-1 || ntitr.second->idx==hItr.first)
{ val += *(hItr.second); }
}
}
else
{
auto pv = anEvent->GetPrimaryVertex();
auto pp = pv->GetPrimary();
val = pp->GetKineticEnergy();
}
analysisManager->FillNtupleDColumn(colID,val*(ntitr.second->fuct));
}
analysisManager->AddNtupleRow();
}
}
void GRRun::Merge(const G4Run * aRun)
{
G4Run::Merge(aRun);
}
+548
View File
@@ -0,0 +1,548 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRRunAction.cc
// Gorad Run Action class that takes care of defining and handling
// histograms and n-tuple.
// Filling histograms is taken care by GRRun class.
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRRunAction.hh"
#include "GRRunActionMessenger.hh"
#include "GRAnalysis.hh"
#include "G4Run.hh"
#include "G4RunManager.hh"
#include "G4UnitsTable.hh"
#include "G4SystemOfUnits.hh"
GRRunAction::GRRunAction()
:fileName("GoradOut"), fileOpen(false), verbose(0), ifCarry(false),
id_offset(100), id_factor(100)
{
messenger = new GRRunActionMessenger(this);
auto analysisManager = G4AnalysisManager::Instance();
G4cout << "Using " << analysisManager->GetType() << G4endl;
analysisManager->SetVerboseLevel(verbose);
//analysisManager->SetNtupleMerging(true);
}
GRRunAction::~GRRunAction()
{
delete G4AnalysisManager::Instance();
delete messenger;
}
void GRRunAction::BeginOfRunAction(const G4Run* /*run*/)
{
// Open an output file
//
OpenFile();
// Define nTuple column if needed
//
DefineNTColumn();
}
void GRRunAction::OpenFile()
{
if(!fileOpen)
{
auto analysisManager = G4AnalysisManager::Instance();
analysisManager->OpenFile(fileName);
if(verbose>0) G4cout << "GRRunAction::BeginOfRunAction ### <" << fileName << "> is opened." << G4endl;
fileOpen = true;
}
}
void GRRunAction::EndOfRunAction(const G4Run* /*run*/)
{
// print histogram statistics
//
if(!ifCarry) Flush();
}
void GRRunAction::Flush()
{
auto analysisManager = G4AnalysisManager::Instance();
analysisManager->Write();
analysisManager->CloseFile();
if(verbose>0) G4cout << "GRRunAction::Flush ### <" << fileName << "> is closed." << G4endl;
fileOpen = false;
if(IsMaster()) MergeNtuple();
}
void GRRunAction::SetVerbose(G4int val)
{
verbose = val;
auto analysisManager = G4AnalysisManager::Instance();
analysisManager->SetVerboseLevel(verbose);
}
void GRRunAction::ListHistograms()
{
G4cout << "################## registered histograms/plots" << G4endl;
G4cout << "id\thistID\thistType\tdetName-X\tpsName-X\tcollID-X\tcopyNo-X\tdetName-Y\tpsName-Y\tcollID-Y\tcopyNo-Y" << G4endl;
for(auto itr : IDMap)
{
G4cout << itr.first << "\t" << itr.second->histID << "\t";
if(itr.second->histType==1) // 1D histogram
{ G4cout << "1-D hist\t" << itr.second->meshName << "\t" << itr.second->primName << "\t" << itr.second->collID << "\t" << itr.second->idx; }
else if(itr.second->histType==2) // 1D profile
{ G4cout << "1-D prof\t" << itr.second->meshName << "\t" << itr.second->primName << "\t" << itr.second->collID; }
G4cout << G4endl;
}
}
G4bool GRRunAction::Open(G4int id)
{
auto hItr = IDMap.find(id);
return (hItr!=IDMap.end());
}
#include "G4SDManager.hh"
using namespace G4Analysis;
G4bool GRRunAction::SetAllPlotting(G4bool val)
{
G4bool valid = true;
for(auto hItr : IDMap)
{
valid = SetPlotting(hItr.first,val);
if(!valid) break;
}
return valid;
}
G4bool GRRunAction::SetPlotting(G4int id,G4bool val)
{
auto hItr = IDMap.find(id);
if(hItr==IDMap.end()) return false;
auto ht = hItr->second;
auto hTyp = ht->histType;
auto analysisManager = G4AnalysisManager::Instance();
if(hTyp==1) // 1D histogram
{ analysisManager->SetH1Plotting(ht->histID,val); }
else if(hTyp==2) // 1D profile
{ analysisManager->SetP1Plotting(ht->histID,val); }
else
{ return false; }
return true;
}
// ------------- 1D histogram
G4int GRRunAction::Create1D(G4String& mName,G4String& pName,G4int cn)
{
G4String collName = mName;
collName += "/";
collName += pName;
auto cID = G4SDManager::GetSDMpointer()->GetCollectionID(collName);
if(cID<0) return cID;
G4int id = (cID+id_offset)*id_factor+cn+1;
auto histoTypeItr = IDMap.find(id);
if(histoTypeItr!=IDMap.end()) return false;
if(verbose) G4cout << "GRRunAction::Create1D for <" << collName
<< ", copyNo=" << cn << "> is registered for hitCollectionID "
<< cID << G4endl;
auto histTyp = new GRHistoType;
histTyp->collID = cID;
histTyp->histType = 1; // 1D histogram
histTyp->meshName = mName;
histTyp->primName = pName;
histTyp->idx = cn;
IDMap[id] = histTyp;
return id;
}
G4int GRRunAction::Create1DForPrimary(G4String& mName,G4bool wgt)
{
G4int cn = wgt ? 1 : 0;
G4int id = 99999 - cn;
auto histoTypeItr = IDMap.find(id);
if(histoTypeItr!=IDMap.end()) return false;
if(verbose) G4cout << "GRRunAction::Create1D for <" << mName
<< "(weighted : " << cn << ")> is registered " << G4endl;
auto histTyp = new GRHistoType;
histTyp->collID = -999;
histTyp->histType = 1; // 1D histogram
histTyp->meshName = "PrimPEnergy";
histTyp->primName = mName;
histTyp->biasf = cn;
IDMap[id] = histTyp;
return id;
}
#include "G4SDManager.hh"
#include "G4ScoringManager.hh"
#include "G4VScoringMesh.hh"
#include "G4VPrimitivePlotter.hh"
G4int GRRunAction::Create1DForPlotter(G4String& mName,G4String& pName,G4bool /*wgt*/)
{
using MeshShape = G4VScoringMesh::MeshShape;
G4String collName = mName;
collName += "/";
collName += pName;
auto cID = G4SDManager::GetSDMpointer()->GetCollectionID(collName);
if(cID<0) return cID;
auto sm = G4ScoringManager::GetScoringManagerIfExist();
assert(sm!=nullptr);
auto mesh = sm->FindMesh(mName);
if(mesh==nullptr)
{ return -2; }
auto shape = mesh->GetShape();
if(shape!=MeshShape::realWorldLogVol && shape!=MeshShape::probe)
{ return -3; }
G4int nBin[3];
mesh->GetNumberOfSegments(nBin);
auto prim = mesh->GetPrimitiveScorer(pName);
if(prim==nullptr)
{ return -3; }
auto pp = dynamic_cast<G4VPrimitivePlotter*>(prim);
if(pp==nullptr)
{ return -4; }
G4int id0 = (cID+id_offset)*id_factor+1;
for(G4int cn=0; cn<nBin[0]; cn++)
{
G4int id = id0+cn;
auto histoTypeItr = IDMap.find(id);
if(histoTypeItr!=IDMap.end())
{ return -5; }
if(verbose) G4cout << "GRRunAction::Create1D for <" << collName
<< ", copyNo=" << cn << "> is registered for hitCollectionID "
<< cID << G4endl;
auto histTyp = new GRHistoType;
histTyp->collID = cID;
histTyp->histType = 1; // 1D histogram
histTyp->histDup = nBin[0];
histTyp->meshName = mName;
histTyp->primName = pName;
histTyp->idx = cn;
histTyp->pplotter = pp;
IDMap[id] = histTyp;
}
return id0;
}
#include "G4UIcommand.hh"
G4bool GRRunAction::Set1D(G4int id0,G4int nBin,G4double valMin,G4double valMax,G4String& unit,
G4String& schem, G4bool logVal)
{
OpenFile();
auto hIt = IDMap.find(id0);
if(hIt==IDMap.end()) return false;
auto analysisManager = G4AnalysisManager::Instance();
auto dup = (hIt->second)->histDup;
for(G4int ii=0;ii<dup;ii++)
{
G4int id = id0 + ii;
auto hItr = IDMap.find(id);
auto ht = hItr->second;
G4String mNam = ht->primName;
G4String nam = ht->meshName + "_" + ht->primName;
if(ht->idx>-1)
{
mNam += "_";
mNam += G4UIcommand::ConvertToString(ht->idx);
nam += "_";
nam += G4UIcommand::ConvertToString(ht->idx);
}
G4int hid = -1;
if(schem=="linear")
{ hid = analysisManager->CreateH1(mNam,nam,nBin,valMin,valMax,unit,"none","linear"); }
else
{
if(logVal)
{ hid = analysisManager->CreateH1(mNam,nam,nBin,valMin,valMax,unit,"log10","linear"); }
else
{
hid = analysisManager->CreateH1(mNam,nam,nBin,valMin,valMax,unit,"none","log");
analysisManager->SetH1XAxisIsLog(hid,true);
}
}
if(verbose) G4cout << "GRRunAction::Set1D for " << mNam << " / " << nam
<< " has the histogram ID " << hid << G4endl;
ht->histID = hid;
auto pp = ht->pplotter;
if(pp!=nullptr) pp->Plot(ht->idx,hid);
}
return true;
}
G4bool GRRunAction::Set1DTitle(G4int id,G4String& title,G4String& x_axis,G4String&y_axis)
{
auto hItr = IDMap.find(id);
if(hItr==IDMap.end()) return false;
auto analysisManager = G4AnalysisManager::Instance();
auto hid = hItr->second->histID;
analysisManager->SetH1Title(hid,title);
analysisManager->SetH1XAxisTitle(hid,x_axis);
analysisManager->SetH1YAxisTitle(hid,y_axis);
return true;
}
G4bool GRRunAction::Set1DYAxisLog(G4int id0,G4bool val)
{
auto hIt = IDMap.find(id0);
if(hIt==IDMap.end()) return false;
auto analysisManager = G4AnalysisManager::Instance();
auto dup = (hIt->second)->histDup;
for(G4int ii=0;ii<dup;ii++)
{
G4int id = id0 + ii;
auto hItr = IDMap.find(id);
analysisManager->SetH1YAxisIsLog(hItr->second->histID,val);
}
return true;
}
// ------------- 1D profile
G4int GRRunAction::Create1P(G4String& mName,G4String& pName,G4int cn)
{
G4String collName = mName;
collName += "/";
collName += pName;
auto cID = G4SDManager::GetSDMpointer()->GetCollectionID(collName);
if(cID<0) return cID;
G4int id = (cID+2*id_offset)*id_factor;
auto histoTypeItr = IDMap.find(id);
if(histoTypeItr!=IDMap.end()) return false;
if(verbose) G4cout << "GRRunAction::Create1P for <" << collName
<< "> is registered for hitCollectionID "
<< cID << G4endl;
auto histTyp = new GRHistoType;
histTyp->collID = cID;
histTyp->histType = 2; // 1D profile
histTyp->meshName = mName;
histTyp->primName = pName;
histTyp->idx = cn;
IDMap[id] = histTyp;
return id;
}
G4bool GRRunAction::Set1P(G4int id,G4double valYMin,G4double valYMax,G4String& unit,
G4String& funcX,G4String& funcY,G4String& schem)
{
OpenFile();
if(verbose) G4cout << "GRRunAction::Set1P for id = " << id << G4endl;
auto hItr = IDMap.find(id);
if(hItr==IDMap.end()) return false;
auto ht = hItr->second;
if(verbose) G4cout << "GRRunAction::Set1P for " << ht->meshName << " / " << ht->primName << G4endl;
auto analysisManager = G4AnalysisManager::Instance();
auto nBin = ht->idx;
G4double valMin = -0.5;
G4double valMax = G4double(nBin) - 0.5;
G4String nam = ht->meshName + "_" + ht->primName;
auto hid = analysisManager->CreateP1(nam,ht->primName,nBin,
valMin,valMax,valYMin,valYMax,"none",unit,funcX,funcY,schem);
if(verbose) G4cout << "GRRunAction::Set1P for " << ht->meshName << " / " << ht->primName
<< " has the histogram ID " << hid << G4endl;
ht->histID = hid;
return true;
}
G4bool GRRunAction::Set1PTitle(G4int id,G4String& title,G4String& x_axis,G4String&y_axis)
{
auto hItr = IDMap.find(id);
if(hItr==IDMap.end()) return false;
auto analysisManager = G4AnalysisManager::Instance();
auto hid = hItr->second->histID;
analysisManager->SetP1Title(hid,title);
analysisManager->SetP1XAxisTitle(hid,x_axis);
analysisManager->SetP1YAxisTitle(hid,y_axis);
return true;
}
// ------------- Ntuple
G4int GRRunAction::NtupleColumn(G4String& mName,G4String& pName,G4String& unit,G4int cn)
{
G4String collName = mName;
collName += "/";
collName += pName;
auto cID = G4SDManager::GetSDMpointer()->GetCollectionID(collName);
if(cID<0) return cID;
G4int id = NTMap.size();
if(verbose) G4cout << "GRRunAction::NtupleColumn : <" << collName
<< ", copyNo=" << cn << "> is registered for nTuple column "
<< id << G4endl;
auto histTyp = new GRHistoType;
histTyp->collID = cID;
histTyp->meshName = mName;
histTyp->primName = pName;
histTyp->meshName2 = unit;
if(unit!="none")
{ histTyp->fuct = 1./(G4UnitDefinition::GetValueOf(unit)); }
histTyp->idx = cn;
NTMap[id] = histTyp;
return id;
}
#include "G4UIcommand.hh"
void GRRunAction::DefineNTColumn()
{
if(NTMap.size()==0) return;
auto analysisManager = G4AnalysisManager::Instance();
analysisManager->CreateNtuple("GRimNtuple","Scores for each event");
for(auto itr : NTMap)
{
G4String colNam = itr.second->meshName;
colNam += "_";
colNam += itr.second->primName;
if(itr.second->idx != -1)
{ colNam += "_"; colNam += G4UIcommand::ConvertToString(itr.second->idx); }
if(itr.second->meshName2 != "none")
{ colNam += "["; colNam += itr.second->meshName2; colNam += "]"; }
analysisManager->CreateNtupleDColumn(colNam);
}
analysisManager->FinishNtuple();
}
#include <fstream>
#include "G4Threading.hh"
#include "G4UImanager.hh"
void GRRunAction::MergeNtuple()
{
if(NTMap.size()==0) return;
if(!(G4Threading::IsMultithreadedApplication())) return;
auto analysisManager = G4AnalysisManager::Instance();
// This MergeNtuple() method is valid only for CSV file format
if(analysisManager->GetType()!="Csv") return;
std::fstream target;
G4String targetFN = "GRimOut_nt_GRimNtuple_total.csv";
target.open(targetFN,std::ios::out);
enum { BUFSIZE = 4096 };
char* line = new char[BUFSIZE];
G4String titleFN = "GRimOut_nt_GRimNtuple.csv";
std::ifstream title;
title.open(titleFN,std::ios::in);
while(1)
{
title.getline(line,BUFSIZE);
if(title.eof()) break;
G4cout << line << G4endl;
target << line << G4endl;
}
title.close();
auto nWorker = G4Threading::GetNumberOfRunningWorkerThreads();
G4String sourceFNBase = "GRimOut_nt_GRimNtuple_t";
for(G4int i = 0; i < nWorker; i++)
{
G4String sourceFN = sourceFNBase;
sourceFN += G4UIcommand::ConvertToString(i);
sourceFN += ".csv";
std::ifstream source;
source.open(sourceFN,std::ios::in);
if(!source)
{
G4ExceptionDescription ed; ed << "Source file <" << sourceFN << "> is not found.";
G4Exception("GRRunAction::MergeNtuple()","GRim12345",FatalException,ed);
}
while(1)
{
source.getline(line,BUFSIZE);
if(line[0]=='#') continue;
if(source.eof()) break;
target << line << G4endl;
}
source.close();
G4String scmd = "rm -f ";
scmd += sourceFN;
auto rc = system(scmd);
if(rc<0)
{
G4ExceptionDescription ed;
ed << "File <" << sourceFN << "> could not be deleted, thought it is merged.";
G4Exception("GRRunAction::MergeNtuple()","GRim12345",JustWarning,ed);
}
}
target.close();
G4String cmd = "mv ";
cmd += targetFN;
cmd += " ";
cmd += titleFN;
auto rcd = system(cmd);
if(rcd<0)
{
G4ExceptionDescription ed;
ed << "File <" << targetFN << "> could not be renamed.";
G4Exception("GRRunAction::MergeNtuple()","GRim12345",JustWarning,ed);
}
}
@@ -0,0 +1,575 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRRunActionMessenger.cc
// A messenger class that defines histograms and n-tuple in GRRunAction.
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRRunActionMessenger.hh"
#include "GRRunAction.hh"
#include "G4UIcommand.hh"
#include "G4UIparameter.hh"
#include "G4UIdirectory.hh"
#include "G4UIcmdWithAString.hh"
#include "G4UIcmdWithABool.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4UIcmdWithoutParameter.hh"
#include "G4UnitsTable.hh"
GRRunActionMessenger::GRRunActionMessenger(GRRunAction* dc)
: pRA(dc), currentID(-1)
{
G4UIparameter* para = nullptr;
anaDir = new G4UIdirectory("/gorad/analysis/");
anaDir->SetGuidance("GORAD analysis commands");
verboseCmd = new G4UIcmdWithAnInteger("/gorad/analysis/verbose",this);
verboseCmd->SetGuidance("Set verbose level");
verboseCmd->SetParameterName("level",true);
verboseCmd->SetDefaultValue(0);
verboseCmd->SetRange("level>=0");
verboseCmd->AvailableForStates(G4State_Idle);
fileCmd = new G4UIcmdWithAString("/gorad/analysis/file",this);
fileCmd->SetGuidance("Define the output file name.");
fileCmd->SetParameterName("file",false);
fileCmd->AvailableForStates(G4State_Idle);
listCmd = new G4UIcmdWithoutParameter("/gorad/analysis/list",this);
listCmd->SetGuidance("List defined histograms.");
listCmd->AvailableForStates(G4State_Idle);
openCmd = new G4UIcmdWithAnInteger("/gorad/analysis/open",this);
openCmd->SetGuidance("Open a histogram that has already been created and closed.");
openCmd->SetGuidance("\"create\" command open the new histogram so you don't need to open it.");
openCmd->SetGuidance("A histogram is closed when another histogram is created. This \"open\" command is required only for reopening the closed histogram.");
openCmd->SetParameterName("id",false);
openCmd->AvailableForStates(G4State_Idle);
plotCmd = new G4UIcmdWithAnInteger("/gorad/analysis/plot",this);
plotCmd->SetGuidance("Create an additional postscript plot for specified histogram/profile.");
plotCmd->SetGuidance("Regardless of this command, histogram is dumped to the output file.");
plotCmd->SetGuidance("If id is not specified, currently open histogram/profile is plotted.");
plotCmd->SetGuidance("If id = -1, all currently defined histograms/profiles are plotted.");
plotCmd->SetParameterName("id",true,true);
plotCmd->AvailableForStates(G4State_Idle);
carryCmd = new G4UIcmdWithABool("/gorad/analysis/carry",this);
carryCmd->SetGuidance("Carry histograms over more than one runs.");
carryCmd->SetGuidance("Once this is set, histograms won't be output until /gorad/analysis/flush is explicitly issued.");
carryCmd->SetGuidance("This command has to be issued before starting the run to be carried over.");
carryCmd->SetParameterName("carry",true);
carryCmd->SetDefaultValue(true);
carryCmd->AvailableForStates(G4State_Idle);
flushCmd = new G4UIcmdWithoutParameter("/gorad/analysis/flush",this);
flushCmd->SetGuidance("Make output. This command is necessary if /gorad/analysis/carry is set.");
flushCmd->AvailableForStates(G4State_Idle);
resetCmd = new G4UIcmdWithoutParameter("/gorad/analysis/reset",this);
resetCmd->SetGuidance("Reset histograms without making output.");
resetCmd->AvailableForStates(G4State_Idle);
idOffsetCmd = new G4UIcommand("/gorad/analysis/idOffset",this);
idOffsetCmd->SetGuidance("Define offset numbers of the histogram ID.");
idOffsetCmd->SetGuidance(" The hostogram ID is set as (scorer_id + <offset>) * <factor> + copy_number - 1");
para = new G4UIparameter("offset",'i',true);
para->SetParameterRange("offset>=0");
para->SetDefaultValue(0);
idOffsetCmd->SetParameter(para);
para = new G4UIparameter("factor",'i',true);
para->SetParameterRange("factor>0");
para->SetDefaultValue(1000);
idOffsetCmd->SetParameter(para);
idOffsetCmd->AvailableForStates(G4State_Idle);
oneDDir = new G4UIdirectory("/gorad/analysis/1D/");
oneDDir->SetGuidance("1-dimentional histogram");
create1DCmd = new G4UIcommand("/gorad/analysis/1D/create",this);
create1DCmd->SetGuidance("Create a 1D histogram and fill it with event-by-event score.");
create1DCmd->SetGuidance("Scoring mesh (logical volume for real-world volume scoring) and");
create1DCmd->SetGuidance("primitive scorers must be defined prior to this command.");
para = new G4UIparameter("meshName",'s',false);
para->SetGuidance("Scoring mesh name. Logical volume name for real-world volume scoring.");
create1DCmd->SetParameter(para);
para = new G4UIparameter("primName",'s',false);
create1DCmd->SetParameter(para);
para = new G4UIparameter("idx",'i',true);
para->SetGuidance("Index (i.e. copy number) of the cell to be scored. \"-1\" (defult) to score all cells.");
para->SetDefaultValue(-1);
para->SetParameterRange("idx>=-1");
create1DCmd->SetParameter(para);
create1DCmd->AvailableForStates(G4State_Idle);
create1DPrimPCmd = new G4UIcommand("/gorad/analysis/1D/primary",this);
create1DPrimPCmd->SetGuidance("Create a 1D energy spectrum histogram and fill it with kinetic energy of each primary particle.");
create1DPrimPCmd->SetGuidance("Weight of each primary track is taken into account if the flag is set.");
para = new G4UIparameter("histName",'s',false);
para->SetGuidance("Histogram name");
create1DPrimPCmd->SetParameter(para);
para = new G4UIparameter("weightFlag",'b',true);
para->SetGuidance("Weight of each primary track is taken into account");
para->SetDefaultValue(true);
create1DPrimPCmd->SetParameter(para);
create1DPrimPCmd->AvailableForStates(G4State_Idle);
create1DPlotPCmd = new G4UIcommand("/gorad/analysis/1D/spectrum",this);
create1DPlotPCmd->SetGuidance("Create a 1D energy spectrum histogram and fill it with each individual track that gets into the volume.");
create1DPlotPCmd->SetGuidance("Histogram is created for each physical volume separately.");
create1DPlotPCmd->SetGuidance("So, this command should not be used for Box or Cylinder mesh type due to memory consumption concern.");
create1DPlotPCmd->SetGuidance("Currently, this is supported only for volume flux scorer.");
para = new G4UIparameter("meshName",'s',false);
para->SetGuidance("Scoring mesh name. Logical volume name for real-world volume scoring.");
create1DPlotPCmd->SetParameter(para);
para = new G4UIparameter("primName",'s',false);
para->SetGuidance("Scoring primitive name.");
create1DPlotPCmd->SetParameter(para);
create1DPlotPCmd->AvailableForStates(G4State_Idle);
set1DCmd = new G4UIcmdWithoutParameter("/gorad/analysis/1D/set",this);
set1DCmd->SetGuidance("This command is obsolete. Use /gorad/analysis/1D/config instead.");
config1DCmd = new G4UIcommand("/gorad/analysis/1D/config",this);
config1DCmd->SetGuidance("Set binning parameters of the current 1D histogram.");
config1DCmd->SetGuidance("<unit> is applied to <minVal> and <maxVal> as well as filled value.");
para = new G4UIparameter("nBin",'i',false);
para->SetParameterRange("nBin>0");
config1DCmd->SetParameter(para);
para = new G4UIparameter("minVal",'d',false);
config1DCmd->SetParameter(para);
para = new G4UIparameter("maxVal",'d',false);
config1DCmd->SetParameter(para);
para = new G4UIparameter("unit",'s',true);
para->SetDefaultValue("none");
config1DCmd->SetParameter(para);
para = new G4UIparameter("scale",'s',true);
para->SetGuidance("Define the binning scale. (default: linear)");
para->SetParameterCandidates("linear log");
para->SetDefaultValue("linear");
config1DCmd->SetParameter(para);
para = new G4UIparameter("logVal",'b',true);
para->SetDefaultValue(false);
config1DCmd->SetParameter(para);
config1DCmd->AvailableForStates(G4State_Idle);
title1DCmd = new G4UIcommand("/gorad/analysis/1D/title",this);
title1DCmd->SetGuidance("Define histogram title");
para = new G4UIparameter("title",'s',false);
title1DCmd->SetParameter(para);
para = new G4UIparameter("x_axis",'s',false);
title1DCmd->SetParameter(para);
para = new G4UIparameter("y_axis",'s',false);
title1DCmd->SetParameter(para);
title1DCmd->AvailableForStates(G4State_Idle);
set1DYaxisLogCmd = new G4UIcmdWithABool("/gorad/analysis/1D/yaxisLog",this);
set1DYaxisLogCmd->SetGuidance("Set y-axis in log scale.");
set1DYaxisLogCmd->SetParameterName("flag",true);
set1DYaxisLogCmd->SetDefaultValue(true);
set1DYaxisLogCmd->AvailableForStates(G4State_Idle);
onePDir = new G4UIdirectory("/gorad/analysis/1P/");
onePDir->SetGuidance("1-dimentional profile plot");
create1PCmd = new G4UIcommand("/gorad/analysis/1P/create",this);
create1PCmd->SetGuidance("Create a 1D profile plot and fill it with event-by-event score.");
create1PCmd->SetGuidance("Scoring mesh (logical volume for real-world volume scoring) and");
create1PCmd->SetGuidance("primitive scorers must be defined prior to this command.");
create1PCmd->SetGuidance("Copy number of the scoring cell is used as the x-axis value.");
para = new G4UIparameter("meshName",'s',false);
para->SetGuidance("Scoring mesh name. Logical volume name for real-world volume scoring.");
create1PCmd->SetParameter(para);
para = new G4UIparameter("primName",'s',false);
create1PCmd->SetParameter(para);
para = new G4UIparameter("idx",'i',false);
para->SetGuidance("Maximum index (i.e. copy number) of the cell to be scored.");
para->SetParameterRange("idx>0");
create1PCmd->SetParameter(para);
create1PCmd->AvailableForStates(G4State_Idle);
set1PCmd = new G4UIcommand("/gorad/analysis/1P/set",this);
set1PCmd->SetGuidance("Set binning parameters of the current 1D profile plot.");
set1PCmd->SetGuidance("<unit> is applied to <minYVal> and <maxYVal> as well as filled value.");
para = new G4UIparameter("minYVal",'d',false);
set1PCmd->SetParameter(para);
para = new G4UIparameter("maxYVal",'d',false);
set1PCmd->SetParameter(para);
para = new G4UIparameter("unit",'s',true);
para->SetDefaultValue("none");
set1PCmd->SetParameter(para);
para = new G4UIparameter("func-x",'s',true);
para->SetGuidance("The function applied to the filled x-value (default: none).");
para->SetParameterCandidates("log log10 exp none");
para->SetDefaultValue("none");
set1PCmd->SetParameter(para);
para = new G4UIparameter("func-y",'s',true);
para->SetGuidance("The function applied to the filled y-value (default: none).");
para->SetParameterCandidates("log log10 exp none");
para->SetDefaultValue("none");
set1PCmd->SetParameter(para);
para = new G4UIparameter("scale",'s',true);
para->SetGuidance("Define the binning scale. (default: linear)");
para->SetParameterCandidates("linear log");
para->SetDefaultValue("linear");
set1PCmd->SetParameter(para);
set1PCmd->AvailableForStates(G4State_Idle);
title1PCmd = new G4UIcommand("/gorad/analysis/1P/title",this);
title1PCmd->SetGuidance("Define histogram title");
para = new G4UIparameter("title",'s',false);
title1PCmd->SetParameter(para);
para = new G4UIparameter("x_axis",'s',false);
title1PCmd->SetParameter(para);
para = new G4UIparameter("y_axis",'s',false);
title1PCmd->SetParameter(para);
title1PCmd->AvailableForStates(G4State_Idle);
ntupleDir = new G4UIdirectory("/gorad/analysis/ntuple/");
onePDir->SetGuidance("Define an ntuple");
addColumnCmd = new G4UIcommand("/gorad/analysis/ntuple/addColumn",this);
addColumnCmd->SetGuidance("Define a column and fill it with event-by-event score.");
addColumnCmd->SetGuidance("Scoring mesh (logical volume for real-world volume scoring) and");
addColumnCmd->SetGuidance("primitive scorers must be defined prior to this command.");
para = new G4UIparameter("meshName",'s',false);
para->SetGuidance("Scoring mesh name. Logical volume name for real-world volume scoring.");
addColumnCmd->SetParameter(para);
para = new G4UIparameter("primName",'s',false);
addColumnCmd->SetParameter(para);
para = new G4UIparameter("unit",'s',true);
para->SetDefaultValue("none");
addColumnCmd->SetParameter(para);
para = new G4UIparameter("idx",'i',true);
para->SetGuidance("Index (i.e. copy number) of the cell to be scored. \"-1\" (defult) to score all cells.");
para->SetDefaultValue(-1);
para->SetParameterRange("idx>=-1");
addColumnCmd->SetParameter(para);
addColumnCmd->AvailableForStates(G4State_Idle);
}
GRRunActionMessenger::~GRRunActionMessenger()
{
delete addColumnCmd;
delete ntupleDir;
delete create1PCmd;
delete set1PCmd;
delete title1PCmd;
delete onePDir;
delete create1DCmd;
delete create1DPrimPCmd;
delete create1DPlotPCmd;
delete set1DCmd;
delete config1DCmd;
delete title1DCmd;
delete set1DYaxisLogCmd;
delete oneDDir;
delete fileCmd;
delete verboseCmd;
delete listCmd;
delete openCmd;
delete plotCmd;
delete carryCmd;
delete flushCmd;
delete resetCmd;
delete idOffsetCmd;
delete anaDir;
}
#include "G4Tokenizer.hh"
void GRRunActionMessenger::SetNewValue(G4UIcommand* cmd, G4String val)
{
if(cmd==fileCmd)
{ pRA->SetFileName(val); }
else if(cmd==verboseCmd)
{ pRA->SetVerbose(verboseCmd->GetNewIntValue(val)); }
else if(cmd==listCmd)
{ pRA->ListHistograms(); }
else if(cmd==openCmd)
{
auto id = openCmd->GetNewIntValue(val);
if(currentID!=id)
{
if(!CheckOpenID(cmd)) return;
auto valid = pRA->Open(id);
if(!valid)
{
G4ExceptionDescription ed;
ed << "<" << id << "> is not a valid histogram ID.";
cmd->CommandFailed(ed);
}
else
{ currentID = id; }
}
}
else if(cmd==plotCmd)
{
auto id = plotCmd->GetNewIntValue(val);
G4bool valid = true;
if(id==-1)
{ valid = pRA->SetAllPlotting(true); }
else
{ valid = pRA->SetPlotting(id,true); }
if(!valid)
{
G4ExceptionDescription ed;
ed << "Histogram/profile id <" << id << "> is not valid.";
cmd->CommandFailed(ed);
}
}
else if(cmd==carryCmd)
{ pRA->SetCarry(carryCmd->GetNewBoolValue(val)); }
else if(cmd==flushCmd)
{ pRA->Flush(); }
else if(cmd==resetCmd)
{ /*pRA->ResetHistograms();*/ }
else if(cmd==idOffsetCmd)
{
G4Tokenizer next(val);
G4int offset = StoI(next());
G4int factor = StoI(next());
pRA->SetOffset(offset,factor);
}
// 1D histogram commands
else if(cmd==create1DCmd)
{
if(!CheckOpenID(cmd)) return;
G4Tokenizer next(val);
G4String meshName = next();
G4String primName = next();
G4int idx = StoI(next());
auto id = pRA->Create1D(meshName,primName,idx);
if(id<0)
{
G4ExceptionDescription ed;
ed << "1D histogram <" << val << "> cannot be created.";
cmd->CommandFailed(ed);
}
else
{ currentID = id; }
}
else if(cmd==create1DPrimPCmd)
{
if(!CheckOpenID(cmd)) return;
G4Tokenizer next(val);
G4String meshName = next();
G4bool wgt = StoB(next());
auto id = pRA->Create1DForPrimary(meshName,wgt);
if(id<0)
{
G4ExceptionDescription ed;
ed << "1D histogram <" << val << "> cannot be created.";
cmd->CommandFailed(ed);
}
else
{ currentID = id; }
}
else if(cmd==create1DPlotPCmd)
{
if(!CheckOpenID(cmd)) return;
G4Tokenizer next(val);
G4String meshName = next();
G4String primName = next();
G4bool wgt = true;
auto id = pRA->Create1DForPlotter(meshName,primName,wgt);
if(id<0)
{
G4ExceptionDescription ed;
ed << "1D histogram <" << val << "> cannot be created.";
cmd->CommandFailed(ed);
}
else
{ currentID = id; }
}
else if(cmd==set1DCmd)
{
G4ExceptionDescription ed;
ed << "This command is OBSOLETE. Use /gorad/analysis/1D/config command!!";
cmd->CommandFailed(ed);
}
else if(cmd==config1DCmd)
{
if(!CheckID(cmd)) return;
G4Tokenizer next(val);
G4int nBin = StoI(next());
G4double minVal = StoD(next());
G4double maxVal = StoD(next());
G4String unit = next();
G4String schem = next();
G4bool logVal = StoB(next());
if(unit!="none" && !(G4UnitDefinition::IsUnitDefined(unit)))
{
G4ExceptionDescription ed;
ed << "Unknown unit <" << unit << ">. Command failed.";
cmd->CommandFailed(ed);
}
else
{ pRA->Set1D(currentID,nBin,minVal,maxVal,unit,schem,logVal); }
}
else if(cmd==title1DCmd)
{
if(!CheckID(cmd)) return;
G4Tokenizer next(val);
G4String title = next();
G4String x_axis = next();
G4String y_axis = next();
pRA->Set1DTitle(currentID,title,x_axis,y_axis);
}
else if(cmd==set1DYaxisLogCmd)
{
if(!CheckID(cmd)) return;
auto succ = pRA->Set1DYAxisLog(currentID,set1DYaxisLogCmd->GetNewBoolValue(val));
if(!succ)
{
G4ExceptionDescription ed;
ed << "This command is not available for this histogram.";
cmd->CommandFailed(ed);
}
}
// 1D profile commands
else if(cmd==create1PCmd)
{
if(!CheckOpenID(cmd)) return;
G4Tokenizer next(val);
G4String meshName = next();
G4String primName = next();
G4int cn = StoI(next());
auto id = pRA->Create1P(meshName,primName,cn);
if(id<0)
{
G4ExceptionDescription ed;
ed << "1D histogram <" << val << "> cannot be created.";
cmd->CommandFailed(ed);
}
else
{ currentID = id; }
}
else if(cmd==set1PCmd)
{
if(!CheckID(cmd)) return;
G4Tokenizer next(val);
G4double minYVal = StoD(next());
G4double maxYVal = StoD(next());
G4String unit = next();
G4String funcX = next();
G4String funcY = next();
G4String schem = next();
if(unit!="none" && !(G4UnitDefinition::IsUnitDefined(unit)))
{
G4ExceptionDescription ed;
ed << "Unknown unit <" << unit << ">. Command failed.";
cmd->CommandFailed(ed);
}
else
{ pRA->Set1P(currentID,minYVal,maxYVal,unit,funcX,funcY,schem); }
}
else if(cmd==title1PCmd)
{
if(!CheckID(cmd)) return;
G4Tokenizer next(val);
G4String title = next();
G4String x_axis = next();
G4String y_axis = next();
pRA->Set1PTitle(currentID,title,x_axis,y_axis);
}
// ntuple commands
else if(cmd==addColumnCmd)
{
G4Tokenizer next(val);
G4String meshName = next();
G4String primName = next();
G4String unit = next();
G4int idx = StoI(next());
if(unit!="none" && !(G4UnitDefinition::IsUnitDefined(unit)))
{
G4ExceptionDescription ed;
ed << "Unknown unit <" << unit << ">. Command failed.";
cmd->CommandFailed(ed);
}
else
{
auto id = pRA->NtupleColumn(meshName,primName,unit,idx);
if(id<0)
{
G4ExceptionDescription ed;
ed << "Ntuple column <" << val << "> cannot be created.";
cmd->CommandFailed(ed);
}
}
}
}
G4String GRRunActionMessenger::GetCurrentValue(G4UIcommand* cmd)
{
G4String val("");
if(cmd==openCmd)
{ val = openCmd->ConvertToString(currentID); }
if(cmd==fileCmd)
{ val = pRA->GetFileName(); }
else if(cmd==verboseCmd)
{ val = verboseCmd->ConvertToString(pRA->GetVerbose()); }
else if(cmd==plotCmd)
{ val = plotCmd->ConvertToString(currentID); }
else if(cmd==carryCmd)
{ val = carryCmd->ConvertToString(pRA->GetCarry()); }
else if(cmd==idOffsetCmd)
{
G4int offset = 0;
G4int factor = 0;
pRA->GetOffset(offset,factor);
val = idOffsetCmd->ConvertToString(offset);
val += " ";
val += idOffsetCmd->ConvertToString(factor);
}
return val;
}
@@ -0,0 +1,297 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Gorad (Geant4 Open-source Radiation Analysis and Design)
//
// Author : Makoto Asai (SLAC National Accelerator Laboratory)
//
// Development of Gorad is funded by NASA Johnson Space Center (JSC)
// under the contract NNJ15HK11B.
//
// ********************************************************************
//
// GRScoreWriter.hh
// Defines the printout format of primitive scorer
//
// History
// September 8th, 2020 : first implementation
//
// ********************************************************************
#include "GRScoreWriter.hh"
#include <map>
#include <fstream>
#include "G4MultiFunctionalDetector.hh"
#include "G4SDParticleFilter.hh"
#include "G4VPrimitiveScorer.hh"
#include "G4VScoringMesh.hh"
GRScoreWriter::GRScoreWriter()
{;}
GRScoreWriter::~GRScoreWriter()
{;}
void GRScoreWriter::DumpQuantityToFile(const G4String& psName,
const G4String& fileName,
const G4String& option) {
// change the option string into lowercase to the case-insensitive.
G4String opt = option;
std::transform(opt.begin(), opt.end(), opt.begin(), (int (*)(int))(tolower));
// confirm the option
if(opt.size() == 0) opt = "csv";
if(opt.find("csv") == std::string::npos &&
opt.find("sequence") == std::string::npos) {
G4cerr << "ERROR : DumpToFile : Unknown option -> "
<< option << G4endl;
return;
}
// open the file
std::ofstream ofile(fileName);
if(!ofile) {
G4cerr << "ERROR : DumpToFile : File open error -> "
<< fileName << G4endl;
return;
}
ofile << "# Mesh or volume name: " << fScoringMesh->GetWorldName() << G4endl;
using MeshScoreMap = G4VScoringMesh::MeshScoreMap;
// retrieve the map
MeshScoreMap fSMap = fScoringMesh->GetScoreMap();
MeshScoreMap::const_iterator msMapItr = fSMap.find(psName);
if(msMapItr == fSMap.end()) {
G4cerr << "ERROR : DumpToFile : Unknown quantity, \""
<< psName << "\"." << G4endl;
return;
}
std::map<G4int, G4StatDouble*> * score = msMapItr->second->GetMap();
ofile << "# Primitive scorer name: " << msMapItr->first << G4endl;
if(fact!=1.0)
{ ofile << "# Multiplication factor : " << fact << G4endl; }
G4double unitValue = fScoringMesh->GetPSUnitValue(psName);
G4String unit = fScoringMesh->GetPSUnit(psName);
G4String divisionAxisNames[3];
fScoringMesh->GetDivisionAxisNames(divisionAxisNames);
ofile << "# First three integer entries: index of a cell of a mesh, just one cell for a volume tally." << G4endl;
ofile << "# Forth entry: sum of scores." << G4endl;
ofile << "# Fifth entry: sum of squared scores." << G4endl;
ofile << "# Sixth entry: number of events with non-zero effect." << G4endl;
ofile << "# Seventh entry: relative statistical error in %." << G4endl << G4endl;
// index of the cell
ofile << "# i" << divisionAxisNames[0]
<< ", i" << divisionAxisNames[1]
<< ", i" << divisionAxisNames[2];
// unit of scored value
ofile << ", total(value) ";
if(unit.size() > 0) ofile << "[" << unit << "]";
ofile << ", total(value^2), number of entries, relative error (%)" << G4endl;
// "sequence" option: write header info
if(opt.find("sequence") != std::string::npos) {
ofile << fNMeshSegments[0] << " " << fNMeshSegments[1] << " " << fNMeshSegments[2]
<< G4endl;
}
// write quantity
long count = 0;
ofile << std::setprecision(16); // for double value with 8 bytes
for(int x = 0; x < fNMeshSegments[0]; x++) {
for(int y = 0; y < fNMeshSegments[1]; y++) {
for(int z = 0; z < fNMeshSegments[2]; z++) {
G4int idx = GetIndex(x, y, z);
if(opt.find("csv") != std::string::npos)
ofile << x << "," << y << "," << z << ",";
std::map<G4int, G4StatDouble*>::iterator value = score->find(idx);
if(value == score->end()) {
ofile << 0. << "," << 0. << "," << 0;
} else {
G4double x1 = value->second->sum_wx()/unitValue*fact;
G4double x2 = value->second->sum_wx2()/unitValue/unitValue*fact*fact;
G4int n = value->second->n();
// rms is sigma = sqrt((x2-x1^2/n)/(n-1))
// var = mean +/- rms/sqrt(n): means that the relative error of the sum = rms*sqrt(n)/x1
G4double rms = value->second->rms()/unitValue*fact;
// Relative error in %
G4double relError = rms*std::sqrt(n)*100./x1;
ofile << x1 << ", " << x2 << ", " << n << ", " << relError;
ofile << G4endl;
G4double factor = relError*relError/100.;
if (factor > 1.)
{
G4cout << "# Mesh or volume name: " << fScoringMesh->GetWorldName()
<< " -- # Primitive scorer name: " << msMapItr->first << G4endl
<< " bin " << x << "," << y << "," << z << " : statistical error " << relError << "(%)" << G4endl
<< " to reduce the statistical error below 10%, increase number of events approximately "
<< factor << " times." << G4endl;
}
}
if(opt.find("csv") != std::string::npos) {
ofile << G4endl;
} else if(opt.find("sequence") != std::string::npos) {
ofile << " ";
if(count++%5 == 4) ofile << G4endl;
}
} // z
} // y
} // x
ofile << std::setprecision(6);
// close the file
ofile.close();
}
void GRScoreWriter::DumpAllQuantitiesToFile(const G4String& fileName,
const G4String& option) {
// change the option string into lowercase to the case-insensitive.
G4String opt = option;
std::transform(opt.begin(), opt.end(), opt.begin(), (int (*)(int))(tolower));
// confirm the option
if(opt.size() == 0) opt = "csv";
if(opt.find("csv") == std::string::npos &&
opt.find("sequence") == std::string::npos) {
G4cerr << "ERROR : DumpToFile : Unknown option -> "
<< option << G4endl;
return;
}
// open the file
std::ofstream ofile(fileName);
if(!ofile) {
G4cerr << "ERROR : DumpToFile : File open error -> "
<< fileName << G4endl;
return;
}
ofile << "# Mesh or volume name: " << fScoringMesh->GetWorldName() << G4endl;
if(fact!=1.0)
{ ofile << "# Multiplication factor : " << fact << G4endl; }
ofile << "# First three integer entries: index of a cell of a mesh, just one cell for a volume tally." << G4endl;
ofile << "# Forth entry: sum of scores." << G4endl;
ofile << "# Fifth entry: sum of squared scores." << G4endl;
ofile << "# Sixth entry: number of events with non-zero effect." << G4endl;
ofile << "# Seventh entry: relative statistical error in %." << G4endl << G4endl;
// retrieve the map
using MeshScoreMap = G4VScoringMesh::MeshScoreMap;
MeshScoreMap fSMap = fScoringMesh->GetScoreMap();
MeshScoreMap::const_iterator msMapItr = fSMap.begin();
std::map<G4int, G4StatDouble*> * score;
for(; msMapItr != fSMap.end(); msMapItr++) {
G4String psname = msMapItr->first;
score = msMapItr->second->GetMap();
ofile << "# Primitive scorer name: " << msMapItr->first << G4endl;
G4double unitValue = fScoringMesh->GetPSUnitValue(psname);
G4String unit = fScoringMesh->GetPSUnit(psname);
G4String divisionAxisNames[3];
fScoringMesh->GetDivisionAxisNames(divisionAxisNames);
// index order
ofile << "# i" << divisionAxisNames[0]
<< ", i" << divisionAxisNames[1]
<< ", i" << divisionAxisNames[2];
// unit of scored value
ofile << ", total(value) ";
if(unit.size() > 0) ofile << "[" << unit << "]";
ofile << ", total(value^2), number of entries, relative error (%)" << G4endl;
// "sequence" option: write header info
if(opt.find("sequence") != std::string::npos) {
ofile << fNMeshSegments[0] << " " << fNMeshSegments[1] << " " << fNMeshSegments[2]
<< G4endl;
}
// write quantity
long count = 0;
ofile << std::setprecision(16); // for double value with 8 bytes
for(int x = 0; x < fNMeshSegments[0]; x++) {
for(int y = 0; y < fNMeshSegments[1]; y++) {
for(int z = 0; z < fNMeshSegments[2]; z++) {
G4int idx = GetIndex(x, y, z);
if(opt.find("csv") != std::string::npos)
ofile << x << "," << y << "," << z << ",";
std::map<G4int, G4StatDouble*>::iterator value = score->find(idx);
if(value == score->end()) {
ofile << 0. << "," << 0. << "," << 0;
} else {
G4double x1 = value->second->sum_wx()/unitValue*fact;
G4double x2 = value->second->sum_wx2()/unitValue/unitValue*fact*fact;
G4int n = value->second->n();
// rms is sigma = sqrt((x2-x1^2/n)/(n-1))
// var = mean +/- rms/sqrt(n): means that the relative error of the sum = rms*sqrt(n)/x1
G4double rms = value->second->rms()/unitValue*fact;
// Relative error in %
G4double relError = rms*std::sqrt(n)*100./x1;
ofile << x1 << ", " << x2 << ", " << n << ", " << relError;
ofile << G4endl;
G4double factor = relError*relError/100.;
if (factor > 1.)
{
G4cout << "# Mesh or volume name: " << fScoringMesh->GetWorldName()
<< " -- # Primitive scorer name: " << msMapItr->first << G4endl
<< " bin " << x << "," << y << "," << z << " : statistical error " << relError << "(%)" << G4endl
<< " to reduce the statistical error below 10%, increase number of events approximately "
<< factor << " times." << G4endl;
}
}
if(opt.find("csv") != std::string::npos) {
ofile << G4endl;
} else if(opt.find("sequence") != std::string::npos) {
ofile << " ";
if(count++%5 == 4) ofile << G4endl;
}
} // z
} // y
} // x
ofile << std::setprecision(6);
} // for(; msMapItr ....)
// close the file
ofile.close();
}