Garfield 0.3
Toolkit for the detailed simulation of particle detectors based on ionization measurement in gases and semiconductors
Loading...
Searching...
No Matches
AvalancheGridSpaceCharge.hh
Go to the documentation of this file.
1#ifndef GARFIELD_AVALANCHEGRIDSPACECHARGE_HH
2#define GARFIELD_AVALANCHEGRIDSPACECHARGE_HH
3
4#include <algorithm>
5#include <string>
6#include <utility>
7#include <vector>
8#include <array>
9
10namespace Garfield {
11class Sensor;
14
19 public:
26
28 void Reset();
29
31 void EnableDebugging(const bool option = true) { m_bDebug = option; }
32
34 void EnableStickyAnode(const bool option = true) { m_bStick = option; }
35
37 void EnableTOF(const bool option = true) { m_bUseTOF = option; }
38
40 void EnableDiffusion(const bool option = true) { m_bDiffusion = option; }
41
43 void EnableSpaceChargeEffect(const bool option = true) {
44 m_bSpaceCharge = option;
45 }
46
48 void EnableAdaptiveTimeStepping(const bool option = true) {
49 m_bAdaptiveTime = option;
50 }
51
56 void EnableMC(const bool option = true) { m_bMC = option; }
57
60 void SetNCrit(const long NCrit = 1e8) { m_lNCrit = NCrit; }
61
67 void SetFieldCalculation(const std::string &option = "coulomb",
68 const int nof_approx = 1.) {
69 m_sFieldOption = std::move(option);
70 m_iFieldApprox = std::move(nof_approx);
71 }
72
75 void SetK(float option = 0.95) { m_fStreamerK = option; }
76
78 void SetStopAtK(bool option = true) { m_bStopAtK = option; }
79
81 void SetSensor(Sensor *sensor);
82
91 void Set2dGrid(double zmin, double zmax, int zsteps, double rmax, int rsteps);
92
96
98 void AddElectron(double x, double y, double z, double t = 0, int n = 1);
99
102 void AddExtraElectron(double y, int n = 1);
103
106 void StartGridAvalanche(double dtime = -1);
107
109 long GetAvalancheSize() const { return m_nTotPosIons; }
110
113
115 [[nodiscard]] long ReachedKPercent() const {
116 if (m_bFieldK)
117 return m_lElectronsK;
118 else
119 return -1;
120 }
121
123 [[nodiscard]] const std::vector<std::pair<double, long>>
126 }
127
132 void ExportGrid(const std::string &filename);
133
134 private:
135 struct GridNode {
136 long nElectron = 0;
137 double nPosIon = 0;
138 double nNegIon = 0;
139 // holder memories for stepping in time:
141 double nPosIonHolder = 0;
142 double nNegIonHolder = 0;
143
144 double townsend = 0;
145 double attachment = 0;
147 double velocity = 0.;
149 double dSigmaL = 0;
151 double dSigmaT = 0;
152
153 double Wv = 0;
154 double Wr = 0;
156 double townsendPT = 0;
158 double attachmentPT = 0;
160 double eFieldR = 0;
162 double eFieldZ = 0;
163
164 double time = 0.;
165
166 bool anode = false;
168 int layerIndex = 0;
170 int gasGapIndex = 0;
171 bool isGasGap = true;
172 };
173
174 struct Point {
175 double x, y, z;
176 double t;
177
179 };
180
181 // Prepare grid and place stored electrons from AvalancheMicroscopic import
183
184 // Assign electron to the closest grid point
185 bool SnapTo2dGrid(double x, double y, double z, long n = 1, int gasLayer = 0);
186
187 // Prepare the mesh with the ComponentParallelPlate
189
190 // Transports the electrons/nodes a timestep
192
193 // Diffuses the electrons/nodes a timestep
194 void DiffuseTimeStep(double dx, long nElectron, double nPosIon,
195 double nNegIon, int iz, int ir, int gasGap);
196
197 // Redistributes the charges
198 void DistributeCharges(long nElectron, double nPosIon, double nNegIon, int iz,
199 int ir, double stepZ, double stepR, int gasGap);
200
201 // Calculate the field from all the contributions to the bin of interest. May
202 // need much more functionalities/tables.
203 void GetLocalField(int iz, int ir, double &eFieldZ, double &eFieldR,
204 const std::string &fieldOption, int gasGap);
205
206 // Calculate the field of charged ring in vacuum using coulomb potentials and
207 // indices
208 void GetFreeChargedRing(int iz, int ir, int fz, int fr, double &eFieldZ,
209 double &eFieldR);
210
211 // Calculate the field of charged ring in vacuum using coulomb potentials and
212 // coordinates
213 void GetFreeChargedRing(double zi, double ri, double zf, double rf,
214 double &eFieldZ, double &eFieldR);
215
216 // Get field at (zi, ri) from N charges at (zf, rf) either as a ring or a
217 // coulomb ball (rf = 0) if i and f are too close it is considered as self
218 // interaction and not included
219 bool AddFieldFromChargeAt(int iz, int ir, int fz, int fr, double N,
220 double &eFieldZ, double &eFieldR);
221
222 // Get field at (zi, ri) from N charges at (zf, rf) either as a ring or a
223 // coulomb ball (rf = 0) if i and f are too close it is considered as self
224 // interaction and not included
225 bool AddFieldFromChargeAt(int iz, int ir, double zf, double rf, double N,
226 double &eFieldZ, double &eFieldR);
227
228 // Get swarm parameters at electric field magnitude
229 void GetSwarmParameters(double MagEField, double &alpha, double &eta,
230 double &drift, double &dSigmaL, double &dSigmaT,
231 double &wv, double &wr, double &alphaPT,
232 double &etaPT, int gasGap);
233
234 // Change from 2dGrid to Global coordinates
235 void GetGlobalCoordinates(double r, double z, double phi, double &xg,
236 double &yg, double &zg, int gasGap);
237
238 // Import elliptic integral values
239 void ImportEllipticIntegralValues(const std::string &filename);
240
241 // Gets elliptic integrals via list
242 void GetEllipticIntegrals(double x, double &K, double &E);
243
244 // Get from index the gas gap number, else -1
245 int GetGasGapNumber(int layerIndex) {
246 auto it =
247 std::find(m_vIndexGasGaps.begin(), m_vIndexGasGaps.end(), layerIndex);
248 return (it != m_vIndexGasGaps.end())
249 ? std::distance(m_vIndexGasGaps.begin(), it)
250 : -1;
251 }
252
253 private:
254 std::string m_className = "AvalancheGridSpaceCharge";
255
256 bool m_bDebug = false;
257 bool m_bDiffusion = false;
258 bool m_bStick = true;
259 // boolean for AvalancheElectron
260 bool m_bDriftAvalanche = false;
261 // boolean for ImportElectronsFromAvalancheMicroscopic
262 bool m_bImportAvalanche = false;
264 long m_lNCrit = 1e8;
265 bool m_bSpaceCharge = true;
266
267 float m_fStreamerK = 0.95;
268 bool m_bStopAtK = false;
269 bool m_bFieldK = false;
271
272 bool m_bAdaptiveTime = true;
273 bool m_bImportElliptic = false;
276 bool m_bUseTOF = true;
278 bool m_bWrAvailable = true;
280 bool m_bRatesAvailable = true;
281
282 bool m_bMC = true;
283
284 int m_iFieldApprox = 1; //< order of approximation in Set(1,2,3,...)
285 double m_dMinGroups = 50; //< same values as lippmann
286
288 Sensor *m_sensor = nullptr;
289
290 std::vector<double> m_zGrid;
291 int m_zSteps = 0;
292 double m_zStepSize = 0.;
293
294 std::vector<double> m_rGrid;
295 int m_rSteps = 0.;
296 double m_rStepSize = 0.;
297
298 bool m_isgridset = false;
299 long m_nTotElectron = 0;
300 long m_nTotPosIons = 0;
301
302 double m_time = 0.;
303 double m_time0 = 0.;
304 double m_dt = 0.;
306 bool m_run = true;
307
308 std::vector<std::vector<int>>
310
311 std::vector<std::vector<GridNode>> m_grid;
313 std::vector<std::vector<Point>> m_vElectrons;
314
315 std::vector<std::pair<double, long>> m_vNElectronEvolution;
316 std::vector<long> m_vGroupSizes = {
317 1500, 800, 400, 200, 100,
318 50, 20, 10, 5, 2};
319
320 std::vector<int> m_vIndexGasGaps = {0};
321
324 std::vector<std::vector<double>> m_vCoNGasLayer{};
326 std::vector<double> m_vYPointInGasGap{};
327
329 std::vector<double> m_ezBkg = {0};
331 std::vector<int> m_vSaturatedGaps{};
332
333 std::string m_sFieldOption = "coulomb";
334 enum class Elliptic : std::size_t
335 {
339 };
340 static const constexpr std::size_t elliptic_size{29981};
341 static const std::array<std::array<double,3>, elliptic_size> m_elliptic;
342};
343
344} // namespace Garfield
345
346#endif // GARFIELD_AVALANCHEGRIDSPACECHARGE_HH
std::vector< std::vector< Point > > m_vElectrons
Electrons to transfer onto grid.
std::vector< double > m_zGrid
Grid points of z-coordinate.
void EnableStickyAnode(const bool option=true)
Enable sticky anode (default on)
bool m_isgridset
Distance between the grid points.
bool AddFieldFromChargeAt(int iz, int ir, int fz, int fr, double N, double &eFieldZ, double &eFieldR)
void Set2dGrid(double zmin, double zmax, int zsteps, double rmax, int rsteps)
void EnableMC(const bool option=true)
Enable Monte Carlo (gain/diffusion) up to a certain total number of electrons e.g.
void ExportGrid(const std::string &filename)
Export the current grid to a txt file (electron, ions numbers and field magnitude) Take care: only wh...
void AddExtraElectron(double y, int n=1)
After calling AddElectron, add more electrons on the same transversal line (y-freedom).
std::vector< std::pair< double, long > > m_vNElectronEvolution
std::vector< double > m_vYPointInGasGap
Example point (y-coord) in each gas gap.
std::vector< std::vector< int > > m_zGasGapBoundaries
[k] -> {izLeft, ..., izRight}
std::vector< double > m_ezBkg
Uniform background field in z direction, can be negative.
std::vector< int > m_vSaturatedGaps
Which gas gaps are saturated if saturation is on.
void SetFieldCalculation(const std::string &option="coulomb", const int nof_approx=1.)
Sets the different options to calculate the space charge field coulomb: free field approximation (rel...
std::vector< double > m_rGrid
Distance between the grid points.
bool m_bRatesAvailable
Flag if temporal rates are available to the simulation.
void EnableDiffusion(const bool option=true)
Enable diffusion (default off)
std::vector< std::vector< GridNode > > m_grid
grid with nodes on it
void GetEllipticIntegrals(double x, double &K, double &E)
bool m_bWrAvailable
Flag if bulk drift velocity is available to the simulation.
void SetStopAtK(bool option=true)
Stop the avalanche if K % field is reached.
std::vector< std::vector< double > > m_vCoNGasLayer
Coordinates of center of electron number.
void SetSensor(Sensor *sensor)
Set the sensor (and determine if it includes a parallel-plate component).
long m_nTotElectron
Total amount of electrons at time step.
void EnableSpaceChargeEffect(const bool option=true)
Enable space charge calculations (default on)
static const constexpr std::size_t elliptic_size
long m_nTotPosIons
total amount of charge created
std::vector< int > m_vIndexGasGaps
Which layer indices are gas layers.
void DiffuseTimeStep(double dx, long nElectron, double nPosIon, double nNegIon, int iz, int ir, int gasGap)
bool m_run
Tracking if the charges are still in the drift gap.
long ReachedKPercent() const
Returns if 100 * K % background charge has been reached.
bool SnapTo2dGrid(double x, double y, double z, long n=1, int gasLayer=0)
void GetSwarmParameters(double MagEField, double &alpha, double &eta, double &drift, double &dSigmaL, double &dSigmaT, double &wv, double &wr, double &alphaPT, double &etaPT, int gasGap)
void EnableAdaptiveTimeStepping(const bool option=true)
Enable adaptive time stepping (default on)
void GetFreeChargedRing(double zi, double ri, double zf, double rf, double &eFieldZ, double &eFieldR)
~AvalancheGridSpaceCharge()=default
Destructor.
void ImportEllipticIntegralValues(const std::string &filename)
void AddElectrons(AvalancheMicroscopic *avmc)
Import electron (no ions) data from AvalancheMicroscopic class to axi-symmetric grid.
void DistributeCharges(long nElectron, double nPosIon, double nNegIon, int iz, int ir, double stepZ, double stepR, int gasGap)
std::vector< long > m_vGroupSizes
same values as Lippmann & Riegler
bool AddFieldFromChargeAt(int iz, int ir, double zf, double rf, double N, double &eFieldZ, double &eFieldR)
double GetMeanDistance()
Return current mean distance of the electrons on the grid.
void SetNCrit(const long NCrit=1e8)
Set electron saturation value applied for each gas gap if space charge effect is turned off (default ...
long GetAvalancheSize() const
Returns the total positive charge in the gap's.
void GetLocalField(int iz, int ir, double &eFieldZ, double &eFieldR, const std::string &fieldOption, int gasGap)
void GetFreeChargedRing(int iz, int ir, int fz, int fr, double &eFieldZ, double &eFieldR)
void EnableTOF(const bool option=true)
Enable to use TOF swarm parameters (default on)
AvalancheGridSpaceCharge(Sensor *sensor)
Constructor.
void Reset()
Reset the charges.
void SetK(float option=0.95)
Set the streamer-inception criterion constant K in the interval (0, ∞) s.t.
bool m_bUseTOF
Flag if TOF parameters should be used, else Magboltz drift and SST spatial coefficients.
static const std::array< std::array< double, 3 >, elliptic_size > m_elliptic
void AddElectron(double x, double y, double z, double t=0, int n=1)
Set n electrons onto the grid.
void StartGridAvalanche(double dtime=-1)
Starts the simulation with the imported electrons for a time step dt (dt = -1 until there are no elec...
void GetGlobalCoordinates(double r, double z, double phi, double &xg, double &yg, double &zg, int gasGap)
const std::vector< std::pair< double, long > > GetElectronEvolution() const
Returns the total electron number evolution.
void EnableDebugging(const bool option=true)
Enable/disable debugging (log messages) (default off)
Calculate electron drift lines and avalanches using microscopic tracking.
Component for parallel-plate geometries.
double attachmentPT
Attachment rate from TOF experiment 1/ns -> 1/cm.
int gasGapIndex
Gas gap index: -1 if not gas gap; starts with 0, 1, ...
double velocity
Magnitude of velocity of the node (not negative) cm/ns.
double eFieldR
Space-charge electric field in R direction (can be negative)
double townsendPT
Ionization rate from TOF experiment 1/ns -> 1/cm.
double nPosIon
pos ion on node (smeared values allowed)
double dSigmaT
Diffusion transverse to E (radial, phi dir is net 0).
double eFieldZ
Space-charge electric field in Z direction (can be negative)
int layerIndex
LayerIndex in ParallelPlate convention != gas gap index.
double nNegIon
neg ion on node (smeared values allowed)