Import Geant4 10.4.1 source tree
This commit is contained in:
@@ -103,7 +103,7 @@ G4GeneralParticleSourceMessenger::G4GeneralParticleSourceMessenger
|
||||
(G4GeneralParticleSource *fPtclGun)
|
||||
: fGPS(fPtclGun),fParticleGun(0),fShootIon(false),
|
||||
fAtomicNumber(0),fAtomicMass(0),fIonCharge(0),fIonExciteEnergy(0.),
|
||||
fShootIonL(0),fAtomicNumberL(0),fAtomicMassL(0),fIonChargeL(0),fIonEnergyLevel(0)
|
||||
fAtomicNumberL(0),fAtomicMassL(0),fIonChargeL(0),fIonEnergyLevel(0)
|
||||
|
||||
{
|
||||
//A.Dotti - 10th October 2014
|
||||
@@ -307,7 +307,7 @@ G4GeneralParticleSourceMessenger::G4GeneralParticleSourceMessenger
|
||||
shapeCmd1->SetGuidance("Sets source shape for Plan, Surface or Volume type source.");
|
||||
shapeCmd1->SetParameterName("Shape",false,false);
|
||||
shapeCmd1->SetDefaultValue("NULL");
|
||||
shapeCmd1->SetCandidates("Circle Annulus Ellipse Square Rectangle Sphere Ellipsoid Cylinder Para");
|
||||
shapeCmd1->SetCandidates("Circle Annulus Ellipse Square Rectangle Sphere Ellipsoid Cylinder EllipticCylinder Para");
|
||||
|
||||
centreCmd1 = new G4UIcmdWith3VectorAndUnit("/gps/pos/centre",this);
|
||||
centreCmd1->SetGuidance("Set centre coordinates of source.");
|
||||
@@ -677,7 +677,7 @@ G4GeneralParticleSourceMessenger::G4GeneralParticleSourceMessenger
|
||||
energytypeCmd1->SetGuidance("Sets energy distribution type");
|
||||
energytypeCmd1->SetParameterName("EnergyDis",false,false);
|
||||
energytypeCmd1->SetDefaultValue("Mono");
|
||||
energytypeCmd1->SetCandidates("Mono Lin Pow Exp Gauss Brem Bbody Cdg User Arb Epn");
|
||||
energytypeCmd1->SetCandidates("Mono Lin Pow Exp CPow Gauss Brem Bbody Cdg User Arb Epn");
|
||||
|
||||
eminCmd1 = new G4UIcmdWithADoubleAndUnit("/gps/ene/min",this);
|
||||
eminCmd1->SetGuidance("Sets minimum energy");
|
||||
@@ -1744,8 +1744,6 @@ G4String G4GeneralParticleSourceMessenger::GetCurrentValue(G4UIcommand *)
|
||||
|
||||
void G4GeneralParticleSourceMessenger::IonCommand(G4String newValues)
|
||||
{
|
||||
fShootIon = true;
|
||||
|
||||
if (fShootIon)
|
||||
{
|
||||
G4Tokenizer next( newValues );
|
||||
@@ -1762,20 +1760,22 @@ void G4GeneralParticleSourceMessenger::IonCommand(G4String newValues)
|
||||
fIonCharge = StoI(sQ);
|
||||
sQ = next();
|
||||
if (sQ.isNull())
|
||||
{
|
||||
{
|
||||
fIonExciteEnergy = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
fIonExciteEnergy = StoD(sQ) * keV;
|
||||
}
|
||||
}
|
||||
}
|
||||
G4ParticleDefinition* ion;
|
||||
ion = G4IonTable::GetIonTable()->GetIon( fAtomicNumber, fAtomicMass, fIonExciteEnergy);
|
||||
if (ion==0)
|
||||
{
|
||||
G4cout << "Ion with Z=" << fAtomicNumber;
|
||||
G4cout << " A=" << fAtomicMass << " is not defined" << G4endl;
|
||||
G4ExceptionDescription ed;
|
||||
ed << "Ion with Z=" << fAtomicNumber;
|
||||
ed << " A=" << fAtomicMass << " is not defined";
|
||||
ionCmd->CommandFailed(ed);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1785,16 +1785,16 @@ void G4GeneralParticleSourceMessenger::IonCommand(G4String newValues)
|
||||
}
|
||||
else
|
||||
{
|
||||
G4cout << "Set /gps/particle to ion before using /gps/ion command";
|
||||
G4cout << G4endl;
|
||||
G4ExceptionDescription ed;
|
||||
ed << "Set /gps/particle to ion before using /gps/ion command";
|
||||
ionCmd->CommandFailed(ed);
|
||||
}
|
||||
}
|
||||
|
||||
void G4GeneralParticleSourceMessenger::IonLvlCommand(G4String newValues)
|
||||
{
|
||||
fShootIonL = true;
|
||||
|
||||
if (fShootIonL) {
|
||||
if (fShootIon)
|
||||
{
|
||||
G4Tokenizer next(newValues);
|
||||
// check argument
|
||||
fAtomicNumberL = StoI(next());
|
||||
@@ -1815,16 +1815,19 @@ void G4GeneralParticleSourceMessenger::IonLvlCommand(G4String newValues)
|
||||
G4ParticleDefinition* ion;
|
||||
ion = G4IonTable::GetIonTable()->GetIon(fAtomicNumberL, fAtomicMassL, fIonEnergyLevel);
|
||||
if (ion == 0) {
|
||||
G4cout << "Ion with Z=" << fAtomicNumberL;
|
||||
G4cout << " A=" << fAtomicMassL << " is not defined" << G4endl;
|
||||
G4ExceptionDescription ed;
|
||||
ed << "Ion with Z=" << fAtomicNumberL;
|
||||
ed << " A=" << fAtomicMassL << " is not defined";
|
||||
ionLvlCmd->CommandFailed(ed);
|
||||
} else {
|
||||
fParticleGun->SetParticleDefinition(ion);
|
||||
fParticleGun->SetParticleCharge(fIonChargeL*eplus);
|
||||
}
|
||||
|
||||
} else {
|
||||
G4cout << "Set /gps/particle to ion before using /gps/ionLvl command";
|
||||
G4cout << G4endl;
|
||||
G4ExceptionDescription ed;
|
||||
ed << "Set /gps/particle to ion before using /gps/ionLvl command";
|
||||
ionLvlCmd->CommandFailed(ed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4ParticleGunMessenger.cc 98744 2016-08-09 13:21:26Z gcosmo $
|
||||
// $Id: G4ParticleGunMessenger.cc 108473 2018-02-15 14:15:09Z gcosmo $
|
||||
//
|
||||
|
||||
#include "G4ParticleGunMessenger.hh"
|
||||
@@ -155,6 +155,8 @@ G4ParticleGunMessenger::G4ParticleGunMessenger(G4ParticleGun * fPtclGun)
|
||||
ionCmd->SetParameter(param);
|
||||
|
||||
ionLvlCmd = new G4UIcommand("/gun/ionL",this);
|
||||
ionLvlCmd->SetGuidance("THIS COMMAND IS DEPRECATED and will be removed in release 10.5.");
|
||||
ionLvlCmd->SetGuidance("Use /gun/ion instead.");
|
||||
ionLvlCmd->SetGuidance("Set properties of ion to be generated.");
|
||||
ionLvlCmd->SetGuidance("[usage] /gun/ionL Z A [Q I]");
|
||||
ionLvlCmd->SetGuidance(" Z:(int) AtomicNumber");
|
||||
@@ -201,6 +203,7 @@ G4ParticleGunMessenger::~G4ParticleGunMessenger()
|
||||
|
||||
void G4ParticleGunMessenger::SetNewValue(G4UIcommand * command,G4String newValues)
|
||||
{
|
||||
G4ExceptionDescription ed;
|
||||
if (command==listCmd) {
|
||||
particleTable->DumpTable();
|
||||
} else if (command==particleCmd) {
|
||||
@@ -209,8 +212,12 @@ void G4ParticleGunMessenger::SetNewValue(G4UIcommand * command,G4String newValue
|
||||
} else {
|
||||
fShootIon = false;
|
||||
G4ParticleDefinition* pd = particleTable->FindParticle(newValues);
|
||||
if(pd != 0)
|
||||
{ fParticleGun->SetParticleDefinition( pd ); }
|
||||
if(pd != 0) {
|
||||
fParticleGun->SetParticleDefinition( pd );
|
||||
} else {
|
||||
ed << "Particle [" << newValues << "] is not found.";
|
||||
command->CommandFailed(ed);
|
||||
}
|
||||
}
|
||||
|
||||
} else if( command==directionCmd )
|
||||
@@ -230,9 +237,28 @@ void G4ParticleGunMessenger::SetNewValue(G4UIcommand * command,G4String newValue
|
||||
else if( command==numberCmd )
|
||||
{ fParticleGun->SetNumberOfParticles(numberCmd->GetNewIntValue(newValues)); }
|
||||
else if( command==ionCmd )
|
||||
{ IonCommand(newValues); }
|
||||
{
|
||||
if (fShootIon) {
|
||||
IonCommand(newValues);
|
||||
} else {
|
||||
ed << "Set /gun/particle to ion before using /gun/ion command";
|
||||
command->CommandFailed(ed);
|
||||
}
|
||||
}
|
||||
else if( command==ionLvlCmd )
|
||||
{ IonLevelCommand(newValues); }
|
||||
{
|
||||
G4ExceptionDescription depWarn;
|
||||
depWarn << "\nCommand /gun/ionL is deprecated and will be removed in release 10.5.\n"
|
||||
<< "Use /gun/ion instead.\n";
|
||||
G4Exception("G4ParticleGunMessenger::SetNewValue","IonLWarn",JustWarning,depWarn);
|
||||
|
||||
if (fShootIon) {
|
||||
IonLevelCommand(newValues);
|
||||
} else {
|
||||
ed << "Set /gun/particle to ion before using /gun/ion command";
|
||||
command->CommandFailed(ed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
G4String G4ParticleGunMessenger::GetCurrentValue(G4UIcommand * command)
|
||||
@@ -288,79 +314,73 @@ G4String G4ParticleGunMessenger::GetCurrentValue(G4UIcommand * command)
|
||||
|
||||
void G4ParticleGunMessenger::IonLevelCommand(G4String newValues)
|
||||
{
|
||||
if (fShootIon) {
|
||||
G4Tokenizer next( newValues );
|
||||
// check argument
|
||||
fAtomicNumber = StoI(next());
|
||||
fAtomicMass = StoI(next());
|
||||
G4String sQ = next();
|
||||
if (sQ.isNull() || StoI(sQ)<0) {
|
||||
fIonCharge = fAtomicNumber;
|
||||
} else {
|
||||
fIonCharge = StoI(sQ);
|
||||
}
|
||||
sQ = next();
|
||||
if (sQ.isNull()) {
|
||||
fIonEnergyLevel = 0;
|
||||
} else {
|
||||
fIonEnergyLevel = StoI(sQ);
|
||||
}
|
||||
G4ParticleDefinition* ion = 0;
|
||||
ion = G4IonTable::GetIonTable()->GetIon(fAtomicNumber,fAtomicMass,fIonEnergyLevel);
|
||||
if (ion == 0) {
|
||||
G4cout << "Ion with Z = " << fAtomicNumber << ", A = " << fAtomicMass
|
||||
<< ", I = " << fIonEnergyLevel << " is not defined " << G4endl;
|
||||
} else {
|
||||
fParticleGun->SetParticleDefinition(ion);
|
||||
fParticleGun->SetParticleCharge(fIonCharge*eplus);
|
||||
}
|
||||
G4Tokenizer next( newValues );
|
||||
// check argument
|
||||
fAtomicNumber = StoI(next());
|
||||
fAtomicMass = StoI(next());
|
||||
G4String sQ = next();
|
||||
if (sQ.isNull() || StoI(sQ)<0) {
|
||||
fIonCharge = fAtomicNumber;
|
||||
} else {
|
||||
G4cout << "Set /gun/particle to ion before using /gun/ion command";
|
||||
G4cout << G4endl;
|
||||
fIonCharge = StoI(sQ);
|
||||
}
|
||||
sQ = next();
|
||||
if (sQ.isNull()) {
|
||||
fIonEnergyLevel = 0;
|
||||
} else {
|
||||
fIonEnergyLevel = StoI(sQ);
|
||||
}
|
||||
G4ParticleDefinition* ion = 0;
|
||||
ion = G4IonTable::GetIonTable()->GetIon(fAtomicNumber,fAtomicMass,fIonEnergyLevel);
|
||||
if (ion == 0) {
|
||||
G4ExceptionDescription ed;
|
||||
ed << "Ion with Z = " << fAtomicNumber << ", A = " << fAtomicMass
|
||||
<< ", I = " << fIonEnergyLevel << " is not defined ";
|
||||
ionLvlCmd->CommandFailed(ed);
|
||||
} else {
|
||||
fParticleGun->SetParticleDefinition(ion);
|
||||
fParticleGun->SetParticleCharge(fIonCharge*eplus);
|
||||
}
|
||||
}
|
||||
|
||||
void G4ParticleGunMessenger::IonCommand(G4String newValues)
|
||||
{
|
||||
if (fShootIon) {
|
||||
G4Tokenizer next( newValues );
|
||||
// check argument
|
||||
fAtomicNumber = StoI(next());
|
||||
fAtomicMass = StoI(next());
|
||||
fIonCharge = fAtomicNumber;
|
||||
fIonExciteEnergy = 0.0;
|
||||
fIonFloatingLevelBase = '\0';
|
||||
G4String sQ = next();
|
||||
G4Tokenizer next( newValues );
|
||||
// check argument
|
||||
fAtomicNumber = StoI(next());
|
||||
fAtomicMass = StoI(next());
|
||||
fIonCharge = fAtomicNumber;
|
||||
fIonExciteEnergy = 0.0;
|
||||
fIonFloatingLevelBase = '\0';
|
||||
G4String sQ = next();
|
||||
if (!(sQ.isNull()))
|
||||
{
|
||||
if (StoI(sQ)>=0)
|
||||
fIonCharge = StoI(sQ);
|
||||
|
||||
sQ = next();
|
||||
if (!(sQ.isNull()))
|
||||
{
|
||||
if (StoI(sQ)>=0)
|
||||
fIonCharge = StoI(sQ);
|
||||
fIonExciteEnergy = StoD(sQ) * keV;
|
||||
|
||||
sQ = next();
|
||||
if (!(sQ.isNull()))
|
||||
{
|
||||
fIonExciteEnergy = StoD(sQ) * keV;
|
||||
|
||||
sQ = next();
|
||||
if (sQ.isNull()||sQ=="noFloat")
|
||||
{ fIonFloatingLevelBase = '\0'; }
|
||||
else
|
||||
{ fIonFloatingLevelBase = sQ[(size_t)0]; }
|
||||
}
|
||||
if (sQ.isNull()||sQ=="noFloat")
|
||||
{ fIonFloatingLevelBase = '\0'; }
|
||||
else
|
||||
{ fIonFloatingLevelBase = sQ[(size_t)0]; }
|
||||
}
|
||||
G4ParticleDefinition* ion = 0;
|
||||
ion = G4IonTable::GetIonTable()->GetIon( fAtomicNumber, fAtomicMass,
|
||||
}
|
||||
G4ParticleDefinition* ion = 0;
|
||||
ion = G4IonTable::GetIonTable()->GetIon( fAtomicNumber, fAtomicMass,
|
||||
fIonExciteEnergy, fIonFloatingLevelBase);
|
||||
if (ion==0) {
|
||||
G4cout << "Ion with Z=" << fAtomicNumber;
|
||||
G4cout << " A=" << fAtomicMass << "is not defined" << G4endl;
|
||||
} else {
|
||||
fParticleGun->SetParticleDefinition(ion);
|
||||
fParticleGun->SetParticleCharge(fIonCharge*eplus);
|
||||
}
|
||||
if (ion==0) {
|
||||
G4ExceptionDescription ed;
|
||||
ed << "Ion with Z=" << fAtomicNumber;
|
||||
ed << " A=" << fAtomicMass << "is not defined";
|
||||
ionCmd->CommandFailed(ed);
|
||||
} else {
|
||||
G4cout << "Set /gun/particle to ion before using /gun/ion command";
|
||||
G4cout << G4endl;
|
||||
fParticleGun->SetParticleDefinition(ion);
|
||||
fParticleGun->SetParticleCharge(fIonCharge*eplus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,10 @@
|
||||
// particularly when the blackbody function is not used. Also moved to dynamically allocated
|
||||
// memory in the LinearInterpolation, ExpInterpolation and LogInterpolation functions. Again,
|
||||
// this will save space if these functions are unused.
|
||||
//
|
||||
//
|
||||
// 24/11/2017 Fan Lei
|
||||
// Added cutoff power-law distribution option. Implementation is similar to that of the BlackBody one.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#include "G4SPSEneDistribution.hh"
|
||||
|
||||
@@ -98,11 +102,15 @@ G4SPSEneDistribution::G4SPSEneDistribution(): Epnflag(false),eneRndm(0),Splinete
|
||||
Arb_grad_cept_flag = false;
|
||||
Arb_alpha_Const_flag = false;
|
||||
Arb_ezero_flag = false;
|
||||
histInit = false;
|
||||
histCalcd = false;
|
||||
BBhistInit = false;
|
||||
BBhistCalcd = false;
|
||||
CPhistInit = false;
|
||||
CPhistCalcd = false;
|
||||
|
||||
BBHist = NULL;
|
||||
Bbody_x = NULL;
|
||||
CPHist = NULL;
|
||||
CP_x = NULL;
|
||||
|
||||
threadLocal_t& data = threadLocalData.Get();
|
||||
data.Emax = Emax;
|
||||
@@ -137,6 +145,8 @@ G4SPSEneDistribution::~G4SPSEneDistribution()
|
||||
}
|
||||
delete Bbody_x;
|
||||
delete BBHist;
|
||||
delete CP_x;
|
||||
delete CPHist;
|
||||
for ( std::vector<G4DataInterpolation*>::iterator it = SplineInt.begin() ; it!=SplineInt.end() ; ++it)
|
||||
{
|
||||
delete *it;
|
||||
@@ -393,20 +403,36 @@ void G4SPSEneDistribution::Calculate()
|
||||
}
|
||||
else if (EnergyDisType == "Bbody")
|
||||
{
|
||||
if(!histInit)
|
||||
if(!BBhistInit)
|
||||
{
|
||||
InitHists();
|
||||
BBInitHists();
|
||||
}
|
||||
CalculateBbodySpectrum();
|
||||
}
|
||||
else if (EnergyDisType == "CPow")
|
||||
{
|
||||
if(!CPhistInit)
|
||||
{
|
||||
CPInitHists();
|
||||
}
|
||||
CalculateCPowSpectrum();
|
||||
}
|
||||
}
|
||||
|
||||
//MT: Lock in caller
|
||||
void G4SPSEneDistribution::InitHists()
|
||||
void G4SPSEneDistribution::BBInitHists()
|
||||
{
|
||||
BBHist = new std::vector<G4double>(10001, 0.0);
|
||||
Bbody_x = new std::vector<G4double>(10001, 0.0);
|
||||
histInit = true;
|
||||
BBhistInit = true;
|
||||
}
|
||||
|
||||
//MT: Lock in caller
|
||||
void G4SPSEneDistribution::CPInitHists()
|
||||
{
|
||||
CPHist = new std::vector<G4double>(10001, 0.0);
|
||||
CP_x = new std::vector<G4double>(10001, 0.0);
|
||||
CPhistInit = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -500,6 +526,42 @@ void G4SPSEneDistribution::CalculateBbodySpectrum()
|
||||
}
|
||||
}
|
||||
|
||||
//MT: Lock in caller
|
||||
void G4SPSEneDistribution::CalculateCPowSpectrum()
|
||||
{
|
||||
// create cutoff power-law spectrum
|
||||
// x^a exp(-x/b)
|
||||
// the integral of this function is an incomplete gamma function, which is only available in the Boost library.
|
||||
//
|
||||
// User inputs are emin, emax and alpha and Ezero. These are used to
|
||||
// create a 10,000 bin histogram.
|
||||
|
||||
G4double erange = threadLocalData.Get().Emax - threadLocalData.Get().Emin;
|
||||
G4double steps = erange / 10000.;
|
||||
alpha = threadLocalData.Get().alpha ;
|
||||
Ezero = threadLocalData.Get().Ezero ;
|
||||
|
||||
G4int count = 0;
|
||||
G4double sum = 0.;
|
||||
CPHist->at(0) = 0.;
|
||||
|
||||
while (count < 10000) {
|
||||
CP_x->at(count) = threadLocalData.Get().Emin + G4double(count * steps);
|
||||
G4double CP_y = std::pow(CP_x->at(count), alpha) * std::exp(-CP_x->at(count) / Ezero);
|
||||
sum = sum + CP_y;
|
||||
CPHist->at(count + 1) = CPHist->at(count) + CP_y;
|
||||
count++;
|
||||
}
|
||||
|
||||
CP_x->at(10000) = threadLocalData.Get().Emax;
|
||||
// Normalise cumulative histo.
|
||||
count = 0;
|
||||
while (count < 10001) {
|
||||
CPHist->at(count) = CPHist->at(count) / sum;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
void G4SPSEneDistribution::InputEnergySpectra(G4bool value) {
|
||||
G4AutoLock l(&mutex);
|
||||
// Allows user to specifiy spectrum is momentum
|
||||
@@ -1143,6 +1205,79 @@ void G4SPSEneDistribution::GeneratePowEnergies(G4bool bArb = false)
|
||||
}
|
||||
}
|
||||
|
||||
void G4SPSEneDistribution::GenerateCPowEnergies()
|
||||
{
|
||||
// Method to generate particle energies distributed in
|
||||
// cutoff power-law distribution
|
||||
|
||||
// CP_x holds Energies, and CPHist holds the cumulative histo.
|
||||
// binary search to find correct bin then lin interpolation.
|
||||
// Use the earlier defined histogram + RandGeneral method to generate
|
||||
// random numbers following the histos distribution.
|
||||
G4double rndm;
|
||||
G4int nabove, nbelow = 0, middle;
|
||||
nabove = 10001;
|
||||
rndm = eneRndm->GenRandEnergy();
|
||||
G4AutoLock l(&mutex);
|
||||
G4bool done = CPhistCalcd;
|
||||
l.unlock();
|
||||
if(!done)
|
||||
{
|
||||
Calculate(); //This is has a lock inside, risk is to do it twice
|
||||
l.lock();
|
||||
CPhistCalcd = true;
|
||||
l.unlock();
|
||||
}
|
||||
|
||||
// Binary search to find bin that rndm is in
|
||||
while (nabove - nbelow > 1)
|
||||
{
|
||||
middle = (nabove + nbelow) / 2;
|
||||
if (rndm == CPHist->at(middle))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (rndm < CPHist->at(middle))
|
||||
{
|
||||
nabove = middle;
|
||||
}
|
||||
else
|
||||
{
|
||||
nbelow = middle;
|
||||
}
|
||||
}
|
||||
|
||||
// Now interpolate in that bin to find the correct output value.
|
||||
G4double x1, x2, y1, y2, t, q;
|
||||
x1 = CP_x->at(nbelow);
|
||||
if(nbelow+1 == static_cast<G4int>(CP_x->size()))
|
||||
{
|
||||
x2 = CP_x->back();
|
||||
}
|
||||
else
|
||||
{
|
||||
x2 = CP_x->at(nbelow + 1);
|
||||
}
|
||||
y1 = CPHist->at(nbelow);
|
||||
if(nbelow+1 == static_cast<G4int>(CPHist->size()))
|
||||
{
|
||||
G4cout << CPHist->back() << G4endl;
|
||||
y2 = CPHist->back();
|
||||
}
|
||||
else
|
||||
{
|
||||
y2 = CPHist->at(nbelow + 1);
|
||||
}
|
||||
t = (y2 - y1) / (x2 - x1);
|
||||
q = y1 - t * x1;
|
||||
|
||||
threadLocalData.Get().particle_energy = (rndm - q) / t;
|
||||
|
||||
if (verbosityLevel >= 1) {
|
||||
G4cout << "Energy is " << threadLocalData.Get().particle_energy << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
void G4SPSEneDistribution::GenerateBiasPowEnergies()//G4double& ene,G4double& wweight)
|
||||
{
|
||||
// Method to generate particle energies distributed as
|
||||
@@ -1294,13 +1429,13 @@ void G4SPSEneDistribution::GenerateBbodyEnergies()
|
||||
nabove = 10001;
|
||||
rndm = eneRndm->GenRandEnergy();
|
||||
G4AutoLock l(&mutex);
|
||||
G4bool done = histCalcd;
|
||||
G4bool done = BBhistCalcd;
|
||||
l.unlock();
|
||||
if(!done)
|
||||
{
|
||||
Calculate(); //This is has a lock inside, risk is to do it twice
|
||||
l.lock();
|
||||
histCalcd = true;
|
||||
BBhistCalcd = true;
|
||||
l.unlock();
|
||||
}
|
||||
|
||||
@@ -1753,6 +1888,10 @@ G4double G4SPSEneDistribution::GenerateOne(G4ParticleDefinition* a)
|
||||
else if (EnergyDisType == "Pow")
|
||||
{
|
||||
GeneratePowEnergies(false);
|
||||
}
|
||||
else if (EnergyDisType == "CPow")
|
||||
{
|
||||
GenerateCPowEnergies();
|
||||
}
|
||||
else if (EnergyDisType == "Exp")
|
||||
{
|
||||
|
||||
@@ -42,9 +42,11 @@
|
||||
// Version 1.0, 05/02/2004, Fan Lei, Created.
|
||||
// Based on the G4GeneralParticleSource class in Geant4 v6.0
|
||||
//
|
||||
// Version 1.1, 13/02/2017, Maxime Chauvin
|
||||
// Added surface and volume shape "EllipticCylinder"
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
#include "G4SPSPosDistribution.hh"
|
||||
|
||||
#include "G4PhysicalConstants.hh"
|
||||
@@ -506,6 +508,7 @@ void G4SPSPosDistribution::GeneratePointsOnSurface(G4ThreeVector& pos)
|
||||
G4double theta, phi;
|
||||
G4double x, y, z;
|
||||
x = y = z = 0.;
|
||||
G4double expression;
|
||||
G4ThreeVector RandPos;
|
||||
// G4double tempx, tempy, tempz;
|
||||
thread_data_t& td = ThreadData.Get();
|
||||
@@ -743,6 +746,101 @@ void G4SPSPosDistribution::GeneratePointsOnSurface(G4ThreeVector& pos)
|
||||
RandPos.setZ(z);
|
||||
|
||||
}
|
||||
else if(Shape == "EllipticCylinder")
|
||||
{
|
||||
G4double AreaTop, AreaBot, AreaLat, AreaTotal;
|
||||
G4double h;
|
||||
G4double prob1, prob2, prob3;
|
||||
G4double testrand;
|
||||
|
||||
// User giver x, y and z-half length
|
||||
// Calculate surface areas, maybe move this to
|
||||
// a different routine.
|
||||
|
||||
AreaTop = pi * halfx * halfy;
|
||||
AreaBot = AreaTop;
|
||||
// Using circumference approximation by Ramanujan (order h^3)
|
||||
//AreaLat = 2*halfz * pi*( 3*(halfx + halfy) - std::sqrt((3*halfx + halfy) * (halfx + 3*halfy)) );
|
||||
// Using circumference approximation by Ramanujan (order h^5)
|
||||
h = ((halfx - halfy)*(halfx - halfy)) / ((halfx + halfy)*(halfx + halfy));
|
||||
AreaLat = 2*halfz * pi*(halfx + halfy)*(1 + (3*h)/(10 + std::sqrt(4 - 3*h)));
|
||||
AreaTotal = AreaTop + AreaBot + AreaLat;
|
||||
|
||||
prob1 = AreaTop / AreaTotal;
|
||||
prob2 = AreaBot / AreaTotal;
|
||||
prob3 = 1.00 - prob1 - prob2;
|
||||
if(std::fabs(prob3 - (AreaLat/AreaTotal)) >= 0.001)
|
||||
{
|
||||
if(verbosityLevel >= 1)
|
||||
G4cout << AreaLat/AreaTotal << " " << prob3<<G4endl;
|
||||
G4cout << "Error in prob3" << G4endl;
|
||||
}
|
||||
|
||||
// Decide surface to calculate point on.
|
||||
|
||||
testrand = G4UniformRand();
|
||||
if(testrand <= prob1)
|
||||
{
|
||||
//Point on Top surface
|
||||
z = halfz;
|
||||
expression = 20.;
|
||||
while(expression > 1.)
|
||||
{
|
||||
x = PosRndm->GenRandX();
|
||||
y = PosRndm->GenRandY();
|
||||
|
||||
x = (x * 2. * halfx) - halfx;
|
||||
y = (y * 2. * halfy) - halfy;
|
||||
|
||||
expression = ((x*x)/(halfx*halfx)) + ((y*y)/(halfy*halfy));
|
||||
}
|
||||
}
|
||||
else if((testrand > prob1) && (testrand <= (prob1 + prob2)))
|
||||
{
|
||||
//Point on Bottom surface
|
||||
z = -halfz;
|
||||
expression = 20.;
|
||||
while(expression > 1.)
|
||||
{
|
||||
x = PosRndm->GenRandX();
|
||||
y = PosRndm->GenRandY();
|
||||
|
||||
x = (x * 2. * halfx) - halfx;
|
||||
y = (y * 2. * halfy) - halfy;
|
||||
|
||||
expression = ((x*x)/(halfx*halfx)) + ((y*y)/(halfy*halfy));
|
||||
}
|
||||
}
|
||||
else if(testrand > (prob1+prob2))
|
||||
{
|
||||
G4double rand;
|
||||
//Point on Lateral Surface
|
||||
rand = PosRndm->GenRandPosPhi();
|
||||
rand = rand * 2. * pi;
|
||||
|
||||
x = halfx * std::cos(rand);
|
||||
y = halfy * std::sin(rand);
|
||||
|
||||
z = PosRndm->GenRandZ();
|
||||
|
||||
z = (z * 2. * halfz) - halfz;
|
||||
}
|
||||
else
|
||||
G4cout << "Error: testrand " << testrand << G4endl;
|
||||
|
||||
RandPos.setX(x);
|
||||
RandPos.setY(y);
|
||||
RandPos.setZ(z);
|
||||
|
||||
// Cosine law
|
||||
G4ThreeVector zdash(x,y,z);
|
||||
zdash = zdash.unit();
|
||||
G4ThreeVector xdash = Rotz.cross(zdash);
|
||||
G4ThreeVector ydash = xdash.cross(zdash);
|
||||
td.CSideRefVec1 = xdash.unit();
|
||||
td.CSideRefVec2 = ydash.unit();
|
||||
td.CSideRefVec3 = zdash.unit();
|
||||
}
|
||||
else if(Shape == "Para")
|
||||
{
|
||||
G4double testrand;
|
||||
@@ -912,6 +1010,7 @@ void G4SPSPosDistribution::GeneratePointsInVolume(G4ThreeVector& pos)
|
||||
G4ThreeVector RandPos;
|
||||
G4double tempx, tempy, tempz;
|
||||
G4double x, y, z;
|
||||
G4double expression;
|
||||
x = y = z = 0.;
|
||||
if(SourcePosType != "Volume" && verbosityLevel >= 1)
|
||||
G4cout << "Error SourcePosType not Volume" << G4endl;
|
||||
@@ -965,6 +1064,22 @@ void G4SPSPosDistribution::GeneratePointsInVolume(G4ThreeVector& pos)
|
||||
z = (z*2.*halfz) - halfz;
|
||||
}
|
||||
}
|
||||
else if(Shape == "EllipticCylinder")
|
||||
{
|
||||
expression = 20.;
|
||||
while(expression > 1.)
|
||||
{
|
||||
x = PosRndm->GenRandX();
|
||||
y = PosRndm->GenRandY();
|
||||
z = PosRndm->GenRandZ();
|
||||
|
||||
x = (x*2.*halfx) - halfx;
|
||||
y = (y*2.*halfy) - halfy;
|
||||
z = (z*2.*halfz) - halfz;
|
||||
|
||||
expression = ((x*x)/(halfx*halfx)) + ((y*y)/(halfy*halfy));
|
||||
}
|
||||
}
|
||||
else if(Shape == "Para")
|
||||
{
|
||||
x = PosRndm->GenRandX();
|
||||
@@ -1036,6 +1151,7 @@ G4bool G4SPSPosDistribution::IsSourceConfined(G4ThreeVector& pos)
|
||||
theVolume=gNavigator->LocateGlobalPointAndSetup(pos,ptr,true);
|
||||
if(!theVolume) return(false);
|
||||
G4String theVolName = theVolume->GetName();
|
||||
|
||||
if(theVolName == VolName)
|
||||
{
|
||||
if(verbosityLevel >= 1)
|
||||
|
||||
Reference in New Issue
Block a user