38 if (!fGarfieldPhysics) {
41 return fGarfieldPhysics;
45 delete fGarfieldPhysics;
49GarfieldPhysics::GarfieldPhysics() {
50 fSecondaryParticles =
new std::vector<GarfieldParticle*>();
53 fComponentAnalyticField = 0;
55 createSecondariesInGeant4 =
false;
56 fIonizationModel =
"PAIPhot";
59GarfieldPhysics::~GarfieldPhysics() {
61 delete fSecondaryParticles;
62 delete fMediumMagboltz;
64 delete fComponentAnalyticField;
67 std::cout <<
"Deconstructor GarfieldPhysics" << std::endl;
73 if (model !=
"PAIPhot" && model !=
"PAI" && model !=
"Heed") {
74 std::cout <<
"Unknown ionization model " << model << std::endl;
75 std::cout <<
"Using PAIPhot as default model!" << std::endl;
78 fIonizationModel = model;
80 if (fIonizationModel ==
"PAIPhot" || fIonizationModel ==
"PAI") {
81 if (useDefaults ==
true) {
100 }
else if (fIonizationModel ==
"Heed") {
101 if (useDefaults ==
true) {
122 double ekin_min_MeV,
double ekin_max_MeV,
123 std::string program) {
124 if (ekin_min_MeV >= ekin_max_MeV) {
125 std::cout <<
"Ekin_min=" << ekin_min_MeV
126 <<
" keV is larger than Ekin_max=" << ekin_max_MeV <<
" keV"
131 if (program ==
"garfield") {
132 std::cout <<
"Garfield model (Heed) is applicable for G4Particle "
133 << particleName <<
" between " << ekin_min_MeV <<
" MeV and "
134 << ekin_max_MeV <<
" MeV" << std::endl;
136 fMapParticlesEnergyGarfield.insert(std::make_pair(
137 particleName, std::make_pair(ekin_min_MeV, ekin_max_MeV)));
139 std::cout << fIonizationModel <<
" is applicable for G4Particle "
140 << particleName <<
" between " << ekin_min_MeV <<
" MeV and "
141 << ekin_max_MeV <<
" MeV" << std::endl;
142 fMapParticlesEnergyGeant4.insert(std::make_pair(
143 particleName, std::make_pair(ekin_min_MeV, ekin_max_MeV)));
148 if (program ==
"garfield") {
149 auto it = fMapParticlesEnergyGarfield.find(name);
150 if (it != fMapParticlesEnergyGarfield.end())
return true;
152 auto it = fMapParticlesEnergyGeant4.find(name);
153 if (it != fMapParticlesEnergyGeant4.end())
return true;
159 std::string program) {
160 if (program ==
"garfield") {
161 auto it = fMapParticlesEnergyGarfield.find(name);
162 if (it != fMapParticlesEnergyGarfield.end()) {
164 if (range.first <= ekin_MeV && range.second >= ekin_MeV) {
169 auto it = fMapParticlesEnergyGeant4.find(name);
170 if (it != fMapParticlesEnergyGeant4.end()) {
172 if (range.first <= ekin_MeV && range.second >= ekin_MeV) {
181 std::string program) {
182 if (program ==
"garfield") {
183 auto it = fMapParticlesEnergyGarfield.find(name);
184 if (it != fMapParticlesEnergyGarfield.end()) {
189 auto it = fMapParticlesEnergyGeant4.find(name);
190 if (it != fMapParticlesEnergyGeant4.end()) {
199 std::string program) {
200 if (program ==
"garfield") {
201 auto it = fMapParticlesEnergyGarfield.find(name);
202 if (it != fMapParticlesEnergyGarfield.end()) {
207 auto it = fMapParticlesEnergyGeant4.find(name);
208 if (it != fMapParticlesEnergyGeant4.end()) {
224 const double rPenning = 0.57;
225 const double lambdaPenning = 0.;
227 fMediumMagboltz->
LoadGasFile(
"ar_70_co2_30_1000mbar.gas");
230 fComponentAnalyticField->
SetMedium(fMediumMagboltz);
232 const double rWire = 25.e-4;
234 const double rTube = 1.451;
236 const double vWire = 1000.;
237 const double vTube = 0.;
239 fComponentAnalyticField->
AddWire(0., 0., 2 * rWire, vWire,
"w");
241 fComponentAnalyticField->
AddTube(rTube, vTube, 0,
"t");
252 double time,
double x_cm,
double y_cm,
double z_cm,
253 double dx,
double dy,
double dz) {
254 G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
265 const double rWire = 25.e-4;
267 const double rTube = 1.45;
269 const double lTube = 10.;
271 double eKin_eV = ekin_MeV * 1e+6;
273 double xc = 0., yc = 0., zc = 0., tc = 0.;
281 if (fIonizationModel !=
"Heed" || particleName ==
"gamma") {
282 if (particleName ==
"gamma") {
283 fTrackHeed->
TransportPhoton(x_cm, y_cm, z_cm, time, eKin_eV, dx, dy, dz,
288 fEnergyDeposit = eKin_eV;
291 for (
int cl = 0; cl < nc; cl++) {
292 double xe, ye, ze, te;
293 double ee, dxe, dye, dze;
294 fTrackHeed->
GetElectron(cl, xe, ye, ze, te, ee, dxe, dye, dze);
295 if (ze < lTube && ze > -lTube && sqrt(xe * xe + ye * ye) < rTube) {
297 if (particleName ==
"gamma") {
298 fEnergyDeposit += fTrackHeed->
GetW();
300 analysisManager->FillH3(1, ze * 10, xe * 10, ye * 10);
301 if (createSecondariesInGeant4) {
303 if (newTime < time) {
307 "e-", ee, newTime, xe, ye, ze, dxe, dye, dze));
312 double xe1, ye1, ze1, te1;
313 double xe2, ye2, ze2, te2;
319 if (0 < xe2 && xe2 < rWire) {
321 }
else if (0 > xe2 && xe2 > -rWire) {
324 if (0 < ye2 && ye2 < rWire) {
326 }
else if (0 > ye2 && ye2 > -rWire) {
335 fAvalancheSize += ne;
341 fTrackHeed->
NewTrack(x_cm, y_cm, z_cm, time, dx, dy, dz);
343 while (fTrackHeed->
GetCluster(xc, yc, zc, tc, nc, ec, extra)) {
344 if (zc < lTube && zc > -lTube && sqrt(xc * xc + yc * yc) < rTube) {
346 fEnergyDeposit += ec;
347 for (
int cl = 0; cl < nc; cl++) {
348 double xe, ye, ze, te;
349 double ee, dxe, dye, dze;
350 fTrackHeed->
GetElectron(cl, xe, ye, ze, te, ee, dxe, dye, dze);
351 if (ze < lTube && ze > -lTube && sqrt(xe * xe + ye * ye) < rTube) {
352 analysisManager->FillH3(1, ze * 10, xe * 10, ye * 10);
353 if (createSecondariesInGeant4) {
355 if (newTime < time) {
359 "e-", ee, newTime, xe, ye, ze, dxe, dye, dze));
364 double xe1, ye1, ze1, te1;
365 double xe2, ye2, ze2, te2;
371 if (0 < xe2 && xe2 < rWire) {
373 }
else if (0 > xe2 && xe2 > -rWire) {
376 if (0 < ye2 && ye2 < rWire) {
378 }
else if (0 > ye2 && ye2 > -rWire) {
387 fAvalancheSize += ne;
393 fGain = fAvalancheSize / nsum;
397 return fSecondaryParticles;
401 if (!fSecondaryParticles->empty()) {
402 fSecondaryParticles->erase(fSecondaryParticles->begin(),
403 fSecondaryParticles->end());
Selection of the analysis technology.
Definition of the GarfieldPhysics class.
std::pair< double, double > EnergyRange_MeV
double GetMaxEnergyMeVParticle(std::string name, std::string program="garfield")
void DeleteSecondaryParticles()
static GarfieldPhysics * GetInstance()
std::vector< GarfieldParticle * > * GetSecondaryParticles()
void SetIonizationModel(std::string model, bool useDefaults=true)
double GetMinEnergyMeVParticle(std::string name, std::string program="garfield")
void AddParticleName(const std::string particleName, double ekin_min_MeV, double ekin_max_MeV, std::string program)
std::string GetIonizationModel()
void DoIt(std::string particleName, double ekin_MeV, double time, double x_cm, double y_cm, double z_cm, double dx, double dy, double dz)
bool FindParticleNameEnergy(std::string name, double ekin_MeV, std::string program="garfield")
bool FindParticleName(const std::string name, std::string program="garfield")
bool DriftElectron(const double x0, const double y0, const double z0, const double t0)
Simulate the drift line of an electron from a given starting point.
void GetElectronEndpoint(const unsigned int i, double &x0, double &y0, double &z0, double &t0, double &x1, double &y1, double &z1, double &t1, int &status) const
void SetSensor(Sensor *s)
Set the sensor.
void SetDistanceSteps(const double d=0.001)
Use fixed distance steps (default 10 um).
Calculate electron drift lines and avalanches using microscopic tracking.
void GetAvalancheSize(int &ne, int &ni) const
Return the number of electrons and ions in the avalanche.
void SetSensor(Sensor *sensor)
Set the sensor.
bool AvalancheElectron(const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0=0., const double dy0=0., const double dz0=0.)
Calculate an avalanche initiated by a given electron.
void AddTube(const double radius, const double voltage, const int nEdges, const std::string &label)
Add a tube.
void SetMedium(Medium *medium)
Set the medium inside the cell.
void AddWire(const double x, const double y, const double diameter, const double voltage, const std::string &label, const double length=100., const double tension=50., const double rho=19.3, const int ntrap=5)
Add a wire at (x, y) .
bool SetComposition(const std::string &gas1, const double f1=1., const std::string &gas2="", const double f2=0., const std::string &gas3="", const double f3=0., const std::string &gas4="", const double f4=0., const std::string &gas5="", const double f5=0., const std::string &gas6="", const double f6=0.)
Set the gas mixture.
bool LoadGasFile(const std::string &filename)
Read table of gas properties (transport parameters) from file.
bool EnablePenningTransfer(const double r, const double lambda) override
bool Initialise(const bool verbose=false)
void SetTemperature(const double t)
Set the temperature [K].
void SetPressure(const double p)
void AddComponent(Component *comp)
Add a component.
Generate tracks using Heed++.
bool GetCluster(double &xcls, double &ycls, double &zcls, double &tcls, int &n, double &e, double &extra) override
void TransportDeltaElectron(const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0, const double dy0, const double dz0, int &ne, int &ni)
bool NewTrack(const double x0, const double y0, const double z0, const double t0, const double dx0, const double dy0, const double dz0) override
void EnableDeltaElectronTransport()
Switch simulation of delta electrons on.
bool GetElectron(const unsigned int i, double &x, double &y, double &z, double &t, double &e, double &dx, double &dy, double &dz)
void TransportPhoton(const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0, const double dy0, const double dz0, int &ne, int &ni)
double GetW() const
Return the W value of the medium (of the last simulated track).
void SetSensor(Sensor *s)
Set the sensor through which to transport the particle.
void SetKineticEnergy(const double ekin)
Set the kinetic energy of the particle.
virtual void SetParticle(const std::string &part)